• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.protocol.tests.exception;
17 
18 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
19 import static com.github.tomakehurst.wiremock.client.WireMock.post;
20 import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
21 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.junit.Assert.assertEquals;
24 import static software.amazon.awssdk.protocol.tests.util.exception.ExceptionTestUtils.stub404Response;
25 
26 import com.github.tomakehurst.wiremock.junit.WireMockRule;
27 import java.net.URI;
28 import java.time.Instant;
29 import java.util.AbstractMap.SimpleEntry;
30 import org.junit.Before;
31 import org.junit.Rule;
32 import org.junit.Test;
33 import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
34 import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
35 import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
36 import software.amazon.awssdk.core.exception.SdkClientException;
37 import software.amazon.awssdk.regions.Region;
38 import software.amazon.awssdk.services.protocolrestxml.ProtocolRestXmlClient;
39 import software.amazon.awssdk.services.protocolrestxml.model.AllTypesRequest;
40 import software.amazon.awssdk.services.protocolrestxml.model.EmptyModeledException;
41 import software.amazon.awssdk.services.protocolrestxml.model.ImplicitPayloadException;
42 import software.amazon.awssdk.services.protocolrestxml.model.MultiLocationOperationRequest;
43 import software.amazon.awssdk.services.protocolrestxml.model.ProtocolRestXmlException;
44 
45 public class RestXmlExceptionTests {
46 
47     private static final String ALL_TYPES_PATH = "/2016-03-11/allTypes";
48 
49     @Rule
50     public WireMockRule wireMock = new WireMockRule(0);
51 
52     private ProtocolRestXmlClient client;
53 
54     @Before
setupClient()55     public void setupClient() {
56         client = ProtocolRestXmlClient.builder()
57                                   .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create("akid", "skid")))
58                                   .region(Region.US_EAST_1)
59                                   .endpointOverride(URI.create("http://localhost:" + wireMock.port()))
60                                   .build();
61     }
62 
63     @Test
unmodeledException_UnmarshalledIntoBaseServiceException()64     public void unmodeledException_UnmarshalledIntoBaseServiceException() {
65         stub404Response(ALL_TYPES_PATH,
66                         "<ErrorResponse><Error><Code>UnmodeledException</Code></Error></ErrorResponse>");
67         assertThrowsServiceBaseException(this::callAllTypes);
68     }
69 
70     @Test
modeledException_UnmarshalledIntoModeledException()71     public void modeledException_UnmarshalledIntoModeledException() {
72         stub404Response(ALL_TYPES_PATH,
73                         "<ErrorResponse><Error><Code>EmptyModeledException</Code></Error></ErrorResponse>");
74         try {
75             callAllTypes();
76         } catch (EmptyModeledException e) {
77             assertThat(e).isInstanceOf(ProtocolRestXmlException.class);
78         }
79     }
80 
81     @Test
modeledExceptionWithImplicitPayloadMembers_UnmarshalledIntoModeledException()82     public void modeledExceptionWithImplicitPayloadMembers_UnmarshalledIntoModeledException() {
83         String xml = "<ErrorResponse>"
84                      + "   <Error>"
85                      + "      <Code>ImplicitPayloadException</Code>"
86                      + "      <Message>this is the service message</Message>"
87                      + "      <StringMember>foo</StringMember>"
88                      + "      <IntegerMember>42</IntegerMember>"
89                      + "      <LongMember>9001</LongMember>"
90                      + "      <DoubleMember>1234.56</DoubleMember>"
91                      + "      <FloatMember>789.10</FloatMember>"
92                      + "      <TimestampMember>2015-01-25T08:00:12Z</TimestampMember>"
93                      + "      <BooleanMember>true</BooleanMember>"
94                      + "      <BlobMember>dGhlcmUh</BlobMember>"
95                      + "      <ListMember>"
96                      + "         <member>valOne</member>"
97                      + "         <member>valTwo</member>"
98                      + "      </ListMember>"
99                      + "      <MapMember>"
100                      + "         <entry>"
101                      + "            <key>keyOne</key>"
102                      + "            <value>valOne</value>"
103                      + "         </entry>"
104                      + "         <entry>"
105                      + "            <key>keyTwo</key>"
106                      + "            <value>valTwo</value>"
107                      + "         </entry>"
108                      + "      </MapMember>"
109                      + "      <SimpleStructMember>"
110                      + "         <StringMember>foobar</StringMember>"
111                      + "      </SimpleStructMember>"
112                      + "   </Error>"
113                      + "</ErrorResponse>";
114         stubFor(post(urlEqualTo(ALL_TYPES_PATH)).willReturn(
115             aResponse().withStatus(404)
116                        .withBody(xml)));
117         try {
118             client.allTypes();
119         } catch (ImplicitPayloadException e) {
120             assertThat(e.stringMember()).isEqualTo("foo");
121             assertThat(e.integerMember()).isEqualTo(42);
122             assertThat(e.longMember()).isEqualTo(9001);
123             assertThat(e.doubleMember()).isEqualTo(1234.56);
124             assertThat(e.floatMember()).isEqualTo(789.10f);
125             assertThat(e.timestampMember()).isEqualTo(Instant.ofEpochMilli(1422172812000L));
126             assertThat(e.booleanMember()).isEqualTo(true);
127             assertThat(e.blobMember().asUtf8String()).isEqualTo("there!");
128             assertThat(e.listMember()).contains("valOne", "valTwo");
129             assertThat(e.mapMember())
130                 .containsOnly(new SimpleEntry<>("keyOne", "valOne"),
131                               new SimpleEntry<>("keyTwo", "valTwo"));
132             assertThat(e.simpleStructMember().stringMember()).isEqualTo("foobar");
133         }
134     }
135 
136     @Test
modeledException_HasExceptionMetadataSet()137     public void modeledException_HasExceptionMetadataSet() {
138         String xml = "<ErrorResponse>"
139                      + "   <Error>"
140                      + "      <Code>EmptyModeledException</Code>"
141                      + "      <Message>This is the service message</Message>"
142                      + "   </Error>"
143                      + "   <RequestId>1234</RequestId>"
144                      + "</ErrorResponse>";
145         stubFor(post(urlEqualTo(ALL_TYPES_PATH)).willReturn(
146             aResponse()
147                 .withStatus(404)
148                 .withBody(xml)));
149         try {
150             client.allTypes();
151         } catch (EmptyModeledException e) {
152             AwsErrorDetails awsErrorDetails = e.awsErrorDetails();
153             assertThat(awsErrorDetails.errorCode()).isEqualTo("EmptyModeledException");
154             assertThat(awsErrorDetails.errorMessage()).isEqualTo("This is the service message");
155             assertThat(awsErrorDetails.serviceName()).isEqualTo("ProtocolRestXml");
156             assertThat(awsErrorDetails.sdkHttpResponse()).isNotNull();
157             assertThat(e.requestId()).isEqualTo("1234");
158             assertThat(e.extendedRequestId()).isNull();
159             assertThat(e.statusCode()).isEqualTo(404);
160         }
161     }
162 
163     @Test
modeledException_HasExceptionMetadataIncludingExtendedRequestIdSet()164     public void modeledException_HasExceptionMetadataIncludingExtendedRequestIdSet() {
165         String xml = "<ErrorResponse>"
166                      + "   <Error>"
167                      + "      <Code>EmptyModeledException</Code>"
168                      + "      <Message>This is the service message</Message>"
169                      + "   </Error>"
170                      + "   <RequestId>1234</RequestId>"
171                      + "</ErrorResponse>";
172         stubFor(post(urlEqualTo(ALL_TYPES_PATH)).willReturn(
173             aResponse()
174                 .withStatus(404)
175                 .withHeader("x-amz-id-2", "5678")
176                 .withBody(xml)));
177         try {
178             client.allTypes();
179         } catch (EmptyModeledException e) {
180             AwsErrorDetails awsErrorDetails = e.awsErrorDetails();
181             assertThat(awsErrorDetails.errorCode()).isEqualTo("EmptyModeledException");
182             assertThat(awsErrorDetails.errorMessage()).isEqualTo("This is the service message");
183             assertThat(awsErrorDetails.serviceName()).isEqualTo("ProtocolRestXml");
184             assertThat(awsErrorDetails.sdkHttpResponse()).isNotNull();
185             assertThat(e.requestId()).isEqualTo("1234");
186             assertThat(e.extendedRequestId()).isEqualTo("5678");
187             assertThat(e.statusCode()).isEqualTo(404);
188         }
189     }
190 
191     @Test
emptyErrorResponse_UnmarshalledIntoBaseServiceException()192     public void emptyErrorResponse_UnmarshalledIntoBaseServiceException() {
193         stub404Response(ALL_TYPES_PATH, "");
194         assertThrowsServiceBaseException(this::callAllTypes);
195     }
196 
197     @Test
malformedErrorResponse_UnmarshalledIntoBaseServiceException()198     public void malformedErrorResponse_UnmarshalledIntoBaseServiceException() {
199         stub404Response(ALL_TYPES_PATH, "THIS ISN'T XML");
200         assertThrowsServiceBaseException(this::callAllTypes);
201     }
202 
203     @Test
illegalArgumentException_nullPathParam()204     public void illegalArgumentException_nullPathParam() {
205         assertThrowsNestedExceptions(() -> client.multiLocationOperation(MultiLocationOperationRequest.builder().build()),
206                                      SdkClientException.class,
207                                      IllegalArgumentException.class);
208     }
209 
210     @Test
illegalArgumentException_emptyPathParam()211     public void illegalArgumentException_emptyPathParam() {
212         assertThrowsNestedExceptions(() -> client.multiLocationOperation(MultiLocationOperationRequest.builder()
213                                                                                                       .pathParam("")
214                                                                                                       .build()),
215                                      SdkClientException.class,
216                                      IllegalArgumentException.class);
217     }
218 
219     @Test
alternateRequestIdInHeader_IsSetOnException()220     public void alternateRequestIdInHeader_IsSetOnException() {
221         stubFor(post(urlEqualTo(ALL_TYPES_PATH)).willReturn(
222             aResponse()
223                 .withStatus(404)
224                 .withHeader("x-amz-request-id", "1234")));
225         try {
226             client.allTypes();
227         } catch (ProtocolRestXmlException e) {
228             assertThat(e.requestId()).isEqualTo("1234");
229         }
230     }
231 
callAllTypes()232     private void callAllTypes() {
233         client.allTypes(AllTypesRequest.builder().build());
234     }
235 
assertThrowsServiceBaseException(Runnable runnable)236     private void assertThrowsServiceBaseException(Runnable runnable) {
237         assertThrowsException(runnable, ProtocolRestXmlException.class);
238     }
239 
assertThrowsIllegalArgumentException(Runnable runnable)240     private void assertThrowsIllegalArgumentException(Runnable runnable) {
241         assertThrowsException(runnable, IllegalArgumentException.class);
242     }
243 
assertThrowsNullPointerException(Runnable runnable)244     private void assertThrowsNullPointerException(Runnable runnable) {
245         assertThrowsException(runnable, NullPointerException.class);
246     }
247 
assertThrowsException(Runnable runnable, Class<? extends Exception> expectedException)248     private void assertThrowsException(Runnable runnable, Class<? extends Exception> expectedException) {
249         try {
250             runnable.run();
251         } catch (Exception e) {
252             assertEquals(expectedException, e.getClass());
253         }
254     }
255 
assertThrowsNestedExceptions(Runnable runnable, Class<? extends Exception> parentException, Class<? extends Exception> nestedException)256     private void assertThrowsNestedExceptions(Runnable runnable, Class<? extends Exception> parentException,
257                                               Class<? extends Exception> nestedException) {
258         try {
259             runnable.run();
260         } catch (Exception e) {
261             assertEquals(parentException, e.getClass());
262             assertEquals(nestedException, e.getCause().getClass());
263         }
264     }
265 }
266