// Use DynamoDB methods for simplicity func TestPagination(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)} err := db.ListTablesPages(params, func(p *dynamodb.ListTablesOutput, last bool) bool { numPages++ for _, t := range p.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) assert.Nil(t, params.ExclusiveStartTableName) }
func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) { server := initTestServer("2014-12-16T01:51:37Z", false) defer server.Close() p := &ec2rolecreds.EC2RoleProvider{ Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), ExpiryWindow: time.Hour * 1, } p.CurrentTime = func() time.Time { return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC) } assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") _, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") p.CurrentTime = func() time.Time { return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC) } assert.True(t, p.IsExpired(), "Expect creds to be expired.") }
func TestCopyIgnoreNilMembers(t *testing.T) { type Foo struct { A *string } f := &Foo{} assert.Nil(t, f.A) var f2 Foo awsutil.Copy(&f2, f) assert.Nil(t, f2.A) fcopy := awsutil.CopyOf(f) f3 := fcopy.(*Foo) assert.Nil(t, f3.A) }
func TestEC2RoleProviderExpiryWindowIsExpired(t *testing.T) { server := initTestServer("2014-12-16T01:51:37Z") defer server.Close() p := &EC2RoleProvider{Client: http.DefaultClient, Endpoint: server.URL, ExpiryWindow: time.Hour * 1} defer func() { currentTime = time.Now }() currentTime = func() time.Time { return time.Date(2014, 12, 15, 0, 51, 37, 0, time.UTC) } assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve.") _, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve.") currentTime = func() time.Time { return time.Date(2014, 12, 16, 0, 55, 37, 0, time.UTC) } assert.True(t, p.IsExpired(), "Expect creds to be expired.") }
// Use S3 for simplicity func TestPaginationTruncation(t *testing.T) { count := 0 client := s3.New(nil) reqNum := &count resps := []*s3.ListObjectsOutput{ {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key1")}}}, {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key2")}}}, {IsTruncated: aws.Bool(false), Contents: []*s3.Object{{Key: aws.String("Key3")}}}, {IsTruncated: aws.Bool(true), Contents: []*s3.Object{{Key: aws.String("Key4")}}}, } client.Handlers.Send.Clear() // mock sending client.Handlers.Unmarshal.Clear() client.Handlers.UnmarshalMeta.Clear() client.Handlers.ValidateResponse.Clear() client.Handlers.Unmarshal.PushBack(func(r *request.Request) { r.Data = resps[*reqNum] *reqNum++ }) params := &s3.ListObjectsInput{Bucket: aws.String("bucket")} results := []string{} err := client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { results = append(results, *p.Contents[0].Key) return true }) assert.Equal(t, []string{"Key1", "Key2", "Key3"}, results) assert.Nil(t, err) // Try again without truncation token at all count = 0 resps[1].IsTruncated = nil resps[2].IsTruncated = aws.Bool(true) results = []string{} err = client.ListObjectsPages(params, func(p *s3.ListObjectsOutput, last bool) bool { results = append(results, *p.Contents[0].Key) return true }) assert.Equal(t, []string{"Key1", "Key2"}, results) assert.Nil(t, err) }
func TestSharedCredentialsProvider(t *testing.T) { os.Clearenv() p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") }
func TestSharedCredentialsProviderIsExpired(t *testing.T) { os.Clearenv() p := SharedCredentialsProvider{Filename: "example.ini", Profile: ""} assert.True(t, p.IsExpired(), "Expect creds to be expired before retrieve") _, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.False(t, p.IsExpired(), "Expect creds to not be expired after retrieve") }
func TestSharedCredentialsProviderWithAWS_SHARED_CREDENTIALS_FILE(t *testing.T) { os.Clearenv() os.Setenv("AWS_SHARED_CREDENTIALS_FILE", "example.ini") p := SharedCredentialsProvider{} creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") }
func TestEnvProviderAlternateNames(t *testing.T) { os.Clearenv() os.Setenv("AWS_ACCESS_KEY", "access") os.Setenv("AWS_SECRET_KEY", "secret") e := EnvProvider{} creds, err := e.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "access", creds.AccessKeyID, "Expected access key ID") assert.Equal(t, "secret", creds.SecretAccessKey, "Expected secret access key") assert.Empty(t, creds.SessionToken, "Expected no token") }
func TestEC2RoleProvider(t *testing.T) { server := initTestServer("2014-12-16T01:51:37Z") defer server.Close() p := &EC2RoleProvider{Client: http.DefaultClient, Endpoint: server.URL} creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") }
func TestEnvProviderRetrieve(t *testing.T) { os.Clearenv() os.Setenv("AWS_ACCESS_KEY_ID", "access") os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") os.Setenv("AWS_SESSION_TOKEN", "token") e := EnvProvider{} creds, err := e.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "access", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") }
func TestStaticProviderGet(t *testing.T) { s := StaticProvider{ Value: Value{ AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "", }, } creds, err := s.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") assert.Empty(t, creds.SessionToken, "Expect no session token") }
func TestEC2RoleProvider(t *testing.T) { server := initTestServer("2014-12-16T01:51:37Z", false) defer server.Close() p := &ec2rolecreds.EC2RoleProvider{ Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), } creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "accessKey", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "secret", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "token", creds.SessionToken, "Expect session token to match") }
func TestEnvProviderIsExpired(t *testing.T) { os.Clearenv() os.Setenv("AWS_ACCESS_KEY_ID", "access") os.Setenv("AWS_SECRET_ACCESS_KEY", "secret") os.Setenv("AWS_SESSION_TOKEN", "token") e := EnvProvider{} assert.True(t, e.IsExpired(), "Expect creds to be expired before retrieve.") _, err := e.Retrieve() assert.Nil(t, err, "Expect no error") assert.False(t, e.IsExpired(), "Expect creds to not be expired after retrieve.") }
func TestCredentialsGet(t *testing.T) { c := NewCredentials(&stubProvider{ creds: Value{ AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "", }, expired: true, }) creds, err := c.Get() assert.Nil(t, err, "Expected no error") assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") assert.Empty(t, creds.SessionToken, "Expect session token to be empty") }
// test that the request is retried after the credentials are expired. func TestRequestRecoverExpiredCreds(t *testing.T) { reqNum := 0 reqs := []http.Response{ http.Response{StatusCode: 400, Body: body(`{"__type":"ExpiredTokenException","message":"expired token"}`)}, http.Response{StatusCode: 200, Body: body(`{"data":"valid"}`)}, } s := NewService(&Config{MaxRetries: 10, Credentials: credentials.NewStaticCredentials("AKID", "SECRET", "")}) s.Handlers.Validate.Clear() s.Handlers.Unmarshal.PushBack(unmarshal) s.Handlers.UnmarshalError.PushBack(unmarshalError) credExpiredBeforeRetry := false credExpiredAfterRetry := false s.Handlers.Retry.PushBack(func(r *Request) { if r.Error != nil && r.Error.(awserr.Error).Code() == "ExpiredTokenException" { credExpiredBeforeRetry = r.Config.Credentials.IsExpired() } }) s.Handlers.AfterRetry.PushBack(func(r *Request) { credExpiredAfterRetry = r.Config.Credentials.IsExpired() }) s.Handlers.Sign.Clear() s.Handlers.Sign.PushBack(func(r *Request) { r.Config.Credentials.Get() }) s.Handlers.Send.Clear() // mock sending s.Handlers.Send.PushBack(func(r *Request) { r.HTTPResponse = &reqs[reqNum] reqNum++ }) out := &testData{} r := NewRequest(s, &Operation{Name: "Operation"}, nil, out) err := r.Send() assert.Nil(t, err) assert.False(t, credExpiredBeforeRetry, "Expect valid creds before retry check") assert.True(t, credExpiredAfterRetry, "Expect expired creds after retry check") assert.False(t, s.Config.Credentials.IsExpired(), "Expect valid creds after cred expired recovery") assert.Equal(t, 1, int(r.RetryCount)) assert.Equal(t, "valid", out.Data) }
func TestChainProviderIsExpired(t *testing.T) { stubProvider := &stubProvider{expired: true} p := &ChainProvider{ Providers: []Provider{ stubProvider, }, } assert.True(t, p.IsExpired(), "Expect expired to be true before any Retrieve") _, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.False(t, p.IsExpired(), "Expect not expired after retrieve") stubProvider.expired = true assert.True(t, p.IsExpired(), "Expect return of expired provider") _, err = p.Retrieve() assert.False(t, p.IsExpired(), "Expect not expired after retrieve") }
func TestEC2RoleProviderFailAssume(t *testing.T) { server := initTestServer("2014-12-16T01:51:37Z", true) defer server.Close() p := &ec2rolecreds.EC2RoleProvider{ Client: ec2metadata.New(&ec2metadata.Config{Endpoint: aws.String(server.URL + "/latest")}), } creds, err := p.Retrieve() assert.Error(t, err, "Expect error") e := err.(awserr.Error) assert.Equal(t, "ErrorCode", e.Code()) assert.Equal(t, "ErrorMsg", e.Message()) assert.Nil(t, e.OrigErr()) assert.Equal(t, "", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "", creds.SecretAccessKey, "Expect secret access key to match") assert.Equal(t, "", creds.SessionToken, "Expect session token to match") }
func TestChainProviderGet(t *testing.T) { p := &ChainProvider{ Providers: []Provider{ &stubProvider{err: awserr.New("FirstError", "first provider error", nil)}, &stubProvider{err: awserr.New("SecondError", "second provider error", nil)}, &stubProvider{ creds: Value{ AccessKeyID: "AKID", SecretAccessKey: "SECRET", SessionToken: "", }, }, }, } creds, err := p.Retrieve() assert.Nil(t, err, "Expect no error") assert.Equal(t, "AKID", creds.AccessKeyID, "Expect access key ID to match") assert.Equal(t, "SECRET", creds.SecretAccessKey, "Expect secret access key to match") assert.Empty(t, creds.SessionToken, "Expect session token to be empty") }
// 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 occur for 5xx status codes func TestRequestRecoverRetry5xx(t *testing.T) { reqNum := 0 reqs := []http.Response{ http.Response{StatusCode: 500, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, http.Response{StatusCode: 501, Body: body(`{"__type":"UnknownError","message":"An error occurred."}`)}, http.Response{StatusCode: 200, Body: body(`{"data":"valid"}`)}, } 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 = &reqs[reqNum] reqNum++ }) out := &testData{} r := NewRequest(s, &Operation{Name: "Operation"}, nil, out) err := r.Send() assert.Nil(t, err) assert.Equal(t, 2, int(r.RetryCount)) assert.Equal(t, "valid", out.Data) }
// test that retries occur for 4xx status codes with a response type that can be retried - see `shouldRetry` func TestRequestRecoverRetry4xxRetryable(t *testing.T) { reqNum := 0 reqs := []http.Response{ http.Response{StatusCode: 400, Body: body(`{"__type":"Throttling","message":"Rate exceeded."}`)}, http.Response{StatusCode: 429, Body: body(`{"__type":"ProvisionedThroughputExceededException","message":"Rate exceeded."}`)}, http.Response{StatusCode: 200, Body: body(`{"data":"valid"}`)}, } 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 = &reqs[reqNum] reqNum++ }) out := &testData{} r := NewRequest(s, &Operation{Name: "Operation"}, nil, out) err := r.Send() assert.Nil(t, err) assert.Equal(t, 2, int(r.RetryCount)) assert.Equal(t, "valid", out.Data) }