1
0
mirror of https://github.com/gogf/gf.git synced 2025-04-05 03:05:05 +08:00

fix(net/ghttp): update response message handling in MiddlewareHandlerResponse (#4162)

This commit is contained in:
hailaz 2025-02-27 11:59:26 +08:00 committed by GitHub
parent a3b3c656d9
commit 63cb3285f8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 274 additions and 101 deletions

View File

@ -30,6 +30,7 @@ jobs:
strategy:
matrix:
go-version: [ 'stable' ]
name: golang-ci-lint
runs-on: ubuntu-latest
steps:
@ -43,7 +44,7 @@ jobs:
uses: golangci/golangci-lint-action@v6
with:
# Required: specify the golangci-lint version without the patch version to always use the latest patch.
version: v1.62.2
version: v1.64.5
only-new-issues: true
skip-cache: true
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -39,6 +39,7 @@ type (
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
GoPackage string `name:"goPackage" short:"g" brief:"{CGenPbEntityBriefGoPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
@ -113,6 +114,7 @@ CONFIGURATION SUPPORT
`
CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefGoPackage = `go package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
@ -239,6 +241,7 @@ func init() {
`CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefGoPackage`: CGenPbEntityBriefGoPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
@ -379,10 +382,13 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
}
}
}
if in.GoPackage == "" {
in.GoPackage = in.Package
}
entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{
"{Imports}": packageImportsArray.Join("\n"),
"{PackageName}": gfile.Basename(in.Package),
"{GoPackage}": in.Package,
"{GoPackage}": in.GoPackage,
"{OptionContent}": in.Option,
"{EntityMessage}": entityMessageDefine,
})

View File

@ -147,7 +147,7 @@ func (c *Client) doUpdate(ctx context.Context) (err error) {
return gerror.New("config file is empty")
}
var j *gjson.Json
if j, err = gjson.DecodeToJson([]byte(c.client.GetContent())); err != nil {
if j, err = gjson.LoadContent([]byte(c.client.GetContent())); err != nil {
return gerror.Wrap(err, `parse config map item from polaris failed`)
}
c.value.Set(j)

View File

@ -62,7 +62,6 @@ func MiddlewareHandlerResponse(r *Request) {
msg = err.Error()
} else {
if r.Response.Status > 0 && r.Response.Status != http.StatusOK {
msg = http.StatusText(r.Response.Status)
switch r.Response.Status {
case http.StatusNotFound:
code = gcode.CodeNotFound
@ -77,6 +76,7 @@ func MiddlewareHandlerResponse(r *Request) {
} else {
code = gcode.CodeOK
}
msg = code.Message()
}
r.Response.WriteJson(DefaultHandlerResponse{

View File

@ -268,28 +268,28 @@ func (r *Request) parseForm() {
if r.ContentLength == 0 {
return
}
if contentType := r.Header.Get("Content-Type"); contentType != "" {
var (
err error
repeatableRead = true
)
if gstr.Contains(contentType, "multipart/") {
var isMultiPartRequest = gstr.Contains(contentType, "multipart/")
var isFormRequest = gstr.Contains(contentType, "form")
var err error
if !isMultiPartRequest {
// To avoid big memory consuming.
// The `multipart/` type form always contains binary data, which is not necessary read twice.
repeatableRead = false
r.MakeBodyRepeatableRead(true)
}
if isMultiPartRequest {
// multipart/form-data, multipart/mixed
if err = r.ParseMultipartForm(r.Server.config.FormParsingMemory); err != nil {
panic(gerror.WrapCode(gcode.CodeInvalidRequest, err, "r.ParseMultipartForm failed"))
}
} else if gstr.Contains(contentType, "form") {
} else if isFormRequest {
// application/x-www-form-urlencoded
if err = r.Request.ParseForm(); err != nil {
panic(gerror.WrapCode(gcode.CodeInvalidRequest, err, "r.Request.ParseForm failed"))
}
}
if repeatableRead {
r.MakeBodyRepeatableRead(true)
}
if len(r.PostForm) > 0 {
// Parse the form data using united parsing way.
params := ""

View File

@ -183,7 +183,7 @@ func (r *Request) doGetRequestStruct(pointer interface{}, mapping ...map[string]
return data, nil
}
// `in` Tag Struct values.
if err = r.mergeInTagStructValue(data, pointer); err != nil {
if err = r.mergeInTagStructValue(data); err != nil {
return data, nil
}
@ -239,7 +239,7 @@ func (r *Request) mergeDefaultStructValue(data map[string]interface{}, pointer i
}
// mergeInTagStructValue merges the request parameters with header or cookie values from struct `in` tag definition.
func (r *Request) mergeInTagStructValue(data map[string]interface{}, pointer interface{}) error {
func (r *Request) mergeInTagStructValue(data map[string]interface{}) error {
fields := r.serveHandler.Handler.Info.ReqStructFields
if len(fields) > 0 {
var (

View File

@ -282,20 +282,3 @@ func createRouterFunc(funcInfo handlerFuncInfo) func(r *Request) {
}
}
}
// trimGeneric removes type definitions string from response type name if generic
func trimGeneric(structName string) string {
var (
leftBraceIndex = strings.LastIndex(structName, "[") // for generic, it is faster to start at the end than at the beginning
rightBraceIndex = strings.LastIndex(structName, "]")
)
if leftBraceIndex == -1 || rightBraceIndex == -1 {
// not found '[' or ']'
return structName
} else if leftBraceIndex+1 == rightBraceIndex {
// may be a slice, because generic is '[X]', not '[]'
// to be compatible with bad return parameter type: []XxxRes
return structName
}
return structName[:leftBraceIndex]
}

View File

@ -59,7 +59,7 @@ func Test_OpenApi_Swagger(t *testing.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
t.Assert(gstr.Contains(c.GetContent(ctx, "/swagger/"), `API Reference`), true)
@ -116,9 +116,9 @@ func Test_OpenApi_Multiple_Methods_Swagger(t *testing.T) {
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
// Only works on GET & POST methods.
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
t.Assert(c.PostContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.PostContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.PostContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
// Not works on other methods.
@ -176,9 +176,9 @@ func Test_OpenApi_Method_All_Swagger(t *testing.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.GetContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
t.Assert(c.PostContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.PostContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(c.PostContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
t.Assert(gstr.Contains(c.GetContent(ctx, "/swagger/"), `API Reference`), true)

View File

@ -115,6 +115,42 @@ func Test_Params_ParseForm(t *testing.T) {
})
}
// https://github.com/gogf/gf/pull/4143
func Test_Params_ParseForm_FixMakeBodyRepeatableRead(t *testing.T) {
type User struct {
Id int
Name string
}
s := g.Server(guid.S())
s.BindHandler("/parse-form", func(r *ghttp.Request) {
var user *User
if err := r.ParseForm(&user); err != nil {
r.Response.WriteExit(err)
}
hasBody := len(r.GetBody()) > 0
r.Response.WriteExit(hasBody)
})
s.SetDumpRouterMap(false)
s.Start()
defer s.Shutdown()
time.Sleep(100 * time.Millisecond)
gtest.C(t, func(t *gtest.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(c.GetContent(ctx, "/parse-form"), `false`)
t.Assert(c.GetContent(ctx, "/parse-form", g.Map{
"id": 1,
"name": "john",
}), false)
t.Assert(c.PostContent(ctx, "/parse-form"), `false`)
t.Assert(c.PostContent(ctx, "/parse-form", g.Map{
"id": 1,
"name": "john",
}), true)
})
}
func Test_Params_ComplexJsonStruct(t *testing.T) {
type ItemEnv struct {
Type string

View File

@ -56,7 +56,7 @@ func Test_Router_Handler_Strict_WithObject(t *testing.T) {
client := g.Client()
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(client.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/test?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/test/error"), `{"code":50,"message":"error","data":{"Id":1,"Age":0,"Name":""}}`)
})
}
@ -153,8 +153,8 @@ func Test_Router_Handler_Strict_WithObjectAndMeta(t *testing.T) {
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(client.GetContent(ctx, "/"), `{"code":65,"message":"Not Found","data":null}`)
t.Assert(client.GetContent(ctx, "/custom-test1?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/custom-test2?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/custom-test1?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/custom-test2?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.PostContent(ctx, "/custom-test2?age=18&name=john"), `{"code":65,"message":"Not Found","data":null}`)
})
}
@ -184,17 +184,17 @@ func Test_Router_Handler_Strict_Group_Bind(t *testing.T) {
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(client.GetContent(ctx, "/"), `{"code":65,"message":"Not Found","data":null}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test1?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test2?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test1?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test2?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.PostContent(ctx, "/api/v1/custom-test2?age=18&name=john"), `{"code":65,"message":"Not Found","data":null}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test3?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test4?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test3?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v1/custom-test4?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test1?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test2?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test3?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test4?age=18&name=john"), `{"code":0,"message":"","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test1?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test2?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Name":"john"}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test3?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Age":18}}`)
t.Assert(client.GetContent(ctx, "/api/v2/custom-test4?age=18&name=john"), `{"code":0,"message":"OK","data":{"Id":1,"Name":"john"}}`)
})
}
@ -251,7 +251,7 @@ func Test_Issue1708(t *testing.T) {
`
t.Assert(
client.PostContent(ctx, "/test", content),
`{"code":0,"message":"","data":{"page":0,"size":0,"targetType":"topic","targetId":10785,"test":[[{"name":"123"}]]}}`,
`{"code":0,"message":"OK","data":{"page":0,"size":0,"targetType":"topic","targetId":10785,"test":[[{"name":"123"}]]}}`,
)
})
}
@ -295,7 +295,7 @@ func Test_Custom_Slice_Type_Attribute(t *testing.T) {
`
t.Assert(
client.PostContent(ctx, "/test", content),
`{"code":0,"message":"","data":{"Content":"{\"Id\":1,\"List\":{\"key\":[\"a\",\"b\",\"c\"]}}"}}`,
`{"code":0,"message":"OK","data":{"Content":"{\"Id\":1,\"List\":{\"key\":[\"a\",\"b\",\"c\"]}}"}}`,
)
})
}
@ -370,12 +370,12 @@ func Test_Router_Handler_Strict_WithGeneric(t *testing.T) {
client := g.Client()
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(client.GetContent(ctx, "/test1?age=1"), `{"code":0,"message":"","data":{"Age":{"Test":1}}}`)
t.Assert(client.GetContent(ctx, "/test1_slice?age=1"), `{"code":0,"message":"","data":[{"Age":{"Test":1}}]}`)
t.Assert(client.GetContent(ctx, "/test2?age=2"), `{"code":0,"message":"","data":{"Test":2}}`)
t.Assert(client.GetContent(ctx, "/test2_slice?age=2"), `{"code":0,"message":"","data":[{"Test":2}]}`)
t.Assert(client.GetContent(ctx, "/test3?age=3"), `{"code":0,"message":"","data":{"Test":3}}`)
t.Assert(client.GetContent(ctx, "/test3_slice?age=3"), `{"code":0,"message":"","data":[{"Test":3}]}`)
t.Assert(client.GetContent(ctx, "/test1?age=1"), `{"code":0,"message":"OK","data":{"Age":{"Test":1}}}`)
t.Assert(client.GetContent(ctx, "/test1_slice?age=1"), `{"code":0,"message":"OK","data":[{"Age":{"Test":1}}]}`)
t.Assert(client.GetContent(ctx, "/test2?age=2"), `{"code":0,"message":"OK","data":{"Test":2}}`)
t.Assert(client.GetContent(ctx, "/test2_slice?age=2"), `{"code":0,"message":"OK","data":[{"Test":2}]}`)
t.Assert(client.GetContent(ctx, "/test3?age=3"), `{"code":0,"message":"OK","data":{"Test":3}}`)
t.Assert(client.GetContent(ctx, "/test3_slice?age=3"), `{"code":0,"message":"OK","data":[{"Test":3}]}`)
})
}
@ -415,7 +415,7 @@ func Test_Router_Handler_Strict_ParameterCaseSensitive(t *testing.T) {
for i := 0; i < 1000; i++ {
t.Assert(
client.PostContent(ctx, "/api/111", `{"Path":"222"}`),
`{"code":0,"message":"","data":{"Path":"222"}}`,
`{"code":0,"message":"OK","data":{"Path":"222"}}`,
)
}
})
@ -474,10 +474,10 @@ func Test_JsonRawMessage_Issue3449(t *testing.T) {
},
}
expect1 := `{"code":0,"message":"","data":{"name":"test","jsonRaw":[{"jkey1":"11","jkey2":"12"},{"jkey1":"21","jkey2":"22"}]}}`
expect1 := `{"code":0,"message":"OK","data":{"name":"test","jsonRaw":[{"jkey1":"11","jkey2":"12"},{"jkey1":"21","jkey2":"22"}]}}`
t.Assert(client.PostContent(ctx, "/test", data), expect1)
expect2 := `{"code":0,"message":"","data":{"name":"test","jsonRaw":{"jkey1":"11","jkey2":"12"}}}`
expect2 := `{"code":0,"message":"OK","data":{"name":"test","jsonRaw":{"jkey1":"11","jkey2":"12"}}}`
t.Assert(client.PostContent(ctx, "/test", map[string]any{
"Name": "test",
"jsonRaw": v1,
@ -524,13 +524,13 @@ func Test_NullString_Issue3465(t *testing.T) {
"name": "null",
}
expect1 := `{"code":0,"message":"","data":{"name":["null"]}}`
expect1 := `{"code":0,"message":"OK","data":{"name":["null"]}}`
t.Assert(client.GetContent(ctx, "/test", data1), expect1)
data2 := map[string]any{
"name": []string{"null", "null"},
}
expect2 := `{"code":0,"message":"","data":{"name":["null","null"]}}`
expect2 := `{"code":0,"message":"OK","data":{"name":["null","null"]}}`
t.Assert(client.GetContent(ctx, "/test", data2), expect2)
})

View File

@ -165,7 +165,7 @@ func Test_Issue1653(t *testing.T) {
}
`
resContent := c.PostContent(ctx, "/boot/test", dataReq)
t.Assert(resContent, `{"code":0,"message":"","data":{"uuid":"28ee701c-7daf-4cdc-9a62-6d6704e6112b","feed_back":"P00001"}}`)
t.Assert(resContent, `{"code":0,"message":"OK","data":{"uuid":"28ee701c-7daf-4cdc-9a62-6d6704e6112b","feed_back":"P00001"}}`)
})
}
@ -261,7 +261,7 @@ func Test_Issue2172(t *testing.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
dataReq := `{"data":{"asd":1}}`
t.Assert(c.PostContent(ctx, "/demo", dataReq), `{"code":0,"message":"","data":{"Content":"{\"asd\":1}"}}`)
t.Assert(c.PostContent(ctx, "/demo", dataReq), `{"code":0,"message":"OK","data":{"Content":"{\"asd\":1}"}}`)
})
}
@ -365,7 +365,7 @@ func Test_Issue2482(t *testing.T) {
]
}
`
t.Assert(c.PutContent(ctx, "/api/v2/order", content), `{"code":0,"message":"","data":null}`)
t.Assert(c.PutContent(ctx, "/api/v2/order", content), `{"code":0,"message":"OK","data":null}`)
})
}
@ -522,7 +522,7 @@ func Test_Issue2457(t *testing.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(c.GetContent(ctx, "/list"), `{"code":0,"message":"","data":{"Code":100,"Data":{"Title":"title","Content":"hello"},"Msg":""}}`)
t.Assert(c.GetContent(ctx, "/list"), `{"code":0,"message":"OK","data":{"Code":100,"Data":{"Title":"title","Content":"hello"},"Msg":""}}`)
})
}
@ -565,7 +565,7 @@ func Test_Issue3245(t *testing.T) {
c.SetHeader("Header-Name", "oldme")
c.SetCookie("Header-Age", "25")
expect := `{"code":0,"message":"","data":{"Reply":{"name":"oldme","X-Header-Name":"oldme","X-Header-Age":25}}}`
expect := `{"code":0,"message":"OK","data":{"Reply":{"name":"oldme","X-Header-Name":"oldme","X-Header-Age":25}}}`
t.Assert(c.GetContent(ctx, "/hello?nickname=oldme"), expect)
})
}
@ -615,7 +615,7 @@ func Test_Issue3789(t *testing.T) {
c := g.Client()
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
expect := `{"code":0,"message":"","data":{"id":"0","secondId":"2","thirdId":"3"}}`
expect := `{"code":0,"message":"OK","data":{"id":"0","secondId":"2","thirdId":"3"}}`
t.Assert(c.GetContent(ctx, "/hello?id=&secondId=2&thirdId=3"), expect)
})
}

View File

@ -9,11 +9,19 @@
package gproc_test
import (
"os"
"path/filepath"
"testing"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/gconv"
)
const (
envKeyPPid = "GPROC_PPID"
)
func Test_ShellExec(t *testing.T) {
@ -28,3 +36,112 @@ func Test_ShellExec(t *testing.T) {
t.AssertNE(err, nil)
})
}
func Test_Pid(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.Assert(os.Getpid(), gproc.Pid())
})
}
func Test_IsChild(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
originalPPid := os.Getenv(envKeyPPid)
defer os.Setenv(envKeyPPid, originalPPid)
os.Setenv(envKeyPPid, "1234")
t.Assert(true, gproc.IsChild())
os.Unsetenv(envKeyPPid)
t.Assert(false, gproc.IsChild())
})
}
func Test_SetPPid(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
err := gproc.SetPPid(1234)
t.AssertNil(err)
t.Assert("1234", os.Getenv(envKeyPPid))
err = gproc.SetPPid(0)
t.AssertNil(err)
t.Assert("", os.Getenv(envKeyPPid))
})
}
func Test_StartTime(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
result := gproc.StartTime()
t.Assert(result, gproc.StartTime())
})
}
func Test_Uptime(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
result := gproc.Uptime()
t.AssertGT(result, 0)
})
}
func Test_SearchBinary_FoundInPath(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
tempDir := t.TempDir()
tempFile := filepath.Join(tempDir, "testbinary")
gfile.Create(tempFile)
os.Chmod(tempFile, 0755)
originalPath := os.Getenv("PATH")
os.Setenv("PATH", tempDir+string(os.PathListSeparator)+originalPath)
defer os.Setenv("PATH", originalPath)
result := gproc.SearchBinary("testbinary")
t.Assert(result, tempFile)
})
}
func Test_SearchBinary_NotFound(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
result := gproc.SearchBinary("nonexistentbinary")
t.Assert(result, "")
})
}
func Test_SearchBinaryPath_FoundInPath(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
tempDir := t.TempDir()
tempFile := filepath.Join(tempDir, "testbinary")
gfile.Create(tempFile)
os.Chmod(tempFile, 0755)
originalPath := os.Getenv("PATH")
os.Setenv("PATH", tempDir+string(os.PathListSeparator)+originalPath)
defer os.Setenv("PATH", originalPath)
result := gproc.SearchBinaryPath("testbinary")
t.Assert(result, tempFile)
})
}
func Test_SearchBinaryPath_NotFound(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
result := gproc.SearchBinaryPath("nonexistentbinary")
t.Assert(result, "")
})
}
func Test_PPidOS(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
ppid := gproc.PPidOS()
expectedPpid := os.Getppid()
t.Assert(ppid, expectedPpid)
})
}
func Test_PPid(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
customPPid := 12345
os.Setenv("GPROC_PPID", gconv.String(customPPid))
defer os.Unsetenv("GPROC_PPID")
t.Assert(gproc.PPid(), customPPid)
})
}

View File

@ -220,7 +220,6 @@ func AssertLE(value, expect interface{}) {
// AssertIN checks `value` is IN `expect`.
// The `expect` should be a slice,
// but the `value` can be a slice or a basic type variable.
// TODO map support.
// TODO: gconv.Strings(0) is not [0]
func AssertIN(value, expect interface{}) {
var (
@ -249,6 +248,14 @@ func AssertIN(value, expect interface{}) {
expectStr = gconv.String(expect)
)
passed = gstr.Contains(expectStr, valueStr)
case reflect.Map:
expectMap := gconv.Map(expect)
for _, v1 := range gconv.Strings(value) {
if _, exists := expectMap[v1]; !exists {
passed = false
break
}
}
default:
panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind))
}
@ -260,7 +267,6 @@ func AssertIN(value, expect interface{}) {
// AssertNI checks `value` is NOT IN `expect`.
// The `expect` should be a slice,
// but the `value` can be a slice or a basic type variable.
// TODO map support.
func AssertNI(value, expect interface{}) {
var (
passed = true
@ -287,6 +293,14 @@ func AssertNI(value, expect interface{}) {
expectStr = gconv.String(expect)
)
passed = !gstr.Contains(expectStr, valueStr)
case reflect.Map:
expectMap := gconv.Map(expect)
for _, v1 := range gconv.Strings(value) {
if _, exists := expectMap[v1]; exists {
passed = false
break
}
}
default:
panic(fmt.Sprintf(`[ASSERT] INVALID EXPECT VALUE TYPE: %v`, expectKind))
}

View File

@ -322,6 +322,22 @@ func TestAssertIN(t *testing.T) {
})
}
func TestAssertIN_Map(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertIN("k1", map[string]string{"k1": "v1", "k2": "v2"})
t.AssertIN(1, map[int64]string{1: "v1", 2: "v2"})
t.AssertIN([]string{"k1", "k2"}, map[string]string{"k1": "v1", "k2": "v2"})
})
}
func TestAssertNI_Map(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNI("k3", map[string]string{"k1": "v1", "k2": "v2"})
t.AssertNI(3, map[int64]string{1: "v1", 2: "v2"})
t.AssertNI([]string{"k3", "k4"}, map[string]string{"k1": "v1", "k2": "v2"})
})
}
func TestAssertNI(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
t.AssertNI("d", []string{"a", "b", "c"})

View File

@ -126,7 +126,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(maps, &mss)
t.AssertNil(err)
t.Assert(len(mss), len(maps))
for k, _ := range maps {
for k := range maps {
t.Assert(maps[k]["Name"], mss[k]["Name"])
t.Assert(maps[k]["Place"], mss[k]["Place"])
}
@ -135,7 +135,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(maps, &msa)
t.AssertNil(err)
t.Assert(len(msa), len(maps))
for k, _ := range maps {
for k := range maps {
t.Assert(maps[k]["Name"], msa[k]["Name"])
t.Assert(maps[k]["Place"], msa[k]["Place"])
}
@ -144,7 +144,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(maps, &maa)
t.AssertNil(err)
t.Assert(len(maa), len(maps))
for k, _ := range maps {
for k := range maps {
t.Assert(maps[k]["Name"], maa[k]["Name"])
t.Assert(maps[k]["Place"], maa[k]["Place"])
}
@ -153,7 +153,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(maps, &ss)
t.AssertNil(err)
t.Assert(len(ss), len(maps))
for k, _ := range maps {
for k := range maps {
t.Assert(maps[k]["Name"], ss[k].Name)
t.Assert(maps[k]["Place"], ss[k].Place)
}
@ -162,7 +162,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(maps, &ssp)
t.AssertNil(err)
t.Assert(len(ssp), len(maps))
for k, _ := range maps {
for k := range maps {
t.Assert(maps[k]["Name"], ssp[k].Name)
t.Assert(maps[k]["Place"], ssp[k].Place)
}
@ -219,7 +219,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(structs, &mss)
t.AssertNil(err)
t.Assert(len(mss), len(structs))
for k, _ := range structs {
for k := range structs {
t.Assert(structs[k].Name, mss[k]["Name"])
t.Assert(structs[k].Place, mss[k]["Place"])
}
@ -228,7 +228,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(structs, &msa)
t.AssertNil(err)
t.Assert(len(msa), len(structs))
for k, _ := range structs {
for k := range structs {
t.Assert(structs[k].Name, msa[k]["Name"])
t.Assert(structs[k].Place, msa[k]["Place"])
}
@ -237,7 +237,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(structs, &maa)
t.AssertNil(err)
t.Assert(len(maa), len(structs))
for k, _ := range structs {
for k := range structs {
t.Assert(structs[k].Name, maa[k]["Name"])
t.Assert(structs[k].Place, maa[k]["Place"])
}
@ -246,7 +246,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(structs, &ss)
t.AssertNil(err)
t.Assert(len(ss), len(structs))
for k, _ := range structs {
for k := range structs {
t.Assert(structs[k].Name, ss[k].Name)
t.Assert(structs[k].Place, ss[k].Place)
}
@ -255,7 +255,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(structs, &ssp)
t.AssertNil(err)
t.Assert(len(ssp), len(structs))
for k, _ := range structs {
for k := range structs {
t.Assert(structs[k].Name, ssp[k].Name)
t.Assert(structs[k].Place, ssp[k].Place)
}
@ -312,7 +312,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(jsons, &mss)
t.AssertNil(err)
t.Assert(len(mss), 2)
for k, _ := range mss {
for k := range mss {
t.Assert("Mars", mss[k]["Name"])
t.Assert("奥林帕斯山", mss[k]["Place"])
}
@ -321,7 +321,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(jsons, &msa)
t.AssertNil(err)
t.Assert(len(msa), 2)
for k, _ := range msa {
for k := range msa {
t.Assert("Mars", msa[k]["Name"])
t.Assert("奥林帕斯山", msa[k]["Place"])
}
@ -336,7 +336,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(jsons, &ss)
t.AssertNil(err)
t.Assert(len(ss), 2)
for k, _ := range ss {
for k := range ss {
t.Assert("Mars", ss[k].Name)
t.Assert("奥林帕斯山", ss[k].Place)
}
@ -345,7 +345,7 @@ func TestScan(t *testing.T) {
err = gconv.Scan(jsons, &ssp)
t.AssertNil(err)
t.Assert(len(ssp), 2)
for k, _ := range ssp {
for k := range ssp {
t.Assert("Mars", ssp[k].Name)
t.Assert("奥林帕斯山", ssp[k].Place)
}

View File

@ -110,7 +110,7 @@ func Test_Issue3636(t *testing.T) {
c.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", s.GetListenedPort()))
t.Assert(
c.PostContent(ctx, "/hello", `{"name": "t", "s" : []}`),
`{"code":0,"message":"","data":{"name":"t","s":[]}}`,
`{"code":0,"message":"OK","data":{"name":"t","s":[]}}`,
)
})
}

View File

@ -39,16 +39,16 @@ func (r RuleBetween) Run(in RunInput) error {
max = float64(0)
)
if len(array) > 0 {
if v, err := strconv.ParseFloat(strings.TrimSpace(array[0]), 10); err == nil {
if v, err := strconv.ParseFloat(strings.TrimSpace(array[0]), 64); err == nil {
min = v
}
}
if len(array) > 1 {
if v, err := strconv.ParseFloat(strings.TrimSpace(array[1]), 10); err == nil {
if v, err := strconv.ParseFloat(strings.TrimSpace(array[1]), 64); err == nil {
max = v
}
}
valueF, err := strconv.ParseFloat(in.Value.String(), 10)
valueF, err := strconv.ParseFloat(in.Value.String(), 64)
if valueF < min || valueF > max || err != nil {
return errors.New(gstr.ReplaceByMap(in.Message, map[string]string{
"{min}": strconv.FormatFloat(min, 'f', -1, 64),

View File

@ -30,7 +30,7 @@ func (r RuleFloat) Message() string {
}
func (r RuleFloat) Run(in RunInput) error {
if _, err := strconv.ParseFloat(in.Value.String(), 10); err == nil {
if _, err := strconv.ParseFloat(in.Value.String(), 64); err == nil {
return nil
}
return errors.New(in.Message)

View File

@ -37,8 +37,8 @@ func (r RuleGT) Message() string {
func (r RuleGT) Run(in RunInput) error {
var (
fieldName, fieldValue = gutil.MapPossibleItemByKey(in.Data.Map(), in.RulePattern)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN <= fieldValueN || err1 != nil || err2 != nil {

View File

@ -37,8 +37,8 @@ func (r RuleGTE) Message() string {
func (r RuleGTE) Run(in RunInput) error {
var (
fieldName, fieldValue = gutil.MapPossibleItemByKey(in.Data.Map(), in.RulePattern)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN < fieldValueN || err1 != nil || err2 != nil {

View File

@ -37,8 +37,8 @@ func (r RuleLT) Message() string {
func (r RuleLT) Run(in RunInput) error {
var (
fieldName, fieldValue = gutil.MapPossibleItemByKey(in.Data.Map(), in.RulePattern)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN >= fieldValueN || err1 != nil || err2 != nil {

View File

@ -37,8 +37,8 @@ func (r RuleLTE) Message() string {
func (r RuleLTE) Run(in RunInput) error {
var (
fieldName, fieldValue = gutil.MapPossibleItemByKey(in.Data.Map(), in.RulePattern)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
fieldValueN, err1 = strconv.ParseFloat(gconv.String(fieldValue), 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN > fieldValueN || err1 != nil || err2 != nil {

View File

@ -33,8 +33,8 @@ func (r RuleMax) Message() string {
func (r RuleMax) Run(in RunInput) error {
var (
max, err1 = strconv.ParseFloat(in.RulePattern, 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
max, err1 = strconv.ParseFloat(in.RulePattern, 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN > max || err1 != nil || err2 != nil {
return errors.New(gstr.Replace(in.Message, "{max}", strconv.FormatFloat(max, 'f', -1, 64)))

View File

@ -33,8 +33,8 @@ func (r RuleMin) Message() string {
func (r RuleMin) Run(in RunInput) error {
var (
min, err1 = strconv.ParseFloat(in.RulePattern, 10)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 10)
min, err1 = strconv.ParseFloat(in.RulePattern, 64)
valueN, err2 = strconv.ParseFloat(in.Value.String(), 64)
)
if valueN < min || err1 != nil || err2 != nil {
return errors.New(gstr.Replace(in.Message, "{min}", strconv.FormatFloat(min, 'f', -1, 64)))