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  }