github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/resty/context_test.go (about) 1 // Copyright (c) 2015-2021 Jeevanandam M (jeeva@myjeeva.com) 2 // 2016 Andrew Grigorev (https://github.com/ei-grad) 3 // All rights reserved. 4 // resty source code and usage is governed by a MIT style 5 // license that can be found in the LICENSE file. 6 7 package resty 8 9 import ( 10 "context" 11 "net/http" 12 "net/url" 13 "strings" 14 "sync/atomic" 15 "testing" 16 "time" 17 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func TestSetContext(t *testing.T) { 22 ts := createGetServer(t) 23 defer ts.Close() 24 25 resp, err := dc().R(). 26 SetContext(context.Background()). 27 Get(ts.URL + "/") 28 29 assert.Nil(t, err) 30 assert.Equal(t, http.StatusOK, resp.StatusCode()) 31 assert.Equal(t, "200 OK", resp.Status()) 32 assert.Equal(t, true, resp.Body() != nil) 33 assert.Equal(t, "TestGet: text response", resp.String()) 34 35 logResponse(t, resp) 36 } 37 38 func TestSetContextWithError(t *testing.T) { 39 ts := createGetServer(t) 40 defer ts.Close() 41 42 resp, err := dcr(). 43 SetContext(context.Background()). 44 Get(ts.URL + "/mypage") 45 46 assert.Nil(t, err) 47 assert.Equal(t, http.StatusBadRequest, resp.StatusCode()) 48 assert.Equal(t, "", resp.String()) 49 50 logResponse(t, resp) 51 } 52 53 func TestSetContextCancel(t *testing.T) { 54 ch := make(chan struct{}) 55 ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { 56 defer func() { 57 ch <- struct{}{} // tell test request is finished 58 }() 59 t.Logf("Server: %v %v", r.Method, r.URL.Path) 60 ch <- struct{}{} 61 <-ch // wait for client to finish request 62 n, err := w.Write([]byte("TestSetContextCancel: response")) 63 // FIXME? test server doesn't handle request cancellation 64 t.Logf("Server: wrote %d bytes", n) 65 t.Logf("Server: err is %v ", err) 66 }) 67 defer ts.Close() 68 69 ctx, cancel := context.WithCancel(context.Background()) 70 71 go func() { 72 <-ch // wait for server to start request handling 73 cancel() 74 }() 75 76 _, err := dc().R(). 77 SetContext(ctx). 78 Get(ts.URL + "/") 79 80 ch <- struct{}{} // tell server to continue request handling 81 82 <-ch // wait for server to finish request handling 83 84 t.Logf("Error: %v", err) 85 if !errIsContextCanceled(err) { 86 t.Errorf("Got unexpected error: %v", err) 87 } 88 } 89 90 func TestSetContextCancelRetry(t *testing.T) { 91 reqCount := 0 92 ch := make(chan struct{}) 93 ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { 94 reqCount++ 95 defer func() { 96 ch <- struct{}{} // tell test request is finished 97 }() 98 t.Logf("Server: %v %v", r.Method, r.URL.Path) 99 ch <- struct{}{} 100 <-ch // wait for client to finish request 101 n, err := w.Write([]byte("TestSetContextCancel: response")) 102 // FIXME? test server doesn't handle request cancellation 103 t.Logf("Server: wrote %d bytes", n) 104 t.Logf("Server: err is %v ", err) 105 }) 106 defer ts.Close() 107 108 ctx, cancel := context.WithCancel(context.Background()) 109 110 go func() { 111 <-ch // wait for server to start request handling 112 cancel() 113 }() 114 115 c := dc(). 116 SetTimeout(time.Second * 3). 117 SetRetryCount(3) 118 119 _, err := c.R(). 120 SetContext(ctx). 121 Get(ts.URL + "/") 122 123 ch <- struct{}{} // tell server to continue request handling 124 125 <-ch // wait for server to finish request handling 126 127 t.Logf("Error: %v", err) 128 if !errIsContextCanceled(err) { 129 t.Errorf("Got unexpected error: %v", err) 130 } 131 132 if reqCount != 1 { 133 t.Errorf("Request was retried %d times instead of 1", reqCount) 134 } 135 } 136 137 func TestSetContextCancelWithError(t *testing.T) { 138 ch := make(chan struct{}) 139 ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { 140 defer func() { 141 ch <- struct{}{} // tell test request is finished 142 }() 143 t.Logf("Server: %v %v", r.Method, r.URL.Path) 144 t.Log("Server: sending StatusBadRequest response") 145 w.WriteHeader(http.StatusBadRequest) 146 ch <- struct{}{} 147 <-ch // wait for client to finish request 148 n, err := w.Write([]byte("TestSetContextCancelWithError: response")) 149 // FIXME? test server doesn't handle request cancellation 150 t.Logf("Server: wrote %d bytes", n) 151 t.Logf("Server: err is %v ", err) 152 }) 153 defer ts.Close() 154 155 ctx, cancel := context.WithCancel(context.Background()) 156 157 go func() { 158 <-ch // wait for server to start request handling 159 cancel() 160 }() 161 162 _, err := dc().R(). 163 SetContext(ctx). 164 Get(ts.URL + "/") 165 166 ch <- struct{}{} // tell server to continue request handling 167 168 <-ch // wait for server to finish request handling 169 170 t.Logf("Error: %v", err) 171 if !errIsContextCanceled(err) { 172 t.Errorf("Got unexpected error: %v", err) 173 } 174 } 175 176 func TestClientRetryWithSetContext(t *testing.T) { 177 var attemptctx int32 178 ts := createTestServer(func(w http.ResponseWriter, r *http.Request) { 179 t.Logf("Method: %v", r.Method) 180 t.Logf("Path: %v", r.URL.Path) 181 attp := atomic.AddInt32(&attemptctx, 1) 182 if attp <= 4 { 183 time.Sleep(time.Second * 2) 184 } 185 _, _ = w.Write([]byte("TestClientRetry page")) 186 }) 187 defer ts.Close() 188 189 c := dc(). 190 SetTimeout(time.Second * 1). 191 SetRetryCount(3) 192 193 _, err := c.R(). 194 SetContext(context.Background()). 195 Get(ts.URL + "/") 196 197 assert.Equal(t, true, (strings.HasPrefix(err.Error(), "Get "+ts.URL+"/") || 198 strings.HasPrefix(err.Error(), "Get \""+ts.URL+"/\""))) 199 } 200 201 func TestRequestContext(t *testing.T) { 202 client := dc() 203 r := client.NewRequest() 204 assert.NotNil(t, r.Context()) 205 206 r.SetContext(context.Background()) 207 assert.NotNil(t, r.Context()) 208 } 209 210 func errIsContextCanceled(err error) bool { 211 ue, ok := err.(*url.Error) 212 if !ok { 213 return false 214 } 215 return ue.Err == context.Canceled 216 }