[add] studio server unit-tests
This commit is contained in:
parent
d71443fd00
commit
ecee5d73db
4 changed files with 205 additions and 23 deletions
|
|
@ -4,6 +4,8 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
|
@ -11,6 +13,8 @@ import (
|
|||
"github.com/yaoapp/gou"
|
||||
)
|
||||
|
||||
var regExcp = regexp.MustCompile("^Exception\\|([0-9]+):(.+)$")
|
||||
|
||||
// Serve start the api server
|
||||
func setRouter(router *gin.Engine) {
|
||||
|
||||
|
|
@ -42,7 +46,7 @@ func setRouter(router *gin.Engine) {
|
|||
}
|
||||
c.JSON(200, res)
|
||||
c.Done()
|
||||
break
|
||||
return
|
||||
|
||||
case "readdir":
|
||||
name := c.Query("name")
|
||||
|
|
@ -62,11 +66,13 @@ func setRouter(router *gin.Engine) {
|
|||
}
|
||||
c.JSON(200, data)
|
||||
c.Done()
|
||||
break
|
||||
return
|
||||
}
|
||||
|
||||
throw(c, 404, fmt.Sprintf("%s method does not found", c.Param("method")))
|
||||
})
|
||||
|
||||
// DSL WriteFile, Mkdir, MkdirAll ...
|
||||
// DSL WriteFile, Mkdir, MkdirAll, Remove, RemoveAll ...
|
||||
router.POST("/dsl/:method", func(c *gin.Context) {
|
||||
|
||||
method := strings.ToLower(c.Param("method"))
|
||||
|
|
@ -97,7 +103,7 @@ func setRouter(router *gin.Engine) {
|
|||
|
||||
c.JSON(200, length)
|
||||
c.Done()
|
||||
break
|
||||
return
|
||||
|
||||
case "mkdir":
|
||||
name := c.Query("name")
|
||||
|
|
@ -113,7 +119,7 @@ func setRouter(router *gin.Engine) {
|
|||
}
|
||||
c.Status(200)
|
||||
c.Done()
|
||||
break
|
||||
return
|
||||
|
||||
case "mkdirall":
|
||||
name := c.Query("name")
|
||||
|
|
@ -129,9 +135,42 @@ func setRouter(router *gin.Engine) {
|
|||
}
|
||||
c.Status(200)
|
||||
c.Done()
|
||||
break
|
||||
return
|
||||
|
||||
case "remove":
|
||||
name := c.Query("name")
|
||||
if name == "" {
|
||||
throw(c, 400, "name is required")
|
||||
return
|
||||
}
|
||||
|
||||
err := dfs.Remove(name)
|
||||
if err != nil {
|
||||
throw(c, 500, err.Error())
|
||||
return
|
||||
}
|
||||
c.Status(200)
|
||||
c.Done()
|
||||
return
|
||||
|
||||
case "removeall":
|
||||
name := c.Query("name")
|
||||
if name == "" {
|
||||
throw(c, 400, "name is required")
|
||||
return
|
||||
}
|
||||
|
||||
err := dfs.RemoveAll(name)
|
||||
if err != nil {
|
||||
throw(c, 500, err.Error())
|
||||
return
|
||||
}
|
||||
c.Status(200)
|
||||
c.Done()
|
||||
return
|
||||
}
|
||||
|
||||
throw(c, 404, fmt.Sprintf("%s method does not found", c.Param("method")))
|
||||
})
|
||||
|
||||
// Cloud Functions
|
||||
|
|
@ -151,21 +190,31 @@ func setRouter(router *gin.Engine) {
|
|||
return
|
||||
}
|
||||
|
||||
if payload == nil || len(payload) > 0 {
|
||||
if payload == nil || len(payload) == 0 {
|
||||
throw(c, 400, "file content is required")
|
||||
return
|
||||
}
|
||||
|
||||
var call cloudCall
|
||||
err = jsoniter.Unmarshal(payload, &call)
|
||||
var fun cfunc
|
||||
err = jsoniter.Unmarshal(payload, &fun)
|
||||
if err != nil {
|
||||
throw(c, 500, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
res, err := gou.Yao.Engine.Call(map[string]interface{}{}, service, call.Method, call.Args...)
|
||||
res, err := gou.Yao.Engine.Call(map[string]interface{}{}, service, fun.Method, fun.Args...)
|
||||
if err != nil {
|
||||
throw(c, 500, err.Error())
|
||||
// parse Exception
|
||||
code := 500
|
||||
message := err.Error()
|
||||
match := regExcp.FindStringSubmatch(message)
|
||||
if len(match) > 0 {
|
||||
code, err = strconv.Atoi(match[1])
|
||||
if err == nil {
|
||||
message = strings.TrimSpace(match[2])
|
||||
}
|
||||
}
|
||||
throw(c, code, message)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ var shutdownSignal = make(chan bool, 1)
|
|||
var dfs fs.FileSystem
|
||||
var scripts = map[string][]byte{}
|
||||
|
||||
type cloudCall struct {
|
||||
type cfunc struct {
|
||||
Method string `json:"method"`
|
||||
Args []interface{} `json:"args,omitempty"`
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@ func Start(cfg config.Config) (err error) {
|
|||
errCh := make(chan error, 1)
|
||||
|
||||
// Set router
|
||||
router := gin.Default()
|
||||
router := gin.New()
|
||||
setRouter(router)
|
||||
|
||||
// Server setting
|
||||
|
|
|
|||
|
|
@ -1,16 +1,22 @@
|
|||
package studio
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/yaoapp/gou"
|
||||
"github.com/yaoapp/yao/config"
|
||||
"github.com/yaoapp/yao/network"
|
||||
)
|
||||
|
||||
type kv map[string]interface{}
|
||||
type arr []interface{}
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
err := Load(config.Conf)
|
||||
if err != nil {
|
||||
|
|
@ -63,16 +69,131 @@ func TestGetAPI(t *testing.T) {
|
|||
defer Stop()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
|
||||
url := fmt.Sprintf("http://127.0.0.1:%d/dsl/readfile?name=/models/user.json", config.Conf.Studio.Port)
|
||||
res := network.RequestGet(url, nil, nil)
|
||||
assert.Equal(t, "用户", res.Data.(map[string]interface{})["name"])
|
||||
code, row := httpGet[kv]("/dsl/ReadFile?name=/models/user.json", t)
|
||||
assert.Equal(t, 200, code)
|
||||
assert.Equal(t, "用户", row["name"])
|
||||
|
||||
url = fmt.Sprintf("http://127.0.0.1:%d/dsl/readdir?name=/models", config.Conf.Studio.Port)
|
||||
res = network.RequestGet(url, nil, nil)
|
||||
assert.Equal(t, 11, len(res.Data.([]interface{})))
|
||||
code, rows := httpGet[arr]("/dsl/ReadDir?name=/models", t)
|
||||
assert.Equal(t, 200, code)
|
||||
assert.Equal(t, 11, len(rows))
|
||||
|
||||
url = fmt.Sprintf("http://127.0.0.1:%d/dsl/readdir?name=/models&recursive=1", config.Conf.Studio.Port)
|
||||
res = network.RequestGet(url, nil, nil)
|
||||
assert.Equal(t, 12, len(res.Data.([]interface{})))
|
||||
code, rows = httpGet[arr]("/dsl/ReadDir?name=/models&recursive=1", t)
|
||||
assert.Equal(t, 200, code)
|
||||
assert.Equal(t, 12, len(rows))
|
||||
|
||||
code, length := httpPost[int]("/dsl/WriteFile?name=/models/foo.mod.json", []byte(`{"name":"foo"}`), t)
|
||||
assert.Equal(t, 200, code)
|
||||
assert.Equal(t, 19, length)
|
||||
|
||||
code, _ = httpPost[kv]("/dsl/Remove?name=/models/foo.mod.json", nil, t)
|
||||
assert.Equal(t, 200, code)
|
||||
|
||||
code, _ = httpPost[kv]("/dsl/Mkdir?name=/models/bar", nil, t)
|
||||
assert.Equal(t, 200, code)
|
||||
|
||||
code, _ = httpPost[kv]("/dsl/Remove?name=/models/bar", nil, t)
|
||||
assert.Equal(t, 200, code)
|
||||
|
||||
code, _ = httpPost[kv]("/dsl/MkdirAll?name=/models/bar/hi", nil, t)
|
||||
assert.Equal(t, 200, code)
|
||||
|
||||
code, _ = httpPost[kv]("/dsl/RemoveAll?name=/models/bar", nil, t)
|
||||
assert.Equal(t, 200, code)
|
||||
|
||||
code, res := httpPostJSON[arr](
|
||||
"/service/table",
|
||||
kv{
|
||||
"method": "UnitTest",
|
||||
"args": []interface{}{
|
||||
"foo", 1, 0.618,
|
||||
kv{"string": "world", "int": 1, "float": 0.618},
|
||||
arr{"foo", 1, 0.618},
|
||||
},
|
||||
}, t)
|
||||
|
||||
assert.Equal(t, 200, code)
|
||||
assert.Equal(t, "foo", res[0])
|
||||
assert.Equal(t, float64(1), res[1])
|
||||
assert.Equal(t, 0.618, res[2])
|
||||
assert.Equal(t, "world", res[3].(map[string]interface{})["string"])
|
||||
assert.Equal(t, float64(1), res[3].(map[string]interface{})["int"])
|
||||
assert.Equal(t, 0.618, res[3].(map[string]interface{})["float"])
|
||||
assert.Equal(t, "foo", res[4].([]interface{})[0])
|
||||
assert.Equal(t, float64(1), res[4].([]interface{})[1])
|
||||
assert.Equal(t, 0.618, res[4].([]interface{})[2])
|
||||
|
||||
code, excp := httpPostJSON[kv]("/service/table", kv{"method": "UnitTest", "args": []interface{}{"throw-test"}}, t)
|
||||
assert.Equal(t, 418, code)
|
||||
assert.Equal(t, float64(418), excp["code"])
|
||||
assert.Equal(t, "I'm a teapot", excp["message"])
|
||||
}
|
||||
|
||||
func httpGet[T kv | arr | interface{} | map[string]interface{} | int | []interface{}](url string, t *testing.T) (int, T) {
|
||||
|
||||
var data T
|
||||
url = fmt.Sprintf("http://127.0.0.1:%d%s", config.Conf.Studio.Port, url)
|
||||
res, err := http.Get(url)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if body != nil {
|
||||
err = jsoniter.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.StatusCode, data
|
||||
}
|
||||
|
||||
func httpPost[T kv | arr | interface{} | map[string]interface{} | int | []interface{}](url string, payload []byte, t *testing.T) (int, T) {
|
||||
|
||||
var data T
|
||||
var buff *bytes.Buffer = bytes.NewBuffer([]byte{})
|
||||
|
||||
if payload != nil {
|
||||
buff = bytes.NewBuffer(payload)
|
||||
}
|
||||
|
||||
url = fmt.Sprintf("http://127.0.0.1:%d%s", config.Conf.Studio.Port, url)
|
||||
res, err := http.Post(url, "application/json", buff)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if res.Body != nil {
|
||||
body, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if body != nil && string(body) != "" {
|
||||
err = jsoniter.Unmarshal(body, &data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res.StatusCode, data
|
||||
}
|
||||
|
||||
func httpPostJSON[T kv | arr | interface{} | map[string]interface{} | int | []interface{}](url string, payload interface{}, t *testing.T) (int, T) {
|
||||
var data []byte
|
||||
var err error
|
||||
if payload != nil {
|
||||
data, err = jsoniter.Marshal(payload)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
return httpPost[T](url, data, t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,3 +31,15 @@ function Model(name) {
|
|||
function Ping() {
|
||||
return "PONG";
|
||||
}
|
||||
|
||||
/**
|
||||
* for unit tests
|
||||
* @param {...any} args
|
||||
* @returns
|
||||
*/
|
||||
function UnitTest(...args) {
|
||||
if (args.length > 0 && args[0] == "throw-test") {
|
||||
throw new Exception("I'm a teapot", 418);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue