From 31a23e724d1c0286f2ab9c83e260b839eedc9f18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=AA=9E?= Date: Mon, 13 Jun 2022 19:31:42 +0800 Subject: [PATCH 1/3] Improve the code coverage of the gclient module (#1899) --- net/gclient/gclient_dump.go | 5 +- net/gclient/gclient_z_example_test.go | 702 ++++++++++++++++++++++++-- net/gclient/gclient_z_unit_test.go | 140 +++++ 3 files changed, 814 insertions(+), 33 deletions(-) diff --git a/net/gclient/gclient_dump.go b/net/gclient/gclient_dump.go index 51750d05a42..e8a8463efb4 100644 --- a/net/gclient/gclient_dump.go +++ b/net/gclient/gclient_dump.go @@ -37,10 +37,7 @@ func getResponseBody(res *http.Response) string { // RawRequest returns the raw content of the request. func (r *Response) RawRequest() string { // Response can be nil. - if r == nil { - return "" - } - if r.request == nil { + if r == nil || r.request == nil { return "" } // DumpRequestOut writes more request headers than DumpRequest, such as User-Agent. diff --git a/net/gclient/gclient_z_example_test.go b/net/gclient/gclient_z_example_test.go index 98bcb9c8581..24d4034d193 100644 --- a/net/gclient/gclient_z_example_test.go +++ b/net/gclient/gclient_z_example_test.go @@ -8,9 +8,14 @@ package gclient_test import ( "context" + "crypto/tls" + "encoding/hex" "fmt" + "github.com/gogf/gf/v2/debug/gdebug" "github.com/gogf/gf/v2/net/gclient" + "github.com/gogf/gf/v2/net/gtcp" "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/gfile" "net/http" "time" @@ -18,6 +23,11 @@ import ( "github.com/gogf/gf/v2/net/ghttp" ) +var ( + crtFile = gfile.Dir(gdebug.CallerFilePath()) + gfile.Separator + "testdata/server.crt" + keyFile = gfile.Dir(gdebug.CallerFilePath()) + gfile.Separator + "testdata/server.key" +) + func init() { // Default server for client. p := 8999 @@ -53,10 +63,39 @@ func init() { ) }) group.HEAD("/", func(r *ghttp.Request) { - r.Response.Write("head") + r.Response.Writef( + "HEAD: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.PATCH("/", func(r *ghttp.Request) { + r.Response.Writef( + "PATCH: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.CONNECT("/", func(r *ghttp.Request) { + r.Response.Writef( + "CONNECT: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) }) group.OPTIONS("/", func(r *ghttp.Request) { - r.Response.Write("options") + r.Response.Writef( + "OPTIONS: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) + }) + group.TRACE("/", func(r *ghttp.Request) { + r.Response.Writef( + "TRACE: form: %d, %s", + r.GetForm("id").Int(), + r.GetForm("name").String(), + ) }) }) // Client chaining operations handlers. @@ -138,6 +177,11 @@ func ExampleClient_Clone() { // {"id":1,"name":"john"} } +func fromHex(s string) []byte { + b, _ := hex.DecodeString(s) + return b +} + func ExampleNew_MultiConn_Recommend() { var ( ctx = gctx.New() @@ -274,6 +318,71 @@ func ExampleClient_PostBytes() { // POST: form: 10000, john } +func ExampleClient_DeleteBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().DeleteBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // DELETE: form: 10000, john +} + +func ExampleClient_HeadBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().HeadBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: +} + +func ExampleClient_PatchBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().PatchBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // PATCH: form: 10000, john +} + +func ExampleClient_ConnectBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().ConnectBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // CONNECT: form: 10000, john +} + +func ExampleClient_OptionsBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().OptionsBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // OPTIONS: form: 10000, john +} + +func ExampleClient_TraceBytes() { + url := "http://127.0.0.1:8999" + fmt.Println(string(g.Client().TraceBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // TRACE: form: 10000, john +} + func ExampleClient_PostContent() { url := "http://127.0.0.1:8999" fmt.Println(g.Client().PostContent(ctx, url, g.Map{ @@ -343,6 +452,19 @@ func ExampleClient_Get() { // GET: query: 10000, john } +func ExampleClient_Put() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Put(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // PUT: form: 10000, john +} + func ExampleClient_GetBytes() { var ( ctx = context.Background() @@ -357,6 +479,20 @@ func ExampleClient_GetBytes() { // GET: query: 10000, john } +func ExampleClient_PutBytes() { + var ( + ctx = context.Background() + url = "http://127.0.0.1:8999" + ) + fmt.Println(string(g.Client().PutBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // PUT: form: 10000, john +} + func ExampleClient_GetContent() { url := "http://127.0.0.1:8999" fmt.Println(g.Client().GetContent(ctx, url, g.Map{ @@ -397,45 +533,52 @@ func ExampleClient_SetProxy() { client := g.Client() client.SetProxy("http://127.0.0.1:1081") client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err := client.Get(ctx, "https://api.ip.sb/ip") + resp, err := client.Get(ctx, "http://127.0.0.1:8999") if err != nil { // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + // eg. Get "http://127.0.0.1:8999": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused } - response.RawDump() + fmt.Println(err != nil) + resp.Close() + // connect to a http proxy server which needs auth client.SetProxy("http://user:password:127.0.0.1:1081") client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") + resp, err = client.Get(ctx, "http://127.0.0.1:8999") if err != nil { // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + // eg. Get "http://127.0.0.1:8999": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused } - response.RawDump() + fmt.Println(err != nil) + resp.Close() // connect to a socks5 proxy server client.SetProxy("socks5://127.0.0.1:1080") client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") + resp, err = client.Get(ctx, "http://127.0.0.1:8999") if err != nil { // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + // eg. Get "http://127.0.0.1:8999": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused } - fmt.Println(response.RawResponse()) + fmt.Println(err != nil) + resp.Close() // connect to a socks5 proxy server which needs auth client.SetProxy("socks5://user:password@127.0.0.1:1080") client.SetTimeout(5 * time.Second) // it's suggested to set http client timeout - response, err = client.Get(ctx, "https://api.ip.sb/ip") + resp, err = client.Get(ctx, "http://127.0.0.1:8999") if err != nil { // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + // eg. Get "http://127.0.0.1:8999": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused } - fmt.Println(response.RawResponse()) + fmt.Println(err != nil) + resp.Close() + + // Output: + // true + // true + // true + // true } // ExampleClientChain_Proxy a chain version of example for `gclient.Client.Proxy` method. @@ -448,20 +591,521 @@ func ExampleClient_Proxy() { ctx = context.Background() ) client := g.Client() - response, err := client.Proxy("http://127.0.0.1:1081").Get(ctx, "https://api.ip.sb/ip") + _, err := client.Proxy("http://127.0.0.1:1081").Get(ctx, "http://127.0.0.1:8999") + fmt.Println(err != nil) + + client2 := g.Client() + _, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "http://127.0.0.1:8999") + fmt.Println(err != nil) + + client3 := g.Client() + _, err = client3.Proxy("").Get(ctx, "http://127.0.0.1:8999") + fmt.Println(err != nil) + + client4 := g.Client() + url := "http://127.0.0.1:1081" + string([]byte{0x7f}) + _, err = client4.Proxy(url).Get(ctx, "http://127.0.0.1:8999") + fmt.Println(err != nil) + + // Output: + // true + // true + // false + // false +} + +func ExampleClient_Prefix() { + p := gtcp.MustGetFreePort() + + var ( + ctx = gctx.New() + prefix = fmt.Sprintf("http://127.0.0.1:%d/api/v1/", p) + ) + + s := g.Server(p) + // HTTP method handlers. + s.Group("/api", func(group *ghttp.RouterGroup) { + group.GET("/v1/prefix", func(r *ghttp.Request) { + r.Response.Write("this is v1 prefix") + }) + group.GET("/v1/hello", func(r *ghttp.Request) { + r.Response.Write("this is v1 hello") + }) + }) + s.SetAccessLogEnabled(false) + s.SetDumpRouterMap(false) + s.SetPort(p) + s.Start() + time.Sleep(time.Millisecond * 100) + + // Add Client URI Prefix + client := g.Client().Prefix(prefix) + + fmt.Println(string(client.GetBytes(ctx, "prefix"))) + fmt.Println(string(client.GetBytes(ctx, "hello"))) + + // Output: + // this is v1 prefix + // this is v1 hello +} + +func ExampleClient_Retry() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + ) + client := g.Client().Retry(2, time.Second) + + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_RedirectLimit() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + ) + client := g.Client().RedirectLimit(1) + + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_SetBrowserMode() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + ) + client := g.Client().SetBrowserMode(true) + + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_SetHeader() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + ) + client := g.Client() + client.SetHeader("Server", "GoFrameServer") + client.SetHeader("Client", "g.Client()") + + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_SetRedirectLimit() { + go func() { + s := g.Server() + s.BindHandler("/hello", func(r *ghttp.Request) { + r.Response.Writeln("hello world") + }) + s.BindHandler("/back", func(r *ghttp.Request) { + r.Response.RedirectBack() + }) + s.SetDumpRouterMap(false) + s.SetPort(8199) + s.Run() + }() + + time.Sleep(time.Second) + + var ( + ctx = gctx.New() + urlHello = "http://127.0.0.1:8199/hello" + urlBack = "http://127.0.0.1:8199/back" + ) + client := g.Client().SetRedirectLimit(1) + client.SetHeader("Referer", urlHello) + + resp, err := client.DoRequest(ctx, http.MethodGet, urlBack, g.Map{ + "id": 10000, + "name": "john", + }) + if err == nil { + fmt.Println(resp.ReadAllString()) + resp.Close() + } + + client.SetRedirectLimit(2) + resp, err = client.DoRequest(ctx, http.MethodGet, urlBack, g.Map{ + "id": 10000, + "name": "john", + }) + if err == nil { + fmt.Println(resp.ReadAllString()) + resp.Close() + } + + // Output: + // Found + // hello world +} + +func ExampleClient_SetTLSKeyCrt() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + testCrtFile = gfile.Dir(gdebug.CallerFilePath()) + gfile.Separator + "testdata/upload/file1.txt" + testKeyFile = gfile.Dir(gdebug.CallerFilePath()) + gfile.Separator + "testdata/upload/file2.txt" + ) + client := g.Client() + client.SetTLSKeyCrt(testCrtFile, testKeyFile) + client.SetTLSKeyCrt(crtFile, keyFile) + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_SetTLSConfig() { + var ( + ctx = gctx.New() + url = "http://127.0.0.1:8999" + tlsConfig = &tls.Config{} + ) + client := g.Client() + client.SetTLSConfig(tlsConfig) + fmt.Println(string(client.GetBytes(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }))) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_PutContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().PutContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // PUT: form: 10000, john +} + +func ExampleClient_DeleteContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().DeleteContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // DELETE: form: 10000, john +} + +func ExampleClient_HeadContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().HeadContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: +} + +func ExampleClient_PatchContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().PatchContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // PATCH: form: 10000, john +} + +func ExampleClient_ConnectContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().ConnectContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // CONNECT: form: 10000, john +} + +func ExampleClient_OptionsContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().OptionsContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // OPTIONS: form: 10000, john +} + +func ExampleClient_TraceContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().TraceContent(ctx, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // TRACE: form: 10000, john +} + +func ExampleClient_RequestContent() { + url := "http://127.0.0.1:8999" + fmt.Println(g.Client().RequestContent(ctx, http.MethodGet, url, g.Map{ + "id": 10000, + "name": "john", + })) + + // Output: + // GET: query: 10000, john +} + +func ExampleClient_RawRequest() { + url := "http://127.0.0.1:8999" + response, _ := g.Client().Get(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + fmt.Println(len(response.RawResponse()) > 100) + + // Output: + // true +} + +func ExampleClient_Delete() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Delete(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // DELETE: form: 10000, john +} + +func ExampleClient_Head() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Head(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // +} + +func ExampleClient_Patch() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Patch(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // PATCH: form: 10000, john +} + +func ExampleClient_Connect() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Connect(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // CONNECT: form: 10000, john +} + +func ExampleClient_Options() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Options(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // OPTIONS: form: 10000, john +} + +func ExampleClient_Trace() { + url := "http://127.0.0.1:8999" + r, _ := g.Client().Trace(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + defer r.Close() + fmt.Println(r.ReadAllString()) + + // Output: + // TRACE: form: 10000, john +} + +func ExampleClient_PutVar() { + type User struct { + Id int + Name string + } + var ( + user *User + ctx = context.Background() + url = "http://127.0.0.1:8999/var/json" + ) + err := g.Client().PutVar(ctx, url).Scan(&user) if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": proxyconnect tcp: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + panic(err) } - fmt.Println(response.RawResponse()) + fmt.Println(user) - client2 := g.Client() - response, err = client2.Proxy("socks5://127.0.0.1:1080").Get(ctx, "https://api.ip.sb/ip") + // Output: + // &{1 john} +} + +func ExampleClient_DeleteVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().DeleteVar(ctx, url).Scan(&users) if err != nil { - // err is not nil when your proxy server is down. - // eg. Get "https://api.ip.sb/ip": socks connect tcp 127.0.0.1:1087->api.ip.sb:443: dial tcp 127.0.0.1:1087: connect: connection refused - fmt.Println(err) + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] +} + +func ExampleClient_HeadVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().HeadVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [] +} + +func ExampleClient_PatchVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().PatchVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] +} + +func ExampleClient_ConnectVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().ConnectVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] +} + +func ExampleClient_OptionsVar() { + type User struct { + Id int + Name string } - fmt.Println(response.RawResponse()) + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().OptionsVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] +} + +func ExampleClient_TraceVar() { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().TraceVar(ctx, url).Scan(&users) + if err != nil { + panic(err) + } + fmt.Println(users) + + // Output: + // [{1 john} {2 smith}] } diff --git a/net/gclient/gclient_z_unit_test.go b/net/gclient/gclient_z_unit_test.go index 73ed9b9a823..806be5f6d6d 100644 --- a/net/gclient/gclient_z_unit_test.go +++ b/net/gclient/gclient_z_unit_test.go @@ -12,6 +12,10 @@ import ( "crypto/tls" "fmt" "github.com/gogf/gf/v2/debug/gdebug" + "github.com/gogf/gf/v2/internal/tracing" + "go.opentelemetry.io/otel" + sdkTrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" "io/ioutil" "net/http" "testing" @@ -488,6 +492,28 @@ func Test_Client_Request_13_Dump(t *testing.T) { t.Assert(gstr.Contains(dumpedText3, "test_for_request_body"), true) dumpedText4 := r2.RawResponse() t.Assert(gstr.Contains(dumpedText4, "test_for_request_body"), false) + r2 = nil + t.Assert(r2.RawRequest(), "") + }) + + gtest.C(t, func(t *gtest.T) { + url := fmt.Sprintf("http://127.0.0.1:%d", p) + response, _ := g.Client().Get(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + response = nil + t.Assert(response.RawRequest(), "") + }) + + gtest.C(t, func(t *gtest.T) { + url := fmt.Sprintf("http://127.0.0.1:%d", p) + response, _ := g.Client().Get(ctx, url, g.Map{ + "id": 10000, + "name": "john", + }) + response.RawDump() + t.AssertGT(len(response.Raw()), 0) }) } @@ -558,3 +584,117 @@ func TestLoadKeyCrt(t *testing.T) { t.AssertNE(tlsConfig, nil) }) } + +func TestClient_DoRequest(t *testing.T) { + p, _ := gtcp.GetFreePort() + s := g.Server(p) + s.BindHandler("/hello", func(r *ghttp.Request) { + r.Response.WriteHeader(200) + r.Response.WriteJson(g.Map{"field": "test_for_response_body"}) + }) + s.SetPort(p) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + c := g.Client() + url := fmt.Sprintf("127.0.0.1:%d/hello", p) + resp, err := c.DoRequest(ctx, http.MethodGet, url) + t.AssertNil(err) + t.AssertNE(resp, nil) + t.Assert(resp.ReadAllString(), "{\"field\":\"test_for_response_body\"}") + + resp.Response = nil + bytes := resp.ReadAll() + t.Assert(bytes, []byte{}) + resp.Close() + }) + + gtest.C(t, func(t *gtest.T) { + c := g.Client() + url := "127.0.0.1:99999/hello" + resp, err := c.DoRequest(ctx, http.MethodGet, url) + t.AssertNil(resp.Response) + t.AssertNE(err, nil) + }) +} + +func TestClient_RequestVar(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + var ( + url = "http://127.0.0.1:99999/var/jsons" + ) + varValue := g.Client().RequestVar(ctx, http.MethodGet, url) + t.AssertNil(varValue) + }) + gtest.C(t, func(t *gtest.T) { + type User struct { + Id int + Name string + } + var ( + users []User + url = "http://127.0.0.1:8999/var/jsons" + ) + err := g.Client().RequestVar(ctx, http.MethodGet, url).Scan(&users) + t.AssertNil(err) + t.AssertNE(users, nil) + }) +} + +type CustomProvider struct { + *sdkTrace.TracerProvider +} + +func NewCustomProvider() *CustomProvider { + return &CustomProvider{ + TracerProvider: sdkTrace.NewTracerProvider( + sdkTrace.WithIDGenerator(NewCustomIDGenerator()), + ), + } +} + +type CustomIDGenerator struct{} + +func NewCustomIDGenerator() *CustomIDGenerator { + return &CustomIDGenerator{} +} + +func (id *CustomIDGenerator) NewIDs(ctx context.Context) (traceID trace.TraceID, spanID trace.SpanID) { + return tracing.NewIDs() +} + +func (id *CustomIDGenerator) NewSpanID(ctx context.Context, traceID trace.TraceID) (spanID trace.SpanID) { + return tracing.NewSpanID() +} + +func TestClient_CustomProvider(t *testing.T) { + provider := otel.GetTracerProvider() + defer otel.SetTracerProvider(provider) + + otel.SetTracerProvider(NewCustomProvider()) + + p, _ := gtcp.GetFreePort() + s := g.Server(p) + s.BindHandler("/hello", func(r *ghttp.Request) { + r.Response.WriteHeader(200) + r.Response.WriteJson(g.Map{"field": "test_for_response_body"}) + }) + s.SetPort(p) + s.SetDumpRouterMap(false) + s.Start() + defer s.Shutdown() + + time.Sleep(100 * time.Millisecond) + gtest.C(t, func(t *gtest.T) { + c := g.Client() + url := fmt.Sprintf("127.0.0.1:%d/hello", p) + resp, err := c.DoRequest(ctx, http.MethodGet, url) + t.AssertNil(err) + t.AssertNE(resp, nil) + t.Assert(resp.ReadAllString(), "{\"field\":\"test_for_response_body\"}") + }) + +} From 4f37abac6a21d7d1502f1a3b28d90d4e01099895 Mon Sep 17 00:00:00 2001 From: Daguang <28806852+DGuang21@users.noreply.github.com> Date: Mon, 13 Jun 2022 19:40:47 +0800 Subject: [PATCH 2/3] upgrade ClickHouse-Go dependencies to V2.0.15 (#1904) --- contrib/drivers/clickhouse/go.mod | 5 ++--- contrib/drivers/clickhouse/go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/contrib/drivers/clickhouse/go.mod b/contrib/drivers/clickhouse/go.mod index dc2dbc48d65..c5a6d545e98 100644 --- a/contrib/drivers/clickhouse/go.mod +++ b/contrib/drivers/clickhouse/go.mod @@ -3,13 +3,12 @@ module github.com/gogf/gf/contrib/drivers/clickhouse/v2 go 1.15 require ( - github.com/ClickHouse/clickhouse-go/v2 v2.0.14 + github.com/ClickHouse/clickhouse-go/v2 v2.0.15 github.com/gogf/gf/v2 v2.0.0 github.com/google/uuid v1.3.0 - github.com/mattn/go-isatty v0.0.14 // indirect ) replace ( - github.com/ClickHouse/clickhouse-go/v2 => github.com/gogf/clickhouse-go/v2 v2.0.14-compatible + github.com/ClickHouse/clickhouse-go/v2 => github.com/gogf/clickhouse-go/v2 v2.0.15-compatible github.com/gogf/gf/v2 => ../../../ ) diff --git a/contrib/drivers/clickhouse/go.sum b/contrib/drivers/clickhouse/go.sum index 613e1f6e7c0..c817f2c1067 100644 --- a/contrib/drivers/clickhouse/go.sum +++ b/contrib/drivers/clickhouse/go.sum @@ -34,8 +34,8 @@ github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gogf/clickhouse-go/v2 v2.0.14-compatible h1:eTT+USRgOZyTXyHyIFzJU+utFUsNVPmrzmQaKS9zdoM= -github.com/gogf/clickhouse-go/v2 v2.0.14-compatible/go.mod h1:NdPxn4Kfffa6Tv14otrFtbV+zH6v2xHVfDf4KICt/0s= +github.com/gogf/clickhouse-go/v2 v2.0.15-compatible h1:VYgibtmI/u+hUQmtJpC7zzg1YJsDCXS052R7vCqGpDc= +github.com/gogf/clickhouse-go/v2 v2.0.15-compatible/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= @@ -96,8 +96,8 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= -github.com/paulmach/orb v0.7.0 h1:l6uxkg+vRU9QJkBHtzvYpkVb09tCIRwnEHbY5MNMNqo= -github.com/paulmach/orb v0.7.0/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A= +github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU= +github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -114,8 +114,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -173,8 +174,6 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32 h1:Js08h5hqB5xyWR789+QqueR6sDE8mk+YvpETZ+F6X9Y= golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba h1:AyHWHCBVlIYI5rgEM3o+1PLd0sLPcIAoaUckGQMaWtw= -golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -213,5 +212,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From b62b2f3598e9e475e7066ec0c73144fda2f34d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E9=AA=9E?= Date: Mon, 13 Jun 2022 22:01:20 +0800 Subject: [PATCH 3/3] Improve the code coverage of the gudp module (#1907) --- net/gudp/gudp_z_unit_test.go | 127 +++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/net/gudp/gudp_z_unit_test.go b/net/gudp/gudp_z_unit_test.go index 55d6f6e8586..504b0a5fd88 100644 --- a/net/gudp/gudp_z_unit_test.go +++ b/net/gudp/gudp_z_unit_test.go @@ -18,6 +18,27 @@ import ( "github.com/gogf/gf/v2/util/gconv" ) +var ( + simpleTimeout = time.Millisecond * 100 + sendData = []byte("hello") + invalidAddr = "127.0.0.1:99999" +) + +func startUDPServer(addr string) { + s := gudp.NewServer(addr, func(conn *gudp.Conn) { + defer conn.Close() + for { + data, err := conn.Recv(-1) + if err != nil { + break + } + conn.Send(data) + } + }) + go s.Run() + time.Sleep(simpleTimeout) +} + func Test_Basic(t *testing.T) { var ( ctx = context.TODO() @@ -46,6 +67,11 @@ func Test_Basic(t *testing.T) { conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", p)) t.AssertNil(err) t.Assert(conn.Send([]byte(gconv.String(i))), nil) + t.AssertNil(conn.RemoteAddr()) + result, err := conn.Recv(-1) + t.AssertNil(err) + t.AssertNE(conn.RemoteAddr(), nil) + t.Assert(string(result), fmt.Sprintf(`> %d`, i)) conn.Close() } }) @@ -60,6 +86,41 @@ func Test_Basic(t *testing.T) { conn.Close() } }) + // gudp.Conn.SendWithTimeout + gtest.C(t, func(t *gtest.T) { + for i := 0; i < 100; i++ { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", p)) + t.AssertNil(err) + err = conn.SendWithTimeout([]byte(gconv.String(i)), time.Second) + t.AssertNil(err) + conn.Close() + } + }) + // gudp.Conn.RecvWithTimeout + gtest.C(t, func(t *gtest.T) { + for i := 0; i < 100; i++ { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", p)) + t.AssertNil(err) + err = conn.Send([]byte(gconv.String(i))) + t.AssertNil(err) + conn.SetRecvBufferWait(time.Millisecond * 100) + result, err := conn.RecvWithTimeout(-1, time.Second) + t.AssertNil(err) + t.Assert(string(result), fmt.Sprintf(`> %d`, i)) + conn.Close() + } + }) + // gudp.Conn.SendRecvWithTimeout + gtest.C(t, func(t *gtest.T) { + for i := 0; i < 100; i++ { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", p)) + t.AssertNil(err) + result, err := conn.SendRecvWithTimeout([]byte(gconv.String(i)), -1, time.Second) + t.AssertNil(err) + t.Assert(string(result), fmt.Sprintf(`> %d`, i)) + conn.Close() + } + }) // gudp.Send gtest.C(t, func(t *gtest.T) { for i := 0; i < 100; i++ { @@ -112,3 +173,69 @@ func Test_Buffer(t *testing.T) { t.Assert(string(result), "4") }) } + +func Test_NewConn(t *testing.T) { + var ( + port, _ = gudp.GetFreePort() + ) + + startUDPServer(fmt.Sprintf("127.0.0.1:%d", port)) + + gtest.C(t, func(t *gtest.T) { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", port), fmt.Sprintf("127.0.0.1:%d", port+1)) + t.AssertNil(err) + conn.SetDeadline(time.Now().Add(time.Second)) + t.Assert(conn.Send(sendData), nil) + conn.Close() + }) + + gtest.C(t, func(t *gtest.T) { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", port), fmt.Sprintf("127.0.0.1:%d", 99999)) + t.AssertNil(conn) + t.AssertNE(err, nil) + }) + + gtest.C(t, func(t *gtest.T) { + conn, err := gudp.NewConn(fmt.Sprintf("127.0.0.1:%d", 99999)) + t.AssertNil(conn) + t.AssertNE(err, nil) + }) +} + +func Test_GetFreePorts(t *testing.T) { + gtest.C(t, func(t *gtest.T) { + ports, err := gudp.GetFreePorts(2) + t.AssertNil(err) + t.AssertEQ(len(ports), 2) + }) +} + +func Test_Server(t *testing.T) { + p, _ := gudp.GetFreePort() + gudp.NewServer(fmt.Sprintf("127.0.0.1:%d", p), func(conn *gudp.Conn) { + defer conn.Close() + for { + data, err := conn.Recv(1) + if len(data) > 0 { + conn.Send(data) + } + if err != nil { + break + } + } + }, "GoFrameUDPServer") + + gtest.C(t, func(t *gtest.T) { + server := gudp.GetServer("GoFrameUDPServer") + t.AssertNE(server, nil) + server = gudp.GetServer("TestUDPServer") + t.AssertNE(server, nil) + server.SetAddress("127.0.0.1:8888") + server.SetHandler(func(conn *gudp.Conn) { + defer conn.Close() + for { + conn.Send([]byte("OtherHandle")) + } + }) + }) +}