diff --git a/settings.gradle.kts b/settings.gradle.kts index ba9479deb25..be6f919cad3 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,7 @@ rootProject.name = "smithy" include(":smithy-aws-traits") include(":smithy-aws-apigateway-openapi") +include(":smithy-aws-protocol-tests") include(":smithy-cli") include(":smithy-codegen-core") include(":smithy-codegen-freemarker") @@ -13,3 +14,10 @@ include(":smithy-jsonschema") include(":smithy-openapi") include(":smithy-utils") include(":smithy-protocol-test-traits") + +pluginManagement { + repositories { + mavenLocal() + gradlePluginPortal() + } +} diff --git a/smithy-aws-protocol-tests/build.gradle.kts b/smithy-aws-protocol-tests/build.gradle.kts new file mode 100644 index 00000000000..1fcc1d00a2c --- /dev/null +++ b/smithy-aws-protocol-tests/build.gradle.kts @@ -0,0 +1,27 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +description = "Defines protocol tests for AWS HTTP protocols." +extra["displayName"] = "Smithy :: AWS :: Protocol Tests" +extra["moduleName"] = "software.amazon.smithy.aws.protocoltests" + +plugins { + id("software.amazon.smithy").version("0.4.2") +} + +dependencies { + api(project(":smithy-protocol-test-traits")) + api(project(":smithy-aws-traits")) +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy b/smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy new file mode 100644 index 00000000000..8c8cbb7a160 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/document-lists.smithy @@ -0,0 +1,255 @@ +// This file defines test cases that serialize lists in XML documents. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This test case serializes XML lists for the following cases for both +/// input and output: +/// +/// 1. Normal XML lists. +/// 2. Normal XML sets. +/// 3. XML lists of lists. +/// 4. XML lists with @xmlName on its members +/// 5. Flattened XML lists. +/// 6. Flattened XML lists with @xmlName. +/// 7. Lists of structures. +@idempotent +@http(uri: "/XmlLists", method: "PUT") +operation XmlLists(XmlListsInputOutput) -> XmlListsInputOutput + +apply XmlLists @httpRequestTests([ + { + id: "XmlLists", + description: "Serializes XML lists", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/XmlLists", + body: """ + + + foo + bar + + + foo + bar + + + 1 + 2 + + + true + false + + + 2014-04-29T18:30:38Z + 2014-04-29T18:30:38Z + + + Foo + 0 + + + + foo + bar + + + baz + qux + + + + foo + bar + + hi + bye + yep + nope + + + 1 + 2 + + + 3 + 4 + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + stringList: ["foo", "bar"], + stringSet: ["foo", "bar"], + integerList: [1, 2], + booleanList: [true, false], + timestampList: [1398796238, 1398796238], + enumList: ["Foo", "0"], + nestedStringList: [["foo", "bar"], ["baz", "qux"]], + renamedListMembers: ["foo", "bar"], + flattenedList: ["hi", "bye"], + flattenedList2: ["yep", "nope"], + structureList: [ + { + a: "1", + b: "2", + }, + { + a: "3", + b: "4", + } + ] + } + } +]) + +apply XmlLists @httpResponseTests([ + { + id: "XmlLists", + description: "Serializes XML lists", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + foo + bar + + + foo + bar + + + 1 + 2 + + + true + false + + + 2014-04-29T18:30:38Z + 2014-04-29T18:30:38Z + + + Foo + 0 + + + + foo + bar + + + baz + qux + + + + foo + bar + + hi + bye + yep + nope + + + 1 + 2 + + + 3 + 4 + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + stringList: ["foo", "bar"], + stringSet: ["foo", "bar"], + integerList: [1, 2], + booleanList: [true, false], + timestampList: [1398796238, 1398796238], + enumList: ["Foo", "0"], + nestedStringList: [["foo", "bar"], ["baz", "qux"]], + renamedListMembers: ["foo", "bar"], + flattenedList: ["hi", "bye"], + flattenedList2: ["yep", "nope"], + structureList: [ + { + a: "1", + b: "2", + }, + { + a: "3", + b: "4", + } + ] + } + } +]) + +structure XmlListsInputOutput { + stringList: StringList, + + stringSet: StringSet, + + integerList: IntegerList, + + booleanList: BooleanList, + + timestampList: TimestampList, + + enumList: FooEnumList, + + nestedStringList: NestedStringList, + + @xmlName("renamed") + renamedListMembers: RenamedListMembers, + + @xmlFlattened + // The xmlname on the targeted list is ignored, and the member name is used. + flattenedList: RenamedListMembers, + + @xmlName("customName") + @xmlFlattened + // the xmlName trait on the targeted list's member is ignored when + // serializing flattened lists in structures. + flattenedList2: RenamedListMembers, + + @xmlName("myStructureList") + structureList: StructureList +} + +list RenamedListMembers { + @xmlName("item") + member: String, +} + +list StructureList { + @xmlName("item") + member: StructureListMember, +} + +structure StructureListMember { + @xmlName("value") + a: String, + + @xmlName("other") + b: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy b/smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy new file mode 100644 index 00000000000..eb395efce8f --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/document-maps.smithy @@ -0,0 +1,356 @@ +// This file defines test cases that serialize maps in XML payloads. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// The example tests basic map serialization. +@http(uri: "/XmlMaps", method: "POST") +operation XmlMaps(XmlMapsInputOutput) -> XmlMapsInputOutput + +apply XmlMaps @httpRequestTests([ + { + id: "XmlMaps", + description: "Serializes XML maps", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlMaps", + body: """ + + + + foo + + there + + + + baz + + bye + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: { + hi: "there" + }, + baz: { + hi: "bye" + } + } + } + } +]) + +apply XmlMaps @httpResponseTests([ + { + id: "XmlMaps", + description: "Serializes XML maps", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + + foo + + there + + + + baz + + bye + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: { + hi: "there" + }, + baz: { + hi: "bye" + } + } + } + } +]) + +structure XmlMapsInputOutput { + myMap: XmlMapsInputOutputMap, +} + +map XmlMapsInputOutputMap { + key: String, + value: GreetingStruct +} + +structure GreetingStruct { + hi: String +} + +// This example tests maps with @xmlName on members. +@http(uri: "/XmlMapsXmlName", method: "POST") +operation XmlMapsXmlName(XmlMapsXmlNameInputOutput) -> XmlMapsXmlNameInputOutput + +apply XmlMapsXmlName @httpRequestTests([ + { + id: "XmlMapsXmlName", + description: "Serializes XML maps that have xmlName on members", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlMapsXmlName", + body: """ + + + + foo + + there + + + + baz + + bye + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: { + hi: "there" + }, + baz: { + hi: "bye" + } + } + } + } +]) + +apply XmlMapsXmlName @httpResponseTests([ + { + id: "XmlMapsXmlName", + description: "Serializes XML lists", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + + foo + + there + + + + baz + + bye + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: { + hi: "there" + }, + baz: { + hi: "bye" + } + } + } + } +]) + +structure XmlMapsXmlNameInputOutput { + myMap: XmlMapsXmlNameInputOutputMap, +} + +map XmlMapsXmlNameInputOutputMap { + @xmlName("Attribute") + key: String, + + @xmlName("Setting") + value: GreetingStruct +} + +/// Flattened maps +@http(uri: "/FlattenedXmlMap", method: "POST") +operation FlattenedXmlMap(FlattenedXmlMapInputOutput) -> FlattenedXmlMapInputOutput + +apply FlattenedXmlMap @httpRequestTests([ + { + id: "FlattenedXmlMap", + description: "Serializes flattened XML maps in requests", + protocol: "aws.rest-xml", + method: "POST", + uri: "/FlattenedXmlMap", + body: """ + + + foo + Foo + + + baz + Baz + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: "Foo", + baz: "Baz" + } + } + } +]) + +apply FlattenedXmlMap @httpResponseTests([ + { + id: "FlattenedXmlMap", + description: "Serializes flattened XML maps in responses", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + foo + Foo + + + baz + Baz + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + foo: "Foo", + baz: "Baz" + } + } + } +]) + +structure FlattenedXmlMapInputOutput { + @xmlFlattened + myMap: FooEnumMap, +} + +/// Flattened maps with @xmlName +@http(uri: "/FlattenedXmlMapWithXmlName", method: "POST") +operation FlattenedXmlMapWithXmlName(FlattenedXmlMapWithXmlNameInputOutput) -> FlattenedXmlMapWithXmlNameInputOutput + +apply FlattenedXmlMapWithXmlName @httpRequestTests([ + { + id: "FlattenedXmlMapWithXmlName", + description: "Serializes flattened XML maps in requests that have xmlName on members", + protocol: "aws.rest-xml", + method: "POST", + uri: "/FlattenedXmlMapWithXmlName", + body: """ + + + a + A + + + b + B + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + a: "A", + b: "B", + } + } + } +]) + +apply FlattenedXmlMapWithXmlName @httpResponseTests([ + { + id: "FlattenedXmlMapWithXmlName", + description: "Serializes flattened XML maps in responses that have xmlName on members", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + a + A + + + b + B + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + myMap: { + a: "A", + b: "B", + } + } + } +]) + +structure FlattenedXmlMapWithXmlNameInputOutput { + @xmlFlattened + @xmlName("KVP") + myMap: FlattenedXmlMapWithXmlNameInputOutputMap, +} + +map FlattenedXmlMapWithXmlNameInputOutputMap { + @xmlName("K") + key: String, + + @xmlName("V") + value: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy b/smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy new file mode 100644 index 00000000000..d7eeb6298c5 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/document-structs.smithy @@ -0,0 +1,645 @@ +// This file defines test cases that serialize synthesized XML documents +// in the payload of HTTP requests and responses. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +// This example serializes simple scalar types in the top level XML document. +// Note that headers are not serialized in the payload. +@idempotent +@http(uri: "/SimpleScalarProperties", method: "PUT") +operation SimpleScalarProperties(SimpleScalarPropertiesInputOutput) -> SimpleScalarPropertiesInputOutput + +apply SimpleScalarProperties @httpRequestTests([ + { + id: "SimpleScalarProperties", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/SimpleScalarProperties", + body: """ + + string + true + false + 1 + 2 + 3 + 4 + 5.5 + 6.5 + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml", + "X-Foo": "Foo", + }, + params: { + foo: "Foo", + stringValue: "string", + trueBooleanValue: true, + falseBooleanValue: false, + byteValue: 1, + shortValue: 2, + integerValue: 3, + longValue: 4, + floatValue: 5.5, + doubleValue: 6.5, + } + } +]) + +apply SimpleScalarProperties @httpResponseTests([ + { + id: "SimpleScalarProperties", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + code: 200, + body: """ + + string + true + false + 1 + 2 + 3 + 4 + 5.5 + 6.5 + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml", + "X-Foo": "Foo", + }, + params: { + foo: "Foo", + stringValue: "string", + trueBooleanValue: true, + falseBooleanValue: false, + byteValue: 1, + shortValue: 2, + integerValue: 3, + longValue: 4, + floatValue: 5.5, + doubleValue: 6.5, + } + } +]) + +structure SimpleScalarPropertiesInputOutput { + @httpHeader("X-Foo") + foo: String, + + stringValue: String, + trueBooleanValue: Boolean, + falseBooleanValue: Boolean, + byteValue: Byte, + shortValue: Short, + integerValue: Integer, + longValue: Long, + floatValue: Float, + + @xmlName("DoubleDribble") + doubleValue: Double, +} + +/// Blobs are base64 encoded +@http(uri: "/XmlBlobs", method: "POST") +operation XmlBlobs(XmlBlobsInputOutput) -> XmlBlobsInputOutput + +apply XmlBlobs @httpRequestTests([ + { + id: "XmlBlobs", + description: "Blobs are base64 encoded", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlBlobs", + body: """ + + dmFsdWU= + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + data: "value" + } + } +]) + +apply XmlBlobs @httpResponseTests([ + { + id: "XmlBlobs", + description: "Blobs are base64 encoded", + protocol: "aws.rest-xml", + code: 200, + body: """ + + dmFsdWU= + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + data: "value" + } + } +]) + +structure XmlBlobsInputOutput { + data: Blob +} + +/// This tests how timestamps are serialized, including using the +/// default format of date-time and various @timestampFormat trait +/// values. +@http(uri: "/XmlTimestamps", method: "POST") +operation XmlTimestamps(XmlTimestampsInputOutput) -> XmlTimestampsInputOutput + +apply XmlTimestamps @httpRequestTests([ + { + id: "XmlTimestamps", + description: "Tests how normal timestamps are serialized", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlTimestamps", + body: """ + + 2014-04-29T18:30:38Z + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + normal: 1398796238 + } + }, + { + id: "XmlTimestampsWithDateTimeFormat", + description: "Ensures that the timestampFormat of date-time works like normal timestamps", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlTimestamps", + body: """ + + 2014-04-29T18:30:38Z + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + dateTime: 1398796238 + } + }, + { + id: "XmlTimestampsWithEpochSecondsFormat", + description: "Ensures that the timestampFormat of epoch-seconds works", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlTimestamps", + body: """ + + 1398796238 + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + epochSeconds: 1398796238 + } + }, + { + id: "XmlTimestampsWithHttpDateFormat", + description: "Ensures that the timestampFormat of http-date works", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlTimestamps", + body: """ + + Tue, 29 Apr 2014 18:30:38 GMT + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + httpDate: 1398796238 + } + }, +]) + +apply XmlTimestamps @httpResponseTests([ + { + id: "XmlTimestamps", + description: "Tests how normal timestamps are serialized", + protocol: "aws.rest-xml", + code: 200, + body: """ + + 2014-04-29T18:30:38Z + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + normal: 1398796238 + } + }, + { + id: "XmlTimestampsWithDateTimeFormat", + description: "Ensures that the timestampFormat of date-time works like normal timestamps", + protocol: "aws.rest-xml", + code: 200, + body: """ + + 2014-04-29T18:30:38Z + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + dateTime: 1398796238 + } + }, + { + id: "XmlTimestampsWithEpochSecondsFormat", + description: "Ensures that the timestampFormat of epoch-seconds works", + protocol: "aws.rest-xml", + code: 200, + body: """ + + 1398796238 + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + epochSeconds: 1398796238 + } + }, + { + id: "XmlTimestampsWithHttpDateFormat", + description: "Ensures that the timestampFormat of http-date works", + protocol: "aws.rest-xml", + code: 200, + body: """ + + Tue, 29 Apr 2014 18:30:38 GMT + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + httpDate: 1398796238 + } + }, +]) + +structure XmlTimestampsInputOutput { + normal: Timestamp, + + @timestampFormat("date-time") + dateTime: Timestamp, + + @timestampFormat("epoch-seconds") + epochSeconds: Timestamp, + + @timestampFormat("http-date") + httpDate: Timestamp, +} + +/// This example serializes enums as top level properties, in lists, sets, and maps. +@idempotent +@http(uri: "/XmlEnums", method: "PUT") +operation XmlEnums(XmlEnumsInputOutput) -> XmlEnumsInputOutput + +apply XmlEnums @httpRequestTests([ + { + id: "XmlEnums", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/XmlEnums", + body: """ + + Foo + 0 + 1 + + Foo + 0 + + + Foo + 0 + + + + hi + Foo + + + zero + 0 + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + fooEnum1: "Foo", + fooEnum2: "0", + fooEnum3: "1", + fooEnumList: ["Foo", "0"], + fooEnumSet: ["Foo", "0"], + fooEnumMap: { + "hi": "Foo", + "zero": "0" + } + } + } +]) + +apply XmlEnums @httpResponseTests([ + { + id: "XmlEnums", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + code: 200, + body: """ + + Foo + 0 + 1 + + Foo + 0 + + + Foo + 0 + + + + hi + Foo + + + zero + 0 + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + fooEnum1: "Foo", + fooEnum2: "0", + fooEnum3: "1", + fooEnumList: ["Foo", "0"], + fooEnumSet: ["Foo", "0"], + fooEnumMap: { + "hi": "Foo", + "zero": "0" + } + } + } +]) + +structure XmlEnumsInputOutput { + fooEnum1: FooEnum, + fooEnum2: FooEnum, + fooEnum3: FooEnum, + fooEnumList: FooEnumList, + fooEnumSet: FooEnumSet, + fooEnumMap: FooEnumMap, +} + +/// Recursive shapes +@idempotent +@http(uri: "/RecursiveShapes", method: "PUT") +operation RecursiveShapes(RecursiveShapesInputOutput) -> RecursiveShapesInputOutput + +apply RecursiveShapes @httpRequestTests([ + { + id: "RecursiveShapes", + description: "Serializes recursive structures", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/XmlEnums", + body: """ + + + Foo1 + + Bar1 + + Foo2 + + Bar2 + + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + foo: "Foo1", + nested: { + bar: "Bar1", + recursiveMember: { + foo: "Foo2", + nested: { + bar: "Bar2" + } + } + } + } + } + } +]) + +apply RecursiveShapes @httpResponseTests([ + { + id: "RecursiveShapes", + description: "Serializes recursive structures", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + Foo1 + + Bar1 + + Foo2 + + Bar2 + + + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + foo: "Foo1", + nested: { + bar: "Bar1", + recursiveMember: { + foo: "Foo2", + nested: { + bar: "Bar2" + } + } + } + } + } + } +]) + +structure RecursiveShapesInputOutput { + nested: RecursiveShapesInputOutputNested1 +} + +structure RecursiveShapesInputOutputNested1 { + foo: String, + nested: RecursiveShapesInputOutputNested2 +} + +structure RecursiveShapesInputOutputNested2 { + bar: String, + recursiveMember: RecursiveShapesInputOutputNested1, +} + +// XML namespace +@http(uri: "/XmlNamespaces", method: "POST") +operation XmlNamespaces(XmlNamespacesInputOutput) -> XmlNamespacesInputOutput + +apply XmlNamespaces @httpRequestTests([ + { + id: "XmlNamespaces", + description: "Serializes XML namespaces", + protocol: "aws.rest-xml", + method: "POST", + uri: "/XmlNamespaces", + body: """ + + + Foo + + Bar + Baz + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + foo: "Foo", + values: [ + "Bar", + "Baz" + ] + } + } + } +]) + +apply XmlNamespaces @httpResponseTests([ + { + id: "XmlNamespaces", + description: "Serializes XML namespaces", + protocol: "aws.rest-xml", + code: 200, + body: """ + + + Foo + + Bar + Baz + + + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + foo: "Foo", + values: [ + "Bar", + "Baz" + ] + } + } + } +]) + +@xmlNamespace(uri: "http://foo.com") +structure XmlNamespacesInputOutput { + nested: XmlNamespaceNested +} + +// Ingored since it's not at the top-level +@xmlNamespace(uri: "http://foo.com") +structure XmlNamespaceNested { + @xmlNamespace(uri: "http://baz.com", prefix: "baz") + foo: String, + + @xmlNamespace(uri: "http://qux.com") + values: XmlNamespacedList +} + +list XmlNamespacedList { + @xmlNamespace(uri: "http://bux.com") + member: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy b/smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy new file mode 100644 index 00000000000..b73816902d6 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/document-xml-attributes.smithy @@ -0,0 +1,125 @@ +// This file defines test cases that serialize XML attributes. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This example serializes an XML attributes on synthesized document. +@idempotent +@http(uri: "/XmlAttributes", method: "PUT") +operation XmlAttributes(XmlAttributesInputOutput) -> XmlAttributesInputOutput + +apply XmlAttributes @httpRequestTests([ + { + id: "XmlAttributes", + description: "Serializes XML attributes on the synthesized document", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/XmlAttributes", + body: """ + + hi + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + foo: "hi", + attr: "test" + } + } +]) + +apply XmlAttributes @httpResponseTests([ + { + id: "XmlAttributes", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + code: 200, + body: """ + + hi + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + foo: "hi", + attr: "test" + } + } +]) + +structure XmlAttributesInputOutput { + foo: String, + + @xmlAttribute + @xmlName("test") + attr: String, +} + +/// This example serializes an XML attributes on a document targeted by httpPayload. +@idempotent +@http(uri: "/XmlAttributesOnPayload", method: "PUT") +operation XmlAttributesOnPayload(XmlAttributesOnPayloadInputOutput) -> XmlAttributesOnPayloadInputOutput + +apply XmlAttributesOnPayload @httpRequestTests([ + { + id: "XmlAttributesOnPayload", + description: "Serializes XML attributes on the synthesized document", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/XmlAttributesOnPayload", + body: """ + + hi + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + payload: { + foo: "hi", + attr: "test" + } + } + } +]) + +apply XmlAttributesOnPayload @httpResponseTests([ + { + id: "XmlAttributesOnPayload", + description: "Serializes simple scalar properties", + protocol: "aws.rest-xml", + code: 200, + body: """ + + hi + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + payload: { + foo: "hi", + attr: "test" + } + } + } +]) + +structure XmlAttributesOnPayloadInputOutput { + @httpPayload + payload: XmlAttributesInputOutput +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy b/smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy new file mode 100644 index 00000000000..0d1f6bf32cf --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/empty-input-output.smithy @@ -0,0 +1,97 @@ +// This file defines test cases that test the basics of empty input and +// output shape serialization. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// The example tests how requests and responses are serialized when there's +/// no request or response payload because the operation has no input or output. +/// While this should be rare, code generators must support this. +@http(uri: "/NoInputAndNoOutput", method: "POST") +operation NoInputAndNoOutput() + +apply NoInputAndNoOutput @httpRequestTests([ + { + id: "NoInputAndNoOutput", + description: "No input serializes no payload", + protocol: "aws.rest-xml", + method: "POST", + uri: "/NoInputAndOutput", + body: "" + } +]) + +apply NoInputAndNoOutput @httpResponseTests([ + { + id: "NoInputAndNoOutput", + description: "No output serializes no payload", + protocol: "aws.rest-xml", + code: 200, + body: "" + } +]) + +/// The example tests how requests and responses are serialized when there's +/// no request or response payload because the operation has no input and the +/// output is empty. While this should be rare, code generators must support +/// this. +@http(uri: "/NoInputAndOutputOutput", method: "POST") +operation NoInputAndOutput() -> NoInputAndOutputOutput + +apply NoInputAndOutput @httpRequestTests([ + { + id: "NoInputAndOutput", + description: "No input serializes no payload", + protocol: "aws.rest-xml", + method: "POST", + uri: "/NoInputAndOutput", + body: "" + } +]) + +apply NoInputAndOutput @httpResponseTests([ + { + id: "NoInputAndOutput", + description: "Empty output serializes no payload", + protocol: "aws.rest-xml", + code: 200, + body: "" + } +]) + +structure NoInputAndOutputOutput {} + +/// The example tests how requests and responses are serialized when there's +/// no request or response payload because the operation has an empty input +/// and empty output structure that reuses the same shape. While this should +/// be rare, code generators must support this. +@http(uri: "/EmptyInputAndEmptyOutput", method: "POST") +operation EmptyInputAndEmptyOutput(EmptyInputAndEmptyOutputInput) -> EmptyInputAndEmptyOutputOutput + +apply EmptyInputAndEmptyOutput @httpRequestTests([ + { + id: "EmptyInputAndEmptyOutput", + description: "Empty input serializes no payload", + protocol: "aws.rest-xml", + method: "POST", + uri: "/EmptyInputAndEmptyOutput", + body: "" + }, +]) + +apply EmptyInputAndEmptyOutput @httpResponseTests([ + { + id: "EmptyInputAndEmptyOutput", + description: "Empty output serializes no payload", + protocol: "aws.rest-xml", + code: 200, + body: "" + }, +]) + +structure EmptyInputAndEmptyOutputInput {} +structure EmptyInputAndEmptyOutputOutput {} diff --git a/smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy b/smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy new file mode 100644 index 00000000000..bce723721f6 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/endpoint-host-trait.smithy @@ -0,0 +1,11 @@ +// This file defines test cases that change the endpoint based on the endpoint trait. +// See: https://awslabs.github.io/smithy/spec/core.html#endpoint-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +// TODO: Write endpoint tests diff --git a/smithy-aws-protocol-tests/model/rest-xml/errors.smithy b/smithy-aws-protocol-tests/model/rest-xml/errors.smithy new file mode 100644 index 00000000000..5b3a92926a5 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/errors.smithy @@ -0,0 +1,127 @@ +// This file defines test cases that test error serialization. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This operation has three possible return values: +/// +/// 1. A successful response in the form of GreetingWithErrorsOutput +/// 2. An InvalidGreeting error. +/// 3. A BadRequest error. +/// +/// Implementations must be able to successfully take a response and +/// properly (de)serialize successful and error responses based on the +/// the presence of the +@idempotent +@http(uri: "/GreetingWithErrors", method: "PUT") +operation GreetingWithErrors() -> GreetingWithErrorsOutput errors [InvalidGreeting, ComplexError] + +apply GreetingWithErrors @httpResponseTests([ + { + id: "GreetingWithErrors", + description: "Ensures that operations with errors successfully know how to deserialize the successful response", + protocol: "aws.rest-xml", + code: 200, + body: "", + headers: { + "X-Greeting": "Hello" + }, + params: { + greeting: "Hello" + } + } +]) + +structure GreetingWithErrorsOutput { + @httpHeader("X-Greeting") + greeting: String, +} + +/// This error is thrown when an invalid greeting value is provided. +@error("client") +@httpError(400) +structure InvalidGreeting { + Message: String, +} + +apply InvalidGreeting @httpResponseTests([ + { + id: "InvalidGreetingError", + description: "Parses simple XML errors", + protocol: "aws.rest-xml", + params: { + Message: "Hi" + }, + code: 400, + headers: { + "Content-Type": "application/xml" + }, + body: """ + + + Sender + InvalidGreeting + Hi + setting + + foo-id + + """, + bodyMediaType: "application/xml", + } +]) + +/// This error is thrown when a request is invalid. +@error("client") +@httpError(403) +structure ComplexError { + // Errors support HTTP bindings! + @httpHeader("X-Header") + Header: String, + + TopLevel: String, + + Nested: ComplexNestedErrorData, +} + +apply ComplexError @httpResponseTests([ + { + id: "ComplexError", + protocol: "aws.rest-xml", + params: { + Header: "Header", + TopLevel: "Top level", + Nested: { + Foo: "bar" + } + }, + code: 400, + headers: { + "Content-Type": "application/xml", + "X-Header": "Header", + }, + body: """ + + + Sender + ComplexError + Hi + Top level + + bar + + + foo-id + + """, + bodyMediaType: "application/xml", + } +]) + +structure ComplexNestedErrorData { + Foo: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy b/smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy new file mode 100644 index 00000000000..23f5e6921c6 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/http-headers.smithy @@ -0,0 +1,385 @@ +// This file defines test cases that test HTTP header bindings. +// See: https://awslabs.github.io/smithy/spec/http.html#httpheader-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// The example tests how requests and responses are serialized when there is +/// no input or output payload but there are HTTP header bindings. +@http(uri: "/InputAndOutputWithHeaders", method: "POST") +operation InputAndOutputWithHeaders(InputAndOutputWithHeadersIO) -> InputAndOutputWithHeadersIO + +apply InputAndOutputWithHeaders @httpRequestTests([ + { + id: "InputAndOutputWithStringHeaders", + description: "Tests requests with string header bindings", + protocol: "aws.rest-xml", + method: "POST", + uri: "/InputAndOutputWithHeaders", + headers: { + "X-String": "Hello", + "X-StringList": "a, b, c", + "X-StringSet": "a, b, c" + }, + body: "", + params: { + headerString: "Hello", + headerStringList: ["a", "b", "c"], + headerStringSet: ["a", "b", "c"], + } + }, + { + id: "InputAndOutputWithNumericHeaders", + description: "Tests requests with numeric header bindings", + protocol: "aws.rest-xml", + method: "POST", + uri: "/InputAndOutputWithHeaders", + headers: { + "X-Byte": "1", + "X-Short": "123", + "X-Integer": "123", + "X-Long": "123", + "X-Float": "1.0", + "X-Double": "1.0", + "X-HeaderIntegerList": "1, 2, 3", + }, + body: "", + params: { + headerByte: 1, + headerShort: 123, + headerInteger: 123, + headerLong: 123, + headerFloat: 1.0, + headerDouble: 1.0, + headerIntegerList: [1, 2, 3], + } + }, + { + id: "InputAndOutputWithBooleanHeaders", + description: "Tests requests with boolean header bindings", + protocol: "aws.rest-xml", + method: "POST", + uri: "/InputAndOutputWithHeaders", + headers: { + "X-Boolean1": "true", + "X-Boolean2": "false", + "X-HeaderBooleanList": "true, false, true" + }, + body: "", + params: { + headerTrueBool: true, + headerFalseBool: true, + headerBooleanList: [true, false, true] + } + }, + { + id: "InputAndOutputWithTimestampHeaders", + description: "Tests requests with timestamp header bindings", + protocol: "aws.rest-xml", + method: "POST", + uri: "/InputAndOutputWithHeaders", + headers: { + "X-HeaderTimestampList": "Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT" + }, + body: "", + params: { + headerTimestampList: [1576540098, 1576540098] + } + }, + { + id: "InputAndOutputWithEnumHeaders", + description: "Tests requests with enum header bindings", + protocol: "aws.rest-xml", + method: "POST", + uri: "/InputAndOutputWithHeaders", + headers: { + "X-Enum": "Foo", + "X-EnumList": "Foo, Baz, Bar" + }, + body: "", + params: { + headerEnum: "Foo", + headerEnumList: ["Foo", "Bar", "Baz"], + } + }, +]) + +apply InputAndOutputWithHeaders @httpResponseTests([ + { + id: "InputAndOutputWithStringHeaders", + description: "Tests responses with string header bindings", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-String": "Hello", + "X-StringList": "a, b, c", + "X-StringSet": "a, b, c" + }, + body: "", + params: { + headerString: "Hello", + headerStringList: ["a", "b", "c"], + headerStringSet: ["a", "b", "c"], + } + }, + { + id: "InputAndOutputWithNumericHeaders", + description: "Tests responses with numeric header bindings", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-Byte": "1", + "X-Short": "123", + "X-Integer": "123", + "X-Long": "123", + "X-Float": "1.0", + "X-Double": "1.0", + "X-HeaderIntegerList": "1, 2, 3", + }, + body: "", + params: { + headerByte: 1, + headerShort: 123, + headerInteger: 123, + headerLong: 123, + headerFloat: 1.0, + headerDouble: 1.0, + headerIntegerList: [1, 2, 3], + } + }, + { + id: "InputAndOutputWithBooleanHeaders", + description: "Tests responses with boolean header bindings", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-Boolean1": "true", + "X-Boolean2": "false", + "X-HeaderBooleanList": "true, false, true" + }, + body: "", + params: { + headerTrueBool: true, + headerFalseBool: true, + headerBooleanList: [true, false, true] + } + }, + { + id: "InputAndOutputWithTimestampHeaders", + description: "Tests responses with timestamp header bindings", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-HeaderTimestampList": "Mon, 16 Dec 2019 23:48:18 GMT, Mon, 16 Dec 2019 23:48:18 GMT" + }, + body: "", + params: { + headerTimestampList: [1576540098, 1576540098] + } + }, + { + id: "InputAndOutputWithEnumHeaders", + description: "Tests responses with enum header bindings", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-Enum": "Foo", + "X-EnumList": "Foo, Baz, Bar" + }, + body: "", + params: { + headerEnum: "Foo", + headerEnumList: ["Foo", "Bar", "Baz"], + } + }, +]) + +structure InputAndOutputWithHeadersIO { + @httpHeader("X-String") + headerString: String, + + @httpHeader("X-Byte") + headerByte: Byte, + + @httpHeader("X-Short") + headerShort: Short, + + @httpHeader("X-Integer") + headerInteger: Integer, + + @httpHeader("X-Long") + headerLong: Long, + + @httpHeader("X-Float") + headerFloat: Float, + + @httpHeader("X-Double") + headerDouble: Double, + + @httpHeader("X-Boolean1") + headerTrueBool: Boolean, + + @httpHeader("X-Boolean2") + headerFalseBool: Boolean, + + @httpHeader("X-StringList") + headerStringList: StringList, + + @httpHeader("X-StringSet") + headerStringSet: StringSet, + + @httpHeader("X-IntegerList") + headerIntegerList: IntegerList, + + @httpHeader("X-BooleanList") + headerBooleanList: BooleanList, + + @httpHeader("X-TimestampList") + headerTimestampList: TimestampList, + + @httpHeader("X-Enum") + headerEnum: FooEnum, + + @httpHeader("X-EnumList") + headerEnumList: FooEnumList, +} + +/// Null and empty headers are not sent over the wire. +@readonly +@http(uri: "/NullAndEmptyHeaders", method: "GET") +operation NullAndEmptyHeaders(NullAndEmptyHeadersIO) -> NullAndEmptyHeadersIO + +apply NullAndEmptyHeaders @httpRequestTests([ + { + id: "NullAndEmptyHeaders", + description: "Do not send null values, empty strings, or empty lists over the wire in headers", + protocol: "aws.rest-xml", + method: "GET", + uri: "/NullAndEmptyHeaders", + forbidHeaders: ["X-A", "X-B", "X-C"], + body: "", + params: { + a: null, + b: "", + c: [], + } + }, +]) + +apply NullAndEmptyHeaders @httpResponseTests([ + { + id: "NullAndEmptyHeaders", + description: "Do not send null or empty headers", + protocol: "aws.rest-xml", + code: 200, + forbidHeaders: ["X-A", "X-B", "X-C"], + body: "", + params: { + a: null, + b: "", + c: [], + } + }, +]) + +structure NullAndEmptyHeadersIO { + @httpHeader("X-A") + a: String, + + @httpHeader("X-B") + b: String, + + @httpHeader("X-C") + c: StringList, +} + +/// The example tests how timestamp request and response headers are serialized. +@http(uri: "/TimestampFormatHeaders", method: "POST") +operation TimestampFormatHeaders(TimestampFormatHeadersIO) -> TimestampFormatHeadersIO + +apply TimestampFormatHeaders @httpRequestTests([ + { + id: "TimestampFormatHeaders", + description: "Tests how timestamp request headers are serialized", + protocol: "aws.rest-xml", + method: "POST", + uri: "/TimestampFormatHeaders", + headers: { + "X-memberEpochSeconds": "1576540098", + "X-memberHttpDate": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-memberDateTime": "2019-12-16T23:48:18Z", + "X-defaultFormat": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-targetEpochSeconds": "1576540098", + "X-targetHttpDate": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-targetDateTime": "2019-12-16T23:48:18Z", + }, + body: "", + params: { + memberEpochSeconds: 1576540098, + memberHttpDate: 1576540098, + memberDateTime: 1576540098, + defaultFormat: 1576540098, + targetEpochSeconds: 1576540098, + targetHttpDate: 1576540098, + targetDateTime: 1576540098, + } + }, +]) + +apply TimestampFormatHeaders @httpResponseTests([ + { + id: "TimestampFormatHeaders", + description: "Tests how timestamp response headers are serialized", + protocol: "aws.rest-xml", + code: 200, + headers: { + "X-memberEpochSeconds": "1576540098", + "X-memberHttpDate": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-memberDateTime": "2019-12-16T23:48:18Z", + "X-defaultFormat": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-targetEpochSeconds": "1576540098", + "X-targetHttpDate": "Mon, 16 Dec 2019 23:48:18 GMT", + "X-targetDateTime": "2019-12-16T23:48:18Z", + }, + body: "", + params: { + memberEpochSeconds: 1576540098, + memberHttpDate: 1576540098, + memberDateTime: 1576540098, + defaultFormat: 1576540098, + targetEpochSeconds: 1576540098, + targetHttpDate: 1576540098, + targetDateTime: 1576540098, + } + }, +]) + +structure TimestampFormatHeadersIO { + @httpHeader("X-memberEpochSeconds") + @timestampFormat("epoch-seconds") + memberEpochSeconds: Timestamp, + + @httpHeader("X-memberHttpDate") + @timestampFormat("http-date") + memberHttpDate: Timestamp, + + @httpHeader("X-memberDateTime") + @timestampFormat("date-time") + memberDateTime: Timestamp, + + @httpHeader("X-defaultFormat") + defaultFormat: Timestamp, + + @httpHeader("X-targetEpochSeconds") + targetEpochSeconds: EpochSeconds, + + @httpHeader("X-targetHttpDate") + targetHttpDate: HttpDate, + + @httpHeader("X-targetDateTime") + targetDateTime: HttpDate, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy b/smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy new file mode 100644 index 00000000000..352b0ac8358 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/http-labels.smithy @@ -0,0 +1,169 @@ +// This file defines test cases that test HTTP URI label bindings. +// See: https://awslabs.github.io/smithy/spec/http.html#httplabel-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// The example tests how requests are serialized when there's no input +/// payload but there are HTTP labels. +@readonly +@http(method: "GET", uri: "/HttpRequestWithLabels/{string}/{short}/{integer}/{long}/{float}/{double}/{boolean}/{timestamp}") +operation HttpRequestWithLabels(HttpRequestWithLabelsInput) + +apply HttpRequestWithLabels @httpRequestTests([ + { + id: "InputWithHeadersAndAllParams", + description: "Sends a GET request that uses URI label bindings", + protocol: "aws.rest-xml", + method: "GET", + uri: "/HttpRequestWithLabels/string/1/2/3/4.0/5.0/true/2019-12-16T23%3A48%3A18Z", + body: "", + params: { + string: "string", + short: 1, + integer: 2, + long: 3, + float: 4.0, + double: 5.0, + boolean: true, + timestamp: 1576540098 + } + }, +]) + +structure HttpRequestWithLabelsInput { + @httpLabel + @required + string: String, + + @httpLabel + @required + short: Short, + + @httpLabel + @required + integer: Integer, + + @httpLabel + @required + long: Long, + + @httpLabel + @required + float: Float, + + @httpLabel + @required + double: Double, + + /// Serialized in the path as true or false. + @httpLabel + @required + boolean: Boolean, + + /// Note that this member has no format, so it's serialized as an RFC 3399 date-time. + @httpLabel + @required + timestamp: Timestamp, +} + +/// The example tests how requests serialize different timestamp formats in the +/// URI path. +@readonly +@http(method: "GET", uri: "/HttpRequestWithLabelsAndTimestampFormat/{memberEpochSeconds}/{memberHttpDate}/{memberDateTime}/{defaultFormat}/{targetEpochSeconds}/{targetHttpDate}/{targetDateTime}") +operation HttpRequestWithLabelsAndTimestampFormat(HttpRequestWithLabelsAndTimestampFormatInput) + +apply HttpRequestWithLabelsAndTimestampFormat @httpRequestTests([ + { + id: "HttpRequestWithLabelsAndTimestampFormat", + description: "Serializes different timestamp formats in URI labels", + protocol: "aws.rest-xml", + method: "GET", + uri: """ + /HttpRequestWithLabelsAndTimestampFormat\ + /1576540098\ + /Mon%2C+16+Dec+2019+23%3A48%3A18+GMT\ + /2019-12-16T23%3A48%3A18Z\ + /2019-12-16T23%3A48%3A18Z\ + /1576540098\ + /Mon%2C+16+Dec+2019+23%3A48%3A18+GMT\ + /2019-12-16T23%3A48%3A18Z""", + body: "", + params: { + memberEpochSeconds: 1576540098, + memberHttpDate: 1576540098, + memberDateTime: 1576540098, + defaultFormat: 1576540098, + targetEpochSeconds: 1576540098, + targetHttpDate: 1576540098, + targetDateTime: 1576540098, + } + }, +]) + +structure HttpRequestWithLabelsAndTimestampFormatInput { + @httpLabel + @required + @timestampFormat("epoch-seconds") + memberEpochSeconds: Timestamp, + + @httpLabel + @required + @timestampFormat("http-date") + memberHttpDate: Timestamp, + + @httpLabel + @required + @timestampFormat("date-time") + memberDateTime: Timestamp, + + @httpLabel + @required + defaultFormat: Timestamp, + + @httpLabel + @required + targetEpochSeconds: EpochSeconds, + + @httpLabel + @required + targetHttpDate: HttpDate, + + @httpLabel + @required + targetDateTime: HttpDate, +} + +// This example uses a greedy label and a normal label. +@readonly +@http(method: "GET", uri: "/HttpRequestWithGreedyLabelInPath/foo/{foo}/baz/{baz+}") +operation HttpRequestWithGreedyLabelInPath(HttpRequestWithGreedyLabelInPathInput) + +apply HttpRequestWithGreedyLabelInPath @httpRequestTests([ + { + id: "HttpRequestWithGreedyLabelInPath", + description: "Serializes greedy labels and normal labels", + protocol: "aws.rest-xml", + method: "GET", + uri: "/HttpRequestWithGreedyLabelInPath/foo/hello/baz/there/guy", + body: "", + params: { + foo: "hello", + baz: "there/guy", + } + }, +]) + +structure HttpRequestWithGreedyLabelInPathInput { + @httpLabel + @required + foo: String, + + @httpLabel + @required + baz: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy b/smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy new file mode 100644 index 00000000000..15e82c25942 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/http-payload.smithy @@ -0,0 +1,381 @@ +// This file defines test cases that test HTTP payload bindings. +// See: https://awslabs.github.io/smithy/spec/http.html#httppayload-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This examples serializes a blob shape in the payload. +/// +/// In this example, no XML document is synthesized because the payload is +/// not a structure or a union type. +@http(uri: "/HttpPayloadTraits", method: "POST") +operation HttpPayloadTraits(HttpPayloadTraitsInputOutput) -> HttpPayloadTraitsInputOutput + +apply HttpPayloadTraits @httpRequestTests([ + { + id: "HttpPayloadTraitsWithBlob", + description: "Serializes a blob in the HTTP payload", + protocol: "aws.rest-xml", + method: "POST", + uri: "/HttpPayloadTraits", + body: "blobby blob blob", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo", + blob: "blobby blob blob" + } + }, + { + id: "HttpPayloadTraitsWithNoBlobBody", + description: "Serializes an empty blob in the HTTP payload", + protocol: "aws.rest-xml", + method: "POST", + uri: "/HttpPayloadTraits", + body: "", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo" + } + }, +]) + +apply HttpPayloadTraits @httpResponseTests([ + { + id: "HttpPayloadTraitsWithBlob", + description: "Serializes a blob in the HTTP payload", + protocol: "aws.rest-xml", + code: 200, + body: "blobby blob blob", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo", + blob: "blobby blob blob" + } + }, + { + id: "HttpPayloadTraitsWithNoBlobBody", + description: "Serializes an empty blob in the HTTP payload", + protocol: "aws.rest-xml", + code: 200, + body: "", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo" + } + } +]) + +structure HttpPayloadTraitsInputOutput { + @httpHeader("X-Foo") + foo: String, + + @httpPayload + blob: Blob, +} + +/// This examples uses a `@mediaType` trait on the payload to force a custom +/// content-type to be serialized. +@http(uri: "/HttpPayloadTraitsWithMediaType", method: "POST") +operation HttpPayloadTraitsWithMediaType(HttpPayloadTraitsWithMediaTypeInputOutput) -> HttpPayloadTraitsWithMediaTypeInputOutput + +apply HttpPayloadTraitsWithMediaType @httpRequestTests([ + { + id: "HttpPayloadTraitsWithMediaTypeWithBlob", + description: "Serializes a blob in the HTTP payload with a content-type", + protocol: "aws.rest-xml", + method: "POST", + uri: "/HttpPayloadTraitsWithMediaType", + body: "blobby blob blob", + headers: { + "X-Foo": "Foo", + "Content-Type": "text/plain" + }, + params: { + foo: "Foo", + blob: "blobby blob blob" + } + } +]) + +apply HttpPayloadTraitsWithMediaType @httpResponseTests([ + { + id: "HttpPayloadTraitsWithMediaTypeWithBlob", + description: "Serializes a blob in the HTTP payload with a content-type", + protocol: "aws.rest-xml", + code: 200, + body: "blobby blob blob", + headers: { + "X-Foo": "Foo", + "Content-Type": "text/plain" + }, + params: { + foo: "Foo", + blob: "blobby blob blob" + } + } +]) + +structure HttpPayloadTraitsWithMediaTypeInputOutput { + @httpHeader("X-Foo") + foo: String, + + @httpPayload + blob: TextPlainBlob, +} + +/// This examples serializes a structure in the payload. +/// +/// Note that serializing a structure changes the wrapper element name +/// to match the targeted structure. +@idempotent +@http(uri: "/HttpPayloadWithStructure", method: "PUT") +operation HttpPayloadWithStructure(HttpPayloadWithStructureInputOutput) -> HttpPayloadWithStructureInputOutput + +apply HttpPayloadWithStructure @httpRequestTests([ + { + id: "HttpPayloadWithStructure", + description: "Serializes a structure in the payload", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/HttpPayloadWithStructure", + body: """ + + hello + Phreddy + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + greeting: "hello", + name: "Phreddy" + } + } + } +]) + +apply HttpPayloadWithStructure @httpResponseTests([ + { + id: "HttpPayloadWithStructure", + description: "Serializes a structure in the payload", + protocol: "aws.rest-xml", + code: 200, + body: """ + + hello + Phreddy + + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + greeting: "hello", + name: "Phreddy" + } + } + } +]) + +structure HttpPayloadWithStructureInputOutput { + @httpPayload + nested: NestedPayload, +} + +structure NestedPayload { + greeting: String, + name: String, +} + +/// The following example serializes a payload that uses an XML name, +/// changing the wrapper name. +@idempotent +@http(uri: "/HttpPayloadWithXmlName", method: "PUT") +operation HttpPayloadWithXmlName(HttpPayloadWithXmlNameInputOutput) -> HttpPayloadWithXmlNameInputOutput + +apply HttpPayloadWithXmlName @httpRequestTests([ + { + id: "HttpPayloadWithXmlName", + description: "Serializes a structure in the payload using a wrapper name based on xmlName", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/HttpPayloadWithStructure", + body: "Phreddy", + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +apply HttpPayloadWithXmlName @httpResponseTests([ + { + id: "HttpPayloadWithXmlName", + description: "Serializes a structure in the payload using a wrapper name based on xmlName", + protocol: "aws.rest-xml", + code: 200, + body: "Phreddy", + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +structure HttpPayloadWithXmlNameInputOutput { + @httpPayload + nested: PayloadWithXmlName, +} + +@xmlName("Hello") +structure PayloadWithXmlName { + name: String +} + +/// The following example serializes a payload that uses an XML namespace. +@idempotent +@http(uri: "/HttpPayloadWithXmlNamespace", method: "PUT") +operation HttpPayloadWithXmlNamespace(HttpPayloadWithXmlNamespaceInputOutput) -> HttpPayloadWithXmlNamespaceInputOutput + +apply HttpPayloadWithXmlNamespace @httpRequestTests([ + { + id: "HttpPayloadWithXmlNamespace", + description: "Serializes a structure in the payload using a wrapper with an XML namespace", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/HttpPayloadWithXmlNamespace", + body: """ + + Phreddy + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +apply HttpPayloadWithXmlNamespace @httpResponseTests([ + { + id: "HttpPayloadWithXmlNamespace", + description: "Serializes a structure in the payload using a wrapper with an XML namespace", + protocol: "aws.rest-xml", + code: 200, + body: """ + + Phreddy + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +structure HttpPayloadWithXmlNamespaceInputOutput { + @httpPayload + nested: PayloadWithXmlNamespace, +} + +@xmlNamespace(uri: "http://foo.com") +structure PayloadWithXmlNamespace { + name: String +} + +/// The following example serializes a payload that uses an XML namespace. +@idempotent +@http(uri: "/HttpPayloadWithXmlNamespaceAndPrefix", method: "PUT") +operation HttpPayloadWithXmlNamespaceAndPrefix(HttpPayloadWithXmlNamespaceAndPrefixInputOutput) + -> HttpPayloadWithXmlNamespaceAndPrefixInputOutput + +apply HttpPayloadWithXmlNamespaceAndPrefix @httpRequestTests([ + { + id: "HttpPayloadWithXmlNamespaceAndPrefix", + description: "Serializes a structure in the payload using a wrapper with an XML namespace", + protocol: "aws.rest-xml", + method: "PUT", + uri: "/HttpPayloadWithXmlNamespaceAndPrefix", + body: """ + + Phreddy + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +apply HttpPayloadWithXmlNamespaceAndPrefix @httpResponseTests([ + { + id: "HttpPayloadWithXmlNamespaceAndPrefix", + description: "Serializes a structure in the payload using a wrapper with an XML namespace", + protocol: "aws.rest-xml", + code: 200, + body: """ + + Phreddy + """, + bodyMediaType: "application/xml", + headers: { + "Content-Type": "application/xml" + }, + params: { + nested: { + name: "Phreddy" + } + } + } +]) + +structure HttpPayloadWithXmlNamespaceAndPrefixInputOutput { + @httpPayload + nested: PayloadWithXmlNamespaceAndPrefix, +} + +@xmlNamespace(uri: "http://foo.com", prefix: "baz") +structure PayloadWithXmlNamespaceAndPrefix { + name: String +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy b/smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy new file mode 100644 index 00000000000..c8a05347958 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/http-prefix-headers.smithy @@ -0,0 +1,102 @@ +// This file defines test cases that test httpPrefix headers. +// See: https://awslabs.github.io/smithy/spec/http.html#httpprefixheaders-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This examples adds headers to the input of a request and response by prefix. +@readonly +@http(uri: "/HttpPrefixHeaders", method: "GET") +@externalDocumentation("https://awslabs.github.io/smithy/spec/http.html#httpprefixheaders-trait") +operation HttpPrefixHeaders(HttpPrefixHeadersInputOutput) -> HttpPrefixHeadersInputOutput + +apply HttpPrefixHeaders @httpRequestTests([ + { + id: "HttpPrefixHeadersArePresent", + description: "Adds headers by prefix", + protocol: "aws.rest-xml", + method: "GET", + uri: "/HttpPrefixHeaders", + body: "", + headers: { + "X-Foo": "Foo", + "X-Foo-Abc": "Abc value", + "X-Foo-Def": "Def value", + }, + params: { + foo: "Foo", + fooMap: { + Abc: "Abc value", + Def: "Def value", + } + } + }, + { + id: "HttpPrefixHeadersAreNotPresent", + description: "No prefix headers are serialized because the value is empty", + protocol: "aws.rest-xml", + method: "GET", + uri: "/HttpPrefixHeaders", + body: "", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo", + fooMap: {} + } + }, +]) + +apply HttpPrefixHeaders @httpResponseTests([ + { + id: "HttpPrefixHeadersArePresent", + description: "Adds headers by prefix", + protocol: "aws.rest-xml", + code: 200, + body: "", + headers: { + "X-Foo": "Foo", + "X-Foo-Abc": "Abc value", + "X-Foo-Def": "Def value", + }, + params: { + foo: "Foo", + fooMap: { + Abc: "Abc value", + Def: "Def value", + } + } + }, + { + id: "HttpPrefixHeadersAreNotPresent", + description: "No prefix headers are serialized because the value is empty", + protocol: "aws.rest-xml", + code: 200, + body: "", + headers: { + "X-Foo": "Foo" + }, + params: { + foo: "Foo", + fooMap: {} + } + }, +]) + +structure HttpPrefixHeadersInputOutput { + @httpHeader("X-Foo") + foo: String, + + @httpPrefixHeaders("X-Foo-") + fooMap: FooPrefixHeaders, +} + +map FooPrefixHeaders { + key: String, + value: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/http-query.smithy b/smithy-aws-protocol-tests/model/rest-xml/http-query.smithy new file mode 100644 index 00000000000..7f59a145754 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/http-query.smithy @@ -0,0 +1,318 @@ +// This file defines test cases that test HTTP query string bindings. +// See: https://awslabs.github.io/smithy/spec/http.html#httpquery-trait + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// This example uses all query string types. +@readonly +@http(uri: "/AllQueryStringTypesInput", method: "GET") +operation AllQueryStringTypes(AllQueryStringTypesInput) + +apply AllQueryStringTypes @httpRequestTests([ + { + id: "AllQueryStringTypes", + description: "Serializes query string parameters with all supported types", + protocol: "aws.rest-xml", + method: "GET", + uri: "/AllQueryStringTypes", + body: "", + queryParams: [ + "String=Hello%20there", + "StringList=a", + "StringList=b", + "StringList=c", + "StringSet=a", + "StringSet=b", + "StringSet=c", + "Byte=1", + "Short=2", + "Integer=3", + "IntegerList=1", + "IntegerList=2", + "IntegerList=3", + "IntegerSet=1", + "IntegerSet=2", + "IntegerSet=3", + "Long=4", + "Float=1", + "Double=1", + "DoubleList=1.0", + "DoubleList=2.0", + "DoubleList=3.0", + "Boolean=true", + "BooleanList=true", + "BooleanList=false", + "BooleanList=true", + "Timestamp=1", + "TimestampList=1", + "TimestampList=2", + "TimestampList=3", + "Enum=Foo", + "EnumList=Foo", + "EnumList=Baz", + "EnumList=Bar", + ], + params: { + queryString: "Hello there", + queryStringList: ["a", "b", "c"], + queryStringSet: ["a", "b", "c"], + queryByte: 1, + queryShort: 2, + queryInteger: 3, + queryIntegerList: [1, 2, 3], + queryIntegerSet: [1, 2, 3], + queryLong: 4, + queryFloat: 1, + queryDouble: 1, + queryDoubleList: [1.0, 2.0, 3.0], + queryBoolean: true, + queryBooleanList: [true, false, true], + queryTimestamp: 1, + queryTimestampList: [1, 2, 3], + queryEnum: "Foo", + queryEnumList: ["Foo", "Baz", "Bar"], + } + } +]) + +structure AllQueryStringTypesInput { + @httpQuery("String") + queryString: String, + + @httpQuery("StringList") + queryStringList: StringList, + + @httpQuery("StringSet") + queryStringSet: StringSet, + + @httpQuery("Byte") + queryByte: Byte, + + @httpQuery("Short") + queryShort: Short, + + @httpQuery("Integer") + queryInteger: Integer, + + @httpQuery("IntegerList") + queryIntegerList: IntegerList, + + @httpQuery("IntegerSet") + queryIntegerSet: IntegerSet, + + @httpQuery("Long") + queryLong: Long, + + @httpQuery("Float") + queryFloat: Float, + + @httpQuery("Double") + queryDouble: Double, + + @httpQuery("DoubleList") + queryDoubleList: DoubleList, + + @httpQuery("Boolean") + queryBoolean: Boolean, + + @httpQuery("BooleanList") + queryBooleanList: BooleanList, + + @httpQuery("Timestamp") + queryTimestamp: Timestamp, + + @httpQuery("TimestampList") + queryTimestampList: TimestampList, + + @httpQuery("Enum") + queryEnum: FooEnum, + + @httpQuery("EnumList") + queryEnumList: FooEnumList, +} + +/// This example uses a constant query string parameters and a label. +/// This simply tests that labels and query string parameters are +/// compatible. The fixed query string parameter named "hello" should +/// in no way conflict with the label, `{hello}`. +@readonly +@http(uri: "/ConstantQueryString/{hello}?foo=bar&hello", method: "GET") +@httpRequestTests([ + { + id: "ConstantQueryString", + description: "Includes constant query string parameters", + protocol: "aws.rest-xml", + method: "GET", + uri: "/ConstantQueryString/hi", + queryParams: [ + "foo=bar", + "hello", + ], + body: "", + params: { + hello: "hi" + } + }, +]) +operation ConstantQueryString(ConstantQueryStringInput) + +structure ConstantQueryStringInput { + @httpLabel + @required + hello: String, +} + +/// This example uses fixed query string params and variable query string params. +/// The fixed query string parameters and variable parameters must both be +/// serialized (implementations may need to merge them together). +@readonly +@http(uri: "/ConstantAndVariableQueryString?foo=bar", method: "GET") +operation ConstantAndVariableQueryString(ConstantAndVariableQueryStringInput) + +apply ConstantAndVariableQueryString @httpRequestTests([ + { + id: "ConstantAndVariableQueryStringMissingOneValue", + description: "Mixes constant and variable query string parameters", + protocol: "aws.rest-xml", + method: "GET", + uri: "/ConstantAndVariableQueryString", + queryParams: [ + "foo=bar", + "baz=bam", + ], + forbidQueryParams: ["maybeSet"], + body: "", + params: { + baz: "bam" + } + }, + { + id: "ConstantAndVariableQueryStringAllValues", + description: "Mixes constant and variable query string parameters", + protocol: "aws.rest-xml", + method: "GET", + uri: "/ConstantAndVariableQueryString", + queryParams: [ + "foo=bar", + "baz=bam", + "maybeSet=yes" + ], + body: "", + params: { + baz: "bam", + maybeSet: "yes" + } + }, +]) + +structure ConstantAndVariableQueryStringInput { + @httpQuery("baz") + baz: String, + + @httpQuery("maybeSet") + maybeSet: String, +} + +/// This example ensures that query string bound request parameters are +/// serialized in the body of responses if the structure is used in both +/// the request and response. +@readonly +@http(uri: "/IgnoreQueryParamsInResponse", method: "GET") +operation IgnoreQueryParamsInResponse() -> IgnoreQueryParamsInResponseOutput + +apply IgnoreQueryParamsInResponse @httpResponseTests([ + { + id: "IgnoreQueryParamsInResponse", + description: "Query parameters must be ignored when serializing the output of an operation", + protocol: "aws.rest-xml", + code: 200, + headers: { + "Content-Type": "application/xml" + }, + body: "bam", + bodyMediaType: "xml", + params: { + baz: "bam" + } + } +]) + +structure IgnoreQueryParamsInResponseOutput { + @httpQuery("baz") + baz: String +} + +/// Omits null, but serializes empty string value. +@readonly +@http(uri: "/OmitsNullSerializesEmptyString", method: "GET") +operation OmitsNullSerializesEmptyString(OmitsNullSerializesEmptyStringInput) + +apply OmitsNullSerializesEmptyString @httpRequestTests([ + { + id: "OmitsNullSerializesEmptyString", + description: "Serializes empty query strings but omits null", + protocol: "aws.rest-xml", + method: "GET", + uri: "/OmitsNullSerializesEmptyString", + body: "", + queryParams: [ + "Empty=", + ], + params: { + nullValue: null, + emptyString: "", + } + } +]) + +structure OmitsNullSerializesEmptyStringInput { + @httpQuery("Null") + nullValue: String, + + @httpQuery("Empty") + emptyString: String, +} + +/// Automatically adds idempotency tokens. +@http(uri: "/QueryIdempotencyTokenAutoFill", method: "POST") +@tags(["client-only"]) +operation QueryIdempotencyTokenAutoFill(QueryIdempotencyTokenAutoFillInput) + +apply QueryIdempotencyTokenAutoFill @httpRequestTests([ + { + id: "QueryIdempotencyTokenAutoFill", + description: "Automatically adds idempotency token when not set", + protocol: "aws.rest-xml", + method: "POST", + uri: "/QueryIdempotencyTokenAutoFill", + body: "", + queryParams: [ + "token=00000000-0000-4000-8000-000000000000", + ] + }, + { + id: "QueryIdempotencyTokenAutoFillIsSet", + description: "Uses the given idempotency token as-is", + protocol: "aws.rest-xml", + method: "POST", + uri: "/QueryIdempotencyTokenAutoFill", + body: "", + queryParams: [ + "token=00000000-0000-4000-8000-000000000123", + ], + params: { + token: "00000000-0000-4000-8000-000000000123" + } + } +]) + +structure QueryIdempotencyTokenAutoFillInput { + @httpQuery("token") + @idempotencyToken + token: String, +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/main.smithy b/smithy-aws-protocol-tests/model/rest-xml/main.smithy new file mode 100644 index 00000000000..8c32f6fa9be --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/main.smithy @@ -0,0 +1,68 @@ +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +use smithy.test#httpRequestTests +use smithy.test#httpResponseTests + +/// A REST XML service that sends XML requests and responses. +@protocols([{"name": "aws.rest-xml"}]) +service RestXml { + version: "2019-12-16", + operations: [ + // Basic input and output tests + NoInputAndNoOutput, + NoInputAndOutput, + EmptyInputAndEmptyOutput, + + // @httpHeader tests + InputAndOutputWithHeaders, + NullAndEmptyHeaders, + TimestampFormatHeaders, + + // @httpLabel tests + HttpRequestWithLabels, + HttpRequestWithLabelsAndTimestampFormat, + HttpRequestWithGreedyLabelInPath, + + // @httpQuery tests + AllQueryStringTypes, + ConstantQueryString, + ConstantAndVariableQueryString, + IgnoreQueryParamsInResponse, + OmitsNullSerializesEmptyString, + QueryIdempotencyTokenAutoFill, + + // @httpPrefixHeaders tests + HttpPrefixHeaders, + + // @httpPayload tests + HttpPayloadTraits, + HttpPayloadTraitsWithMediaType, + HttpPayloadWithStructure, + HttpPayloadWithXmlName, + HttpPayloadWithXmlNamespace, + HttpPayloadWithXmlNamespaceAndPrefix, + + // Errors + GreetingWithErrors, + + // Synthesized XML document body tests + SimpleScalarProperties, + XmlTimestamps, + XmlEnums, + RecursiveShapes, + XmlLists, + XmlMaps, + XmlMapsXmlName, + FlattenedXmlMap, + FlattenedXmlMapWithXmlName, + + // @xmlAttribute tests + XmlAttributes, + XmlAttributesOnPayload, + + // @xmlNamespace trait tests + XmlNamespaces, + ] +} diff --git a/smithy-aws-protocol-tests/model/rest-xml/shared-types.smithy b/smithy-aws-protocol-tests/model/rest-xml/shared-types.smithy new file mode 100644 index 00000000000..2b227276881 --- /dev/null +++ b/smithy-aws-protocol-tests/model/rest-xml/shared-types.smithy @@ -0,0 +1,76 @@ +// This file contains shared types that are used throughout the rest-xml +// test cases. Anything that is generic enough that it could potentially +// be reused should be defined in this file. However, things like input +// or output structures or other test-case specific shapes should be +// defined closer to the test case and in its same file. + +$version: "0.5.0" + +namespace aws.protocols.tests.restxml + +list StringList { + member: String, +} + +set StringSet { + member: String, +} + +/// A list of lists of strings. +list NestedStringList { + member: StringList, +} + +list IntegerList { + member: Integer, +} + +set IntegerSet { + member: Integer, +} + +list DoubleList { + member: Double, +} + +list BooleanList { + member: PrimitiveBoolean, +} + +list TimestampList { + member: Timestamp, +} + +@enum( + Foo: {}, + Baz: {}, + Bar: {}, + "1": {}, + "0": {}, +) +string FooEnum + +list FooEnumList { + member: FooEnum, +} + +set FooEnumSet { + member: FooEnum, +} + +map FooEnumMap { + key: String, + value: FooEnum, +} + +@timestampFormat("date-time") +timestamp DateTime + +@timestampFormat("epoch-seconds") +timestamp EpochSeconds + +@timestampFormat("http-date") +timestamp HttpDate + +@mediaType("text/plain") +blob TextPlainBlob