diff options
Diffstat (limited to 'src/encoding/xml/marshal_test.go')
-rw-r--r-- | src/encoding/xml/marshal_test.go | 551 |
1 files changed, 542 insertions, 9 deletions
diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go index d79b99a1e0..0126146d33 100644 --- a/src/encoding/xml/marshal_test.go +++ b/src/encoding/xml/marshal_test.go @@ -386,6 +386,140 @@ func ifaceptr(x interface{}) interface{} { return &x } +func stringptr(x string) *string { + return &x +} + +type T1 struct{} +type T2 struct{} +type T3 struct{} + +type IndirComment struct { + T1 T1 + Comment *string `xml:",comment"` + T2 T2 +} + +type DirectComment struct { + T1 T1 + Comment string `xml:",comment"` + T2 T2 +} + +type IfaceComment struct { + T1 T1 + Comment interface{} `xml:",comment"` + T2 T2 +} + +type IndirChardata struct { + T1 T1 + Chardata *string `xml:",chardata"` + T2 T2 +} + +type DirectChardata struct { + T1 T1 + Chardata string `xml:",chardata"` + T2 T2 +} + +type IfaceChardata struct { + T1 T1 + Chardata interface{} `xml:",chardata"` + T2 T2 +} + +type IndirCDATA struct { + T1 T1 + CDATA *string `xml:",cdata"` + T2 T2 +} + +type DirectCDATA struct { + T1 T1 + CDATA string `xml:",cdata"` + T2 T2 +} + +type IfaceCDATA struct { + T1 T1 + CDATA interface{} `xml:",cdata"` + T2 T2 +} + +type IndirInnerXML struct { + T1 T1 + InnerXML *string `xml:",innerxml"` + T2 T2 +} + +type DirectInnerXML struct { + T1 T1 + InnerXML string `xml:",innerxml"` + T2 T2 +} + +type IfaceInnerXML struct { + T1 T1 + InnerXML interface{} `xml:",innerxml"` + T2 T2 +} + +type IndirElement struct { + T1 T1 + Element *string + T2 T2 +} + +type DirectElement struct { + T1 T1 + Element string + T2 T2 +} + +type IfaceElement struct { + T1 T1 + Element interface{} + T2 T2 +} + +type IndirOmitEmpty struct { + T1 T1 + OmitEmpty *string `xml:",omitempty"` + T2 T2 +} + +type DirectOmitEmpty struct { + T1 T1 + OmitEmpty string `xml:",omitempty"` + T2 T2 +} + +type IfaceOmitEmpty struct { + T1 T1 + OmitEmpty interface{} `xml:",omitempty"` + T2 T2 +} + +type IndirAny struct { + T1 T1 + Any *string `xml:",any"` + T2 T2 +} + +type DirectAny struct { + T1 T1 + Any string `xml:",any"` + T2 T2 +} + +type IfaceAny struct { + T1 T1 + Any interface{} `xml:",any"` + T2 T2 +} + var ( nameAttr = "Sarah" ageAttr = uint(12) @@ -398,10 +532,12 @@ var ( // please try to make them two-way as well to ensure that // marshaling and unmarshaling are as symmetrical as feasible. var marshalTests = []struct { - Value interface{} - ExpectXML string - MarshalOnly bool - UnmarshalOnly bool + Value interface{} + ExpectXML string + MarshalOnly bool + MarshalError string + UnmarshalOnly bool + UnmarshalError string }{ // Test nil marshals to nothing {Value: nil, ExpectXML: ``, MarshalOnly: true}, @@ -1133,6 +1269,382 @@ var marshalTests = []struct { ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`, Value: &NestedAndCData{AB: make([]string, 2), CDATA: "test"}, }, + // Test pointer indirection in various kinds of fields. + // https://golang.org/issue/19063 + { + ExpectXML: `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`, + Value: &IndirComment{Comment: stringptr("hi")}, + MarshalOnly: true, + }, + { + ExpectXML: `<IndirComment><T1></T1><T2></T2></IndirComment>`, + Value: &IndirComment{Comment: stringptr("")}, + MarshalOnly: true, + }, + { + ExpectXML: `<IndirComment><T1></T1><T2></T2></IndirComment>`, + Value: &IndirComment{Comment: nil}, + MarshalError: "xml: bad type for comment field of xml.IndirComment", + }, + { + ExpectXML: `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`, + Value: &IndirComment{Comment: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`, + Value: &IfaceComment{Comment: "hi"}, + MarshalOnly: true, + }, + { + ExpectXML: `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`, + Value: &IfaceComment{Comment: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceComment><T1></T1><T2></T2></IfaceComment>`, + Value: &IfaceComment{Comment: nil}, + MarshalError: "xml: bad type for comment field of xml.IfaceComment", + }, + { + ExpectXML: `<IfaceComment><T1></T1><T2></T2></IfaceComment>`, + Value: &IfaceComment{Comment: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectComment><T1></T1><!--hi--><T2></T2></DirectComment>`, + Value: &DirectComment{Comment: string("hi")}, + }, + { + ExpectXML: `<DirectComment><T1></T1><T2></T2></DirectComment>`, + Value: &DirectComment{Comment: string("")}, + }, + { + ExpectXML: `<IndirChardata><T1></T1>hi<T2></T2></IndirChardata>`, + Value: &IndirChardata{Chardata: stringptr("hi")}, + }, + { + ExpectXML: `<IndirChardata><T1></T1><![CDATA[hi]]><T2></T2></IndirChardata>`, + Value: &IndirChardata{Chardata: stringptr("hi")}, + UnmarshalOnly: true, // marshals without CDATA + }, + { + ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`, + Value: &IndirChardata{Chardata: stringptr("")}, + }, + { + ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`, + Value: &IndirChardata{Chardata: nil}, + MarshalOnly: true, // unmarshal leaves Chardata=stringptr("") + }, + { + ExpectXML: `<IfaceChardata><T1></T1>hi<T2></T2></IfaceChardata>`, + Value: &IfaceChardata{Chardata: string("hi")}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceChardata><T1></T1><![CDATA[hi]]><T2></T2></IfaceChardata>`, + Value: &IfaceChardata{Chardata: string("hi")}, + UnmarshalOnly: true, // marshals without CDATA + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`, + Value: &IfaceChardata{Chardata: string("")}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`, + Value: &IfaceChardata{Chardata: nil}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<DirectChardata><T1></T1>hi<T2></T2></DirectChardata>`, + Value: &DirectChardata{Chardata: string("hi")}, + }, + { + ExpectXML: `<DirectChardata><T1></T1><![CDATA[hi]]><T2></T2></DirectChardata>`, + Value: &DirectChardata{Chardata: string("hi")}, + UnmarshalOnly: true, // marshals without CDATA + }, + { + ExpectXML: `<DirectChardata><T1></T1><T2></T2></DirectChardata>`, + Value: &DirectChardata{Chardata: string("")}, + }, + { + ExpectXML: `<IndirCDATA><T1></T1><![CDATA[hi]]><T2></T2></IndirCDATA>`, + Value: &IndirCDATA{CDATA: stringptr("hi")}, + }, + { + ExpectXML: `<IndirCDATA><T1></T1>hi<T2></T2></IndirCDATA>`, + Value: &IndirCDATA{CDATA: stringptr("hi")}, + UnmarshalOnly: true, // marshals with CDATA + }, + { + ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`, + Value: &IndirCDATA{CDATA: stringptr("")}, + }, + { + ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`, + Value: &IndirCDATA{CDATA: nil}, + MarshalOnly: true, // unmarshal leaves CDATA=stringptr("") + }, + { + ExpectXML: `<IfaceCDATA><T1></T1><![CDATA[hi]]><T2></T2></IfaceCDATA>`, + Value: &IfaceCDATA{CDATA: string("hi")}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceCDATA><T1></T1>hi<T2></T2></IfaceCDATA>`, + Value: &IfaceCDATA{CDATA: string("hi")}, + UnmarshalOnly: true, // marshals with CDATA + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`, + Value: &IfaceCDATA{CDATA: string("")}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`, + Value: &IfaceCDATA{CDATA: nil}, + UnmarshalError: "cannot unmarshal into interface {}", + }, + { + ExpectXML: `<DirectCDATA><T1></T1><![CDATA[hi]]><T2></T2></DirectCDATA>`, + Value: &DirectCDATA{CDATA: string("hi")}, + }, + { + ExpectXML: `<DirectCDATA><T1></T1>hi<T2></T2></DirectCDATA>`, + Value: &DirectCDATA{CDATA: string("hi")}, + UnmarshalOnly: true, // marshals with CDATA + }, + { + ExpectXML: `<DirectCDATA><T1></T1><T2></T2></DirectCDATA>`, + Value: &DirectCDATA{CDATA: string("")}, + }, + { + ExpectXML: `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`, + Value: &IndirInnerXML{InnerXML: stringptr("<hi/>")}, + MarshalOnly: true, + }, + { + ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`, + Value: &IndirInnerXML{InnerXML: stringptr("")}, + MarshalOnly: true, + }, + { + ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`, + Value: &IndirInnerXML{InnerXML: nil}, + }, + { + ExpectXML: `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`, + Value: &IndirInnerXML{InnerXML: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`, + Value: &IfaceInnerXML{InnerXML: "<hi/>"}, + MarshalOnly: true, + }, + { + ExpectXML: `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`, + Value: &IfaceInnerXML{InnerXML: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`, + Value: &IfaceInnerXML{InnerXML: nil}, + }, + { + ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`, + Value: &IfaceInnerXML{InnerXML: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`, + Value: &DirectInnerXML{InnerXML: string("<hi/>")}, + MarshalOnly: true, + }, + { + ExpectXML: `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`, + Value: &DirectInnerXML{InnerXML: string("<T1></T1><hi/><T2></T2>")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`, + Value: &DirectInnerXML{InnerXML: string("")}, + MarshalOnly: true, + }, + { + ExpectXML: `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`, + Value: &DirectInnerXML{InnerXML: string("<T1></T1><T2></T2>")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IndirElement><T1></T1><Element>hi</Element><T2></T2></IndirElement>`, + Value: &IndirElement{Element: stringptr("hi")}, + }, + { + ExpectXML: `<IndirElement><T1></T1><Element></Element><T2></T2></IndirElement>`, + Value: &IndirElement{Element: stringptr("")}, + }, + { + ExpectXML: `<IndirElement><T1></T1><T2></T2></IndirElement>`, + Value: &IndirElement{Element: nil}, + }, + { + ExpectXML: `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`, + Value: &IfaceElement{Element: "hi"}, + MarshalOnly: true, + }, + { + ExpectXML: `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`, + Value: &IfaceElement{Element: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`, + Value: &IfaceElement{Element: nil}, + }, + { + ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`, + Value: &IfaceElement{Element: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectElement><T1></T1><Element>hi</Element><T2></T2></DirectElement>`, + Value: &DirectElement{Element: string("hi")}, + }, + { + ExpectXML: `<DirectElement><T1></T1><Element></Element><T2></T2></DirectElement>`, + Value: &DirectElement{Element: string("")}, + }, + { + ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IndirOmitEmpty>`, + Value: &IndirOmitEmpty{OmitEmpty: stringptr("hi")}, + }, + { + // Note: Changed in Go 1.8 to include <OmitEmpty> element (because x.OmitEmpty != nil). + ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`, + Value: &IndirOmitEmpty{OmitEmpty: stringptr("")}, + MarshalOnly: true, + }, + { + ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`, + Value: &IndirOmitEmpty{OmitEmpty: stringptr("")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IndirOmitEmpty><T1></T1><T2></T2></IndirOmitEmpty>`, + Value: &IndirOmitEmpty{OmitEmpty: nil}, + }, + { + ExpectXML: `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`, + Value: &IfaceOmitEmpty{OmitEmpty: "hi"}, + MarshalOnly: true, + }, + { + ExpectXML: `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`, + Value: &IfaceOmitEmpty{OmitEmpty: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`, + Value: &IfaceOmitEmpty{OmitEmpty: nil}, + }, + { + ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`, + Value: &IfaceOmitEmpty{OmitEmpty: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></DirectOmitEmpty>`, + Value: &DirectOmitEmpty{OmitEmpty: string("hi")}, + }, + { + ExpectXML: `<DirectOmitEmpty><T1></T1><T2></T2></DirectOmitEmpty>`, + Value: &DirectOmitEmpty{OmitEmpty: string("")}, + }, + { + ExpectXML: `<IndirAny><T1></T1><Any>hi</Any><T2></T2></IndirAny>`, + Value: &IndirAny{Any: stringptr("hi")}, + }, + { + ExpectXML: `<IndirAny><T1></T1><Any></Any><T2></T2></IndirAny>`, + Value: &IndirAny{Any: stringptr("")}, + }, + { + ExpectXML: `<IndirAny><T1></T1><T2></T2></IndirAny>`, + Value: &IndirAny{Any: nil}, + }, + { + ExpectXML: `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`, + Value: &IfaceAny{Any: "hi"}, + MarshalOnly: true, + }, + { + ExpectXML: `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`, + Value: &IfaceAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`, + Value: &IfaceAny{Any: nil}, + }, + { + ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`, + Value: &IfaceAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectAny><T1></T1><Any>hi</Any><T2></T2></DirectAny>`, + Value: &DirectAny{Any: string("hi")}, + }, + { + ExpectXML: `<DirectAny><T1></T1><Any></Any><T2></T2></DirectAny>`, + Value: &DirectAny{Any: string("")}, + }, + { + ExpectXML: `<IndirFoo><T1></T1><Foo>hi</Foo><T2></T2></IndirFoo>`, + Value: &IndirAny{Any: stringptr("hi")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IndirFoo><T1></T1><Foo></Foo><T2></T2></IndirFoo>`, + Value: &IndirAny{Any: stringptr("")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IndirFoo><T1></T1><T2></T2></IndirFoo>`, + Value: &IndirAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceFoo><T1></T1><Foo>hi</Foo><T2></T2></IfaceFoo>`, + Value: &IfaceAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`, + Value: &IfaceAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`, + Value: &IfaceAny{Any: nil}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectFoo><T1></T1><Foo>hi</Foo><T2></T2></DirectFoo>`, + Value: &DirectAny{Any: string("hi")}, + UnmarshalOnly: true, + }, + { + ExpectXML: `<DirectFoo><T1></T1><Foo></Foo><T2></T2></DirectFoo>`, + Value: &DirectAny{Any: string("")}, + UnmarshalOnly: true, + }, } func TestMarshal(t *testing.T) { @@ -1142,7 +1654,17 @@ func TestMarshal(t *testing.T) { } data, err := Marshal(test.Value) if err != nil { - t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err) + if test.MarshalError == "" { + t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err) + continue + } + if !strings.Contains(err.Error(), test.MarshalError) { + t.Errorf("#%d: marshal(%#v): %s, want %q", idx, test.Value, err, test.MarshalError) + } + continue + } + if test.MarshalError != "" { + t.Errorf("#%d: Marshal succeeded, want error %q", idx, test.MarshalError) continue } if got, want := string(data), test.ExpectXML; got != want { @@ -1268,8 +1790,16 @@ func TestUnmarshal(t *testing.T) { } if err != nil { - t.Errorf("#%d: unexpected error: %#v", i, err) - } else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) { + if test.UnmarshalError == "" { + t.Errorf("#%d: unmarshal(%#v): %s", i, test.ExpectXML, err) + continue + } + if !strings.Contains(err.Error(), test.UnmarshalError) { + t.Errorf("#%d: unmarshal(%#v): %s, want %q", i, test.ExpectXML, err, test.UnmarshalError) + } + continue + } + if got, want := dest, test.Value; !reflect.DeepEqual(got, want) { t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want) } } @@ -1898,7 +2428,10 @@ func TestIssue16158(t *testing.T) { err := Unmarshal([]byte(data), &struct { B byte `xml:"b,attr,omitempty"` }{}) - if err == nil { - t.Errorf("Unmarshal: expected error, got nil") + + // For Go 1.8.1 we've restored the old "no errors reported" behavior. + // We'll try again in Go 1.9 to report errors. + if err != nil { + t.Errorf("Unmarshal: expected nil, got error") } } |