123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- package waiter_test
- import (
- "bytes"
- "io/ioutil"
- "net/http"
- "testing"
- "github.com/stretchr/testify/assert"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/awserr"
- "github.com/aws/aws-sdk-go/aws/client"
- "github.com/aws/aws-sdk-go/aws/request"
- "github.com/aws/aws-sdk-go/awstesting"
- "github.com/aws/aws-sdk-go/private/waiter"
- )
- type mockClient struct {
- *client.Client
- }
- type MockInput struct{}
- type MockOutput struct {
- States []*MockState
- }
- type MockState struct {
- State *string
- }
- func (c *mockClient) MockRequest(input *MockInput) (*request.Request, *MockOutput) {
- op := &request.Operation{
- Name: "Mock",
- HTTPMethod: "POST",
- HTTPPath: "/",
- }
- if input == nil {
- input = &MockInput{}
- }
- output := &MockOutput{}
- req := c.NewRequest(op, input, output)
- req.Data = output
- return req, output
- }
- func TestWaiterPathAll(t *testing.T) {
- svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
- Region: aws.String("mock-region"),
- })}
- svc.Handlers.Send.Clear() // mock sending
- svc.Handlers.Unmarshal.Clear()
- svc.Handlers.UnmarshalMeta.Clear()
- svc.Handlers.ValidateResponse.Clear()
- reqNum := 0
- resps := []*MockOutput{
- { // Request 1
- States: []*MockState{
- {State: aws.String("pending")},
- {State: aws.String("pending")},
- },
- },
- { // Request 2
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("pending")},
- },
- },
- { // Request 3
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("running")},
- },
- },
- }
- numBuiltReq := 0
- svc.Handlers.Build.PushBack(func(r *request.Request) {
- numBuiltReq++
- })
- svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
- if reqNum >= len(resps) {
- assert.Fail(t, "too many polling requests made")
- return
- }
- r.Data = resps[reqNum]
- reqNum++
- })
- waiterCfg := waiter.Config{
- Operation: "Mock",
- Delay: 0,
- MaxAttempts: 10,
- Acceptors: []waiter.WaitAcceptor{
- {
- State: "success",
- Matcher: "pathAll",
- Argument: "States[].State",
- Expected: "running",
- },
- },
- }
- w := waiter.Waiter{
- Client: svc,
- Input: &MockInput{},
- Config: waiterCfg,
- }
- err := w.Wait()
- assert.NoError(t, err)
- assert.Equal(t, 3, numBuiltReq)
- assert.Equal(t, 3, reqNum)
- }
- func TestWaiterPath(t *testing.T) {
- svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
- Region: aws.String("mock-region"),
- })}
- svc.Handlers.Send.Clear() // mock sending
- svc.Handlers.Unmarshal.Clear()
- svc.Handlers.UnmarshalMeta.Clear()
- svc.Handlers.ValidateResponse.Clear()
- reqNum := 0
- resps := []*MockOutput{
- { // Request 1
- States: []*MockState{
- {State: aws.String("pending")},
- {State: aws.String("pending")},
- },
- },
- { // Request 2
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("pending")},
- },
- },
- { // Request 3
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("running")},
- },
- },
- }
- numBuiltReq := 0
- svc.Handlers.Build.PushBack(func(r *request.Request) {
- numBuiltReq++
- })
- svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
- if reqNum >= len(resps) {
- assert.Fail(t, "too many polling requests made")
- return
- }
- r.Data = resps[reqNum]
- reqNum++
- })
- waiterCfg := waiter.Config{
- Operation: "Mock",
- Delay: 0,
- MaxAttempts: 10,
- Acceptors: []waiter.WaitAcceptor{
- {
- State: "success",
- Matcher: "path",
- Argument: "States[].State",
- Expected: "running",
- },
- },
- }
- w := waiter.Waiter{
- Client: svc,
- Input: &MockInput{},
- Config: waiterCfg,
- }
- err := w.Wait()
- assert.NoError(t, err)
- assert.Equal(t, 3, numBuiltReq)
- assert.Equal(t, 3, reqNum)
- }
- func TestWaiterFailure(t *testing.T) {
- svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
- Region: aws.String("mock-region"),
- })}
- svc.Handlers.Send.Clear() // mock sending
- svc.Handlers.Unmarshal.Clear()
- svc.Handlers.UnmarshalMeta.Clear()
- svc.Handlers.ValidateResponse.Clear()
- reqNum := 0
- resps := []*MockOutput{
- { // Request 1
- States: []*MockState{
- {State: aws.String("pending")},
- {State: aws.String("pending")},
- },
- },
- { // Request 2
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("pending")},
- },
- },
- { // Request 3
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("stopping")},
- },
- },
- }
- numBuiltReq := 0
- svc.Handlers.Build.PushBack(func(r *request.Request) {
- numBuiltReq++
- })
- svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
- if reqNum >= len(resps) {
- assert.Fail(t, "too many polling requests made")
- return
- }
- r.Data = resps[reqNum]
- reqNum++
- })
- waiterCfg := waiter.Config{
- Operation: "Mock",
- Delay: 0,
- MaxAttempts: 10,
- Acceptors: []waiter.WaitAcceptor{
- {
- State: "success",
- Matcher: "pathAll",
- Argument: "States[].State",
- Expected: "running",
- },
- {
- State: "failure",
- Matcher: "pathAny",
- Argument: "States[].State",
- Expected: "stopping",
- },
- },
- }
- w := waiter.Waiter{
- Client: svc,
- Input: &MockInput{},
- Config: waiterCfg,
- }
- err := w.Wait().(awserr.Error)
- assert.Error(t, err)
- assert.Equal(t, "ResourceNotReady", err.Code())
- assert.Equal(t, "failed waiting for successful resource state", err.Message())
- assert.Equal(t, 3, numBuiltReq)
- assert.Equal(t, 3, reqNum)
- }
- func TestWaiterError(t *testing.T) {
- svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
- Region: aws.String("mock-region"),
- })}
- svc.Handlers.Send.Clear() // mock sending
- svc.Handlers.Unmarshal.Clear()
- svc.Handlers.UnmarshalMeta.Clear()
- svc.Handlers.UnmarshalError.Clear()
- svc.Handlers.ValidateResponse.Clear()
- reqNum := 0
- resps := []*MockOutput{
- { // Request 1
- States: []*MockState{
- {State: aws.String("pending")},
- {State: aws.String("pending")},
- },
- },
- { // Request 2, error case
- },
- { // Request 3
- States: []*MockState{
- {State: aws.String("running")},
- {State: aws.String("running")},
- },
- },
- }
- numBuiltReq := 0
- svc.Handlers.Build.PushBack(func(r *request.Request) {
- numBuiltReq++
- })
- svc.Handlers.Send.PushBack(func(r *request.Request) {
- code := 200
- if reqNum == 1 {
- code = 400
- }
- r.HTTPResponse = &http.Response{
- StatusCode: code,
- Status: http.StatusText(code),
- Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
- }
- })
- svc.Handlers.Unmarshal.PushBack(func(r *request.Request) {
- if reqNum >= len(resps) {
- assert.Fail(t, "too many polling requests made")
- return
- }
- r.Data = resps[reqNum]
- reqNum++
- })
- svc.Handlers.UnmarshalMeta.PushBack(func(r *request.Request) {
- if reqNum == 1 {
- r.Error = awserr.New("MockException", "mock exception message", nil)
- // If there was an error unmarshal error will be called instead of unmarshal
- // need to increment count here also
- reqNum++
- }
- })
- waiterCfg := waiter.Config{
- Operation: "Mock",
- Delay: 0,
- MaxAttempts: 10,
- Acceptors: []waiter.WaitAcceptor{
- {
- State: "success",
- Matcher: "pathAll",
- Argument: "States[].State",
- Expected: "running",
- },
- {
- State: "retry",
- Matcher: "error",
- Argument: "",
- Expected: "MockException",
- },
- },
- }
- w := waiter.Waiter{
- Client: svc,
- Input: &MockInput{},
- Config: waiterCfg,
- }
- err := w.Wait()
- assert.NoError(t, err)
- assert.Equal(t, 3, numBuiltReq)
- assert.Equal(t, 3, reqNum)
- }
- func TestWaiterStatus(t *testing.T) {
- svc := &mockClient{Client: awstesting.NewClient(&aws.Config{
- Region: aws.String("mock-region"),
- })}
- svc.Handlers.Send.Clear() // mock sending
- svc.Handlers.Unmarshal.Clear()
- svc.Handlers.UnmarshalMeta.Clear()
- svc.Handlers.ValidateResponse.Clear()
- reqNum := 0
- svc.Handlers.Build.PushBack(func(r *request.Request) {
- reqNum++
- })
- svc.Handlers.Send.PushBack(func(r *request.Request) {
- code := 200
- if reqNum == 3 {
- code = 404
- r.Error = awserr.New("NotFound", "Not Found", nil)
- }
- r.HTTPResponse = &http.Response{
- StatusCode: code,
- Status: http.StatusText(code),
- Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
- }
- })
- waiterCfg := waiter.Config{
- Operation: "Mock",
- Delay: 0,
- MaxAttempts: 10,
- Acceptors: []waiter.WaitAcceptor{
- {
- State: "success",
- Matcher: "status",
- Argument: "",
- Expected: 404,
- },
- },
- }
- w := waiter.Waiter{
- Client: svc,
- Input: &MockInput{},
- Config: waiterCfg,
- }
- err := w.Wait()
- assert.NoError(t, err)
- assert.Equal(t, 3, reqNum)
- }
|