1package customizations_test
2
3import (
4	"context"
5	"errors"
6	"net/http"
7	"net/http/httptest"
8	"strings"
9	"testing"
10
11	"github.com/aws/aws-sdk-go-v2/aws"
12	"github.com/aws/aws-sdk-go-v2/service/route53"
13	"github.com/aws/aws-sdk-go-v2/service/route53/types"
14)
15
16func TestCustomErrorDeserialization(t *testing.T) {
17	cases := map[string]struct {
18		responseStatus     int
19		responseBody       []byte
20		expectedError      string
21		expectedRequestID  string
22		expectedResponseID string
23	}{
24		"invalidChangeBatchError": {
25			responseStatus: 500,
26			responseBody: []byte(`<?xml version="1.0" encoding="UTF-8"?>
27		<InvalidChangeBatch xmlns="https://route53.amazonaws.com/doc/2013-04-01/">
28		  <Messages>
29		    <Message>Tried to create resource record set duplicate.example.com. type A, but it already exists</Message>
30		  </Messages>
31		  <RequestId>b25f48e8-84fd-11e6-80d9-574e0c4664cb</RequestId>
32		</InvalidChangeBatch>`),
33			expectedError:     "InvalidChangeBatch: ChangeBatch errors occurred",
34			expectedRequestID: "b25f48e8-84fd-11e6-80d9-574e0c4664cb",
35		},
36
37		"standardRestXMLError": {
38			responseStatus: 500,
39			responseBody: []byte(`<?xml version="1.0"?>
40		<ErrorResponse xmlns="http://route53.amazonaws.com/doc/2016-09-07/">
41		  <Error>
42		    <Type>Sender</Type>
43		    <Code>MalformedXML</Code>
44		    <Message>1 validation error detected: Value null at 'route53#ChangeSet' failed to satisfy constraint: Member must not be null</Message>
45		  </Error>
46		  <RequestId>b25f48e8-84fd-11e6-80d9-574e0c4664cb</RequestId>
47		</ErrorResponse>
48		`),
49			expectedError:     "1 validation error detected:",
50			expectedRequestID: "b25f48e8-84fd-11e6-80d9-574e0c4664cb",
51		},
52
53		"Success response": {
54			responseStatus: 200,
55			responseBody: []byte(`<?xml version="1.0" encoding="UTF-8"?>
56		<ChangeResourceRecordSetsResponse>
57   			<ChangeInfo>
58      		<Comment>mockComment</Comment>
59      		<Id>mockID</Id>
60   		</ChangeInfo>
61		</ChangeResourceRecordSetsResponse>`),
62			expectedResponseID: "mockID",
63		},
64	}
65
66	for name, c := range cases {
67		server := httptest.NewServer(http.HandlerFunc(
68			func(w http.ResponseWriter, r *http.Request) {
69				w.WriteHeader(c.responseStatus)
70				w.Write(c.responseBody)
71			}))
72		defer server.Close()
73
74		t.Run(name, func(t *testing.T) {
75			svc := route53.NewFromConfig(aws.Config{
76				Region: "us-east-1",
77				EndpointResolver: aws.EndpointResolverFunc(func(service, region string) (aws.Endpoint, error) {
78					return aws.Endpoint{
79						URL:         server.URL,
80						SigningName: "route53",
81					}, nil
82				}),
83				Retryer: func() aws.Retryer {
84					return aws.NopRetryer{}
85				},
86			})
87			resp, err := svc.ChangeResourceRecordSets(context.Background(), &route53.ChangeResourceRecordSetsInput{
88				ChangeBatch: &types.ChangeBatch{
89					Changes: []types.Change{},
90					Comment: aws.String("mock"),
91				},
92				HostedZoneId: aws.String("zone"),
93			})
94
95			if err == nil && len(c.expectedError) != 0 {
96				t.Fatalf("expected err, got none")
97			}
98
99			if len(c.expectedError) != 0 {
100				if e, a := c.expectedError, err.Error(); !strings.Contains(a, e) {
101					t.Fatalf("expected error to be %s, got %s", e, a)
102				}
103
104				var responseError interface {
105					ServiceRequestID() string
106				}
107
108				if !errors.As(err, &responseError) {
109					t.Fatalf("expected error to be of type %T, was not", responseError)
110				}
111
112				if e, a := c.expectedRequestID, responseError.ServiceRequestID(); !strings.EqualFold(e, a) {
113					t.Fatalf("expected request id to be %s, got %s", e, a)
114				}
115			}
116
117			if len(c.expectedResponseID) != 0 {
118				if e, a := c.expectedResponseID, *resp.ChangeInfo.Id; !strings.EqualFold(e, a) {
119					t.Fatalf("expected response to have id %v, got %v", e, a)
120				}
121			}
122
123		})
124	}
125}
126