github.com/aavshr/aws-sdk-go@v1.41.3/aws/request/request_retry_test.go (about) 1 package request 2 3 import ( 4 "fmt" 5 "net" 6 "net/http" 7 "net/http/httptest" 8 "net/url" 9 "os" 10 "testing" 11 "time" 12 13 "github.com/aavshr/aws-sdk-go/aws/awserr" 14 ) 15 16 func newRequest(t *testing.T, url string) *http.Request { 17 r, err := http.NewRequest("GET", url, nil) 18 if err != nil { 19 t.Fatalf("can't forge request: %v", err) 20 } 21 return r 22 } 23 24 func TestShouldRetryError_nil(t *testing.T) { 25 if shouldRetryError(nil) != true { 26 t.Error("shouldRetryError(nil) should return true") 27 } 28 } 29 30 func TestShouldRetryError_timeout(t *testing.T) { 31 32 tr := &http.Transport{} 33 defer tr.CloseIdleConnections() 34 client := http.Client{ 35 Timeout: time.Nanosecond, 36 Transport: tr, 37 } 38 39 resp, err := client.Do(newRequest(t, "https://179.179.179.179/no/such/host")) 40 if resp != nil { 41 resp.Body.Close() 42 } 43 if err == nil { 44 t.Fatal("This should have failed.") 45 } 46 debugerr(t, err) 47 48 if shouldRetryError(err) == false { 49 t.Errorf("this request timed out and should be retried") 50 } 51 } 52 53 func TestShouldRetryError_cancelled(t *testing.T) { 54 tr := &http.Transport{} 55 defer tr.CloseIdleConnections() 56 client := http.Client{ 57 Transport: tr, 58 } 59 60 cancelWait := make(chan bool) 61 srvrWait := make(chan bool) 62 srvr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 63 close(cancelWait) // Trigger the request cancel. 64 time.Sleep(100 * time.Millisecond) 65 66 fmt.Fprintf(w, "Hello") 67 w.(http.Flusher).Flush() // send headers and some body 68 <-srvrWait // block forever 69 })) 70 defer srvr.Close() 71 defer close(srvrWait) 72 73 r := newRequest(t, srvr.URL) 74 ch := make(chan struct{}) 75 r.Cancel = ch 76 77 // Ensure the request has started, and client has started to receive bytes. 78 // This ensures the test is stable and does not run into timing with the 79 // request being canceled, before or after the http request is made. 80 go func() { 81 <-cancelWait 82 close(ch) // request is cancelled before anything 83 }() 84 85 resp, err := client.Do(r) 86 if resp != nil { 87 resp.Body.Close() 88 } 89 if err == nil { 90 t.Fatal("This should have failed.") 91 } 92 93 debugerr(t, err) 94 95 if shouldRetryError(err) == true { 96 t.Errorf("this request was cancelled and should not be retried") 97 } 98 } 99 100 func TestShouldRetry(t *testing.T) { 101 102 syscallError := os.SyscallError{ 103 Err: ErrInvalidParams{}, 104 Syscall: "open", 105 } 106 107 opError := net.OpError{ 108 Op: "dial", 109 Net: "tcp", 110 Source: net.Addr(nil), 111 Err: &syscallError, 112 } 113 114 urlError := url.Error{ 115 Op: "Post", 116 URL: "https://localhost:52398", 117 Err: &opError, 118 } 119 origError := awserr.New("ErrorTestShouldRetry", "Test should retry when error received", &urlError).OrigErr() 120 if e, a := true, shouldRetryError(origError); e != a { 121 t.Errorf("Expected to return %v to retry when error occurred, got %v instead", e, a) 122 } 123 124 } 125 126 func debugerr(t *testing.T, err error) { 127 t.Logf("Error, %v", err) 128 129 switch err := err.(type) { 130 case temporary: 131 t.Logf("%s is a temporary error: %t", err, err.Temporary()) 132 return 133 case *url.Error: 134 t.Logf("err: %s, nested err: %#v", err, err.Err) 135 if operr, ok := err.Err.(*net.OpError); ok { 136 t.Logf("operr: %#v", operr) 137 } 138 debugerr(t, err.Err) 139 return 140 default: 141 return 142 } 143 } 144 145 func TestRequest_retryCustomCodes(t *testing.T) { 146 cases := map[string]struct { 147 Code string 148 RetryErrorCodes []string 149 ThrottleErrorCodes []string 150 Retryable bool 151 Throttle bool 152 }{ 153 "retry code": { 154 Code: "RetryMePlease", 155 RetryErrorCodes: []string{ 156 "RetryMePlease", 157 "SomeOtherError", 158 }, 159 Retryable: true, 160 }, 161 "throttle code": { 162 Code: "AThrottleableError", 163 RetryErrorCodes: []string{ 164 "RetryMePlease", 165 "SomeOtherError", 166 }, 167 ThrottleErrorCodes: []string{ 168 "AThrottleableError", 169 "SomeOtherError", 170 }, 171 Throttle: true, 172 }, 173 "unknown code": { 174 Code: "UnknownCode", 175 RetryErrorCodes: []string{ 176 "RetryMePlease", 177 "SomeOtherError", 178 }, 179 Retryable: false, 180 }, 181 } 182 183 for name, c := range cases { 184 req := Request{ 185 HTTPRequest: &http.Request{}, 186 HTTPResponse: &http.Response{}, 187 Error: awserr.New(c.Code, "some error", nil), 188 RetryErrorCodes: c.RetryErrorCodes, 189 ThrottleErrorCodes: c.ThrottleErrorCodes, 190 } 191 192 retryable := req.IsErrorRetryable() 193 if e, a := c.Retryable, retryable; e != a { 194 t.Errorf("%s, expect %v retryable, got %v", name, e, a) 195 } 196 197 throttle := req.IsErrorThrottle() 198 if e, a := c.Throttle, throttle; e != a { 199 t.Errorf("%s, expect %v throttle, got %v", name, e, a) 200 } 201 } 202 }