diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index d15a80869..4e646ce4c 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -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 }} diff --git a/cmd/gf/internal/cmd/genpbentity/genpbentity.go b/cmd/gf/internal/cmd/genpbentity/genpbentity.go index 8d497fe8e..a552686d9 100644 --- a/cmd/gf/internal/cmd/genpbentity/genpbentity.go +++ b/cmd/gf/internal/cmd/genpbentity/genpbentity.go @@ -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, }) diff --git a/contrib/config/polaris/polaris.go b/contrib/config/polaris/polaris.go index 04765d659..1f9d6ee05 100644 --- a/contrib/config/polaris/polaris.go +++ b/contrib/config/polaris/polaris.go @@ -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) diff --git a/net/ghttp/ghttp_middleware_handler_response.go b/net/ghttp/ghttp_middleware_handler_response.go index 7eb50b2d1..23d3bab7a 100644 --- a/net/ghttp/ghttp_middleware_handler_response.go +++ b/net/ghttp/ghttp_middleware_handler_response.go @@ -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{ diff --git a/net/ghttp/ghttp_request_param.go b/net/ghttp/ghttp_request_param.go index 20f67d2ef..b7f7e67e4 100644 --- a/net/ghttp/ghttp_request_param.go +++ b/net/ghttp/ghttp_request_param.go @@ -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 := "" diff --git a/net/ghttp/ghttp_request_param_request.go b/net/ghttp/ghttp_request_param_request.go index a2874d9de..601e3f06a 100644 --- a/net/ghttp/ghttp_request_param_request.go +++ b/net/ghttp/ghttp_request_param_request.go @@ -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 ( diff --git a/net/ghttp/ghttp_server_service_handler.go b/net/ghttp/ghttp_server_service_handler.go index 76de26aaa..7e248c75c 100644 --- a/net/ghttp/ghttp_server_service_handler.go +++ b/net/ghttp/ghttp_server_service_handler.go @@ -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] -} diff --git a/net/ghttp/ghttp_z_unit_feature_openapi_swagger_test.go b/net/ghttp/ghttp_z_unit_feature_openapi_swagger_test.go index 2ce097ac9..b1b423424 100644 --- a/net/ghttp/ghttp_z_unit_feature_openapi_swagger_test.go +++ b/net/ghttp/ghttp_z_unit_feature_openapi_swagger_test.go @@ -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) diff --git a/net/ghttp/ghttp_z_unit_feature_request_struct_test.go b/net/ghttp/ghttp_z_unit_feature_request_struct_test.go index af846b75d..a54e73ae4 100644 --- a/net/ghttp/ghttp_z_unit_feature_request_struct_test.go +++ b/net/ghttp/ghttp_z_unit_feature_request_struct_test.go @@ -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 diff --git a/net/ghttp/ghttp_z_unit_feature_router_strict_test.go b/net/ghttp/ghttp_z_unit_feature_router_strict_test.go index fba43a894..ef4fa1211 100644 --- a/net/ghttp/ghttp_z_unit_feature_router_strict_test.go +++ b/net/ghttp/ghttp_z_unit_feature_router_strict_test.go @@ -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) }) diff --git a/net/ghttp/ghttp_z_unit_issue_test.go b/net/ghttp/ghttp_z_unit_issue_test.go index b695d35fc..df5838301 100644 --- a/net/ghttp/ghttp_z_unit_issue_test.go +++ b/net/ghttp/ghttp_z_unit_issue_test.go @@ -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) }) } diff --git a/os/gproc/gproc_z_unit_test.go b/os/gproc/gproc_z_unit_test.go index b4e21bbfc..0c6e31c7a 100644 --- a/os/gproc/gproc_z_unit_test.go +++ b/os/gproc/gproc_z_unit_test.go @@ -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) + }) +} diff --git a/test/gtest/gtest_util.go b/test/gtest/gtest_util.go index c9ccb9f0b..c1609474d 100644 --- a/test/gtest/gtest_util.go +++ b/test/gtest/gtest_util.go @@ -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)) } diff --git a/test/gtest/gtest_z_unit_test.go b/test/gtest/gtest_z_unit_test.go index 2c1197f22..7d576fd79 100644 --- a/test/gtest/gtest_z_unit_test.go +++ b/test/gtest/gtest_z_unit_test.go @@ -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"}) diff --git a/util/gconv/gconv_z_unit_scan_test.go b/util/gconv/gconv_z_unit_scan_test.go index 76620d1f4..eddfc9bbc 100644 --- a/util/gconv/gconv_z_unit_scan_test.go +++ b/util/gconv/gconv_z_unit_scan_test.go @@ -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) } diff --git a/util/gvalid/gvalid_z_unit_issue_test.go b/util/gvalid/gvalid_z_unit_issue_test.go index 38aea0739..3e9490226 100644 --- a/util/gvalid/gvalid_z_unit_issue_test.go +++ b/util/gvalid/gvalid_z_unit_issue_test.go @@ -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":[]}}`, ) }) } diff --git a/util/gvalid/internal/builtin/builtin_between.go b/util/gvalid/internal/builtin/builtin_between.go index ebfcdbf64..c14f04130 100644 --- a/util/gvalid/internal/builtin/builtin_between.go +++ b/util/gvalid/internal/builtin/builtin_between.go @@ -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), diff --git a/util/gvalid/internal/builtin/builtin_float.go b/util/gvalid/internal/builtin/builtin_float.go index cbf93d5b6..bd273ef3d 100644 --- a/util/gvalid/internal/builtin/builtin_float.go +++ b/util/gvalid/internal/builtin/builtin_float.go @@ -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) diff --git a/util/gvalid/internal/builtin/builtin_gt.go b/util/gvalid/internal/builtin/builtin_gt.go index 369fff2a0..7cd523e0d 100644 --- a/util/gvalid/internal/builtin/builtin_gt.go +++ b/util/gvalid/internal/builtin/builtin_gt.go @@ -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 { diff --git a/util/gvalid/internal/builtin/builtin_gte.go b/util/gvalid/internal/builtin/builtin_gte.go index e25a97869..a19705855 100644 --- a/util/gvalid/internal/builtin/builtin_gte.go +++ b/util/gvalid/internal/builtin/builtin_gte.go @@ -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 { diff --git a/util/gvalid/internal/builtin/builtin_lt.go b/util/gvalid/internal/builtin/builtin_lt.go index f5ada9245..4bb67c036 100644 --- a/util/gvalid/internal/builtin/builtin_lt.go +++ b/util/gvalid/internal/builtin/builtin_lt.go @@ -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 { diff --git a/util/gvalid/internal/builtin/builtin_lte.go b/util/gvalid/internal/builtin/builtin_lte.go index c5511221e..428d9922c 100644 --- a/util/gvalid/internal/builtin/builtin_lte.go +++ b/util/gvalid/internal/builtin/builtin_lte.go @@ -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 { diff --git a/util/gvalid/internal/builtin/builtin_max.go b/util/gvalid/internal/builtin/builtin_max.go index 6dcb3dc33..6083fad51 100644 --- a/util/gvalid/internal/builtin/builtin_max.go +++ b/util/gvalid/internal/builtin/builtin_max.go @@ -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))) diff --git a/util/gvalid/internal/builtin/builtin_min.go b/util/gvalid/internal/builtin/builtin_min.go index 5ee370a7f..2cfd08757 100644 --- a/util/gvalid/internal/builtin/builtin_min.go +++ b/util/gvalid/internal/builtin/builtin_min.go @@ -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)))