Skip to content

Commit 4bf8e38

Browse files
alextwoodsdavidh44
andauthored
Add Query Compatible protocol tests (#6230)
* Add model files and test classes * Update test cases * Add support for test case id * Update output test cases * Fix test cases * Update tests * Update tests * Update tests * Add binaryBody - query compat cbor output tests now pass --------- Co-authored-by: hdavidh <[email protected]>
1 parent ee827e1 commit 4bf8e38

28 files changed

+1080
-5
lines changed

test/protocol-tests-core/src/main/java/software/amazon/awssdk/protocol/model/TestCase.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,21 @@
1717

1818
public class TestCase {
1919

20+
private String id;
2021
private String description;
2122
// Given is optional
2223
private Given given = new Given();
2324
private When when;
2425
private Then then;
2526

27+
public String getId() {
28+
return id;
29+
}
30+
31+
public void setId(String id) {
32+
this.id = id;
33+
}
34+
2635
public String getDescription() {
2736
return description;
2837
}
@@ -57,7 +66,7 @@ public void setThen(Then then) {
5766

5867
@Override
5968
public String toString() {
60-
return description;
69+
return id;
6170
}
6271

6372
}

test/protocol-tests-core/src/main/java/software/amazon/awssdk/protocol/model/Then.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@ public class Then {
2929
private final MarshallingAssertion serializedAs;
3030
private final UnmarshallingAssertion deserializedAs;
3131
private final UnmarshallingAssertion errorDeserializedAs;
32+
private final String errorCode;
3233

3334
@JsonCreator
3435
public Then(@JsonProperty("serializedAs") SerializedAs serializedAs,
35-
@JsonProperty("deserializedAs") JsonNode deserializedAs) {
36+
@JsonProperty("deserializedAs") JsonNode deserializedAs,
37+
@JsonProperty("errorCode") String errorCode) {
3638
this.serializedAs = serializedAs;
3739
this.deserializedAs = new UnmarshalledResultAssertion(deserializedAs);
3840
this.errorDeserializedAs = new UnmarshalledErrorAssertion(deserializedAs);
41+
this.errorCode = errorCode;
3942
}
4043

4144
/**
@@ -59,4 +62,12 @@ public UnmarshallingAssertion getUnmarshallingAssertion() {
5962
public UnmarshallingAssertion getErrorUnmarshallingAssertion() {
6063
return errorDeserializedAs;
6164
}
65+
66+
/**
67+
*
68+
* @return The errorCode String to use for error unmarshalling tests
69+
*/
70+
public String getErrorCode() {
71+
return errorCode;
72+
}
6273
}

test/protocol-tests-core/src/main/java/software/amazon/awssdk/protocol/runners/ProtocolTestRunner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void runTests(List<TestCase> tests) throws Exception {
6666
}
6767

6868
public void runTest(TestCase testCase) throws Exception {
69-
log.info("Running test: {}", testCase.getDescription());
69+
log.info("Running test: [{}] {}", testCase.getId(), testCase.getDescription());
7070
switch (testCase.getWhen().getAction()) {
7171
case MARSHALL:
7272
marshallingTestRunner.runTest(testCase);

test/protocol-tests-core/src/main/java/software/amazon/awssdk/protocol/runners/UnmarshallingTestRunner.java

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,17 @@
2525
import com.github.tomakehurst.wiremock.client.WireMock;
2626
import java.lang.reflect.InvocationTargetException;
2727
import java.util.Base64;
28+
import org.junit.Assert;
29+
import software.amazon.awssdk.awscore.exception.AwsErrorDetails;
30+
import software.amazon.awssdk.awscore.exception.AwsServiceException;
2831
import software.amazon.awssdk.codegen.model.intermediate.IntermediateModel;
2932
import software.amazon.awssdk.codegen.model.intermediate.Metadata;
3033
import software.amazon.awssdk.core.sync.ResponseTransformer;
3134
import software.amazon.awssdk.http.AbortableInputStream;
3235
import software.amazon.awssdk.protocol.asserts.unmarshalling.UnmarshallingTestContext;
3336
import software.amazon.awssdk.protocol.model.GivenResponse;
3437
import software.amazon.awssdk.protocol.model.TestCase;
38+
import software.amazon.awssdk.protocol.model.Then;
3539
import software.amazon.awssdk.protocol.reflect.ClientReflector;
3640
import software.amazon.awssdk.protocol.reflect.ShapeModelReflector;
3741
import software.amazon.awssdk.utils.IoUtils;
@@ -90,9 +94,30 @@ private void runErrorUnmarshallTest(TestCase testCase) throws Exception {
9094
throw new IllegalStateException("Test case expected client to throw error");
9195
} catch (InvocationTargetException t) {
9296
String errorName = testCase.getWhen().getErrorName();
93-
testCase.getThen().getErrorUnmarshallingAssertion().assertMatches(
94-
createErrorContext(operationName, errorName), t.getCause());
97+
Throwable cause = t.getCause();
98+
Then then = testCase.getThen();
99+
100+
then.getErrorUnmarshallingAssertion().assertMatches(
101+
createErrorContext(operationName, errorName), cause);
102+
103+
validateErrorCodeIfPresent(then, cause);
104+
}
105+
}
106+
107+
private void validateErrorCodeIfPresent(Then then, Throwable cause) {
108+
String expectedErrorCode = then.getErrorCode();
109+
if (expectedErrorCode != null) {
110+
String actualErrorCode = extractErrorCode(cause);
111+
Assert.assertEquals(expectedErrorCode, actualErrorCode);
112+
}
113+
}
114+
115+
private String extractErrorCode(Throwable cause) {
116+
if (!(cause instanceof AwsServiceException)) {
117+
return null;
95118
}
119+
AwsErrorDetails awsErrorDetails = ((AwsServiceException) cause).awsErrorDetails();
120+
return awsErrorDetails.errorCode();
96121
}
97122

98123
private UnmarshallingTestContext createErrorContext(String operationName, String errorName) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[
2+
{
3+
"id": "QueryCompatibleAwsJson10CborSendsQueryModeHeader",
4+
"description": "Clients for query-compatible services MUST send the x-amzn-query-mode header.",
5+
"given": {
6+
"input": {}
7+
},
8+
"when": {
9+
"action": "marshall",
10+
"operation": "QueryCompatibleOperation"
11+
},
12+
"then": {
13+
"serializedAs": {
14+
"method": "POST",
15+
"headers": {
16+
"contains": {
17+
"X-Amz-Target": "QueryCompatibleJsonRpc10.QueryCompatibleOperation",
18+
"x-amzn-query-mode": "true",
19+
"Content-Type": "application/x-amz-json-1.0"
20+
}
21+
},
22+
"body": {
23+
"jsonEquals": "{}"
24+
},
25+
"uri": "/"
26+
}
27+
}
28+
}
29+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[
2+
{
3+
"id": "QueryCompatibleAwsJson10CborNoCustomCodeError",
4+
"description": "Parses simple errors with no query error code",
5+
"given": {
6+
"response": {
7+
"status_code": 400,
8+
"headers": {
9+
"Content-Type": "application/x-amz-json-1.0"
10+
},
11+
"body": "{\n \"__type\": \"aws.protocoltests.json10#NoCustomCodeError\",\n \"Message\": \"Hi\"\n}"
12+
}
13+
},
14+
"when": {
15+
"action": "errorUnmarshall",
16+
"operation": "QueryCompatibleOperation",
17+
"error": "NoCustomCodeError"
18+
},
19+
"then": {
20+
"deserializedAs": {
21+
"message": "Hi"
22+
}
23+
}
24+
},
25+
{
26+
"id": "QueryCompatibleAwsJson10CustomCodeError",
27+
"description": "Parses simple errors with query error code",
28+
"given": {
29+
"response": {
30+
"status_code": 400,
31+
"headers": {
32+
"x-amzn-query-error": "Customized;Sender",
33+
"Content-Type": "application/x-amz-json-1.0"
34+
},
35+
"body": "{\n \"__type\": \"aws.protocoltests.json10#CustomCodeError\",\n \"Message\": \"Hi\"\n}"
36+
}
37+
},
38+
"when": {
39+
"action": "errorUnmarshall",
40+
"operation": "QueryCompatibleOperation",
41+
"error": "CustomCodeError"
42+
},
43+
"then": {
44+
"deserializedAs": {
45+
"message": "Hi"
46+
},
47+
"errorCode": "Customized"
48+
}
49+
}
50+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[
2+
{
3+
"id": "NonQueryCompatibleRpcV2CborForbidsQueryModeHeader",
4+
"description": "The query mode header MUST NOT be set on non-query-compatible services.",
5+
"given": {
6+
"input": {}
7+
},
8+
"when": {
9+
"action": "marshall",
10+
"operation": "NonQueryCompatibleOperation"
11+
},
12+
"then": {
13+
"serializedAs": {
14+
"method": "POST",
15+
"headers": {
16+
"contains": {
17+
"Accept": "application/cbor",
18+
"smithy-protocol": "rpc-v2-cbor"
19+
},
20+
"doesNotContain": [
21+
"x-amzn-query-mode"
22+
]
23+
},
24+
"body": {
25+
"encodedEquals": ""
26+
},
27+
"uri": "/service/NonQueryCompatibleRpcV2Protocol/operation/NonQueryCompatibleOperation"
28+
}
29+
}
30+
}
31+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
[
2+
{
3+
"id": "QueryCompatibleRpcV2CborSendsQueryModeHeader",
4+
"description": "Clients for query-compatible services MUST send the x-amzn-query-mode header.",
5+
"given": {
6+
"input": {}
7+
},
8+
"when": {
9+
"action": "marshall",
10+
"operation": "QueryCompatibleOperation"
11+
},
12+
"then": {
13+
"serializedAs": {
14+
"method": "POST",
15+
"headers": {
16+
"contains": {
17+
"smithy-protocol": "rpc-v2-cbor",
18+
"Accept": "application/cbor",
19+
"x-amzn-query-mode": "true"
20+
},
21+
"doesNotContain": [
22+
"Content-Type",
23+
"X-Amz-Target"
24+
]
25+
},
26+
"body": {
27+
"encodedEquals": ""
28+
},
29+
"uri": "/service/QueryCompatibleRpcV2Protocol/operation/QueryCompatibleOperation"
30+
}
31+
}
32+
}
33+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[
2+
{
3+
"id": "QueryCompatibleRpcV2CborNoCustomCodeError",
4+
"description": "Parses simple RpcV2 CBOR errors with no query error code",
5+
"given": {
6+
"response": {
7+
"status_code": 400,
8+
"headers": {
9+
"smithy-protocol": "rpc-v2-cbor",
10+
"Content-Type": "application/cbor"
11+
},
12+
"binaryBody": "uQACZl9fdHlwZXgtYXdzLnByb3RvY29sdGVzdHMucnBjdjJjYm9yI05vQ3VzdG9tQ29kZUVycm9yZ01lc3NhZ2ViSGk="
13+
}
14+
},
15+
"when": {
16+
"action": "errorUnmarshall",
17+
"operation": "QueryCompatibleOperation",
18+
"error": "NoCustomCodeError"
19+
},
20+
"then": {
21+
"deserializedAs": {
22+
"message": "Hi"
23+
}
24+
}
25+
},
26+
{
27+
"id": "QueryCompatibleRpcV2CborCustomCodeError",
28+
"description": "Parses simple RpcV2 CBOR errors with query error code",
29+
"given": {
30+
"response": {
31+
"status_code": 400,
32+
"headers": {
33+
"x-amzn-query-error": "Customized;Sender",
34+
"smithy-protocol": "rpc-v2-cbor",
35+
"Content-Type": "application/cbor"
36+
},
37+
"binaryBody": "uQACZl9fdHlwZXgrYXdzLnByb3RvY29sdGVzdHMucnBjdjJjYm9yI0N1c3RvbUNvZGVFcnJvcmdNZXNzYWdlYkhp"
38+
}
39+
},
40+
"when": {
41+
"action": "errorUnmarshall",
42+
"operation": "QueryCompatibleOperation",
43+
"error": "CustomCodeError"
44+
},
45+
"then": {
46+
"deserializedAs": {
47+
"message": "Hi"
48+
},
49+
"errorCode": "Customized"
50+
}
51+
}
52+
]

0 commit comments

Comments
 (0)