Unverified Commit 392463d0 authored by Russell Cohen's avatar Russell Cohen Committed by GitHub
Browse files

Add more XML protocol tests (#382)

* Add more XML protocol tests

* Update rest-xml-extras.smithy

* Update rest-xml-unwrapped-errors.smithy
parent 0e582882
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -44,6 +44,18 @@ val CodegenTests = listOf(
        "aws.protocoltests.restxml#RestXml",
        "rest_xml"
    ),
    CodegenTest(
        "aws.protocoltests.restxml.xmlns#RestXmlWithNamespace",
        "rest_xml_namespace"
    ),
    CodegenTest(
        "aws.protocoltests.restxml#RestXmlExtras",
        "rest_xml_extras"
    ),
    CodegenTest(
        "aws.protocoltests.restxmlunwrapped#RestXmlExtrasUnwrappedErrors",
        "rest_xml_extras_unwrapped"
    ),
    CodegenTest(
        "crate#Config",
        "naming_test", """
+100 −0
Original line number Diff line number Diff line
$version: "1.0"
namespace aws.protocoltests.restxml

use aws.protocols#restXml
use aws.api#service
use smithy.test#httpResponseTests


/// A REST XML service that sends XML requests and responses.
@service(sdkId: "Rest XML Protocol")
@restXml
service RestXmlExtras {
    version: "2019-12-16",
    operations: [AttributeParty, XmlMapsFlattenedNestedXmlNamespace]
}

@enum([{"value": "enumvalue", "name": "V"}])
string StringEnum

integer PrimitiveInt

structure AttributePartyInputOutput {
    @xmlAttribute
    enum: StringEnum,

    @xmlAttribute
    @xmlName("prefix:anumber")
    number: PrimitiveInt,

    @xmlAttribute
    ts: Timestamp,

    @xmlAttribute
    bool: Boolean
}

@httpResponseTests([{
        id: "DeserAttributes",
        code: 200,
        body: "<AttributePartyInputOutput enum=\"enumvalue\" prefix:anumber=\"5\" ts=\"1985-04-12T23:20:50.00Z\" bool=\"true\"/>",
        params: {
            enum: "enumvalue",
            number: 5,
            ts: 482196050,
            bool: true
        },
        protocol: "aws.protocols#restXml"

}])
@http(uri: "/AttributeParty", method: "POST")
operation AttributeParty {
    output: AttributePartyInputOutput
}

@httpResponseTests([{
        id: "DeserFlatNamespaceMaps",
        code: 200,
        body: "<XmlMapsFlattenedNestedXmlNamespaceInputOutput xmlns=\"http://aoo.com\"><myMap><yek xmlns=\"http://doo.com\">map2</yek><eulav xmlns=\"http://eoo.com\"><entry><K xmlns=\"http://goo.com\">third</K><V xmlns=\"http://hoo.com\">plz</V></entry><entry><K xmlns=\"http://goo.com\">fourth</K><V xmlns=\"http://hoo.com\">onegai</V></entry></eulav></myMap><myMap><yek xmlns=\"http://doo.com\">map1</yek><eulav xmlns=\"http://eoo.com\"><entry><K xmlns=\"http://goo.com\">second</K><V xmlns=\"http://hoo.com\">konnichiwa</V></entry><entry><K xmlns=\"http://goo.com\">first</K><V xmlns=\"http://hoo.com\">hi</V></entry></eulav></myMap></XmlMapsFlattenedNestedXmlNamespaceInput>",
        params: {
            "myMap": {
                "map2": {"fourth": "onegai", "third": "plz" },
                "map1": {"second": "konnichiwa", "first": "hi" }
            }
        },
        protocol: "aws.protocols#restXml"
}])
@http(uri: "/XmlMapsFlattenedNestedXmlNamespace", method: "POST")
operation XmlMapsFlattenedNestedXmlNamespace {
    input: XmlMapsFlattenedNestedXmlNamespaceInputOutput,
    output: XmlMapsFlattenedNestedXmlNamespaceInputOutput
}

@xmlNamespace(uri: "http://aoo.com")
structure XmlMapsFlattenedNestedXmlNamespaceInputOutput {
    @xmlNamespace(uri: "http://boo.com")
    @xmlFlattened
    myMap: XmlMapsNestedNamespaceInputOutputMap,
}

@xmlNamespace(uri: "http://coo.com")
map XmlMapsNestedNamespaceInputOutputMap {
    @xmlNamespace(uri: "http://doo.com")
    @xmlName("yek")
    key: String,

    @xmlNamespace(uri: "http://eoo.com")
    @xmlName("eulav")
    value: XmlMapsNestedNestedNamespaceInputOutputMap
}

@xmlNamespace(uri: "http://foo.com")
map XmlMapsNestedNestedNamespaceInputOutputMap {
    @xmlNamespace(uri: "http://goo.com")
    @xmlName("K")
    key: String,

    @xmlNamespace(uri: "http://hoo.com")
    @xmlName("V")
    value: String
}
+137 −0
Original line number Diff line number Diff line
// This file defines test cases that test error serialization.

$version: "1.0"

namespace aws.protocoltests.restxmlunwrapped

use aws.protocols#restXml
use smithy.test#httpRequestTests
use smithy.test#httpResponseTests
use aws.api#service


/// A REST XML service that sends XML requests and responses.
@service(sdkId: "Rest XML Protocol")
@restXml(noErrorWrapping: true)
service RestXmlExtrasUnwrappedErrors {
    version: "2019-12-16",
    operations: [GreetingWithUnwrappedErrors]
}

/// 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 GreetingWithUnwrappedErrors {
    output: GreetingWithErrorsOutput,
    errors: [InvalidGreetingUnwrapped, ComplexErrorUnwrapped]
}

apply GreetingWithUnwrappedErrors @httpResponseTests([
    {
        id: "GreetingWithErrorsUnwrapped",
        documentation: "Ensures that operations with errors successfully know how to deserialize the successful response",
        protocol: restXml,
        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 InvalidGreetingUnwrapped {
    Message: String,
}

apply InvalidGreetingUnwrapped @httpResponseTests([
    {
        id: "InvalidGreetingErrorUnwrapped",
        documentation: "Parses simple XML errors",
        protocol: restXml,
        params: {
            Message: "Hi"
        },
        code: 400,
        headers: {
            "Content-Type": "application/xml"
        },
        body: """
                 <Error>
                    <Type>Sender</Type>
                    <Code>InvalidGreetingUnwrapped</Code>
                    <Message>Hi</Message>
                    <AnotherSetting>setting</AnotherSetting>
                    <RequestId>foo-id</RequestId>
                 </Error>
              """,
        bodyMediaType: "application/xml",
    }
])

/// This error is thrown when a request is invalid.
@error("client")
@httpError(403)
structure ComplexErrorUnwrapped {
    // Errors support HTTP bindings!
    @httpHeader("X-Header")
    Header: String,

    TopLevel: String,

    Nested: ComplexNestedErrorData,
}

apply ComplexErrorUnwrapped @httpResponseTests([
    {
        id: "ComplexErrorUnwrapped",
        protocol: restXml,
        params: {
            Header: "Header",
            TopLevel: "Top level",
            Nested: {
                Foo: "bar"
            }
        },
        code: 400,
        headers: {
            "Content-Type": "application/xml",
            "X-Header": "Header",
        },
        body: """
                 <Error>
                    <Type>Sender</Type>
                    <Code>ComplexErrorUnwrapped</Code>
                    <Message>Hi</Message>
                    <TopLevel>Top level</TopLevel>
                    <Nested>
                        <Foo>bar</Foo>
                    </Nested>
                 <RequestId>foo-id</RequestId>
                 </Error>
              """,
        bodyMediaType: "application/xml",
    }
])

structure ComplexNestedErrorData {
    Foo: String,
}
+6 −0
Original line number Diff line number Diff line
@@ -135,6 +135,7 @@ class XmlBindingTraitParserGenerator(protocolConfig: ProtocolConfig, private val
                    """
                    use std::convert::TryFrom;
                    let mut doc = #{Document}::try_from(inp)?;
                    ##[allow(unused_mut)]
                    let mut decoder = doc.root_element()?;
                    let start_el = decoder.start_el();
                    if !(${shapeName.compareTo("start_el")}) {
@@ -189,6 +190,7 @@ class XmlBindingTraitParserGenerator(protocolConfig: ProtocolConfig, private val
                    """
                    use std::convert::TryFrom;
                    let mut doc = #{Document}::try_from(inp)?;
                    ##[allow(unused_mut)]
                    let mut decoder = doc.root_element()?;
                    let start_el = decoder.start_el();
                    if !(${shapeName.compareTo("start_el")}) {
@@ -249,6 +251,10 @@ class XmlBindingTraitParserGenerator(protocolConfig: ProtocolConfig, private val
            }
            rust("$builder.${symbolProvider.toMemberName(member)} = $temp;")
        }
        // No need to generate a parse loop if there are no non-attribute members
        if (members.dataMembers.isEmpty()) {
            return
        }
        parseLoop(outerCtx) { ctx ->
            members.dataMembers.forEach { member ->
                case(member) {