package xmlutil import ( "encoding/xml" "fmt" "io" "reflect" "strings" "testing" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awsutil" ) type mockBody struct { DoneErr error Body io.Reader } func (m *mockBody) Read(p []byte) (int, error) { n, err := m.Body.Read(p) if (n == 0 || err == io.EOF) && m.DoneErr != nil { return n, m.DoneErr } return n, err } type mockOutput struct { _ struct{} `type:"structure"` String *string `type:"string"` Integer *int64 `type:"integer"` Nested *mockNestedStruct `type:"structure"` List []*mockListElem `locationName:"List" locationNameList:"Elem" type:"list"` Closed *mockClosedTags `type:"structure"` } type mockNestedStruct struct { _ struct{} `type:"structure"` NestedString *string `type:"string"` NestedInt *int64 `type:"integer"` } type mockClosedTags struct { _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` Attr *string `locationName:"xsi:attrval" type:"string" xmlAttribute:"true"` } type mockListElem struct { _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` String *string `type:"string"` NestedElem *mockNestedListElem `type:"structure"` } type mockNestedListElem struct { _ struct{} `type:"structure" xmlPrefix:"xsi" xmlURI:"http://www.w3.org/2001/XMLSchema-instance"` String *string `type:"string"` Type *string `locationName:"xsi:type" type:"string" xmlAttribute:"true"` } func TestUnmarshal(t *testing.T) { const xmlBodyStr = ` string value 123 nested string value 321 nested elem string value elem string value ` expect := mockOutput{ String: aws.String("string value"), Integer: aws.Int64(123), Closed: &mockClosedTags{ Attr: aws.String("attr value"), }, Nested: &mockNestedStruct{ NestedString: aws.String("nested string value"), NestedInt: aws.Int64(321), }, List: []*mockListElem{ { String: aws.String("elem string value"), NestedElem: &mockNestedListElem{ String: aws.String("nested elem string value"), Type: aws.String("type"), }, }, }, } actual := mockOutput{} decoder := xml.NewDecoder(strings.NewReader(xmlBodyStr)) err := UnmarshalXML(&actual, decoder, "") if err != nil { t.Fatalf("expect no error, got %v", err) } if !reflect.DeepEqual(expect, actual) { t.Errorf("expect unmarshal to match\nExpect: %s\nActual: %s", awsutil.Prettify(expect), awsutil.Prettify(actual)) } } func TestUnmarshal_UnexpectedEOF(t *testing.T) { const partialXMLBody = ` first value Second val` out := struct { First *string `locationName:"First" type:"string"` Second *string `locationName:"Second" type:"string"` }{} expect := out expect.First = aws.String("first") expect.Second = aws.String("second") expectErr := fmt.Errorf("expected read error") body := &mockBody{ DoneErr: expectErr, Body: strings.NewReader(partialXMLBody), } decoder := xml.NewDecoder(body) err := UnmarshalXML(&out, decoder, "") if err == nil { t.Fatalf("expect error, got none") } if e, a := expectErr, err; e != a { t.Errorf("expect %v error in %v, but was not", e, a) } }