Skip to content

Commit ca099f2

Browse files
authored
Update protocol test request body comparison (#268)
This commit updates the request body comparison generation for protocol tests to safely handle having multiple bodyMediaType settings in the same suite of protocol tests. It also updates the methodology for comparing blob bodies to not be a special case in the generator, as they can have alternate media types.
1 parent ad2012a commit ca099f2

File tree

7 files changed

+49
-30
lines changed

7 files changed

+49
-30
lines changed

smithy-typescript-codegen/src/main/java/software/amazon/smithy/typescript/codegen/HttpProtocolTestGenerator.java

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -278,53 +278,42 @@ private void writeRequestBodyAssertions(OperationShape operation, HttpRequestTes
278278
writer.write("expect(r.body).toBeDefined();");
279279

280280
// Otherwise load a media type specific comparator and do a comparison.
281-
String mediaType = testCase.getBodyMediaType().orElse(null);
282-
283-
// Fast check if we have an undescribed or plain text body.
284-
if (mediaType == null || mediaType.equals("text/plain")) {
285-
// Handle converting to the right comparison format for blob payloads.
286-
HttpBindingIndex httpBindingIndex = HttpBindingIndex.of(model);
287-
List<HttpBinding> payloadBindings = httpBindingIndex.getRequestBindings(operation, Location.PAYLOAD);
288-
if (!payloadBindings.isEmpty() && hasBlobBinding(payloadBindings)) {
289-
writer.write("expect(r.body).toMatchObject(Uint8Array.from($S, c => c.charCodeAt(0)));", body);
290-
} else {
291-
writer.write("expect(r.body).toBe($S);", body);
292-
}
293-
return;
294-
}
295-
registerBodyComparatorStub(mediaType);
281+
String mediaType = testCase.getBodyMediaType().orElse("UNKNOWN");
282+
String comparatorInvoke = registerBodyComparatorStub(mediaType);
296283

297284
// Handle escaping strings with quotes inside them.
298285
writer.write("const bodyString = `$L`;", body.replace("\"", "\\\""));
299-
writer.write("const unequalParts: any = compareEquivalentBodies(bodyString, r.body.toString());");
286+
writer.write("const unequalParts: any = $L;", comparatorInvoke);
300287
writer.write("expect(unequalParts).toBeUndefined();");
301288
});
302289
}
303290

304-
private boolean hasBlobBinding(List<HttpBinding> payloadBindings) {
305-
// Can only have one payload binding at a time.
306-
return model.expectShape(payloadBindings.get(0).getMember().getTarget()).isBlobShape();
307-
}
308-
309-
private void registerBodyComparatorStub(String mediaType) {
291+
private String registerBodyComparatorStub(String mediaType) {
310292
// Load an additional stub to handle body comparisons for the
311293
// set of bodyMediaType values we know of.
312294
switch (mediaType) {
313295
case "application/x-www-form-urlencoded":
314296
additionalStubs.add("protocol-test-form-urlencoded-stub.ts");
315-
break;
297+
return "compareEquivalentFormUrlencodedBodies(bodyString, r.body.toString())";
316298
case "application/json":
317299
additionalStubs.add("protocol-test-json-stub.ts");
318-
break;
300+
return "compareEquivalentJsonBodies(bodyString, r.body.toString())";
319301
case "application/xml":
320302
writer.addDependency(TypeScriptDependency.XML_PARSER);
321303
writer.addImport("parse", "xmlParse", "fast-xml-parser");
322304
additionalStubs.add("protocol-test-xml-stub.ts");
323-
break;
305+
return "compareEquivalentXmlBodies(bodyString, r.body.toString())";
306+
case "application/octet-stream":
307+
additionalStubs.add("protocol-test-octet-stream-stub.ts");
308+
return "compareEquivalentOctetStreamBodies(client.config, bodyString, r.body)";
309+
case "text/plain":
310+
additionalStubs.add("protocol-test-text-stub.ts");
311+
return "compareEquivalentTextBodies(bodyString, r.body)";
324312
default:
325313
LOGGER.warning("Unable to compare bodies with unknown media type `" + mediaType
326314
+ "`, defaulting to direct comparison.");
327315
additionalStubs.add("protocol-test-unknown-type-stub.ts");
316+
return "compareEquivalentUnknownTypeBodies(client.config, bodyString, r.body)";
328317
}
329318
}
330319

smithy-typescript-codegen/src/main/resources/software/amazon/smithy/typescript/codegen/protocol-test-form-urlencoded-stub.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Returns a map of key names that were un-equal to value objects showing the
33
* discrepancies between the components.
44
*/
5-
const compareEquivalentBodies = (expectedBody: string, generatedBody: string): Object => {
5+
const compareEquivalentFormUrlencodedBodies = (expectedBody: string, generatedBody: string): Object => {
66
const fromEntries = (components: string[][]): { [key: string]: string } => {
77
const parts: { [key: string]: string } = {};
88

smithy-typescript-codegen/src/main/resources/software/amazon/smithy/typescript/codegen/protocol-test-json-stub.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Returns a map of key names that were un-equal to value objects showing the
33
* discrepancies between the components.
44
*/
5-
const compareEquivalentBodies = (expectedBody: string, generatedBody: string): Object => {
5+
const compareEquivalentJsonBodies = (expectedBody: string, generatedBody: string): Object => {
66
const expectedParts = JSON.parse(expectedBody);
77
const generatedParts = JSON.parse(generatedBody);
88

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Returns a map of key names that were un-equal to value objects showing the
3+
* discrepancies between the components.
4+
*/
5+
const compareEquivalentOctetStreamBodies = (
6+
config: any,
7+
expectedBody: string,
8+
generatedBody: Uint8Array
9+
): Object => {
10+
const expectedParts = {Value: expectedBody};
11+
const generatedParts = {Value: config.utf8Encoder(generatedBody)};
12+
13+
return compareParts(expectedParts, generatedParts);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/**
2+
* Returns a map of key names that were un-equal to value objects showing the
3+
* discrepancies between the components.
4+
*/
5+
const compareEquivalentTextBodies = (expectedBody: string, generatedBody: string): Object => {
6+
const expectedParts = {Value: expectedBody};
7+
const generatedParts = {Value: generatedBody};
8+
9+
return compareParts(expectedParts, generatedParts);
10+
}

smithy-typescript-codegen/src/main/resources/software/amazon/smithy/typescript/codegen/protocol-test-unknown-type-stub.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@
22
* Returns a map of key names that were un-equal to value objects showing the
33
* discrepancies between the components.
44
*/
5-
const compareEquivalentBodies = (expectedBody: string, generatedBody: string): Object => {
5+
const compareEquivalentUnknownTypeBodies = (
6+
config: any,
7+
expectedBody: string,
8+
generatedBody: string | Uint8Array
9+
): Object => {
610
const expectedParts = {Value: expectedBody};
7-
const generatedParts = {Value: generatedBody};
11+
const generatedParts = {
12+
Value: generatedBody instanceof Uint8Array ? config.utf8Encoder(generatedBody) : generatedBody
13+
};
814

915
return compareParts(expectedParts, generatedParts);
1016
}

smithy-typescript-codegen/src/main/resources/software/amazon/smithy/typescript/codegen/protocol-test-xml-stub.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Returns a map of key names that were un-equal to value objects showing the
33
* discrepancies between the components.
44
*/
5-
const compareEquivalentBodies = (expectedBody: string, generatedBody: string): Object => {
5+
const compareEquivalentXmlBodies = (expectedBody: string, generatedBody: string): Object => {
66
const decodeEscapedXml = (str: string) => {
77
return str
88
.replace(/&amp;/g, "&")

0 commit comments

Comments
 (0)