src/encoding/xml/marshal_test.go GO 2,603 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,603.
1// Copyright 2011 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45package xml67import (8	"bytes"9	"errors"10	"fmt"11	"io"12	"reflect"13	"strconv"14	"strings"15	"sync"16	"testing"17	"time"18)1920type DriveType int2122const (23	HyperDrive DriveType = iota24	ImprobabilityDrive25)2627type Passenger struct {28	Name   []string `xml:"name"`29	Weight float32  `xml:"weight"`30}3132type Ship struct {33	XMLName struct{} `xml:"spaceship"`3435	Name      string       `xml:"name,attr"`36	Pilot     string       `xml:"pilot,attr"`37	Drive     DriveType    `xml:"drive"`38	Age       uint         `xml:"age"`39	Passenger []*Passenger `xml:"passenger"`40	secret    string41}4243type NamedType string4445type Port struct {46	XMLName struct{} `xml:"port"`47	Type    string   `xml:"type,attr,omitempty"`48	Comment string   `xml:",comment"`49	Number  string   `xml:",chardata"`50}5152type Domain struct {53	XMLName struct{} `xml:"domain"`54	Country string   `xml:",attr,omitempty"`55	Name    []byte   `xml:",chardata"`56	Comment []byte   `xml:",comment"`57}5859type Book struct {60	XMLName struct{} `xml:"book"`61	Title   string   `xml:",chardata"`62}6364type Event struct {65	XMLName struct{} `xml:"event"`66	Year    int      `xml:",chardata"`67}6869type Movie struct {70	XMLName struct{} `xml:"movie"`71	Length  uint     `xml:",chardata"`72}7374type Pi struct {75	XMLName       struct{} `xml:"pi"`76	Approximation float32  `xml:",chardata"`77}7879type Universe struct {80	XMLName struct{} `xml:"universe"`81	Visible float64  `xml:",chardata"`82}8384type Particle struct {85	XMLName struct{} `xml:"particle"`86	HasMass bool     `xml:",chardata"`87}8889type Departure struct {90	XMLName struct{}  `xml:"departure"`91	When    time.Time `xml:",chardata"`92}9394type SecretAgent struct {95	XMLName   struct{} `xml:"agent"`96	Handle    string   `xml:"handle,attr"`97	Identity  string98	Obfuscate string `xml:",innerxml"`99}100101type NestedItems struct {102	XMLName struct{} `xml:"result"`103	Items   []string `xml:">item"`104	Item1   []string `xml:"Items>item1"`105}106107type NestedOrder struct {108	XMLName struct{} `xml:"result"`109	Field1  string   `xml:"parent>c"`110	Field2  string   `xml:"parent>b"`111	Field3  string   `xml:"parent>a"`112}113114type MixedNested struct {115	XMLName struct{} `xml:"result"`116	A       string   `xml:"parent1>a"`117	B       string   `xml:"b"`118	C       string   `xml:"parent1>parent2>c"`119	D       string   `xml:"parent1>d"`120}121122type NilTest struct {123	A any `xml:"parent1>parent2>a"`124	B any `xml:"parent1>b"`125	C any `xml:"parent1>parent2>c"`126}127128type Service struct {129	XMLName struct{} `xml:"service"`130	Domain  *Domain  `xml:"host>domain"`131	Port    *Port    `xml:"host>port"`132	Extra1  any133	Extra2  any `xml:"host>extra2"`134}135136var nilStruct *Ship137138type EmbedA struct {139	EmbedC140	EmbedB EmbedB141	FieldA string142	embedD143}144145type EmbedB struct {146	FieldB string147	*EmbedC148}149150type EmbedC struct {151	FieldA1 string `xml:"FieldA>A1"`152	FieldA2 string `xml:"FieldA>A2"`153	FieldB  string154	FieldC  string155}156157type embedD struct {158	fieldD string159	FieldE string // Promoted and visible when embedD is embedded.160}161162type NameCasing struct {163	XMLName struct{} `xml:"casing"`164	Xy      string165	XY      string166	XyA     string `xml:"Xy,attr"`167	XYA     string `xml:"XY,attr"`168}169170type NamePrecedence struct {171	XMLName     Name              `xml:"Parent"`172	FromTag     XMLNameWithoutTag `xml:"InTag"`173	FromNameVal XMLNameWithoutTag174	FromNameTag XMLNameWithTag175	InFieldName string176}177178type XMLNameWithTag struct {179	XMLName Name   `xml:"InXMLNameTag"`180	Value   string `xml:",chardata"`181}182183type XMLNameWithoutTag struct {184	XMLName Name185	Value   string `xml:",chardata"`186}187188type NameInField struct {189	Foo Name `xml:"ns foo"`190}191192type AttrTest struct {193	Int   int     `xml:",attr"`194	Named int     `xml:"int,attr"`195	Float float64 `xml:",attr"`196	Uint8 uint8   `xml:",attr"`197	Bool  bool    `xml:",attr"`198	Str   string  `xml:",attr"`199	Bytes []byte  `xml:",attr"`200}201202type AttrsTest struct {203	Attrs []Attr  `xml:",any,attr"`204	Int   int     `xml:",attr"`205	Named int     `xml:"int,attr"`206	Float float64 `xml:",attr"`207	Uint8 uint8   `xml:",attr"`208	Bool  bool    `xml:",attr"`209	Str   string  `xml:",attr"`210	Bytes []byte  `xml:",attr"`211}212213type OmitAttrTest struct {214	Int   int     `xml:",attr,omitempty"`215	Named int     `xml:"int,attr,omitempty"`216	Float float64 `xml:",attr,omitempty"`217	Uint8 uint8   `xml:",attr,omitempty"`218	Bool  bool    `xml:",attr,omitempty"`219	Str   string  `xml:",attr,omitempty"`220	Bytes []byte  `xml:",attr,omitempty"`221	PStr  *string `xml:",attr,omitempty"`222}223224type OmitFieldTest struct {225	Int   int           `xml:",omitempty"`226	Named int           `xml:"int,omitempty"`227	Float float64       `xml:",omitempty"`228	Uint8 uint8         `xml:",omitempty"`229	Bool  bool          `xml:",omitempty"`230	Str   string        `xml:",omitempty"`231	Bytes []byte        `xml:",omitempty"`232	PStr  *string       `xml:",omitempty"`233	Ptr   *PresenceTest `xml:",omitempty"`234}235236type AnyTest struct {237	XMLName  struct{}  `xml:"a"`238	Nested   string    `xml:"nested>value"`239	AnyField AnyHolder `xml:",any"`240}241242type AnyOmitTest struct {243	XMLName  struct{}   `xml:"a"`244	Nested   string     `xml:"nested>value"`245	AnyField *AnyHolder `xml:",any,omitempty"`246}247248type AnySliceTest struct {249	XMLName  struct{}    `xml:"a"`250	Nested   string      `xml:"nested>value"`251	AnyField []AnyHolder `xml:",any"`252}253254type AnyHolder struct {255	XMLName Name256	XML     string `xml:",innerxml"`257}258259type RecurseA struct {260	A string261	B *RecurseB262}263264type RecurseB struct {265	A *RecurseA266	B string267}268269type PresenceTest struct {270	Exists *struct{}271}272273type IgnoreTest struct {274	PublicSecret string `xml:"-"`275}276277type MyBytes []byte278279type Data struct {280	Bytes  []byte281	Attr   []byte `xml:",attr"`282	Custom MyBytes283}284285type Plain struct {286	V any287}288289type MyInt int290291type EmbedInt struct {292	MyInt293}294295type Strings struct {296	X []string `xml:"A>B,omitempty"`297}298299type PointerFieldsTest struct {300	XMLName  Name    `xml:"dummy"`301	Name     *string `xml:"name,attr"`302	Age      *uint   `xml:"age,attr"`303	Empty    *string `xml:"empty,attr"`304	Contents *string `xml:",chardata"`305}306307type ChardataEmptyTest struct {308	XMLName  Name    `xml:"test"`309	Contents *string `xml:",chardata"`310}311312type PointerAnonFields struct {313	*MyInt314	*NamedType315}316317type MyMarshalerTest struct {318}319320var _ Marshaler = (*MyMarshalerTest)(nil)321322func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {323	e.EncodeToken(start)324	e.EncodeToken(CharData([]byte("hello world")))325	e.EncodeToken(EndElement{start.Name})326	return nil327}328329type MyMarshalerAttrTest struct {330}331332var _ MarshalerAttr = (*MyMarshalerAttrTest)(nil)333334func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {335	return Attr{name, "hello world"}, nil336}337338func (m *MyMarshalerAttrTest) UnmarshalXMLAttr(attr Attr) error {339	return nil340}341342type MarshalerStruct struct {343	Foo MyMarshalerAttrTest `xml:",attr"`344}345346type InnerStruct struct {347	XMLName Name `xml:"testns outer"`348}349350type OuterStruct struct {351	InnerStruct352	IntAttr int `xml:"int,attr"`353}354355type OuterNamedStruct struct {356	InnerStruct357	XMLName Name `xml:"outerns test"`358	IntAttr int  `xml:"int,attr"`359}360361type OuterNamedOrderedStruct struct {362	XMLName Name `xml:"outerns test"`363	InnerStruct364	IntAttr int `xml:"int,attr"`365}366367type OuterOuterStruct struct {368	OuterStruct369}370371type NestedAndChardata struct {372	AB       []string `xml:"A>B"`373	Chardata string   `xml:",chardata"`374}375376type NestedAndComment struct {377	AB      []string `xml:"A>B"`378	Comment string   `xml:",comment"`379}380381type CDataTest struct {382	Chardata string `xml:",cdata"`383}384385type NestedAndCData struct {386	AB    []string `xml:"A>B"`387	CDATA string   `xml:",cdata"`388}389390func ifaceptr(x any) any {391	return &x392}393394func stringptr(x string) *string {395	return &x396}397398type T1 struct{}399type T2 struct{}400401type IndirComment struct {402	T1      T1403	Comment *string `xml:",comment"`404	T2      T2405}406407type DirectComment struct {408	T1      T1409	Comment string `xml:",comment"`410	T2      T2411}412413type IfaceComment struct {414	T1      T1415	Comment any `xml:",comment"`416	T2      T2417}418419type IndirChardata struct {420	T1       T1421	Chardata *string `xml:",chardata"`422	T2       T2423}424425type DirectChardata struct {426	T1       T1427	Chardata string `xml:",chardata"`428	T2       T2429}430431type IfaceChardata struct {432	T1       T1433	Chardata any `xml:",chardata"`434	T2       T2435}436437type IndirCDATA struct {438	T1    T1439	CDATA *string `xml:",cdata"`440	T2    T2441}442443type DirectCDATA struct {444	T1    T1445	CDATA string `xml:",cdata"`446	T2    T2447}448449type IfaceCDATA struct {450	T1    T1451	CDATA any `xml:",cdata"`452	T2    T2453}454455type IndirInnerXML struct {456	T1       T1457	InnerXML *string `xml:",innerxml"`458	T2       T2459}460461type DirectInnerXML struct {462	T1       T1463	InnerXML string `xml:",innerxml"`464	T2       T2465}466467type IfaceInnerXML struct {468	T1       T1469	InnerXML any `xml:",innerxml"`470	T2       T2471}472473type IndirElement struct {474	T1      T1475	Element *string476	T2      T2477}478479type DirectElement struct {480	T1      T1481	Element string482	T2      T2483}484485type IfaceElement struct {486	T1      T1487	Element any488	T2      T2489}490491type IndirOmitEmpty struct {492	T1        T1493	OmitEmpty *string `xml:",omitempty"`494	T2        T2495}496497type DirectOmitEmpty struct {498	T1        T1499	OmitEmpty string `xml:",omitempty"`500	T2        T2501}502503type IfaceOmitEmpty struct {504	T1        T1505	OmitEmpty any `xml:",omitempty"`506	T2        T2507}508509type IndirAny struct {510	T1  T1511	Any *string `xml:",any"`512	T2  T2513}514515type DirectAny struct {516	T1  T1517	Any string `xml:",any"`518	T2  T2519}520521type IfaceAny struct {522	T1  T1523	Any any `xml:",any"`524	T2  T2525}526527type Generic[T any] struct {528	X T529}530531var (532	nameAttr     = "Sarah"533	ageAttr      = uint(12)534	contentsAttr = "lorem ipsum"535	empty        = ""536)537538// Unless explicitly stated as such (or *Plain), all of the539// tests below are two-way tests. When introducing new tests,540// please try to make them two-way as well to ensure that541// marshaling and unmarshaling are as symmetrical as feasible.542var marshalTests = []struct {543	Value          any544	ExpectXML      string545	MarshalOnly    bool546	MarshalError   string547	UnmarshalOnly  bool548	UnmarshalError string549}{550	// Test nil marshals to nothing551	{Value: nil, ExpectXML: ``, MarshalOnly: true},552	{Value: nilStruct, ExpectXML: ``, MarshalOnly: true},553554	// Test value types555	{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},556	{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},557	{Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},558	{Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},559	{Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},560	{Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},561	{Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},562	{Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},563	{Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},564	{Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},565	{Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},566	{Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},567	{Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},568	{Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},569	{Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},570	{Value: &Plain{"</>"}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},571	{Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},572	{Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},573	{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},574	{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},575	{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},576	{Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},577578	// Test time.579	{580		Value:     &Plain{time.Unix(1e9, 123456789).UTC()},581		ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,582	},583584	// A pointer to struct{} may be used to test for an element's presence.585	{586		Value:     &PresenceTest{new(struct{})},587		ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,588	},589	{590		Value:     &PresenceTest{},591		ExpectXML: `<PresenceTest></PresenceTest>`,592	},593594	// A []byte field is only nil if the element was not found.595	{596		Value:         &Data{},597		ExpectXML:     `<Data></Data>`,598		UnmarshalOnly: true,599	},600	{601		Value:         &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},602		ExpectXML:     `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,603		UnmarshalOnly: true,604	},605606	// Check that []byte works, including named []byte types.607	{608		Value:     &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},609		ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,610	},611612	// Test innerxml613	{614		Value: &SecretAgent{615			Handle:    "007",616			Identity:  "James Bond",617			Obfuscate: "<redacted/>",618		},619		ExpectXML:   `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,620		MarshalOnly: true,621	},622	{623		Value: &SecretAgent{624			Handle:    "007",625			Identity:  "James Bond",626			Obfuscate: "<Identity>James Bond</Identity><redacted/>",627		},628		ExpectXML:     `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,629		UnmarshalOnly: true,630	},631632	// Test structs633	{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},634	{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},635	{Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},636	{Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},637	{Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},638	{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},639	{Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},640	{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},641	{Value: &Event{Year: -3114}, ExpectXML: `<event>-3114</event>`},642	{Value: &Movie{Length: 13440}, ExpectXML: `<movie>13440</movie>`},643	{Value: &Pi{Approximation: 3.14159265}, ExpectXML: `<pi>3.1415927</pi>`},644	{Value: &Universe{Visible: 9.3e13}, ExpectXML: `<universe>9.3e+13</universe>`},645	{Value: &Particle{HasMass: true}, ExpectXML: `<particle>true</particle>`},646	{Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `<departure>2013-01-09T00:15:00-09:00</departure>`},647	{Value: atomValue, ExpectXML: atomXML},648	{Value: &Generic[int]{1}, ExpectXML: `<Generic><X>1</X></Generic>`},649	{650		Value: &Ship{651			Name:  "Heart of Gold",652			Pilot: "Computer",653			Age:   1,654			Drive: ImprobabilityDrive,655			Passenger: []*Passenger{656				{657					Name:   []string{"Zaphod", "Beeblebrox"},658					Weight: 7.25,659				},660				{661					Name:   []string{"Trisha", "McMillen"},662					Weight: 5.5,663				},664				{665					Name:   []string{"Ford", "Prefect"},666					Weight: 7,667				},668				{669					Name:   []string{"Arthur", "Dent"},670					Weight: 6.75,671				},672			},673		},674		ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +675			`<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +676			`<age>1</age>` +677			`<passenger>` +678			`<name>Zaphod</name>` +679			`<name>Beeblebrox</name>` +680			`<weight>7.25</weight>` +681			`</passenger>` +682			`<passenger>` +683			`<name>Trisha</name>` +684			`<name>McMillen</name>` +685			`<weight>5.5</weight>` +686			`</passenger>` +687			`<passenger>` +688			`<name>Ford</name>` +689			`<name>Prefect</name>` +690			`<weight>7</weight>` +691			`</passenger>` +692			`<passenger>` +693			`<name>Arthur</name>` +694			`<name>Dent</name>` +695			`<weight>6.75</weight>` +696			`</passenger>` +697			`</spaceship>`,698	},699700	// Test a>b701	{702		Value: &NestedItems{Items: nil, Item1: nil},703		ExpectXML: `<result>` +704			`<Items>` +705			`</Items>` +706			`</result>`,707	},708	{709		Value: &NestedItems{Items: []string{}, Item1: []string{}},710		ExpectXML: `<result>` +711			`<Items>` +712			`</Items>` +713			`</result>`,714		MarshalOnly: true,715	},716	{717		Value: &NestedItems{Items: nil, Item1: []string{"A"}},718		ExpectXML: `<result>` +719			`<Items>` +720			`<item1>A</item1>` +721			`</Items>` +722			`</result>`,723	},724	{725		Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},726		ExpectXML: `<result>` +727			`<Items>` +728			`<item>A</item>` +729			`<item>B</item>` +730			`</Items>` +731			`</result>`,732	},733	{734		Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},735		ExpectXML: `<result>` +736			`<Items>` +737			`<item>A</item>` +738			`<item>B</item>` +739			`<item1>C</item1>` +740			`</Items>` +741			`</result>`,742	},743	{744		Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},745		ExpectXML: `<result>` +746			`<parent>` +747			`<c>C</c>` +748			`<b>B</b>` +749			`<a>A</a>` +750			`</parent>` +751			`</result>`,752	},753	{754		Value: &NilTest{A: "A", B: nil, C: "C"},755		ExpectXML: `<NilTest>` +756			`<parent1>` +757			`<parent2><a>A</a></parent2>` +758			`<parent2><c>C</c></parent2>` +759			`</parent1>` +760			`</NilTest>`,761		MarshalOnly: true, // Uses interface{}762	},763	{764		Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},765		ExpectXML: `<result>` +766			`<parent1><a>A</a></parent1>` +767			`<b>B</b>` +768			`<parent1>` +769			`<parent2><c>C</c></parent2>` +770			`<d>D</d>` +771			`</parent1>` +772			`</result>`,773	},774	{775		Value:     &Service{Port: &Port{Number: "80"}},776		ExpectXML: `<service><host><port>80</port></host></service>`,777	},778	{779		Value:     &Service{},780		ExpectXML: `<service></service>`,781	},782	{783		Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},784		ExpectXML: `<service>` +785			`<host><port>80</port></host>` +786			`<Extra1>A</Extra1>` +787			`<host><extra2>B</extra2></host>` +788			`</service>`,789		MarshalOnly: true,790	},791	{792		Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},793		ExpectXML: `<service>` +794			`<host><port>80</port></host>` +795			`<host><extra2>example</extra2></host>` +796			`</service>`,797		MarshalOnly: true,798	},799	{800		Value: &struct {801			XMLName struct{} `xml:"space top"`802			A       string   `xml:"x>a"`803			B       string   `xml:"x>b"`804			C       string   `xml:"space x>c"`805			C1      string   `xml:"space1 x>c"`806			D1      string   `xml:"space1 x>d"`807		}{808			A:  "a",809			B:  "b",810			C:  "c",811			C1: "c1",812			D1: "d1",813		},814		ExpectXML: `<top xmlns="space">` +815			`<x><a>a</a><b>b</b><c xmlns="space">c</c>` +816			`<c xmlns="space1">c1</c>` +817			`<d xmlns="space1">d1</d>` +818			`</x>` +819			`</top>`,820	},821	{822		Value: &struct {823			XMLName Name824			A       string `xml:"x>a"`825			B       string `xml:"x>b"`826			C       string `xml:"space x>c"`827			C1      string `xml:"space1 x>c"`828			D1      string `xml:"space1 x>d"`829		}{830			XMLName: Name{831				Space: "space0",832				Local: "top",833			},834			A:  "a",835			B:  "b",836			C:  "c",837			C1: "c1",838			D1: "d1",839		},840		ExpectXML: `<top xmlns="space0">` +841			`<x><a>a</a><b>b</b>` +842			`<c xmlns="space">c</c>` +843			`<c xmlns="space1">c1</c>` +844			`<d xmlns="space1">d1</d>` +845			`</x>` +846			`</top>`,847	},848	{849		Value: &struct {850			XMLName struct{} `xml:"top"`851			B       string   `xml:"space x>b"`852			B1      string   `xml:"space1 x>b"`853		}{854			B:  "b",855			B1: "b1",856		},857		ExpectXML: `<top>` +858			`<x><b xmlns="space">b</b>` +859			`<b xmlns="space1">b1</b></x>` +860			`</top>`,861	},862863	// Test struct embedding864	{865		Value: &EmbedA{866			EmbedC: EmbedC{867				FieldA1: "", // Shadowed by A.A868				FieldA2: "", // Shadowed by A.A869				FieldB:  "A.C.B",870				FieldC:  "A.C.C",871			},872			EmbedB: EmbedB{873				FieldB: "A.B.B",874				EmbedC: &EmbedC{875					FieldA1: "A.B.C.A1",876					FieldA2: "A.B.C.A2",877					FieldB:  "", // Shadowed by A.B.B878					FieldC:  "A.B.C.C",879				},880			},881			FieldA: "A.A",882			embedD: embedD{883				FieldE: "A.D.E",884			},885		},886		ExpectXML: `<EmbedA>` +887			`<FieldB>A.C.B</FieldB>` +888			`<FieldC>A.C.C</FieldC>` +889			`<EmbedB>` +890			`<FieldB>A.B.B</FieldB>` +891			`<FieldA>` +892			`<A1>A.B.C.A1</A1>` +893			`<A2>A.B.C.A2</A2>` +894			`</FieldA>` +895			`<FieldC>A.B.C.C</FieldC>` +896			`</EmbedB>` +897			`<FieldA>A.A</FieldA>` +898			`<FieldE>A.D.E</FieldE>` +899			`</EmbedA>`,900	},901902	// Embedded struct pointer field which is nil903	{904		Value:     &EmbedB{},905		ExpectXML: `<EmbedB><FieldB></FieldB></EmbedB>`,906	},907908	// Other kinds of nil embedded fields909	{910		Value:     &PointerAnonFields{},911		ExpectXML: `<PointerAnonFields></PointerAnonFields>`,912	},913914	// Test that name casing matters915	{916		Value:     &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},917		ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,918	},919920	// Test the order in which the XML element name is chosen921	{922		Value: &NamePrecedence{923			FromTag:     XMLNameWithoutTag{Value: "A"},924			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},925			FromNameTag: XMLNameWithTag{Value: "C"},926			InFieldName: "D",927		},928		ExpectXML: `<Parent>` +929			`<InTag>A</InTag>` +930			`<InXMLName>B</InXMLName>` +931			`<InXMLNameTag>C</InXMLNameTag>` +932			`<InFieldName>D</InFieldName>` +933			`</Parent>`,934		MarshalOnly: true,935	},936	{937		Value: &NamePrecedence{938			XMLName:     Name{Local: "Parent"},939			FromTag:     XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},940			FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},941			FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},942			InFieldName: "D",943		},944		ExpectXML: `<Parent>` +945			`<InTag>A</InTag>` +946			`<FromNameVal>B</FromNameVal>` +947			`<InXMLNameTag>C</InXMLNameTag>` +948			`<InFieldName>D</InFieldName>` +949			`</Parent>`,950		UnmarshalOnly: true,951	},952953	// xml.Name works in a plain field as well.954	{955		Value:     &NameInField{Name{Space: "ns", Local: "foo"}},956		ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,957	},958	{959		Value:         &NameInField{Name{Space: "ns", Local: "foo"}},960		ExpectXML:     `<NameInField><foo xmlns="ns"><ignore></ignore></foo></NameInField>`,961		UnmarshalOnly: true,962	},963964	// Marshaling zero xml.Name uses the tag or field name.965	{966		Value:       &NameInField{},967		ExpectXML:   `<NameInField><foo xmlns="ns"></foo></NameInField>`,968		MarshalOnly: true,969	},970971	// Test attributes972	{973		Value: &AttrTest{974			Int:   8,975			Named: 9,976			Float: 23.5,977			Uint8: 255,978			Bool:  true,979			Str:   "str",980			Bytes: []byte("byt"),981		},982		ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +983			` Bool="true" Str="str" Bytes="byt"></AttrTest>`,984	},985	{986		Value: &AttrTest{Bytes: []byte{}},987		ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +988			` Bool="false" Str="" Bytes=""></AttrTest>`,989	},990	{991		Value: &AttrsTest{992			Attrs: []Attr{993				{Name: Name{Local: "Answer"}, Value: "42"},994				{Name: Name{Local: "Int"}, Value: "8"},995				{Name: Name{Local: "int"}, Value: "9"},996				{Name: Name{Local: "Float"}, Value: "23.5"},997				{Name: Name{Local: "Uint8"}, Value: "255"},998				{Name: Name{Local: "Bool"}, Value: "true"},999				{Name: Name{Local: "Str"}, Value: "str"},1000				{Name: Name{Local: "Bytes"}, Value: "byt"},1001			},1002		},1003		ExpectXML:   `<AttrsTest Answer="42" Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="str" Bytes="byt" Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes=""></AttrsTest>`,1004		MarshalOnly: true,1005	},1006	{1007		Value: &AttrsTest{1008			Attrs: []Attr{1009				{Name: Name{Local: "Answer"}, Value: "42"},1010			},1011			Int:   8,1012			Named: 9,1013			Float: 23.5,1014			Uint8: 255,1015			Bool:  true,1016			Str:   "str",1017			Bytes: []byte("byt"),1018		},1019		ExpectXML: `<AttrsTest Answer="42" Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="str" Bytes="byt"></AttrsTest>`,1020	},1021	{1022		Value: &AttrsTest{1023			Attrs: []Attr{1024				{Name: Name{Local: "Int"}, Value: "0"},1025				{Name: Name{Local: "int"}, Value: "0"},1026				{Name: Name{Local: "Float"}, Value: "0"},1027				{Name: Name{Local: "Uint8"}, Value: "0"},1028				{Name: Name{Local: "Bool"}, Value: "false"},1029				{Name: Name{Local: "Str"}},1030				{Name: Name{Local: "Bytes"}},1031			},1032			Bytes: []byte{},1033		},1034		ExpectXML:   `<AttrsTest Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes="" Int="0" int="0" Float="0" Uint8="0" Bool="false" Str="" Bytes=""></AttrsTest>`,1035		MarshalOnly: true,1036	},1037	{1038		Value: &OmitAttrTest{1039			Int:   8,1040			Named: 9,1041			Float: 23.5,1042			Uint8: 255,1043			Bool:  true,1044			Str:   "str",1045			Bytes: []byte("byt"),1046			PStr:  &empty,1047		},1048		ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +1049			` Bool="true" Str="str" Bytes="byt" PStr=""></OmitAttrTest>`,1050	},1051	{1052		Value:     &OmitAttrTest{},1053		ExpectXML: `<OmitAttrTest></OmitAttrTest>`,1054	},10551056	// pointer fields1057	{1058		Value:       &PointerFieldsTest{Name: &nameAttr, Age: &ageAttr, Contents: &contentsAttr},1059		ExpectXML:   `<dummy name="Sarah" age="12">lorem ipsum</dummy>`,1060		MarshalOnly: true,1061	},10621063	// empty chardata pointer field1064	{1065		Value:       &ChardataEmptyTest{},1066		ExpectXML:   `<test></test>`,1067		MarshalOnly: true,1068	},10691070	// omitempty on fields1071	{1072		Value: &OmitFieldTest{1073			Int:   8,1074			Named: 9,1075			Float: 23.5,1076			Uint8: 255,1077			Bool:  true,1078			Str:   "str",1079			Bytes: []byte("byt"),1080			PStr:  &empty,1081			Ptr:   &PresenceTest{},1082		},1083		ExpectXML: `<OmitFieldTest>` +1084			`<Int>8</Int>` +1085			`<int>9</int>` +1086			`<Float>23.5</Float>` +1087			`<Uint8>255</Uint8>` +1088			`<Bool>true</Bool>` +1089			`<Str>str</Str>` +1090			`<Bytes>byt</Bytes>` +1091			`<PStr></PStr>` +1092			`<Ptr></Ptr>` +1093			`</OmitFieldTest>`,1094	},1095	{1096		Value:     &OmitFieldTest{},1097		ExpectXML: `<OmitFieldTest></OmitFieldTest>`,1098	},10991100	// Test ",any"1101	{1102		ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,1103		Value: &AnyTest{1104			Nested: "known",1105			AnyField: AnyHolder{1106				XMLName: Name{Local: "other"},1107				XML:     "<sub>unknown</sub>",1108			},1109		},1110	},1111	{1112		Value: &AnyTest{Nested: "known",1113			AnyField: AnyHolder{1114				XML:     "<unknown/>",1115				XMLName: Name{Local: "AnyField"},1116			},1117		},1118		ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,1119	},1120	{1121		ExpectXML: `<a><nested><value>b</value></nested></a>`,1122		Value: &AnyOmitTest{1123			Nested: "b",1124		},1125	},1126	{1127		ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,1128		Value: &AnySliceTest{1129			Nested: "b",1130			AnyField: []AnyHolder{1131				{1132					XMLName: Name{Local: "c"},1133					XML:     "<d>e</d>",1134				},1135				{1136					XMLName: Name{Space: "f", Local: "g"},1137					XML:     "<h>i</h>",1138				},1139			},1140		},1141	},1142	{1143		ExpectXML: `<a><nested><value>b</value></nested></a>`,1144		Value: &AnySliceTest{1145			Nested: "b",1146		},1147	},11481149	// Test recursive types.1150	{1151		Value: &RecurseA{1152			A: "a1",1153			B: &RecurseB{1154				A: &RecurseA{"a2", nil},1155				B: "b1",1156			},1157		},1158		ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,1159	},11601161	// Test ignoring fields via "-" tag1162	{1163		ExpectXML: `<IgnoreTest></IgnoreTest>`,1164		Value:     &IgnoreTest{},1165	},1166	{1167		ExpectXML:   `<IgnoreTest></IgnoreTest>`,1168		Value:       &IgnoreTest{PublicSecret: "can't tell"},1169		MarshalOnly: true,1170	},1171	{1172		ExpectXML:     `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,1173		Value:         &IgnoreTest{},1174		UnmarshalOnly: true,1175	},11761177	// Test escaping.1178	{1179		ExpectXML: `<a><nested><value>dquote: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</value></nested><empty></empty></a>`,1180		Value: &AnyTest{1181			Nested:   `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,1182			AnyField: AnyHolder{XMLName: Name{Local: "empty"}},1183		},1184	},1185	{1186		ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested><AnyField></AnyField></a>`,1187		Value: &AnyTest{1188			Nested:   "newline: \n; cr: \r; tab: \t;",1189			AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},1190		},1191	},1192	{1193		ExpectXML: "<a><nested><value>1\r2\r\n3\n\r4\n5</value></nested></a>",1194		Value: &AnyTest{1195			Nested: "1\n2\n3\n\n4\n5",1196		},1197		UnmarshalOnly: true,1198	},1199	{1200		ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,1201		Value: &EmbedInt{1202			MyInt: 42,1203		},1204	},1205	// Test outputting CDATA-wrapped text.1206	{1207		ExpectXML: `<CDataTest></CDataTest>`,1208		Value:     &CDataTest{},1209	},1210	{1211		ExpectXML: `<CDataTest><![CDATA[http://example.com/tests/1?foo=1&bar=baz]]></CDataTest>`,1212		Value: &CDataTest{1213			Chardata: "http://example.com/tests/1?foo=1&bar=baz",1214		},1215	},1216	{1217		ExpectXML: `<CDataTest><![CDATA[Literal <![CDATA[Nested]]]]><![CDATA[>!]]></CDataTest>`,1218		Value: &CDataTest{1219			Chardata: "Literal <![CDATA[Nested]]>!",1220		},1221	},1222	{1223		ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,1224		Value: &CDataTest{1225			Chardata: "<![CDATA[Nested]]> Literal!",1226		},1227	},1228	{1229		ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal! <![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,1230		Value: &CDataTest{1231			Chardata: "<![CDATA[Nested]]> Literal! <![CDATA[Nested]]> Literal!",1232		},1233	},1234	{1235		ExpectXML: `<CDataTest><![CDATA[<![CDATA[<![CDATA[Nested]]]]><![CDATA[>]]]]><![CDATA[>]]></CDataTest>`,1236		Value: &CDataTest{1237			Chardata: "<![CDATA[<![CDATA[Nested]]>]]>",1238		},1239	},12401241	// Test omitempty with parent chain; see golang.org/issue/4168.1242	{1243		ExpectXML: `<Strings><A></A></Strings>`,1244		Value:     &Strings{},1245	},1246	// Custom marshalers.1247	{1248		ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,1249		Value:     &MyMarshalerTest{},1250	},1251	{1252		ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,1253		Value:     &MarshalerStruct{},1254	},1255	{1256		ExpectXML: `<outer xmlns="testns" int="10"></outer>`,1257		Value:     &OuterStruct{IntAttr: 10},1258	},1259	{1260		ExpectXML: `<test xmlns="outerns" int="10"></test>`,1261		Value:     &OuterNamedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},1262	},1263	{1264		ExpectXML: `<test xmlns="outerns" int="10"></test>`,1265		Value:     &OuterNamedOrderedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},1266	},1267	{1268		ExpectXML: `<outer xmlns="testns" int="10"></outer>`,1269		Value:     &OuterOuterStruct{OuterStruct{IntAttr: 10}},1270	},1271	{1272		ExpectXML: `<NestedAndChardata><A><B></B><B></B></A>test</NestedAndChardata>`,1273		Value:     &NestedAndChardata{AB: make([]string, 2), Chardata: "test"},1274	},1275	{1276		ExpectXML: `<NestedAndComment><A><B></B><B></B></A><!--test--></NestedAndComment>`,1277		Value:     &NestedAndComment{AB: make([]string, 2), Comment: "test"},1278	},1279	{1280		ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`,1281		Value:     &NestedAndCData{AB: make([]string, 2), CDATA: "test"},1282	},1283	// Test pointer indirection in various kinds of fields.1284	// https://golang.org/issue/190631285	{1286		ExpectXML:   `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,1287		Value:       &IndirComment{Comment: stringptr("hi")},1288		MarshalOnly: true,1289	},1290	{1291		ExpectXML:   `<IndirComment><T1></T1><T2></T2></IndirComment>`,1292		Value:       &IndirComment{Comment: stringptr("")},1293		MarshalOnly: true,1294	},1295	{1296		ExpectXML:    `<IndirComment><T1></T1><T2></T2></IndirComment>`,1297		Value:        &IndirComment{Comment: nil},1298		MarshalError: "xml: bad type for comment field of xml.IndirComment",1299	},1300	{1301		ExpectXML:     `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,1302		Value:         &IndirComment{Comment: nil},1303		UnmarshalOnly: true,1304	},1305	{1306		ExpectXML:   `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,1307		Value:       &IfaceComment{Comment: "hi"},1308		MarshalOnly: true,1309	},1310	{1311		ExpectXML:     `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,1312		Value:         &IfaceComment{Comment: nil},1313		UnmarshalOnly: true,1314	},1315	{1316		ExpectXML:    `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,1317		Value:        &IfaceComment{Comment: nil},1318		MarshalError: "xml: bad type for comment field of xml.IfaceComment",1319	},1320	{1321		ExpectXML:     `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,1322		Value:         &IfaceComment{Comment: nil},1323		UnmarshalOnly: true,1324	},1325	{1326		ExpectXML: `<DirectComment><T1></T1><!--hi--><T2></T2></DirectComment>`,1327		Value:     &DirectComment{Comment: string("hi")},1328	},1329	{1330		ExpectXML: `<DirectComment><T1></T1><T2></T2></DirectComment>`,1331		Value:     &DirectComment{Comment: string("")},1332	},1333	{1334		ExpectXML: `<IndirChardata><T1></T1>hi<T2></T2></IndirChardata>`,1335		Value:     &IndirChardata{Chardata: stringptr("hi")},1336	},1337	{1338		ExpectXML:     `<IndirChardata><T1></T1><![CDATA[hi]]><T2></T2></IndirChardata>`,1339		Value:         &IndirChardata{Chardata: stringptr("hi")},1340		UnmarshalOnly: true, // marshals without CDATA1341	},1342	{1343		ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,1344		Value:     &IndirChardata{Chardata: stringptr("")},1345	},1346	{1347		ExpectXML:   `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,1348		Value:       &IndirChardata{Chardata: nil},1349		MarshalOnly: true, // unmarshal leaves Chardata=stringptr("")1350	},1351	{1352		ExpectXML:      `<IfaceChardata><T1></T1>hi<T2></T2></IfaceChardata>`,1353		Value:          &IfaceChardata{Chardata: string("hi")},1354		UnmarshalError: "cannot unmarshal into interface {}",1355	},1356	{1357		ExpectXML:      `<IfaceChardata><T1></T1><![CDATA[hi]]><T2></T2></IfaceChardata>`,1358		Value:          &IfaceChardata{Chardata: string("hi")},1359		UnmarshalOnly:  true, // marshals without CDATA1360		UnmarshalError: "cannot unmarshal into interface {}",1361	},1362	{1363		ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,1364		Value:          &IfaceChardata{Chardata: string("")},1365		UnmarshalError: "cannot unmarshal into interface {}",1366	},1367	{1368		ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,1369		Value:          &IfaceChardata{Chardata: nil},1370		UnmarshalError: "cannot unmarshal into interface {}",1371	},1372	{1373		ExpectXML: `<DirectChardata><T1></T1>hi<T2></T2></DirectChardata>`,1374		Value:     &DirectChardata{Chardata: string("hi")},1375	},1376	{1377		ExpectXML:     `<DirectChardata><T1></T1><![CDATA[hi]]><T2></T2></DirectChardata>`,1378		Value:         &DirectChardata{Chardata: string("hi")},1379		UnmarshalOnly: true, // marshals without CDATA1380	},1381	{1382		ExpectXML: `<DirectChardata><T1></T1><T2></T2></DirectChardata>`,1383		Value:     &DirectChardata{Chardata: string("")},1384	},1385	{1386		ExpectXML: `<IndirCDATA><T1></T1><![CDATA[hi]]><T2></T2></IndirCDATA>`,1387		Value:     &IndirCDATA{CDATA: stringptr("hi")},1388	},1389	{1390		ExpectXML:     `<IndirCDATA><T1></T1>hi<T2></T2></IndirCDATA>`,1391		Value:         &IndirCDATA{CDATA: stringptr("hi")},1392		UnmarshalOnly: true, // marshals with CDATA1393	},1394	{1395		ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,1396		Value:     &IndirCDATA{CDATA: stringptr("")},1397	},1398	{1399		ExpectXML:   `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,1400		Value:       &IndirCDATA{CDATA: nil},1401		MarshalOnly: true, // unmarshal leaves CDATA=stringptr("")1402	},1403	{1404		ExpectXML:      `<IfaceCDATA><T1></T1><![CDATA[hi]]><T2></T2></IfaceCDATA>`,1405		Value:          &IfaceCDATA{CDATA: string("hi")},1406		UnmarshalError: "cannot unmarshal into interface {}",1407	},1408	{1409		ExpectXML:      `<IfaceCDATA><T1></T1>hi<T2></T2></IfaceCDATA>`,1410		Value:          &IfaceCDATA{CDATA: string("hi")},1411		UnmarshalOnly:  true, // marshals with CDATA1412		UnmarshalError: "cannot unmarshal into interface {}",1413	},1414	{1415		ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,1416		Value:          &IfaceCDATA{CDATA: string("")},1417		UnmarshalError: "cannot unmarshal into interface {}",1418	},1419	{1420		ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,1421		Value:          &IfaceCDATA{CDATA: nil},1422		UnmarshalError: "cannot unmarshal into interface {}",1423	},1424	{1425		ExpectXML: `<DirectCDATA><T1></T1><![CDATA[hi]]><T2></T2></DirectCDATA>`,1426		Value:     &DirectCDATA{CDATA: string("hi")},1427	},1428	{1429		ExpectXML:     `<DirectCDATA><T1></T1>hi<T2></T2></DirectCDATA>`,1430		Value:         &DirectCDATA{CDATA: string("hi")},1431		UnmarshalOnly: true, // marshals with CDATA1432	},1433	{1434		ExpectXML: `<DirectCDATA><T1></T1><T2></T2></DirectCDATA>`,1435		Value:     &DirectCDATA{CDATA: string("")},1436	},1437	{1438		ExpectXML:   `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,1439		Value:       &IndirInnerXML{InnerXML: stringptr("<hi/>")},1440		MarshalOnly: true,1441	},1442	{1443		ExpectXML:   `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,1444		Value:       &IndirInnerXML{InnerXML: stringptr("")},1445		MarshalOnly: true,1446	},1447	{1448		ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,1449		Value:     &IndirInnerXML{InnerXML: nil},1450	},1451	{1452		ExpectXML:     `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,1453		Value:         &IndirInnerXML{InnerXML: nil},1454		UnmarshalOnly: true,1455	},1456	{1457		ExpectXML:   `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,1458		Value:       &IfaceInnerXML{InnerXML: "<hi/>"},1459		MarshalOnly: true,1460	},1461	{1462		ExpectXML:     `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,1463		Value:         &IfaceInnerXML{InnerXML: nil},1464		UnmarshalOnly: true,1465	},1466	{1467		ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,1468		Value:     &IfaceInnerXML{InnerXML: nil},1469	},1470	{1471		ExpectXML:     `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,1472		Value:         &IfaceInnerXML{InnerXML: nil},1473		UnmarshalOnly: true,1474	},1475	{1476		ExpectXML:   `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,1477		Value:       &DirectInnerXML{InnerXML: string("<hi/>")},1478		MarshalOnly: true,1479	},1480	{1481		ExpectXML:     `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,1482		Value:         &DirectInnerXML{InnerXML: string("<T1></T1><hi/><T2></T2>")},1483		UnmarshalOnly: true,1484	},1485	{1486		ExpectXML:   `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,1487		Value:       &DirectInnerXML{InnerXML: string("")},1488		MarshalOnly: true,1489	},1490	{1491		ExpectXML:     `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,1492		Value:         &DirectInnerXML{InnerXML: string("<T1></T1><T2></T2>")},1493		UnmarshalOnly: true,1494	},1495	{1496		ExpectXML: `<IndirElement><T1></T1><Element>hi</Element><T2></T2></IndirElement>`,1497		Value:     &IndirElement{Element: stringptr("hi")},1498	},1499	{1500		ExpectXML: `<IndirElement><T1></T1><Element></Element><T2></T2></IndirElement>`,1501		Value:     &IndirElement{Element: stringptr("")},1502	},1503	{1504		ExpectXML: `<IndirElement><T1></T1><T2></T2></IndirElement>`,1505		Value:     &IndirElement{Element: nil},1506	},1507	{1508		ExpectXML:   `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,1509		Value:       &IfaceElement{Element: "hi"},1510		MarshalOnly: true,1511	},1512	{1513		ExpectXML:     `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,1514		Value:         &IfaceElement{Element: nil},1515		UnmarshalOnly: true,1516	},1517	{1518		ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,1519		Value:     &IfaceElement{Element: nil},1520	},1521	{1522		ExpectXML:     `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,1523		Value:         &IfaceElement{Element: nil},1524		UnmarshalOnly: true,1525	},1526	{1527		ExpectXML: `<DirectElement><T1></T1><Element>hi</Element><T2></T2></DirectElement>`,1528		Value:     &DirectElement{Element: string("hi")},1529	},1530	{1531		ExpectXML: `<DirectElement><T1></T1><Element></Element><T2></T2></DirectElement>`,1532		Value:     &DirectElement{Element: string("")},1533	},1534	{1535		ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IndirOmitEmpty>`,1536		Value:     &IndirOmitEmpty{OmitEmpty: stringptr("hi")},1537	},1538	{1539		// Note: Changed in Go 1.8 to include <OmitEmpty> element (because x.OmitEmpty != nil).1540		ExpectXML:   `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,1541		Value:       &IndirOmitEmpty{OmitEmpty: stringptr("")},1542		MarshalOnly: true,1543	},1544	{1545		ExpectXML:     `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,1546		Value:         &IndirOmitEmpty{OmitEmpty: stringptr("")},1547		UnmarshalOnly: true,1548	},1549	{1550		ExpectXML: `<IndirOmitEmpty><T1></T1><T2></T2></IndirOmitEmpty>`,1551		Value:     &IndirOmitEmpty{OmitEmpty: nil},1552	},1553	{1554		ExpectXML:   `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,1555		Value:       &IfaceOmitEmpty{OmitEmpty: "hi"},1556		MarshalOnly: true,1557	},1558	{1559		ExpectXML:     `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,1560		Value:         &IfaceOmitEmpty{OmitEmpty: nil},1561		UnmarshalOnly: true,1562	},1563	{1564		ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,1565		Value:     &IfaceOmitEmpty{OmitEmpty: nil},1566	},1567	{1568		ExpectXML:     `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,1569		Value:         &IfaceOmitEmpty{OmitEmpty: nil},1570		UnmarshalOnly: true,1571	},1572	{1573		ExpectXML: `<DirectOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></DirectOmitEmpty>`,1574		Value:     &DirectOmitEmpty{OmitEmpty: string("hi")},1575	},1576	{1577		ExpectXML: `<DirectOmitEmpty><T1></T1><T2></T2></DirectOmitEmpty>`,1578		Value:     &DirectOmitEmpty{OmitEmpty: string("")},1579	},1580	{1581		ExpectXML: `<IndirAny><T1></T1><Any>hi</Any><T2></T2></IndirAny>`,1582		Value:     &IndirAny{Any: stringptr("hi")},1583	},1584	{1585		ExpectXML: `<IndirAny><T1></T1><Any></Any><T2></T2></IndirAny>`,1586		Value:     &IndirAny{Any: stringptr("")},1587	},1588	{1589		ExpectXML: `<IndirAny><T1></T1><T2></T2></IndirAny>`,1590		Value:     &IndirAny{Any: nil},1591	},1592	{1593		ExpectXML:   `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,1594		Value:       &IfaceAny{Any: "hi"},1595		MarshalOnly: true,1596	},1597	{1598		ExpectXML:     `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,1599		Value:         &IfaceAny{Any: nil},1600		UnmarshalOnly: true,1601	},1602	{1603		ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,1604		Value:     &IfaceAny{Any: nil},1605	},1606	{1607		ExpectXML:     `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,1608		Value:         &IfaceAny{Any: nil},1609		UnmarshalOnly: true,1610	},1611	{1612		ExpectXML: `<DirectAny><T1></T1><Any>hi</Any><T2></T2></DirectAny>`,1613		Value:     &DirectAny{Any: string("hi")},1614	},1615	{1616		ExpectXML: `<DirectAny><T1></T1><Any></Any><T2></T2></DirectAny>`,1617		Value:     &DirectAny{Any: string("")},1618	},1619	{1620		ExpectXML:     `<IndirFoo><T1></T1><Foo>hi</Foo><T2></T2></IndirFoo>`,1621		Value:         &IndirAny{Any: stringptr("hi")},1622		UnmarshalOnly: true,1623	},1624	{1625		ExpectXML:     `<IndirFoo><T1></T1><Foo></Foo><T2></T2></IndirFoo>`,1626		Value:         &IndirAny{Any: stringptr("")},1627		UnmarshalOnly: true,1628	},1629	{1630		ExpectXML:     `<IndirFoo><T1></T1><T2></T2></IndirFoo>`,1631		Value:         &IndirAny{Any: nil},1632		UnmarshalOnly: true,1633	},1634	{1635		ExpectXML:     `<IfaceFoo><T1></T1><Foo>hi</Foo><T2></T2></IfaceFoo>`,1636		Value:         &IfaceAny{Any: nil},1637		UnmarshalOnly: true,1638	},1639	{1640		ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,1641		Value:         &IfaceAny{Any: nil},1642		UnmarshalOnly: true,1643	},1644	{1645		ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,1646		Value:         &IfaceAny{Any: nil},1647		UnmarshalOnly: true,1648	},1649	{1650		ExpectXML:     `<DirectFoo><T1></T1><Foo>hi</Foo><T2></T2></DirectFoo>`,1651		Value:         &DirectAny{Any: string("hi")},1652		UnmarshalOnly: true,1653	},1654	{1655		ExpectXML:     `<DirectFoo><T1></T1><Foo></Foo><T2></T2></DirectFoo>`,1656		Value:         &DirectAny{Any: string("")},1657		UnmarshalOnly: true,1658	},1659}16601661func TestMarshal(t *testing.T) {1662	for idx, test := range marshalTests {1663		if test.UnmarshalOnly {1664			continue1665		}16661667		t.Run(fmt.Sprintf("%d", idx), func(t *testing.T) {1668			data, err := Marshal(test.Value)1669			if err != nil {1670				if test.MarshalError == "" {1671					t.Errorf("marshal(%#v): %s", test.Value, err)1672					return1673				}1674				if !strings.Contains(err.Error(), test.MarshalError) {1675					t.Errorf("marshal(%#v): %s, want %q", test.Value, err, test.MarshalError)1676				}1677				return1678			}1679			if test.MarshalError != "" {1680				t.Errorf("Marshal succeeded, want error %q", test.MarshalError)1681				return1682			}1683			if got, want := string(data), test.ExpectXML; got != want {1684				if strings.Contains(want, "\n") {1685					t.Errorf("marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", test.Value, got, want)1686				} else {1687					t.Errorf("marshal(%#v):\nhave %#q\nwant %#q", test.Value, got, want)1688				}1689			}1690		})1691	}1692}16931694type AttrParent struct {1695	X string `xml:"X>Y,attr"`1696}16971698type BadAttr struct {1699	Name map[string]string `xml:"name,attr"`1700}17011702var marshalErrorTests = []struct {1703	Value any1704	Err   string1705	Kind  reflect.Kind1706}{1707	{1708		Value: make(chan bool),1709		Err:   "xml: unsupported type: chan bool",1710		Kind:  reflect.Chan,1711	},1712	{1713		Value: map[string]string{1714			"question": "What do you get when you multiply six by nine?",1715			"answer":   "42",1716		},1717		Err:  "xml: unsupported type: map[string]string",1718		Kind: reflect.Map,1719	},1720	{1721		Value: map[*Ship]bool{nil: false},1722		Err:   "xml: unsupported type: map[*xml.Ship]bool",1723		Kind:  reflect.Map,1724	},1725	{1726		Value: &Domain{Comment: []byte("f--bar")},1727		Err:   `xml: comments must not contain "--"`,1728	},1729	// Reject parent chain with attr, never worked; see golang.org/issue/5033.1730	{1731		Value: &AttrParent{},1732		Err:   `xml: X>Y chain not valid with attr flag`,1733	},1734	{1735		Value: BadAttr{map[string]string{"X": "Y"}},1736		Err:   `xml: unsupported type: map[string]string`,1737	},1738}17391740var marshalIndentTests = []struct {1741	Value     any1742	Prefix    string1743	Indent    string1744	ExpectXML string1745}{1746	{1747		Value: &SecretAgent{1748			Handle:    "007",1749			Identity:  "James Bond",1750			Obfuscate: "<redacted/>",1751		},1752		Prefix:    "",1753		Indent:    "\t",1754		ExpectXML: "<agent handle=\"007\">\n\t<Identity>James Bond</Identity><redacted/>\n</agent>",1755	},1756}17571758func TestMarshalErrors(t *testing.T) {1759	for idx, test := range marshalErrorTests {1760		data, err := Marshal(test.Value)1761		if err == nil {1762			t.Errorf("#%d: marshal(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)1763			continue1764		}1765		if err.Error() != test.Err {1766			t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)1767		}1768		if test.Kind != reflect.Invalid {1769			if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {1770				t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)1771			}1772		}1773	}1774}17751776// Do invertibility testing on the various structures that we test1777func TestUnmarshal(t *testing.T) {1778	for i, test := range marshalTests {1779		if test.MarshalOnly {1780			continue1781		}1782		if _, ok := test.Value.(*Plain); ok {1783			continue1784		}1785		if test.ExpectXML == `<top>`+1786			`<x><b xmlns="space">b</b>`+1787			`<b xmlns="space1">b1</b></x>`+1788			`</top>` {1789			// TODO(rogpeppe): re-enable this test in1790			// https://go-review.googlesource.com/#/c/5910/1791			continue1792		}17931794		vt := reflect.TypeOf(test.Value)1795		dest := reflect.New(vt.Elem()).Interface()1796		err := Unmarshal([]byte(test.ExpectXML), dest)17971798		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {1799			switch fix := dest.(type) {1800			case *Feed:1801				fix.Author.InnerXML = ""1802				for i := range fix.Entry {1803					fix.Entry[i].Author.InnerXML = ""1804				}1805			}18061807			if err != nil {1808				if test.UnmarshalError == "" {1809					t.Errorf("unmarshal(%#v): %s", test.ExpectXML, err)1810					return1811				}1812				if !strings.Contains(err.Error(), test.UnmarshalError) {1813					t.Errorf("unmarshal(%#v): %s, want %q", test.ExpectXML, err, test.UnmarshalError)1814				}1815				return1816			}1817			if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {1818				t.Errorf("unmarshal(%q):\nhave %#v\nwant %#v", test.ExpectXML, got, want)1819			}1820		})1821	}1822}18231824func TestMarshalIndent(t *testing.T) {1825	for i, test := range marshalIndentTests {1826		data, err := MarshalIndent(test.Value, test.Prefix, test.Indent)1827		if err != nil {1828			t.Errorf("#%d: Error: %s", i, err)1829			continue1830		}1831		if got, want := string(data), test.ExpectXML; got != want {1832			t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want)1833		}1834	}1835}18361837type limitedBytesWriter struct {1838	w      io.Writer1839	remain int // until writes fail1840}18411842func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {1843	if lw.remain <= 0 {1844		println("error")1845		return 0, errors.New("write limit hit")1846	}1847	if len(p) > lw.remain {1848		p = p[:lw.remain]1849		n, _ = lw.w.Write(p)1850		lw.remain = 01851		return n, errors.New("write limit hit")1852	}1853	n, err = lw.w.Write(p)1854	lw.remain -= n1855	return n, err1856}18571858func TestMarshalWriteErrors(t *testing.T) {1859	var buf bytes.Buffer1860	const writeCap = 10241861	w := &limitedBytesWriter{&buf, writeCap}1862	enc := NewEncoder(w)1863	var err error1864	var i int1865	const n = 40001866	for i = 1; i <= n; i++ {1867		err = enc.Encode(&Passenger{1868			Name:   []string{"Alice", "Bob"},1869			Weight: 5,1870		})1871		if err != nil {1872			break1873		}1874	}1875	if err == nil {1876		t.Error("expected an error")1877	}1878	if i == n {1879		t.Errorf("expected to fail before the end")1880	}1881	if buf.Len() != writeCap {1882		t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)1883	}1884}18851886func TestMarshalWriteIOErrors(t *testing.T) {1887	enc := NewEncoder(errWriter{})18881889	expectErr := "unwritable"1890	err := enc.Encode(&Passenger{})1891	if err == nil || err.Error() != expectErr {1892		t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)1893	}1894}18951896func TestMarshalFlush(t *testing.T) {1897	var buf strings.Builder1898	enc := NewEncoder(&buf)1899	if err := enc.EncodeToken(CharData("hello world")); err != nil {1900		t.Fatalf("enc.EncodeToken: %v", err)1901	}1902	if buf.Len() > 0 {1903		t.Fatalf("enc.EncodeToken caused actual write: %q", buf.String())1904	}1905	if err := enc.Flush(); err != nil {1906		t.Fatalf("enc.Flush: %v", err)1907	}1908	if buf.String() != "hello world" {1909		t.Fatalf("after enc.Flush, buf.String() = %q, want %q", buf.String(), "hello world")1910	}1911}19121913func BenchmarkMarshal(b *testing.B) {1914	b.ReportAllocs()1915	b.RunParallel(func(pb *testing.PB) {1916		for pb.Next() {1917			Marshal(atomValue)1918		}1919	})1920}19211922func BenchmarkUnmarshal(b *testing.B) {1923	b.ReportAllocs()1924	xml := []byte(atomXML)1925	b.RunParallel(func(pb *testing.PB) {1926		for pb.Next() {1927			Unmarshal(xml, &Feed{})1928		}1929	})1930}19311932// golang.org/issue/65561933func TestStructPointerMarshal(t *testing.T) {1934	type A struct {1935		XMLName string `xml:"a"`1936		B       []any1937	}1938	type C struct {1939		XMLName Name1940		Value   string `xml:"value"`1941	}19421943	a := new(A)1944	a.B = append(a.B, &C{1945		XMLName: Name{Local: "c"},1946		Value:   "x",1947	})19481949	b, err := Marshal(a)1950	if err != nil {1951		t.Fatal(err)1952	}1953	if x := string(b); x != "<a><c><value>x</value></c></a>" {1954		t.Fatal(x)1955	}1956	var v A1957	err = Unmarshal(b, &v)1958	if err != nil {1959		t.Fatal(err)1960	}1961}19621963var encodeTokenTests = []struct {1964	desc string1965	toks []Token1966	want string1967	err  string1968}{{1969	desc: "start element with name space",1970	toks: []Token{1971		StartElement{Name{"space", "local"}, nil},1972	},1973	want: `<local xmlns="space">`,1974}, {1975	desc: "start element with no name",1976	toks: []Token{1977		StartElement{Name{"space", ""}, nil},1978	},1979	err: "xml: start tag with no name",1980}, {1981	desc: "end element with no name",1982	toks: []Token{1983		EndElement{Name{"space", ""}},1984	},1985	err: "xml: end tag with no name",1986}, {1987	desc: "char data",1988	toks: []Token{1989		CharData("foo"),1990	},1991	want: `foo`,1992}, {1993	desc: "char data with escaped chars",1994	toks: []Token{1995		CharData(" \t\n"),1996	},1997	want: " &#x9;\n",1998}, {1999	desc: "comment",2000	toks: []Token{

Code quality findings 14

Empty interface; prefer specific types or generics for type safety
empty-interface
MarshalOnly: true, // Uses interface{}
Blank identifier discarding results; verify intentional ignoring of return values
warning correctness blank-identifier-discard
n, _ = lw.w.Write(p)
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for idx, test := range marshalTests {
Deeply nested control structures reduce readability; consider extracting to functions or using early returns
info maintainability deep-nesting
if test.MarshalError == "" {
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for idx, test := range marshalErrorTests {
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for i, test := range marshalTests {
String to byte slice conversion inside loop allocates a new slice each iteration; convert once before the loop
info correctness string-to-byte-in-loop
err := Unmarshal([]byte(test.ExpectXML), dest)
Type switch without default case; unhandled types will silently do nothing. Add a default case for safety
info correctness unchecked-type-switch
switch fix := dest.(type) {
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for i, test := range marshalIndentTests {
String to byte slice conversion inside loop allocates a new slice each iteration; convert once before the loop
info correctness string-to-byte-in-loop
xml := []byte(atomXML)
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for i, tt := range encodeTokenTests {
Deeply nested control structures reduce readability; consider extracting to functions or using early returns
info maintainability deep-nesting
for i, tt := range encodeTokenTests {
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for j, tok := range tt.toks {
Range over slice copies each element by value; use index or pointer receiver for large structs to avoid copies
info performance copy-large-struct
for j, tok := range tt.toks {

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.