// Use DynamoDB methods for simplicity func TestPaginationEachPage(t *testing.T) { db := dynamodb.New(nil) tokens, pages, numPages, gotToEnd := []string{}, []string{}, 0, false reqNum := 0 resps := []*dynamodb.ListTablesOutput{ {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, {TableNames: []*string{aws.String("Table5")}}, } db.Handlers.Send.Clear() // mock sending db.Handlers.Unmarshal.Clear() db.Handlers.UnmarshalMeta.Clear() db.Handlers.ValidateResponse.Clear() db.Handlers.Build.PushBack(func(r *request.Request) { in := r.Params.(*dynamodb.ListTablesInput) if in == nil { tokens = append(tokens, "") } else if in.ExclusiveStartTableName != nil { tokens = append(tokens, *in.ExclusiveStartTableName) } }) db.Handlers.Unmarshal.PushBack(func(r *request.Request) { r.Data = resps[reqNum] reqNum++ }) params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} req, _ := db.ListTablesRequest(params) err := req.EachPage(func(p interface{}, last bool) bool { numPages++ for _, t := range p.(*dynamodb.ListTablesOutput).TableNames { pages = append(pages, *t) } if last { if gotToEnd { assert.Fail(t, "last=true happened twice") } gotToEnd = true } return true }) assert.Equal(t, []string{"Table2", "Table4"}, tokens) assert.Equal(t, []string{"Table1", "Table2", "Table3", "Table4", "Table5"}, pages) assert.Equal(t, 3, numPages) assert.True(t, gotToEnd) assert.Nil(t, err) }
func TestRequestExhaustRetries(t *testing.T) { delays := []time.Duration{} sleepDelay := func(delay time.Duration) { delays = append(delays, delay) } reqNum := 0 reqs := []http.Response{ {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, {StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, } s := service.New(aws.NewConfig().WithMaxRetries(aws.DefaultRetries).WithSleepDelay(sleepDelay)) s.Handlers.Validate.Clear() s.Handlers.Unmarshal.PushBack(unmarshal) s.Handlers.UnmarshalError.PushBack(unmarshalError) s.Handlers.Send.Clear() // mock sending s.Handlers.Send.PushBack(func(r *request.Request) { r.HTTPResponse = &reqs[reqNum] reqNum++ }) r := s.NewRequest(&request.Operation{Name: "Operation"}, nil, nil) err := r.Send() assert.NotNil(t, err) if e, ok := err.(awserr.RequestFailure); ok { assert.Equal(t, 500, e.StatusCode()) } else { assert.Fail(t, "Expected error to be a service failure") } assert.Equal(t, "UnknownError", err.(awserr.Error).Code()) assert.Equal(t, "An error occurred.", err.(awserr.Error).Message()) assert.Equal(t, 3, int(r.RetryCount)) expectDelays := []struct{ min, max time.Duration }{{30, 59}, {60, 118}, {120, 236}} for i, v := range delays { min := expectDelays[i].min * time.Millisecond max := expectDelays[i].max * time.Millisecond assert.True(t, min <= v && v <= max, "Expect delay to be within range, i:%d, v:%s, min:%s, max:%s", i, v, min, max) } }
// Use DynamoDB methods for simplicity func TestPaginationEarlyExit(t *testing.T) { db := dynamodb.New(nil) numPages, gotToEnd := 0, false reqNum := 0 resps := []*dynamodb.ListTablesOutput{ {TableNames: []*string{aws.String("Table1"), aws.String("Table2")}, LastEvaluatedTableName: aws.String("Table2")}, {TableNames: []*string{aws.String("Table3"), aws.String("Table4")}, LastEvaluatedTableName: aws.String("Table4")}, {TableNames: []*string{aws.String("Table5")}}, } db.Handlers.Send.Clear() // mock sending db.Handlers.Unmarshal.Clear() db.Handlers.UnmarshalMeta.Clear() db.Handlers.ValidateResponse.Clear() db.Handlers.Unmarshal.PushBack(func(r *request.Request) { r.Data = resps[reqNum] reqNum++ }) params := &dynamodb.ListTablesInput{Limit: aws.Int64(2)} err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { numPages++ if numPages == 2 { return false } if last { if gotToEnd { assert.Fail(t, "last=true happened twice") } gotToEnd = true } return true }) assert.Equal(t, 2, numPages) assert.False(t, gotToEnd) assert.Nil(t, err) }
// test that retries don't occur for 4xx status codes with a response type that can't be retried func TestRequest4xxUnretryable(t *testing.T) { s := NewService(&Config{MaxRetries: 10}) s.Handlers.Validate.Clear() s.Handlers.Unmarshal.PushBack(unmarshal) s.Handlers.UnmarshalError.PushBack(unmarshalError) s.Handlers.Send.Clear() // mock sending s.Handlers.Send.PushBack(func(r *Request) { r.HTTPResponse = &http.Response{StatusCode: 401, Body: body(`{"__type":"SignatureDoesNotMatch","message":"Signature does not match."}`)} }) out := &testData{} r := NewRequest(s, &Operation{Name: "Operation"}, nil, out) err := r.Send() assert.NotNil(t, err) if e, ok := err.(awserr.RequestFailure); ok { assert.Equal(t, 401, e.StatusCode()) } else { assert.Fail(t, "Expected error to be a service failure") } assert.Equal(t, "SignatureDoesNotMatch", err.(awserr.Error).Code()) assert.Equal(t, "Signature does not match.", err.(awserr.Error).Message()) assert.Equal(t, 0, int(r.RetryCount)) }
func TestRequestExhaustRetries(t *testing.T) { delays := []time.Duration{} sleepDelay = func(delay time.Duration) { delays = append(delays, delay) } reqNum := 0 reqs := []http.Response{ http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, } s := NewService(&Config{MaxRetries: -1}) s.Handlers.Validate.Clear() s.Handlers.Unmarshal.PushBack(unmarshal) s.Handlers.UnmarshalError.PushBack(unmarshalError) s.Handlers.Send.Clear() // mock sending s.Handlers.Send.PushBack(func(r *Request) { r.HTTPResponse = &reqs[reqNum] reqNum++ }) r := NewRequest(s, &Operation{Name: "Operation"}, nil, nil) err := r.Send() assert.NotNil(t, err) if e, ok := err.(awserr.RequestFailure); ok { assert.Equal(t, 500, e.StatusCode()) } else { assert.Fail(t, "Expected error to be a service failure") } assert.Equal(t, "UnknownError", err.(awserr.Error).Code()) assert.Equal(t, "An error occurred.", err.(awserr.Error).Message()) assert.Equal(t, 3, int(r.RetryCount)) assert.True(t, reflect.DeepEqual([]time.Duration{30 * time.Millisecond, 60 * time.Millisecond, 120 * time.Millisecond}, delays)) }