...
Run Format

Source file src/encoding/xml/marshal_test.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package xml
     6	
     7	import (
     8		"bytes"
     9		"errors"
    10		"fmt"
    11		"io"
    12		"reflect"
    13		"strconv"
    14		"strings"
    15		"sync"
    16		"testing"
    17		"time"
    18	)
    19	
    20	type DriveType int
    21	
    22	const (
    23		HyperDrive DriveType = iota
    24		ImprobabilityDrive
    25	)
    26	
    27	type Passenger struct {
    28		Name   []string `xml:"name"`
    29		Weight float32  `xml:"weight"`
    30	}
    31	
    32	type Ship struct {
    33		XMLName struct{} `xml:"spaceship"`
    34	
    35		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    string
    41	}
    42	
    43	type NamedType string
    44	
    45	type 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	}
    51	
    52	type Domain struct {
    53		XMLName struct{} `xml:"domain"`
    54		Country string   `xml:",attr,omitempty"`
    55		Name    []byte   `xml:",chardata"`
    56		Comment []byte   `xml:",comment"`
    57	}
    58	
    59	type Book struct {
    60		XMLName struct{} `xml:"book"`
    61		Title   string   `xml:",chardata"`
    62	}
    63	
    64	type Event struct {
    65		XMLName struct{} `xml:"event"`
    66		Year    int      `xml:",chardata"`
    67	}
    68	
    69	type Movie struct {
    70		XMLName struct{} `xml:"movie"`
    71		Length  uint     `xml:",chardata"`
    72	}
    73	
    74	type Pi struct {
    75		XMLName       struct{} `xml:"pi"`
    76		Approximation float32  `xml:",chardata"`
    77	}
    78	
    79	type Universe struct {
    80		XMLName struct{} `xml:"universe"`
    81		Visible float64  `xml:",chardata"`
    82	}
    83	
    84	type Particle struct {
    85		XMLName struct{} `xml:"particle"`
    86		HasMass bool     `xml:",chardata"`
    87	}
    88	
    89	type Departure struct {
    90		XMLName struct{}  `xml:"departure"`
    91		When    time.Time `xml:",chardata"`
    92	}
    93	
    94	type SecretAgent struct {
    95		XMLName   struct{} `xml:"agent"`
    96		Handle    string   `xml:"handle,attr"`
    97		Identity  string
    98		Obfuscate string `xml:",innerxml"`
    99	}
   100	
   101	type NestedItems struct {
   102		XMLName struct{} `xml:"result"`
   103		Items   []string `xml:">item"`
   104		Item1   []string `xml:"Items>item1"`
   105	}
   106	
   107	type 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	}
   113	
   114	type 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	}
   121	
   122	type NilTest struct {
   123		A interface{} `xml:"parent1>parent2>a"`
   124		B interface{} `xml:"parent1>b"`
   125		C interface{} `xml:"parent1>parent2>c"`
   126	}
   127	
   128	type Service struct {
   129		XMLName struct{} `xml:"service"`
   130		Domain  *Domain  `xml:"host>domain"`
   131		Port    *Port    `xml:"host>port"`
   132		Extra1  interface{}
   133		Extra2  interface{} `xml:"host>extra2"`
   134	}
   135	
   136	var nilStruct *Ship
   137	
   138	type EmbedA struct {
   139		EmbedC
   140		EmbedB EmbedB
   141		FieldA string
   142		embedD
   143	}
   144	
   145	type EmbedB struct {
   146		FieldB string
   147		*EmbedC
   148	}
   149	
   150	type EmbedC struct {
   151		FieldA1 string `xml:"FieldA>A1"`
   152		FieldA2 string `xml:"FieldA>A2"`
   153		FieldB  string
   154		FieldC  string
   155	}
   156	
   157	type embedD struct {
   158		fieldD string
   159		FieldE string // Promoted and visible when embedD is embedded.
   160	}
   161	
   162	type NameCasing struct {
   163		XMLName struct{} `xml:"casing"`
   164		Xy      string
   165		XY      string
   166		XyA     string `xml:"Xy,attr"`
   167		XYA     string `xml:"XY,attr"`
   168	}
   169	
   170	type NamePrecedence struct {
   171		XMLName     Name              `xml:"Parent"`
   172		FromTag     XMLNameWithoutTag `xml:"InTag"`
   173		FromNameVal XMLNameWithoutTag
   174		FromNameTag XMLNameWithTag
   175		InFieldName string
   176	}
   177	
   178	type XMLNameWithTag struct {
   179		XMLName Name   `xml:"InXMLNameTag"`
   180		Value   string `xml:",chardata"`
   181	}
   182	
   183	type XMLNameWithoutTag struct {
   184		XMLName Name
   185		Value   string `xml:",chardata"`
   186	}
   187	
   188	type NameInField struct {
   189		Foo Name `xml:"ns foo"`
   190	}
   191	
   192	type 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	}
   201	
   202	type 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	}
   212	
   213	type 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	}
   223	
   224	type 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	}
   235	
   236	type AnyTest struct {
   237		XMLName  struct{}  `xml:"a"`
   238		Nested   string    `xml:"nested>value"`
   239		AnyField AnyHolder `xml:",any"`
   240	}
   241	
   242	type AnyOmitTest struct {
   243		XMLName  struct{}   `xml:"a"`
   244		Nested   string     `xml:"nested>value"`
   245		AnyField *AnyHolder `xml:",any,omitempty"`
   246	}
   247	
   248	type AnySliceTest struct {
   249		XMLName  struct{}    `xml:"a"`
   250		Nested   string      `xml:"nested>value"`
   251		AnyField []AnyHolder `xml:",any"`
   252	}
   253	
   254	type AnyHolder struct {
   255		XMLName Name
   256		XML     string `xml:",innerxml"`
   257	}
   258	
   259	type RecurseA struct {
   260		A string
   261		B *RecurseB
   262	}
   263	
   264	type RecurseB struct {
   265		A *RecurseA
   266		B string
   267	}
   268	
   269	type PresenceTest struct {
   270		Exists *struct{}
   271	}
   272	
   273	type IgnoreTest struct {
   274		PublicSecret string `xml:"-"`
   275	}
   276	
   277	type MyBytes []byte
   278	
   279	type Data struct {
   280		Bytes  []byte
   281		Attr   []byte `xml:",attr"`
   282		Custom MyBytes
   283	}
   284	
   285	type Plain struct {
   286		V interface{}
   287	}
   288	
   289	type MyInt int
   290	
   291	type EmbedInt struct {
   292		MyInt
   293	}
   294	
   295	type Strings struct {
   296		X []string `xml:"A>B,omitempty"`
   297	}
   298	
   299	type 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	}
   306	
   307	type ChardataEmptyTest struct {
   308		XMLName  Name    `xml:"test"`
   309		Contents *string `xml:",chardata"`
   310	}
   311	
   312	type MyMarshalerTest struct {
   313	}
   314	
   315	var _ Marshaler = (*MyMarshalerTest)(nil)
   316	
   317	func (m *MyMarshalerTest) MarshalXML(e *Encoder, start StartElement) error {
   318		e.EncodeToken(start)
   319		e.EncodeToken(CharData([]byte("hello world")))
   320		e.EncodeToken(EndElement{start.Name})
   321		return nil
   322	}
   323	
   324	type MyMarshalerAttrTest struct {
   325	}
   326	
   327	var _ MarshalerAttr = (*MyMarshalerAttrTest)(nil)
   328	
   329	func (m *MyMarshalerAttrTest) MarshalXMLAttr(name Name) (Attr, error) {
   330		return Attr{name, "hello world"}, nil
   331	}
   332	
   333	func (m *MyMarshalerAttrTest) UnmarshalXMLAttr(attr Attr) error {
   334		return nil
   335	}
   336	
   337	type MarshalerStruct struct {
   338		Foo MyMarshalerAttrTest `xml:",attr"`
   339	}
   340	
   341	type InnerStruct struct {
   342		XMLName Name `xml:"testns outer"`
   343	}
   344	
   345	type OuterStruct struct {
   346		InnerStruct
   347		IntAttr int `xml:"int,attr"`
   348	}
   349	
   350	type OuterNamedStruct struct {
   351		InnerStruct
   352		XMLName Name `xml:"outerns test"`
   353		IntAttr int  `xml:"int,attr"`
   354	}
   355	
   356	type OuterNamedOrderedStruct struct {
   357		XMLName Name `xml:"outerns test"`
   358		InnerStruct
   359		IntAttr int `xml:"int,attr"`
   360	}
   361	
   362	type OuterOuterStruct struct {
   363		OuterStruct
   364	}
   365	
   366	type NestedAndChardata struct {
   367		AB       []string `xml:"A>B"`
   368		Chardata string   `xml:",chardata"`
   369	}
   370	
   371	type NestedAndComment struct {
   372		AB      []string `xml:"A>B"`
   373		Comment string   `xml:",comment"`
   374	}
   375	
   376	type CDataTest struct {
   377		Chardata string `xml:",cdata"`
   378	}
   379	
   380	type NestedAndCData struct {
   381		AB    []string `xml:"A>B"`
   382		CDATA string   `xml:",cdata"`
   383	}
   384	
   385	func ifaceptr(x interface{}) interface{} {
   386		return &x
   387	}
   388	
   389	func stringptr(x string) *string {
   390		return &x
   391	}
   392	
   393	type T1 struct{}
   394	type T2 struct{}
   395	type T3 struct{}
   396	
   397	type IndirComment struct {
   398		T1      T1
   399		Comment *string `xml:",comment"`
   400		T2      T2
   401	}
   402	
   403	type DirectComment struct {
   404		T1      T1
   405		Comment string `xml:",comment"`
   406		T2      T2
   407	}
   408	
   409	type IfaceComment struct {
   410		T1      T1
   411		Comment interface{} `xml:",comment"`
   412		T2      T2
   413	}
   414	
   415	type IndirChardata struct {
   416		T1       T1
   417		Chardata *string `xml:",chardata"`
   418		T2       T2
   419	}
   420	
   421	type DirectChardata struct {
   422		T1       T1
   423		Chardata string `xml:",chardata"`
   424		T2       T2
   425	}
   426	
   427	type IfaceChardata struct {
   428		T1       T1
   429		Chardata interface{} `xml:",chardata"`
   430		T2       T2
   431	}
   432	
   433	type IndirCDATA struct {
   434		T1    T1
   435		CDATA *string `xml:",cdata"`
   436		T2    T2
   437	}
   438	
   439	type DirectCDATA struct {
   440		T1    T1
   441		CDATA string `xml:",cdata"`
   442		T2    T2
   443	}
   444	
   445	type IfaceCDATA struct {
   446		T1    T1
   447		CDATA interface{} `xml:",cdata"`
   448		T2    T2
   449	}
   450	
   451	type IndirInnerXML struct {
   452		T1       T1
   453		InnerXML *string `xml:",innerxml"`
   454		T2       T2
   455	}
   456	
   457	type DirectInnerXML struct {
   458		T1       T1
   459		InnerXML string `xml:",innerxml"`
   460		T2       T2
   461	}
   462	
   463	type IfaceInnerXML struct {
   464		T1       T1
   465		InnerXML interface{} `xml:",innerxml"`
   466		T2       T2
   467	}
   468	
   469	type IndirElement struct {
   470		T1      T1
   471		Element *string
   472		T2      T2
   473	}
   474	
   475	type DirectElement struct {
   476		T1      T1
   477		Element string
   478		T2      T2
   479	}
   480	
   481	type IfaceElement struct {
   482		T1      T1
   483		Element interface{}
   484		T2      T2
   485	}
   486	
   487	type IndirOmitEmpty struct {
   488		T1        T1
   489		OmitEmpty *string `xml:",omitempty"`
   490		T2        T2
   491	}
   492	
   493	type DirectOmitEmpty struct {
   494		T1        T1
   495		OmitEmpty string `xml:",omitempty"`
   496		T2        T2
   497	}
   498	
   499	type IfaceOmitEmpty struct {
   500		T1        T1
   501		OmitEmpty interface{} `xml:",omitempty"`
   502		T2        T2
   503	}
   504	
   505	type IndirAny struct {
   506		T1  T1
   507		Any *string `xml:",any"`
   508		T2  T2
   509	}
   510	
   511	type DirectAny struct {
   512		T1  T1
   513		Any string `xml:",any"`
   514		T2  T2
   515	}
   516	
   517	type IfaceAny struct {
   518		T1  T1
   519		Any interface{} `xml:",any"`
   520		T2  T2
   521	}
   522	
   523	var (
   524		nameAttr     = "Sarah"
   525		ageAttr      = uint(12)
   526		contentsAttr = "lorem ipsum"
   527		empty        = ""
   528	)
   529	
   530	// Unless explicitly stated as such (or *Plain), all of the
   531	// tests below are two-way tests. When introducing new tests,
   532	// please try to make them two-way as well to ensure that
   533	// marshaling and unmarshaling are as symmetrical as feasible.
   534	var marshalTests = []struct {
   535		Value          interface{}
   536		ExpectXML      string
   537		MarshalOnly    bool
   538		MarshalError   string
   539		UnmarshalOnly  bool
   540		UnmarshalError string
   541	}{
   542		// Test nil marshals to nothing
   543		{Value: nil, ExpectXML: ``, MarshalOnly: true},
   544		{Value: nilStruct, ExpectXML: ``, MarshalOnly: true},
   545	
   546		// Test value types
   547		{Value: &Plain{true}, ExpectXML: `<Plain><V>true</V></Plain>`},
   548		{Value: &Plain{false}, ExpectXML: `<Plain><V>false</V></Plain>`},
   549		{Value: &Plain{int(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   550		{Value: &Plain{int8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   551		{Value: &Plain{int16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   552		{Value: &Plain{int32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   553		{Value: &Plain{uint(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   554		{Value: &Plain{uint8(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   555		{Value: &Plain{uint16(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   556		{Value: &Plain{uint32(42)}, ExpectXML: `<Plain><V>42</V></Plain>`},
   557		{Value: &Plain{float32(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
   558		{Value: &Plain{float64(1.25)}, ExpectXML: `<Plain><V>1.25</V></Plain>`},
   559		{Value: &Plain{uintptr(0xFFDD)}, ExpectXML: `<Plain><V>65501</V></Plain>`},
   560		{Value: &Plain{"gopher"}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
   561		{Value: &Plain{[]byte("gopher")}, ExpectXML: `<Plain><V>gopher</V></Plain>`},
   562		{Value: &Plain{"</>"}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
   563		{Value: &Plain{[]byte("</>")}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
   564		{Value: &Plain{[3]byte{'<', '/', '>'}}, ExpectXML: `<Plain><V>&lt;/&gt;</V></Plain>`},
   565		{Value: &Plain{NamedType("potato")}, ExpectXML: `<Plain><V>potato</V></Plain>`},
   566		{Value: &Plain{[]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
   567		{Value: &Plain{[3]int{1, 2, 3}}, ExpectXML: `<Plain><V>1</V><V>2</V><V>3</V></Plain>`},
   568		{Value: ifaceptr(true), MarshalOnly: true, ExpectXML: `<bool>true</bool>`},
   569	
   570		// Test time.
   571		{
   572			Value:     &Plain{time.Unix(1e9, 123456789).UTC()},
   573			ExpectXML: `<Plain><V>2001-09-09T01:46:40.123456789Z</V></Plain>`,
   574		},
   575	
   576		// A pointer to struct{} may be used to test for an element's presence.
   577		{
   578			Value:     &PresenceTest{new(struct{})},
   579			ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
   580		},
   581		{
   582			Value:     &PresenceTest{},
   583			ExpectXML: `<PresenceTest></PresenceTest>`,
   584		},
   585	
   586		// A pointer to struct{} may be used to test for an element's presence.
   587		{
   588			Value:     &PresenceTest{new(struct{})},
   589			ExpectXML: `<PresenceTest><Exists></Exists></PresenceTest>`,
   590		},
   591		{
   592			Value:     &PresenceTest{},
   593			ExpectXML: `<PresenceTest></PresenceTest>`,
   594		},
   595	
   596		// A []byte field is only nil if the element was not found.
   597		{
   598			Value:         &Data{},
   599			ExpectXML:     `<Data></Data>`,
   600			UnmarshalOnly: true,
   601		},
   602		{
   603			Value:         &Data{Bytes: []byte{}, Custom: MyBytes{}, Attr: []byte{}},
   604			ExpectXML:     `<Data Attr=""><Bytes></Bytes><Custom></Custom></Data>`,
   605			UnmarshalOnly: true,
   606		},
   607	
   608		// Check that []byte works, including named []byte types.
   609		{
   610			Value:     &Data{Bytes: []byte("ab"), Custom: MyBytes("cd"), Attr: []byte{'v'}},
   611			ExpectXML: `<Data Attr="v"><Bytes>ab</Bytes><Custom>cd</Custom></Data>`,
   612		},
   613	
   614		// Test innerxml
   615		{
   616			Value: &SecretAgent{
   617				Handle:    "007",
   618				Identity:  "James Bond",
   619				Obfuscate: "<redacted/>",
   620			},
   621			ExpectXML:   `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
   622			MarshalOnly: true,
   623		},
   624		{
   625			Value: &SecretAgent{
   626				Handle:    "007",
   627				Identity:  "James Bond",
   628				Obfuscate: "<Identity>James Bond</Identity><redacted/>",
   629			},
   630			ExpectXML:     `<agent handle="007"><Identity>James Bond</Identity><redacted/></agent>`,
   631			UnmarshalOnly: true,
   632		},
   633	
   634		// Test structs
   635		{Value: &Port{Type: "ssl", Number: "443"}, ExpectXML: `<port type="ssl">443</port>`},
   636		{Value: &Port{Number: "443"}, ExpectXML: `<port>443</port>`},
   637		{Value: &Port{Type: "<unix>"}, ExpectXML: `<port type="&lt;unix&gt;"></port>`},
   638		{Value: &Port{Number: "443", Comment: "https"}, ExpectXML: `<port><!--https-->443</port>`},
   639		{Value: &Port{Number: "443", Comment: "add space-"}, ExpectXML: `<port><!--add space- -->443</port>`, MarshalOnly: true},
   640		{Value: &Domain{Name: []byte("google.com&friends")}, ExpectXML: `<domain>google.com&amp;friends</domain>`},
   641		{Value: &Domain{Name: []byte("google.com"), Comment: []byte(" &friends ")}, ExpectXML: `<domain>google.com<!-- &friends --></domain>`},
   642		{Value: &Book{Title: "Pride & Prejudice"}, ExpectXML: `<book>Pride &amp; Prejudice</book>`},
   643		{Value: &Event{Year: -3114}, ExpectXML: `<event>-3114</event>`},
   644		{Value: &Movie{Length: 13440}, ExpectXML: `<movie>13440</movie>`},
   645		{Value: &Pi{Approximation: 3.14159265}, ExpectXML: `<pi>3.1415927</pi>`},
   646		{Value: &Universe{Visible: 9.3e13}, ExpectXML: `<universe>9.3e+13</universe>`},
   647		{Value: &Particle{HasMass: true}, ExpectXML: `<particle>true</particle>`},
   648		{Value: &Departure{When: ParseTime("2013-01-09T00:15:00-09:00")}, ExpectXML: `<departure>2013-01-09T00:15:00-09:00</departure>`},
   649		{Value: atomValue, ExpectXML: atomXml},
   650		{
   651			Value: &Ship{
   652				Name:  "Heart of Gold",
   653				Pilot: "Computer",
   654				Age:   1,
   655				Drive: ImprobabilityDrive,
   656				Passenger: []*Passenger{
   657					{
   658						Name:   []string{"Zaphod", "Beeblebrox"},
   659						Weight: 7.25,
   660					},
   661					{
   662						Name:   []string{"Trisha", "McMillen"},
   663						Weight: 5.5,
   664					},
   665					{
   666						Name:   []string{"Ford", "Prefect"},
   667						Weight: 7,
   668					},
   669					{
   670						Name:   []string{"Arthur", "Dent"},
   671						Weight: 6.75,
   672					},
   673				},
   674			},
   675			ExpectXML: `<spaceship name="Heart of Gold" pilot="Computer">` +
   676				`<drive>` + strconv.Itoa(int(ImprobabilityDrive)) + `</drive>` +
   677				`<age>1</age>` +
   678				`<passenger>` +
   679				`<name>Zaphod</name>` +
   680				`<name>Beeblebrox</name>` +
   681				`<weight>7.25</weight>` +
   682				`</passenger>` +
   683				`<passenger>` +
   684				`<name>Trisha</name>` +
   685				`<name>McMillen</name>` +
   686				`<weight>5.5</weight>` +
   687				`</passenger>` +
   688				`<passenger>` +
   689				`<name>Ford</name>` +
   690				`<name>Prefect</name>` +
   691				`<weight>7</weight>` +
   692				`</passenger>` +
   693				`<passenger>` +
   694				`<name>Arthur</name>` +
   695				`<name>Dent</name>` +
   696				`<weight>6.75</weight>` +
   697				`</passenger>` +
   698				`</spaceship>`,
   699		},
   700	
   701		// Test a>b
   702		{
   703			Value: &NestedItems{Items: nil, Item1: nil},
   704			ExpectXML: `<result>` +
   705				`<Items>` +
   706				`</Items>` +
   707				`</result>`,
   708		},
   709		{
   710			Value: &NestedItems{Items: []string{}, Item1: []string{}},
   711			ExpectXML: `<result>` +
   712				`<Items>` +
   713				`</Items>` +
   714				`</result>`,
   715			MarshalOnly: true,
   716		},
   717		{
   718			Value: &NestedItems{Items: nil, Item1: []string{"A"}},
   719			ExpectXML: `<result>` +
   720				`<Items>` +
   721				`<item1>A</item1>` +
   722				`</Items>` +
   723				`</result>`,
   724		},
   725		{
   726			Value: &NestedItems{Items: []string{"A", "B"}, Item1: nil},
   727			ExpectXML: `<result>` +
   728				`<Items>` +
   729				`<item>A</item>` +
   730				`<item>B</item>` +
   731				`</Items>` +
   732				`</result>`,
   733		},
   734		{
   735			Value: &NestedItems{Items: []string{"A", "B"}, Item1: []string{"C"}},
   736			ExpectXML: `<result>` +
   737				`<Items>` +
   738				`<item>A</item>` +
   739				`<item>B</item>` +
   740				`<item1>C</item1>` +
   741				`</Items>` +
   742				`</result>`,
   743		},
   744		{
   745			Value: &NestedOrder{Field1: "C", Field2: "B", Field3: "A"},
   746			ExpectXML: `<result>` +
   747				`<parent>` +
   748				`<c>C</c>` +
   749				`<b>B</b>` +
   750				`<a>A</a>` +
   751				`</parent>` +
   752				`</result>`,
   753		},
   754		{
   755			Value: &NilTest{A: "A", B: nil, C: "C"},
   756			ExpectXML: `<NilTest>` +
   757				`<parent1>` +
   758				`<parent2><a>A</a></parent2>` +
   759				`<parent2><c>C</c></parent2>` +
   760				`</parent1>` +
   761				`</NilTest>`,
   762			MarshalOnly: true, // Uses interface{}
   763		},
   764		{
   765			Value: &MixedNested{A: "A", B: "B", C: "C", D: "D"},
   766			ExpectXML: `<result>` +
   767				`<parent1><a>A</a></parent1>` +
   768				`<b>B</b>` +
   769				`<parent1>` +
   770				`<parent2><c>C</c></parent2>` +
   771				`<d>D</d>` +
   772				`</parent1>` +
   773				`</result>`,
   774		},
   775		{
   776			Value:     &Service{Port: &Port{Number: "80"}},
   777			ExpectXML: `<service><host><port>80</port></host></service>`,
   778		},
   779		{
   780			Value:     &Service{},
   781			ExpectXML: `<service></service>`,
   782		},
   783		{
   784			Value: &Service{Port: &Port{Number: "80"}, Extra1: "A", Extra2: "B"},
   785			ExpectXML: `<service>` +
   786				`<host><port>80</port></host>` +
   787				`<Extra1>A</Extra1>` +
   788				`<host><extra2>B</extra2></host>` +
   789				`</service>`,
   790			MarshalOnly: true,
   791		},
   792		{
   793			Value: &Service{Port: &Port{Number: "80"}, Extra2: "example"},
   794			ExpectXML: `<service>` +
   795				`<host><port>80</port></host>` +
   796				`<host><extra2>example</extra2></host>` +
   797				`</service>`,
   798			MarshalOnly: true,
   799		},
   800		{
   801			Value: &struct {
   802				XMLName struct{} `xml:"space top"`
   803				A       string   `xml:"x>a"`
   804				B       string   `xml:"x>b"`
   805				C       string   `xml:"space x>c"`
   806				C1      string   `xml:"space1 x>c"`
   807				D1      string   `xml:"space1 x>d"`
   808			}{
   809				A:  "a",
   810				B:  "b",
   811				C:  "c",
   812				C1: "c1",
   813				D1: "d1",
   814			},
   815			ExpectXML: `<top xmlns="space">` +
   816				`<x><a>a</a><b>b</b><c xmlns="space">c</c>` +
   817				`<c xmlns="space1">c1</c>` +
   818				`<d xmlns="space1">d1</d>` +
   819				`</x>` +
   820				`</top>`,
   821		},
   822		{
   823			Value: &struct {
   824				XMLName Name
   825				A       string `xml:"x>a"`
   826				B       string `xml:"x>b"`
   827				C       string `xml:"space x>c"`
   828				C1      string `xml:"space1 x>c"`
   829				D1      string `xml:"space1 x>d"`
   830			}{
   831				XMLName: Name{
   832					Space: "space0",
   833					Local: "top",
   834				},
   835				A:  "a",
   836				B:  "b",
   837				C:  "c",
   838				C1: "c1",
   839				D1: "d1",
   840			},
   841			ExpectXML: `<top xmlns="space0">` +
   842				`<x><a>a</a><b>b</b>` +
   843				`<c xmlns="space">c</c>` +
   844				`<c xmlns="space1">c1</c>` +
   845				`<d xmlns="space1">d1</d>` +
   846				`</x>` +
   847				`</top>`,
   848		},
   849		{
   850			Value: &struct {
   851				XMLName struct{} `xml:"top"`
   852				B       string   `xml:"space x>b"`
   853				B1      string   `xml:"space1 x>b"`
   854			}{
   855				B:  "b",
   856				B1: "b1",
   857			},
   858			ExpectXML: `<top>` +
   859				`<x><b xmlns="space">b</b>` +
   860				`<b xmlns="space1">b1</b></x>` +
   861				`</top>`,
   862		},
   863	
   864		// Test struct embedding
   865		{
   866			Value: &EmbedA{
   867				EmbedC: EmbedC{
   868					FieldA1: "", // Shadowed by A.A
   869					FieldA2: "", // Shadowed by A.A
   870					FieldB:  "A.C.B",
   871					FieldC:  "A.C.C",
   872				},
   873				EmbedB: EmbedB{
   874					FieldB: "A.B.B",
   875					EmbedC: &EmbedC{
   876						FieldA1: "A.B.C.A1",
   877						FieldA2: "A.B.C.A2",
   878						FieldB:  "", // Shadowed by A.B.B
   879						FieldC:  "A.B.C.C",
   880					},
   881				},
   882				FieldA: "A.A",
   883				embedD: embedD{
   884					FieldE: "A.D.E",
   885				},
   886			},
   887			ExpectXML: `<EmbedA>` +
   888				`<FieldB>A.C.B</FieldB>` +
   889				`<FieldC>A.C.C</FieldC>` +
   890				`<EmbedB>` +
   891				`<FieldB>A.B.B</FieldB>` +
   892				`<FieldA>` +
   893				`<A1>A.B.C.A1</A1>` +
   894				`<A2>A.B.C.A2</A2>` +
   895				`</FieldA>` +
   896				`<FieldC>A.B.C.C</FieldC>` +
   897				`</EmbedB>` +
   898				`<FieldA>A.A</FieldA>` +
   899				`<FieldE>A.D.E</FieldE>` +
   900				`</EmbedA>`,
   901		},
   902	
   903		// Test that name casing matters
   904		{
   905			Value:     &NameCasing{Xy: "mixed", XY: "upper", XyA: "mixedA", XYA: "upperA"},
   906			ExpectXML: `<casing Xy="mixedA" XY="upperA"><Xy>mixed</Xy><XY>upper</XY></casing>`,
   907		},
   908	
   909		// Test the order in which the XML element name is chosen
   910		{
   911			Value: &NamePrecedence{
   912				FromTag:     XMLNameWithoutTag{Value: "A"},
   913				FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "InXMLName"}, Value: "B"},
   914				FromNameTag: XMLNameWithTag{Value: "C"},
   915				InFieldName: "D",
   916			},
   917			ExpectXML: `<Parent>` +
   918				`<InTag>A</InTag>` +
   919				`<InXMLName>B</InXMLName>` +
   920				`<InXMLNameTag>C</InXMLNameTag>` +
   921				`<InFieldName>D</InFieldName>` +
   922				`</Parent>`,
   923			MarshalOnly: true,
   924		},
   925		{
   926			Value: &NamePrecedence{
   927				XMLName:     Name{Local: "Parent"},
   928				FromTag:     XMLNameWithoutTag{XMLName: Name{Local: "InTag"}, Value: "A"},
   929				FromNameVal: XMLNameWithoutTag{XMLName: Name{Local: "FromNameVal"}, Value: "B"},
   930				FromNameTag: XMLNameWithTag{XMLName: Name{Local: "InXMLNameTag"}, Value: "C"},
   931				InFieldName: "D",
   932			},
   933			ExpectXML: `<Parent>` +
   934				`<InTag>A</InTag>` +
   935				`<FromNameVal>B</FromNameVal>` +
   936				`<InXMLNameTag>C</InXMLNameTag>` +
   937				`<InFieldName>D</InFieldName>` +
   938				`</Parent>`,
   939			UnmarshalOnly: true,
   940		},
   941	
   942		// xml.Name works in a plain field as well.
   943		{
   944			Value:     &NameInField{Name{Space: "ns", Local: "foo"}},
   945			ExpectXML: `<NameInField><foo xmlns="ns"></foo></NameInField>`,
   946		},
   947		{
   948			Value:         &NameInField{Name{Space: "ns", Local: "foo"}},
   949			ExpectXML:     `<NameInField><foo xmlns="ns"><ignore></ignore></foo></NameInField>`,
   950			UnmarshalOnly: true,
   951		},
   952	
   953		// Marshaling zero xml.Name uses the tag or field name.
   954		{
   955			Value:       &NameInField{},
   956			ExpectXML:   `<NameInField><foo xmlns="ns"></foo></NameInField>`,
   957			MarshalOnly: true,
   958		},
   959	
   960		// Test attributes
   961		{
   962			Value: &AttrTest{
   963				Int:   8,
   964				Named: 9,
   965				Float: 23.5,
   966				Uint8: 255,
   967				Bool:  true,
   968				Str:   "str",
   969				Bytes: []byte("byt"),
   970			},
   971			ExpectXML: `<AttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
   972				` Bool="true" Str="str" Bytes="byt"></AttrTest>`,
   973		},
   974		{
   975			Value: &AttrTest{Bytes: []byte{}},
   976			ExpectXML: `<AttrTest Int="0" int="0" Float="0" Uint8="0"` +
   977				` Bool="false" Str="" Bytes=""></AttrTest>`,
   978		},
   979		{
   980			Value: &AttrsTest{
   981				Attrs: []Attr{
   982					{Name: Name{Local: "Answer"}, Value: "42"},
   983					{Name: Name{Local: "Int"}, Value: "8"},
   984					{Name: Name{Local: "int"}, Value: "9"},
   985					{Name: Name{Local: "Float"}, Value: "23.5"},
   986					{Name: Name{Local: "Uint8"}, Value: "255"},
   987					{Name: Name{Local: "Bool"}, Value: "true"},
   988					{Name: Name{Local: "Str"}, Value: "str"},
   989					{Name: Name{Local: "Bytes"}, Value: "byt"},
   990				},
   991			},
   992			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>`,
   993			MarshalOnly: true,
   994		},
   995		{
   996			Value: &AttrsTest{
   997				Attrs: []Attr{
   998					{Name: Name{Local: "Answer"}, Value: "42"},
   999				},
  1000				Int:   8,
  1001				Named: 9,
  1002				Float: 23.5,
  1003				Uint8: 255,
  1004				Bool:  true,
  1005				Str:   "str",
  1006				Bytes: []byte("byt"),
  1007			},
  1008			ExpectXML: `<AttrsTest Answer="42" Int="8" int="9" Float="23.5" Uint8="255" Bool="true" Str="str" Bytes="byt"></AttrsTest>`,
  1009		},
  1010		{
  1011			Value: &AttrsTest{
  1012				Attrs: []Attr{
  1013					{Name: Name{Local: "Int"}, Value: "0"},
  1014					{Name: Name{Local: "int"}, Value: "0"},
  1015					{Name: Name{Local: "Float"}, Value: "0"},
  1016					{Name: Name{Local: "Uint8"}, Value: "0"},
  1017					{Name: Name{Local: "Bool"}, Value: "false"},
  1018					{Name: Name{Local: "Str"}},
  1019					{Name: Name{Local: "Bytes"}},
  1020				},
  1021				Bytes: []byte{},
  1022			},
  1023			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>`,
  1024			MarshalOnly: true,
  1025		},
  1026		{
  1027			Value: &OmitAttrTest{
  1028				Int:   8,
  1029				Named: 9,
  1030				Float: 23.5,
  1031				Uint8: 255,
  1032				Bool:  true,
  1033				Str:   "str",
  1034				Bytes: []byte("byt"),
  1035				PStr:  &empty,
  1036			},
  1037			ExpectXML: `<OmitAttrTest Int="8" int="9" Float="23.5" Uint8="255"` +
  1038				` Bool="true" Str="str" Bytes="byt" PStr=""></OmitAttrTest>`,
  1039		},
  1040		{
  1041			Value:     &OmitAttrTest{},
  1042			ExpectXML: `<OmitAttrTest></OmitAttrTest>`,
  1043		},
  1044	
  1045		// pointer fields
  1046		{
  1047			Value:       &PointerFieldsTest{Name: &nameAttr, Age: &ageAttr, Contents: &contentsAttr},
  1048			ExpectXML:   `<dummy name="Sarah" age="12">lorem ipsum</dummy>`,
  1049			MarshalOnly: true,
  1050		},
  1051	
  1052		// empty chardata pointer field
  1053		{
  1054			Value:       &ChardataEmptyTest{},
  1055			ExpectXML:   `<test></test>`,
  1056			MarshalOnly: true,
  1057		},
  1058	
  1059		// omitempty on fields
  1060		{
  1061			Value: &OmitFieldTest{
  1062				Int:   8,
  1063				Named: 9,
  1064				Float: 23.5,
  1065				Uint8: 255,
  1066				Bool:  true,
  1067				Str:   "str",
  1068				Bytes: []byte("byt"),
  1069				PStr:  &empty,
  1070				Ptr:   &PresenceTest{},
  1071			},
  1072			ExpectXML: `<OmitFieldTest>` +
  1073				`<Int>8</Int>` +
  1074				`<int>9</int>` +
  1075				`<Float>23.5</Float>` +
  1076				`<Uint8>255</Uint8>` +
  1077				`<Bool>true</Bool>` +
  1078				`<Str>str</Str>` +
  1079				`<Bytes>byt</Bytes>` +
  1080				`<PStr></PStr>` +
  1081				`<Ptr></Ptr>` +
  1082				`</OmitFieldTest>`,
  1083		},
  1084		{
  1085			Value:     &OmitFieldTest{},
  1086			ExpectXML: `<OmitFieldTest></OmitFieldTest>`,
  1087		},
  1088	
  1089		// Test ",any"
  1090		{
  1091			ExpectXML: `<a><nested><value>known</value></nested><other><sub>unknown</sub></other></a>`,
  1092			Value: &AnyTest{
  1093				Nested: "known",
  1094				AnyField: AnyHolder{
  1095					XMLName: Name{Local: "other"},
  1096					XML:     "<sub>unknown</sub>",
  1097				},
  1098			},
  1099		},
  1100		{
  1101			Value: &AnyTest{Nested: "known",
  1102				AnyField: AnyHolder{
  1103					XML:     "<unknown/>",
  1104					XMLName: Name{Local: "AnyField"},
  1105				},
  1106			},
  1107			ExpectXML: `<a><nested><value>known</value></nested><AnyField><unknown/></AnyField></a>`,
  1108		},
  1109		{
  1110			ExpectXML: `<a><nested><value>b</value></nested></a>`,
  1111			Value: &AnyOmitTest{
  1112				Nested: "b",
  1113			},
  1114		},
  1115		{
  1116			ExpectXML: `<a><nested><value>b</value></nested><c><d>e</d></c><g xmlns="f"><h>i</h></g></a>`,
  1117			Value: &AnySliceTest{
  1118				Nested: "b",
  1119				AnyField: []AnyHolder{
  1120					{
  1121						XMLName: Name{Local: "c"},
  1122						XML:     "<d>e</d>",
  1123					},
  1124					{
  1125						XMLName: Name{Space: "f", Local: "g"},
  1126						XML:     "<h>i</h>",
  1127					},
  1128				},
  1129			},
  1130		},
  1131		{
  1132			ExpectXML: `<a><nested><value>b</value></nested></a>`,
  1133			Value: &AnySliceTest{
  1134				Nested: "b",
  1135			},
  1136		},
  1137	
  1138		// Test recursive types.
  1139		{
  1140			Value: &RecurseA{
  1141				A: "a1",
  1142				B: &RecurseB{
  1143					A: &RecurseA{"a2", nil},
  1144					B: "b1",
  1145				},
  1146			},
  1147			ExpectXML: `<RecurseA><A>a1</A><B><A><A>a2</A></A><B>b1</B></B></RecurseA>`,
  1148		},
  1149	
  1150		// Test ignoring fields via "-" tag
  1151		{
  1152			ExpectXML: `<IgnoreTest></IgnoreTest>`,
  1153			Value:     &IgnoreTest{},
  1154		},
  1155		{
  1156			ExpectXML:   `<IgnoreTest></IgnoreTest>`,
  1157			Value:       &IgnoreTest{PublicSecret: "can't tell"},
  1158			MarshalOnly: true,
  1159		},
  1160		{
  1161			ExpectXML:     `<IgnoreTest><PublicSecret>ignore me</PublicSecret></IgnoreTest>`,
  1162			Value:         &IgnoreTest{},
  1163			UnmarshalOnly: true,
  1164		},
  1165	
  1166		// Test escaping.
  1167		{
  1168			ExpectXML: `<a><nested><value>dquote: &#34;; squote: &#39;; ampersand: &amp;; less: &lt;; greater: &gt;;</value></nested><empty></empty></a>`,
  1169			Value: &AnyTest{
  1170				Nested:   `dquote: "; squote: '; ampersand: &; less: <; greater: >;`,
  1171				AnyField: AnyHolder{XMLName: Name{Local: "empty"}},
  1172			},
  1173		},
  1174		{
  1175			ExpectXML: `<a><nested><value>newline: &#xA;; cr: &#xD;; tab: &#x9;;</value></nested><AnyField></AnyField></a>`,
  1176			Value: &AnyTest{
  1177				Nested:   "newline: \n; cr: \r; tab: \t;",
  1178				AnyField: AnyHolder{XMLName: Name{Local: "AnyField"}},
  1179			},
  1180		},
  1181		{
  1182			ExpectXML: "<a><nested><value>1\r2\r\n3\n\r4\n5</value></nested></a>",
  1183			Value: &AnyTest{
  1184				Nested: "1\n2\n3\n\n4\n5",
  1185			},
  1186			UnmarshalOnly: true,
  1187		},
  1188		{
  1189			ExpectXML: `<EmbedInt><MyInt>42</MyInt></EmbedInt>`,
  1190			Value: &EmbedInt{
  1191				MyInt: 42,
  1192			},
  1193		},
  1194		// Test outputting CDATA-wrapped text.
  1195		{
  1196			ExpectXML: `<CDataTest></CDataTest>`,
  1197			Value:     &CDataTest{},
  1198		},
  1199		{
  1200			ExpectXML: `<CDataTest><![CDATA[http://example.com/tests/1?foo=1&bar=baz]]></CDataTest>`,
  1201			Value: &CDataTest{
  1202				Chardata: "http://example.com/tests/1?foo=1&bar=baz",
  1203			},
  1204		},
  1205		{
  1206			ExpectXML: `<CDataTest><![CDATA[Literal <![CDATA[Nested]]]]><![CDATA[>!]]></CDataTest>`,
  1207			Value: &CDataTest{
  1208				Chardata: "Literal <![CDATA[Nested]]>!",
  1209			},
  1210		},
  1211		{
  1212			ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,
  1213			Value: &CDataTest{
  1214				Chardata: "<![CDATA[Nested]]> Literal!",
  1215			},
  1216		},
  1217		{
  1218			ExpectXML: `<CDataTest><![CDATA[<![CDATA[Nested]]]]><![CDATA[> Literal! <![CDATA[Nested]]]]><![CDATA[> Literal!]]></CDataTest>`,
  1219			Value: &CDataTest{
  1220				Chardata: "<![CDATA[Nested]]> Literal! <![CDATA[Nested]]> Literal!",
  1221			},
  1222		},
  1223		{
  1224			ExpectXML: `<CDataTest><![CDATA[<![CDATA[<![CDATA[Nested]]]]><![CDATA[>]]]]><![CDATA[>]]></CDataTest>`,
  1225			Value: &CDataTest{
  1226				Chardata: "<![CDATA[<![CDATA[Nested]]>]]>",
  1227			},
  1228		},
  1229	
  1230		// Test omitempty with parent chain; see golang.org/issue/4168.
  1231		{
  1232			ExpectXML: `<Strings><A></A></Strings>`,
  1233			Value:     &Strings{},
  1234		},
  1235		// Custom marshalers.
  1236		{
  1237			ExpectXML: `<MyMarshalerTest>hello world</MyMarshalerTest>`,
  1238			Value:     &MyMarshalerTest{},
  1239		},
  1240		{
  1241			ExpectXML: `<MarshalerStruct Foo="hello world"></MarshalerStruct>`,
  1242			Value:     &MarshalerStruct{},
  1243		},
  1244		{
  1245			ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
  1246			Value:     &OuterStruct{IntAttr: 10},
  1247		},
  1248		{
  1249			ExpectXML: `<test xmlns="outerns" int="10"></test>`,
  1250			Value:     &OuterNamedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
  1251		},
  1252		{
  1253			ExpectXML: `<test xmlns="outerns" int="10"></test>`,
  1254			Value:     &OuterNamedOrderedStruct{XMLName: Name{Space: "outerns", Local: "test"}, IntAttr: 10},
  1255		},
  1256		{
  1257			ExpectXML: `<outer xmlns="testns" int="10"></outer>`,
  1258			Value:     &OuterOuterStruct{OuterStruct{IntAttr: 10}},
  1259		},
  1260		{
  1261			ExpectXML: `<NestedAndChardata><A><B></B><B></B></A>test</NestedAndChardata>`,
  1262			Value:     &NestedAndChardata{AB: make([]string, 2), Chardata: "test"},
  1263		},
  1264		{
  1265			ExpectXML: `<NestedAndComment><A><B></B><B></B></A><!--test--></NestedAndComment>`,
  1266			Value:     &NestedAndComment{AB: make([]string, 2), Comment: "test"},
  1267		},
  1268		{
  1269			ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`,
  1270			Value:     &NestedAndCData{AB: make([]string, 2), CDATA: "test"},
  1271		},
  1272		// Test pointer indirection in various kinds of fields.
  1273		// https://golang.org/issue/19063
  1274		{
  1275			ExpectXML:   `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
  1276			Value:       &IndirComment{Comment: stringptr("hi")},
  1277			MarshalOnly: true,
  1278		},
  1279		{
  1280			ExpectXML:   `<IndirComment><T1></T1><T2></T2></IndirComment>`,
  1281			Value:       &IndirComment{Comment: stringptr("")},
  1282			MarshalOnly: true,
  1283		},
  1284		{
  1285			ExpectXML:    `<IndirComment><T1></T1><T2></T2></IndirComment>`,
  1286			Value:        &IndirComment{Comment: nil},
  1287			MarshalError: "xml: bad type for comment field of xml.IndirComment",
  1288		},
  1289		{
  1290			ExpectXML:     `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
  1291			Value:         &IndirComment{Comment: nil},
  1292			UnmarshalOnly: true,
  1293		},
  1294		{
  1295			ExpectXML:   `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
  1296			Value:       &IfaceComment{Comment: "hi"},
  1297			MarshalOnly: true,
  1298		},
  1299		{
  1300			ExpectXML:     `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
  1301			Value:         &IfaceComment{Comment: nil},
  1302			UnmarshalOnly: true,
  1303		},
  1304		{
  1305			ExpectXML:    `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
  1306			Value:        &IfaceComment{Comment: nil},
  1307			MarshalError: "xml: bad type for comment field of xml.IfaceComment",
  1308		},
  1309		{
  1310			ExpectXML:     `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
  1311			Value:         &IfaceComment{Comment: nil},
  1312			UnmarshalOnly: true,
  1313		},
  1314		{
  1315			ExpectXML: `<DirectComment><T1></T1><!--hi--><T2></T2></DirectComment>`,
  1316			Value:     &DirectComment{Comment: string("hi")},
  1317		},
  1318		{
  1319			ExpectXML: `<DirectComment><T1></T1><T2></T2></DirectComment>`,
  1320			Value:     &DirectComment{Comment: string("")},
  1321		},
  1322		{
  1323			ExpectXML: `<IndirChardata><T1></T1>hi<T2></T2></IndirChardata>`,
  1324			Value:     &IndirChardata{Chardata: stringptr("hi")},
  1325		},
  1326		{
  1327			ExpectXML:     `<IndirChardata><T1></T1><![CDATA[hi]]><T2></T2></IndirChardata>`,
  1328			Value:         &IndirChardata{Chardata: stringptr("hi")},
  1329			UnmarshalOnly: true, // marshals without CDATA
  1330		},
  1331		{
  1332			ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
  1333			Value:     &IndirChardata{Chardata: stringptr("")},
  1334		},
  1335		{
  1336			ExpectXML:   `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
  1337			Value:       &IndirChardata{Chardata: nil},
  1338			MarshalOnly: true, // unmarshal leaves Chardata=stringptr("")
  1339		},
  1340		{
  1341			ExpectXML:      `<IfaceChardata><T1></T1>hi<T2></T2></IfaceChardata>`,
  1342			Value:          &IfaceChardata{Chardata: string("hi")},
  1343			UnmarshalError: "cannot unmarshal into interface {}",
  1344		},
  1345		{
  1346			ExpectXML:      `<IfaceChardata><T1></T1><![CDATA[hi]]><T2></T2></IfaceChardata>`,
  1347			Value:          &IfaceChardata{Chardata: string("hi")},
  1348			UnmarshalOnly:  true, // marshals without CDATA
  1349			UnmarshalError: "cannot unmarshal into interface {}",
  1350		},
  1351		{
  1352			ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
  1353			Value:          &IfaceChardata{Chardata: string("")},
  1354			UnmarshalError: "cannot unmarshal into interface {}",
  1355		},
  1356		{
  1357			ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
  1358			Value:          &IfaceChardata{Chardata: nil},
  1359			UnmarshalError: "cannot unmarshal into interface {}",
  1360		},
  1361		{
  1362			ExpectXML: `<DirectChardata><T1></T1>hi<T2></T2></DirectChardata>`,
  1363			Value:     &DirectChardata{Chardata: string("hi")},
  1364		},
  1365		{
  1366			ExpectXML:     `<DirectChardata><T1></T1><![CDATA[hi]]><T2></T2></DirectChardata>`,
  1367			Value:         &DirectChardata{Chardata: string("hi")},
  1368			UnmarshalOnly: true, // marshals without CDATA
  1369		},
  1370		{
  1371			ExpectXML: `<DirectChardata><T1></T1><T2></T2></DirectChardata>`,
  1372			Value:     &DirectChardata{Chardata: string("")},
  1373		},
  1374		{
  1375			ExpectXML: `<IndirCDATA><T1></T1><![CDATA[hi]]><T2></T2></IndirCDATA>`,
  1376			Value:     &IndirCDATA{CDATA: stringptr("hi")},
  1377		},
  1378		{
  1379			ExpectXML:     `<IndirCDATA><T1></T1>hi<T2></T2></IndirCDATA>`,
  1380			Value:         &IndirCDATA{CDATA: stringptr("hi")},
  1381			UnmarshalOnly: true, // marshals with CDATA
  1382		},
  1383		{
  1384			ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
  1385			Value:     &IndirCDATA{CDATA: stringptr("")},
  1386		},
  1387		{
  1388			ExpectXML:   `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
  1389			Value:       &IndirCDATA{CDATA: nil},
  1390			MarshalOnly: true, // unmarshal leaves CDATA=stringptr("")
  1391		},
  1392		{
  1393			ExpectXML:      `<IfaceCDATA><T1></T1><![CDATA[hi]]><T2></T2></IfaceCDATA>`,
  1394			Value:          &IfaceCDATA{CDATA: string("hi")},
  1395			UnmarshalError: "cannot unmarshal into interface {}",
  1396		},
  1397		{
  1398			ExpectXML:      `<IfaceCDATA><T1></T1>hi<T2></T2></IfaceCDATA>`,
  1399			Value:          &IfaceCDATA{CDATA: string("hi")},
  1400			UnmarshalOnly:  true, // marshals with CDATA
  1401			UnmarshalError: "cannot unmarshal into interface {}",
  1402		},
  1403		{
  1404			ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
  1405			Value:          &IfaceCDATA{CDATA: string("")},
  1406			UnmarshalError: "cannot unmarshal into interface {}",
  1407		},
  1408		{
  1409			ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
  1410			Value:          &IfaceCDATA{CDATA: nil},
  1411			UnmarshalError: "cannot unmarshal into interface {}",
  1412		},
  1413		{
  1414			ExpectXML: `<DirectCDATA><T1></T1><![CDATA[hi]]><T2></T2></DirectCDATA>`,
  1415			Value:     &DirectCDATA{CDATA: string("hi")},
  1416		},
  1417		{
  1418			ExpectXML:     `<DirectCDATA><T1></T1>hi<T2></T2></DirectCDATA>`,
  1419			Value:         &DirectCDATA{CDATA: string("hi")},
  1420			UnmarshalOnly: true, // marshals with CDATA
  1421		},
  1422		{
  1423			ExpectXML: `<DirectCDATA><T1></T1><T2></T2></DirectCDATA>`,
  1424			Value:     &DirectCDATA{CDATA: string("")},
  1425		},
  1426		{
  1427			ExpectXML:   `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
  1428			Value:       &IndirInnerXML{InnerXML: stringptr("<hi/>")},
  1429			MarshalOnly: true,
  1430		},
  1431		{
  1432			ExpectXML:   `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
  1433			Value:       &IndirInnerXML{InnerXML: stringptr("")},
  1434			MarshalOnly: true,
  1435		},
  1436		{
  1437			ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
  1438			Value:     &IndirInnerXML{InnerXML: nil},
  1439		},
  1440		{
  1441			ExpectXML:     `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
  1442			Value:         &IndirInnerXML{InnerXML: nil},
  1443			UnmarshalOnly: true,
  1444		},
  1445		{
  1446			ExpectXML:   `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
  1447			Value:       &IfaceInnerXML{InnerXML: "<hi/>"},
  1448			MarshalOnly: true,
  1449		},
  1450		{
  1451			ExpectXML:     `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
  1452			Value:         &IfaceInnerXML{InnerXML: nil},
  1453			UnmarshalOnly: true,
  1454		},
  1455		{
  1456			ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
  1457			Value:     &IfaceInnerXML{InnerXML: nil},
  1458		},
  1459		{
  1460			ExpectXML:     `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
  1461			Value:         &IfaceInnerXML{InnerXML: nil},
  1462			UnmarshalOnly: true,
  1463		},
  1464		{
  1465			ExpectXML:   `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
  1466			Value:       &DirectInnerXML{InnerXML: string("<hi/>")},
  1467			MarshalOnly: true,
  1468		},
  1469		{
  1470			ExpectXML:     `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
  1471			Value:         &DirectInnerXML{InnerXML: string("<T1></T1><hi/><T2></T2>")},
  1472			UnmarshalOnly: true,
  1473		},
  1474		{
  1475			ExpectXML:   `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
  1476			Value:       &DirectInnerXML{InnerXML: string("")},
  1477			MarshalOnly: true,
  1478		},
  1479		{
  1480			ExpectXML:     `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
  1481			Value:         &DirectInnerXML{InnerXML: string("<T1></T1><T2></T2>")},
  1482			UnmarshalOnly: true,
  1483		},
  1484		{
  1485			ExpectXML: `<IndirElement><T1></T1><Element>hi</Element><T2></T2></IndirElement>`,
  1486			Value:     &IndirElement{Element: stringptr("hi")},
  1487		},
  1488		{
  1489			ExpectXML: `<IndirElement><T1></T1><Element></Element><T2></T2></IndirElement>`,
  1490			Value:     &IndirElement{Element: stringptr("")},
  1491		},
  1492		{
  1493			ExpectXML: `<IndirElement><T1></T1><T2></T2></IndirElement>`,
  1494			Value:     &IndirElement{Element: nil},
  1495		},
  1496		{
  1497			ExpectXML:   `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
  1498			Value:       &IfaceElement{Element: "hi"},
  1499			MarshalOnly: true,
  1500		},
  1501		{
  1502			ExpectXML:     `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
  1503			Value:         &IfaceElement{Element: nil},
  1504			UnmarshalOnly: true,
  1505		},
  1506		{
  1507			ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
  1508			Value:     &IfaceElement{Element: nil},
  1509		},
  1510		{
  1511			ExpectXML:     `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
  1512			Value:         &IfaceElement{Element: nil},
  1513			UnmarshalOnly: true,
  1514		},
  1515		{
  1516			ExpectXML: `<DirectElement><T1></T1><Element>hi</Element><T2></T2></DirectElement>`,
  1517			Value:     &DirectElement{Element: string("hi")},
  1518		},
  1519		{
  1520			ExpectXML: `<DirectElement><T1></T1><Element></Element><T2></T2></DirectElement>`,
  1521			Value:     &DirectElement{Element: string("")},
  1522		},
  1523		{
  1524			ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IndirOmitEmpty>`,
  1525			Value:     &IndirOmitEmpty{OmitEmpty: stringptr("hi")},
  1526		},
  1527		{
  1528			// Note: Changed in Go 1.8 to include <OmitEmpty> element (because x.OmitEmpty != nil).
  1529			ExpectXML:   `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
  1530			Value:       &IndirOmitEmpty{OmitEmpty: stringptr("")},
  1531			MarshalOnly: true,
  1532		},
  1533		{
  1534			ExpectXML:     `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
  1535			Value:         &IndirOmitEmpty{OmitEmpty: stringptr("")},
  1536			UnmarshalOnly: true,
  1537		},
  1538		{
  1539			ExpectXML: `<IndirOmitEmpty><T1></T1><T2></T2></IndirOmitEmpty>`,
  1540			Value:     &IndirOmitEmpty{OmitEmpty: nil},
  1541		},
  1542		{
  1543			ExpectXML:   `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
  1544			Value:       &IfaceOmitEmpty{OmitEmpty: "hi"},
  1545			MarshalOnly: true,
  1546		},
  1547		{
  1548			ExpectXML:     `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
  1549			Value:         &IfaceOmitEmpty{OmitEmpty: nil},
  1550			UnmarshalOnly: true,
  1551		},
  1552		{
  1553			ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
  1554			Value:     &IfaceOmitEmpty{OmitEmpty: nil},
  1555		},
  1556		{
  1557			ExpectXML:     `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
  1558			Value:         &IfaceOmitEmpty{OmitEmpty: nil},
  1559			UnmarshalOnly: true,
  1560		},
  1561		{
  1562			ExpectXML: `<DirectOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></DirectOmitEmpty>`,
  1563			Value:     &DirectOmitEmpty{OmitEmpty: string("hi")},
  1564		},
  1565		{
  1566			ExpectXML: `<DirectOmitEmpty><T1></T1><T2></T2></DirectOmitEmpty>`,
  1567			Value:     &DirectOmitEmpty{OmitEmpty: string("")},
  1568		},
  1569		{
  1570			ExpectXML: `<IndirAny><T1></T1><Any>hi</Any><T2></T2></IndirAny>`,
  1571			Value:     &IndirAny{Any: stringptr("hi")},
  1572		},
  1573		{
  1574			ExpectXML: `<IndirAny><T1></T1><Any></Any><T2></T2></IndirAny>`,
  1575			Value:     &IndirAny{Any: stringptr("")},
  1576		},
  1577		{
  1578			ExpectXML: `<IndirAny><T1></T1><T2></T2></IndirAny>`,
  1579			Value:     &IndirAny{Any: nil},
  1580		},
  1581		{
  1582			ExpectXML:   `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
  1583			Value:       &IfaceAny{Any: "hi"},
  1584			MarshalOnly: true,
  1585		},
  1586		{
  1587			ExpectXML:     `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
  1588			Value:         &IfaceAny{Any: nil},
  1589			UnmarshalOnly: true,
  1590		},
  1591		{
  1592			ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
  1593			Value:     &IfaceAny{Any: nil},
  1594		},
  1595		{
  1596			ExpectXML:     `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
  1597			Value:         &IfaceAny{Any: nil},
  1598			UnmarshalOnly: true,
  1599		},
  1600		{
  1601			ExpectXML: `<DirectAny><T1></T1><Any>hi</Any><T2></T2></DirectAny>`,
  1602			Value:     &DirectAny{Any: string("hi")},
  1603		},
  1604		{
  1605			ExpectXML: `<DirectAny><T1></T1><Any></Any><T2></T2></DirectAny>`,
  1606			Value:     &DirectAny{Any: string("")},
  1607		},
  1608		{
  1609			ExpectXML:     `<IndirFoo><T1></T1><Foo>hi</Foo><T2></T2></IndirFoo>`,
  1610			Value:         &IndirAny{Any: stringptr("hi")},
  1611			UnmarshalOnly: true,
  1612		},
  1613		{
  1614			ExpectXML:     `<IndirFoo><T1></T1><Foo></Foo><T2></T2></IndirFoo>`,
  1615			Value:         &IndirAny{Any: stringptr("")},
  1616			UnmarshalOnly: true,
  1617		},
  1618		{
  1619			ExpectXML:     `<IndirFoo><T1></T1><T2></T2></IndirFoo>`,
  1620			Value:         &IndirAny{Any: nil},
  1621			UnmarshalOnly: true,
  1622		},
  1623		{
  1624			ExpectXML:     `<IfaceFoo><T1></T1><Foo>hi</Foo><T2></T2></IfaceFoo>`,
  1625			Value:         &IfaceAny{Any: nil},
  1626			UnmarshalOnly: true,
  1627		},
  1628		{
  1629			ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
  1630			Value:         &IfaceAny{Any: nil},
  1631			UnmarshalOnly: true,
  1632		},
  1633		{
  1634			ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
  1635			Value:         &IfaceAny{Any: nil},
  1636			UnmarshalOnly: true,
  1637		},
  1638		{
  1639			ExpectXML:     `<DirectFoo><T1></T1><Foo>hi</Foo><T2></T2></DirectFoo>`,
  1640			Value:         &DirectAny{Any: string("hi")},
  1641			UnmarshalOnly: true,
  1642		},
  1643		{
  1644			ExpectXML:     `<DirectFoo><T1></T1><Foo></Foo><T2></T2></DirectFoo>`,
  1645			Value:         &DirectAny{Any: string("")},
  1646			UnmarshalOnly: true,
  1647		},
  1648	}
  1649	
  1650	func TestMarshal(t *testing.T) {
  1651		for idx, test := range marshalTests {
  1652			if test.UnmarshalOnly {
  1653				continue
  1654			}
  1655			data, err := Marshal(test.Value)
  1656			if err != nil {
  1657				if test.MarshalError == "" {
  1658					t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
  1659					continue
  1660				}
  1661				if !strings.Contains(err.Error(), test.MarshalError) {
  1662					t.Errorf("#%d: marshal(%#v): %s, want %q", idx, test.Value, err, test.MarshalError)
  1663				}
  1664				continue
  1665			}
  1666			if test.MarshalError != "" {
  1667				t.Errorf("#%d: Marshal succeeded, want error %q", idx, test.MarshalError)
  1668				continue
  1669			}
  1670			if got, want := string(data), test.ExpectXML; got != want {
  1671				if strings.Contains(want, "\n") {
  1672					t.Errorf("#%d: marshal(%#v):\nHAVE:\n%s\nWANT:\n%s", idx, test.Value, got, want)
  1673				} else {
  1674					t.Errorf("#%d: marshal(%#v):\nhave %#q\nwant %#q", idx, test.Value, got, want)
  1675				}
  1676			}
  1677		}
  1678	}
  1679	
  1680	type AttrParent struct {
  1681		X string `xml:"X>Y,attr"`
  1682	}
  1683	
  1684	type BadAttr struct {
  1685		Name map[string]string `xml:"name,attr"`
  1686	}
  1687	
  1688	var marshalErrorTests = []struct {
  1689		Value interface{}
  1690		Err   string
  1691		Kind  reflect.Kind
  1692	}{
  1693		{
  1694			Value: make(chan bool),
  1695			Err:   "xml: unsupported type: chan bool",
  1696			Kind:  reflect.Chan,
  1697		},
  1698		{
  1699			Value: map[string]string{
  1700				"question": "What do you get when you multiply six by nine?",
  1701				"answer":   "42",
  1702			},
  1703			Err:  "xml: unsupported type: map[string]string",
  1704			Kind: reflect.Map,
  1705		},
  1706		{
  1707			Value: map[*Ship]bool{nil: false},
  1708			Err:   "xml: unsupported type: map[*xml.Ship]bool",
  1709			Kind:  reflect.Map,
  1710		},
  1711		{
  1712			Value: &Domain{Comment: []byte("f--bar")},
  1713			Err:   `xml: comments must not contain "--"`,
  1714		},
  1715		// Reject parent chain with attr, never worked; see golang.org/issue/5033.
  1716		{
  1717			Value: &AttrParent{},
  1718			Err:   `xml: X>Y chain not valid with attr flag`,
  1719		},
  1720		{
  1721			Value: BadAttr{map[string]string{"X": "Y"}},
  1722			Err:   `xml: unsupported type: map[string]string`,
  1723		},
  1724	}
  1725	
  1726	var marshalIndentTests = []struct {
  1727		Value     interface{}
  1728		Prefix    string
  1729		Indent    string
  1730		ExpectXML string
  1731	}{
  1732		{
  1733			Value: &SecretAgent{
  1734				Handle:    "007",
  1735				Identity:  "James Bond",
  1736				Obfuscate: "<redacted/>",
  1737			},
  1738			Prefix:    "",
  1739			Indent:    "\t",
  1740			ExpectXML: fmt.Sprintf("<agent handle=\"007\">\n\t<Identity>James Bond</Identity><redacted/>\n</agent>"),
  1741		},
  1742	}
  1743	
  1744	func TestMarshalErrors(t *testing.T) {
  1745		for idx, test := range marshalErrorTests {
  1746			data, err := Marshal(test.Value)
  1747			if err == nil {
  1748				t.Errorf("#%d: marshal(%#v) = [success] %q, want error %v", idx, test.Value, data, test.Err)
  1749				continue
  1750			}
  1751			if err.Error() != test.Err {
  1752				t.Errorf("#%d: marshal(%#v) = [error] %v, want %v", idx, test.Value, err, test.Err)
  1753			}
  1754			if test.Kind != reflect.Invalid {
  1755				if kind := err.(*UnsupportedTypeError).Type.Kind(); kind != test.Kind {
  1756					t.Errorf("#%d: marshal(%#v) = [error kind] %s, want %s", idx, test.Value, kind, test.Kind)
  1757				}
  1758			}
  1759		}
  1760	}
  1761	
  1762	// Do invertibility testing on the various structures that we test
  1763	func TestUnmarshal(t *testing.T) {
  1764		for i, test := range marshalTests {
  1765			if test.MarshalOnly {
  1766				continue
  1767			}
  1768			if _, ok := test.Value.(*Plain); ok {
  1769				continue
  1770			}
  1771			if test.ExpectXML == `<top>`+
  1772				`<x><b xmlns="space">b</b>`+
  1773				`<b xmlns="space1">b1</b></x>`+
  1774				`</top>` {
  1775				// TODO(rogpeppe): re-enable this test in
  1776				// https://go-review.googlesource.com/#/c/5910/
  1777				continue
  1778			}
  1779	
  1780			vt := reflect.TypeOf(test.Value)
  1781			dest := reflect.New(vt.Elem()).Interface()
  1782			err := Unmarshal([]byte(test.ExpectXML), dest)
  1783	
  1784			switch fix := dest.(type) {
  1785			case *Feed:
  1786				fix.Author.InnerXML = ""
  1787				for i := range fix.Entry {
  1788					fix.Entry[i].Author.InnerXML = ""
  1789				}
  1790			}
  1791	
  1792			if err != nil {
  1793				if test.UnmarshalError == "" {
  1794					t.Errorf("#%d: unmarshal(%#v): %s", i, test.ExpectXML, err)
  1795					continue
  1796				}
  1797				if !strings.Contains(err.Error(), test.UnmarshalError) {
  1798					t.Errorf("#%d: unmarshal(%#v): %s, want %q", i, test.ExpectXML, err, test.UnmarshalError)
  1799				}
  1800				continue
  1801			}
  1802			if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
  1803				t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
  1804			}
  1805		}
  1806	}
  1807	
  1808	func TestMarshalIndent(t *testing.T) {
  1809		for i, test := range marshalIndentTests {
  1810			data, err := MarshalIndent(test.Value, test.Prefix, test.Indent)
  1811			if err != nil {
  1812				t.Errorf("#%d: Error: %s", i, err)
  1813				continue
  1814			}
  1815			if got, want := string(data), test.ExpectXML; got != want {
  1816				t.Errorf("#%d: MarshalIndent:\nGot:%s\nWant:\n%s", i, got, want)
  1817			}
  1818		}
  1819	}
  1820	
  1821	type limitedBytesWriter struct {
  1822		w      io.Writer
  1823		remain int // until writes fail
  1824	}
  1825	
  1826	func (lw *limitedBytesWriter) Write(p []byte) (n int, err error) {
  1827		if lw.remain <= 0 {
  1828			println("error")
  1829			return 0, errors.New("write limit hit")
  1830		}
  1831		if len(p) > lw.remain {
  1832			p = p[:lw.remain]
  1833			n, _ = lw.w.Write(p)
  1834			lw.remain = 0
  1835			return n, errors.New("write limit hit")
  1836		}
  1837		n, err = lw.w.Write(p)
  1838		lw.remain -= n
  1839		return n, err
  1840	}
  1841	
  1842	func TestMarshalWriteErrors(t *testing.T) {
  1843		var buf bytes.Buffer
  1844		const writeCap = 1024
  1845		w := &limitedBytesWriter{&buf, writeCap}
  1846		enc := NewEncoder(w)
  1847		var err error
  1848		var i int
  1849		const n = 4000
  1850		for i = 1; i <= n; i++ {
  1851			err = enc.Encode(&Passenger{
  1852				Name:   []string{"Alice", "Bob"},
  1853				Weight: 5,
  1854			})
  1855			if err != nil {
  1856				break
  1857			}
  1858		}
  1859		if err == nil {
  1860			t.Error("expected an error")
  1861		}
  1862		if i == n {
  1863			t.Errorf("expected to fail before the end")
  1864		}
  1865		if buf.Len() != writeCap {
  1866			t.Errorf("buf.Len() = %d; want %d", buf.Len(), writeCap)
  1867		}
  1868	}
  1869	
  1870	func TestMarshalWriteIOErrors(t *testing.T) {
  1871		enc := NewEncoder(errWriter{})
  1872	
  1873		expectErr := "unwritable"
  1874		err := enc.Encode(&Passenger{})
  1875		if err == nil || err.Error() != expectErr {
  1876			t.Errorf("EscapeTest = [error] %v, want %v", err, expectErr)
  1877		}
  1878	}
  1879	
  1880	func TestMarshalFlush(t *testing.T) {
  1881		var buf bytes.Buffer
  1882		enc := NewEncoder(&buf)
  1883		if err := enc.EncodeToken(CharData("hello world")); err != nil {
  1884			t.Fatalf("enc.EncodeToken: %v", err)
  1885		}
  1886		if buf.Len() > 0 {
  1887			t.Fatalf("enc.EncodeToken caused actual write: %q", buf.Bytes())
  1888		}
  1889		if err := enc.Flush(); err != nil {
  1890			t.Fatalf("enc.Flush: %v", err)
  1891		}
  1892		if buf.String() != "hello world" {
  1893			t.Fatalf("after enc.Flush, buf.String() = %q, want %q", buf.String(), "hello world")
  1894		}
  1895	}
  1896	
  1897	func BenchmarkMarshal(b *testing.B) {
  1898		b.ReportAllocs()
  1899		for i := 0; i < b.N; i++ {
  1900			Marshal(atomValue)
  1901		}
  1902	}
  1903	
  1904	func BenchmarkUnmarshal(b *testing.B) {
  1905		b.ReportAllocs()
  1906		xml := []byte(atomXml)
  1907		for i := 0; i < b.N; i++ {
  1908			Unmarshal(xml, &Feed{})
  1909		}
  1910	}
  1911	
  1912	// golang.org/issue/6556
  1913	func TestStructPointerMarshal(t *testing.T) {
  1914		type A struct {
  1915			XMLName string `xml:"a"`
  1916			B       []interface{}
  1917		}
  1918		type C struct {
  1919			XMLName Name
  1920			Value   string `xml:"value"`
  1921		}
  1922	
  1923		a := new(A)
  1924		a.B = append(a.B, &C{
  1925			XMLName: Name{Local: "c"},
  1926			Value:   "x",
  1927		})
  1928	
  1929		b, err := Marshal(a)
  1930		if err != nil {
  1931			t.Fatal(err)
  1932		}
  1933		if x := string(b); x != "<a><c><value>x</value></c></a>" {
  1934			t.Fatal(x)
  1935		}
  1936		var v A
  1937		err = Unmarshal(b, &v)
  1938		if err != nil {
  1939			t.Fatal(err)
  1940		}
  1941	}
  1942	
  1943	var encodeTokenTests = []struct {
  1944		desc string
  1945		toks []Token
  1946		want string
  1947		err  string
  1948	}{{
  1949		desc: "start element with name space",
  1950		toks: []Token{
  1951			StartElement{Name{"space", "local"}, nil},
  1952		},
  1953		want: `<local xmlns="space">`,
  1954	}, {
  1955		desc: "start element with no name",
  1956		toks: []Token{
  1957			StartElement{Name{"space", ""}, nil},
  1958		},
  1959		err: "xml: start tag with no name",
  1960	}, {
  1961		desc: "end element with no name",
  1962		toks: []Token{
  1963			EndElement{Name{"space", ""}},
  1964		},
  1965		err: "xml: end tag with no name",
  1966	}, {
  1967		desc: "char data",
  1968		toks: []Token{
  1969			CharData("foo"),
  1970		},
  1971		want: `foo`,
  1972	}, {
  1973		desc: "char data with escaped chars",
  1974		toks: []Token{
  1975			CharData(" \t\n"),
  1976		},
  1977		want: " &#x9;\n",
  1978	}, {
  1979		desc: "comment",
  1980		toks: []Token{
  1981			Comment("foo"),
  1982		},
  1983		want: `<!--foo-->`,
  1984	}, {
  1985		desc: "comment with invalid content",
  1986		toks: []Token{
  1987			Comment("foo-->"),
  1988		},
  1989		err: "xml: EncodeToken of Comment containing --> marker",
  1990	}, {
  1991		desc: "proc instruction",
  1992		toks: []Token{
  1993			ProcInst{"Target", []byte("Instruction")},
  1994		},
  1995		want: `<?Target Instruction?>`,
  1996	}, {
  1997		desc: "proc instruction with empty target",
  1998		toks: []Token{
  1999			ProcInst{"", []byte("Instruction")},
  2000		},
  2001		err: "xml: EncodeToken of ProcInst with invalid Target",
  2002	}, {
  2003		desc: "proc instruction with bad content",
  2004		toks: []Token{
  2005			ProcInst{"", []byte("Instruction?>")},
  2006		},
  2007		err: "xml: EncodeToken of ProcInst with invalid Target",
  2008	}, {
  2009		desc: "directive",
  2010		toks: []Token{
  2011			Directive("foo"),
  2012		},
  2013		want: `<!foo>`,
  2014	}, {
  2015		desc: "more complex directive",
  2016		toks: []Token{
  2017			Directive("DOCTYPE doc [ <!ELEMENT doc '>'> <!-- com>ment --> ]"),
  2018		},
  2019		want: `<!DOCTYPE doc [ <!ELEMENT doc '>'> <!-- com>ment --> ]>`,
  2020	}, {
  2021		desc: "directive instruction with bad name",
  2022		toks: []Token{
  2023			Directive("foo>"),
  2024		},
  2025		err: "xml: EncodeToken of Directive containing wrong < or > markers",
  2026	}, {
  2027		desc: "end tag without start tag",
  2028		toks: []Token{
  2029			EndElement{Name{"foo", "bar"}},
  2030		},
  2031		err: "xml: end tag </bar> without start tag",
  2032	}, {
  2033		desc: "mismatching end tag local name",
  2034		toks: []Token{
  2035			StartElement{Name{"", "foo"}, nil},
  2036			EndElement{Name{"", "bar"}},
  2037		},
  2038		err:  "xml: end tag </bar> does not match start tag <foo>",
  2039		want: `<foo>`,
  2040	}, {
  2041		desc: "mismatching end tag namespace",
  2042		toks: []Token{
  2043			StartElement{Name{"space", "foo"}, nil},
  2044			EndElement{Name{"another", "foo"}},
  2045		},
  2046		err:  "xml: end tag </foo> in namespace another does not match start tag <foo> in namespace space",
  2047		want: `<foo xmlns="space">`,
  2048	}, {
  2049		desc: "start element with explicit namespace",
  2050		toks: []Token{
  2051			StartElement{Name{"space", "local"}, []Attr{
  2052				{Name{"xmlns", "x"}, "space"},
  2053				{Name{"space", "foo"}, "value"},
  2054			}},
  2055		},
  2056		want: `<local xmlns="space" xmlns:_xmlns="xmlns" _xmlns:x="space" xmlns:space="space" space:foo="value">`,
  2057	}, {
  2058		desc: "start element with explicit namespace and colliding prefix",
  2059		toks: []Token{
  2060			StartElement{Name{"space", "local"}, []Attr{
  2061				{Name{"xmlns", "x"}, "space"},
  2062				{Name{"space", "foo"}, "value"},
  2063				{Name{"x", "bar"}, "other"},
  2064			}},
  2065		},
  2066		want: `<local xmlns="space" xmlns:_xmlns="xmlns" _xmlns:x="space" xmlns:space="space" space:foo="value" xmlns:x="x" x:bar="other">`,
  2067	}, {
  2068		desc: "start element using previously defined namespace",
  2069		toks: []Token{
  2070			StartElement{Name{"", "local"}, []Attr{
  2071				{Name{"xmlns", "x"}, "space"},
  2072			}},
  2073			StartElement{Name{"space", "foo"}, []Attr{
  2074				{Name{"space", "x"}, "y"},
  2075			}},
  2076		},
  2077		want: `<local xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" xmlns:space="space" space:x="y">`,
  2078	}, {
  2079		desc: "nested name space with same prefix",
  2080		toks: []Token{
  2081			StartElement{Name{"", "foo"}, []Attr{
  2082				{Name{"xmlns", "x"}, "space1"},
  2083			}},
  2084			StartElement{Name{"", "foo"}, []Attr{
  2085				{Name{"xmlns", "x"}, "space2"},
  2086			}},
  2087			StartElement{Name{"", "foo"}, []Attr{
  2088				{Name{"space1", "a"}, "space1 value"},
  2089				{Name{"space2", "b"}, "space2 value"},
  2090			}},
  2091			EndElement{Name{"", "foo"}},
  2092			EndElement{Name{"", "foo"}},
  2093			StartElement{Name{"", "foo"}, []Attr{
  2094				{Name{"space1", "a"}, "space1 value"},
  2095				{Name{"space2", "b"}, "space2 value"},
  2096			}},
  2097		},
  2098		want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space1"><foo _xmlns:x="space2"><foo xmlns:space1="space1" space1:a="space1 value" xmlns:space2="space2" space2:b="space2 value"></foo></foo><foo xmlns:space1="space1" space1:a="space1 value" xmlns:space2="space2" space2:b="space2 value">`,
  2099	}, {
  2100		desc: "start element defining several prefixes for the same name space",
  2101		toks: []Token{
  2102			StartElement{Name{"space", "foo"}, []Attr{
  2103				{Name{"xmlns", "a"}, "space"},
  2104				{Name{"xmlns", "b"}, "space"},
  2105				{Name{"space", "x"}, "value"},
  2106			}},
  2107		},
  2108		want: `<foo xmlns="space" xmlns:_xmlns="xmlns" _xmlns:a="space" _xmlns:b="space" xmlns:space="space" space:x="value">`,
  2109	}, {
  2110		desc: "nested element redefines name space",
  2111		toks: []Token{
  2112			StartElement{Name{"", "foo"}, []Attr{
  2113				{Name{"xmlns", "x"}, "space"},
  2114			}},
  2115			StartElement{Name{"space", "foo"}, []Attr{
  2116				{Name{"xmlns", "y"}, "space"},
  2117				{Name{"space", "a"}, "value"},
  2118			}},
  2119		},
  2120		want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" _xmlns:y="space" xmlns:space="space" space:a="value">`,
  2121	}, {
  2122		desc: "nested element creates alias for default name space",
  2123		toks: []Token{
  2124			StartElement{Name{"space", "foo"}, []Attr{
  2125				{Name{"", "xmlns"}, "space"},
  2126			}},
  2127			StartElement{Name{"space", "foo"}, []Attr{
  2128				{Name{"xmlns", "y"}, "space"},
  2129				{Name{"space", "a"}, "value"},
  2130			}},
  2131		},
  2132		want: `<foo xmlns="space" xmlns="space"><foo xmlns="space" xmlns:_xmlns="xmlns" _xmlns:y="space" xmlns:space="space" space:a="value">`,
  2133	}, {
  2134		desc: "nested element defines default name space with existing prefix",
  2135		toks: []Token{
  2136			StartElement{Name{"", "foo"}, []Attr{
  2137				{Name{"xmlns", "x"}, "space"},
  2138			}},
  2139			StartElement{Name{"space", "foo"}, []Attr{
  2140				{Name{"", "xmlns"}, "space"},
  2141				{Name{"space", "a"}, "value"},
  2142			}},
  2143		},
  2144		want: `<foo xmlns:_xmlns="xmlns" _xmlns:x="space"><foo xmlns="space" xmlns="space" xmlns:space="space" space:a="value">`,
  2145	}, {
  2146		desc: "nested element uses empty attribute name space when default ns defined",
  2147		toks: []Token{
  2148			StartElement{Name{"space", "foo"}, []Attr{
  2149				{Name{"", "xmlns"}, "space"},
  2150			}},
  2151			StartElement{Name{"space", "foo"}, []Attr{
  2152				{Name{"", "attr"}, "value"},
  2153			}},
  2154		},
  2155		want: `<foo xmlns="space" xmlns="space"><foo xmlns="space" attr="value">`,
  2156	}, {
  2157		desc: "redefine xmlns",
  2158		toks: []Token{
  2159			StartElement{Name{"", "foo"}, []Attr{
  2160				{Name{"foo", "xmlns"}, "space"},
  2161			}},
  2162		},
  2163		want: `<foo xmlns:foo="foo" foo:xmlns="space">`,
  2164	}, {
  2165		desc: "xmlns with explicit name space #1",
  2166		toks: []Token{
  2167			StartElement{Name{"space", "foo"}, []Attr{
  2168				{Name{"xml", "xmlns"}, "space"},
  2169			}},
  2170		},
  2171		want: `<foo xmlns="space" xmlns:_xml="xml" _xml:xmlns="space">`,
  2172	}, {
  2173		desc: "xmlns with explicit name space #2",
  2174		toks: []Token{
  2175			StartElement{Name{"space", "foo"}, []Attr{
  2176				{Name{xmlURL, "xmlns"}, "space"},
  2177			}},
  2178		},
  2179		want: `<foo xmlns="space" xml:xmlns="space">`,
  2180	}, {
  2181		desc: "empty name space declaration is ignored",
  2182		toks: []Token{
  2183			StartElement{Name{"", "foo"}, []Attr{
  2184				{Name{"xmlns", "foo"}, ""},
  2185			}},
  2186		},
  2187		want: `<foo xmlns:_xmlns="xmlns" _xmlns:foo="">`,
  2188	}, {
  2189		desc: "attribute with no name is ignored",
  2190		toks: []Token{
  2191			StartElement{Name{"", "foo"}, []Attr{
  2192				{Name{"", ""}, "value"},
  2193			}},
  2194		},
  2195		want: `<foo>`,
  2196	}, {
  2197		desc: "namespace URL with non-valid name",
  2198		toks: []Token{
  2199			StartElement{Name{"/34", "foo"}, []Attr{
  2200				{Name{"/34", "x"}, "value"},
  2201			}},
  2202		},
  2203		want: `<foo xmlns="/34" xmlns:_="/34" _:x="value">`,
  2204	}, {
  2205		desc: "nested element resets default namespace to empty",
  2206		toks: []Token{
  2207			StartElement{Name{"space", "foo"}, []Attr{
  2208				{Name{"", "xmlns"}, "space"},
  2209			}},
  2210			StartElement{Name{"", "foo"}, []Attr{
  2211				{Name{"", "xmlns"}, ""},
  2212				{Name{"", "x"}, "value"},
  2213				{Name{"space", "x"}, "value"},
  2214			}},
  2215		},
  2216		want: `<foo xmlns="space" xmlns="space"><foo xmlns="" x="value" xmlns:space="space" space:x="value">`,
  2217	}, {
  2218		desc: "nested element requires empty default name space",
  2219		toks: []Token{
  2220			StartElement{Name{"space", "foo"}, []Attr{
  2221				{Name{"", "xmlns"}, "space"},
  2222			}},
  2223			StartElement{Name{"", "foo"}, nil},
  2224		},
  2225		want: `<foo xmlns="space" xmlns="space"><foo>`,
  2226	}, {
  2227		desc: "attribute uses name space from xmlns",
  2228		toks: []Token{
  2229			StartElement{Name{"some/space", "foo"}, []Attr{
  2230				{Name{"", "attr"}, "value"},
  2231				{Name{"some/space", "other"}, "other value"},
  2232			}},
  2233		},
  2234		want: `<foo xmlns="some/space" attr="value" xmlns:space="some/space" space:other="other value">`,
  2235	}, {
  2236		desc: "default name space should not be used by attributes",
  2237		toks: []Token{
  2238			StartElement{Name{"space", "foo"}, []Attr{
  2239				{Name{"", "xmlns"}, "space"},
  2240				{Name{"xmlns", "bar"}, "space"},
  2241				{Name{"space", "baz"}, "foo"},
  2242			}},
  2243			StartElement{Name{"space", "baz"}, nil},
  2244			EndElement{Name{"space", "baz"}},
  2245			EndElement{Name{"space", "foo"}},
  2246		},
  2247		want: `<foo xmlns="space" xmlns="space" xmlns:_xmlns="xmlns" _xmlns:bar="space" xmlns:space="space" space:baz="foo"><baz xmlns="space"></baz></foo>`,
  2248	}, {
  2249		desc: "default name space not used by attributes, not explicitly defined",
  2250		toks: []Token{
  2251			StartElement{Name{"space", "foo"}, []Attr{
  2252				{Name{"", "xmlns"}, "space"},
  2253				{Name{"space", "baz"}, "foo"},
  2254			}},
  2255			StartElement{Name{"space", "baz"}, nil},
  2256			EndElement{Name{"space", "baz"}},
  2257			EndElement{Name{"space", "foo"}},
  2258		},
  2259		want: `<foo xmlns="space" xmlns="space" xmlns:space="space" space:baz="foo"><baz xmlns="space"></baz></foo>`,
  2260	}, {
  2261		desc: "impossible xmlns declaration",
  2262		toks: []Token{
  2263			StartElement{Name{"", "foo"}, []Attr{
  2264				{Name{"", "xmlns"}, "space"},
  2265			}},
  2266			StartElement{Name{"space", "bar"}, []Attr{
  2267				{Name{"space", "attr"}, "value"},
  2268			}},
  2269		},
  2270		want: `<foo xmlns="space"><bar xmlns="space" xmlns:space="space" space:attr="value">`,
  2271	}}
  2272	
  2273	func TestEncodeToken(t *testing.T) {
  2274	loop:
  2275		for i, tt := range encodeTokenTests {
  2276			var buf bytes.Buffer
  2277			enc := NewEncoder(&buf)
  2278			var err error
  2279			for j, tok := range tt.toks {
  2280				err = enc.EncodeToken(tok)
  2281				if err != nil && j < len(tt.toks)-1 {
  2282					t.Errorf("#%d %s token #%d: %v", i, tt.desc, j, err)
  2283					continue loop
  2284				}
  2285			}
  2286			errorf := func(f string, a ...interface{}) {
  2287				t.Errorf("#%d %s token #%d:%s", i, tt.desc, len(tt.toks)-1, fmt.Sprintf(f, a...))
  2288			}
  2289			switch {
  2290			case tt.err != "" && err == nil:
  2291				errorf(" expected error; got none")
  2292				continue
  2293			case tt.err == "" && err != nil:
  2294				errorf(" got error: %v", err)
  2295				continue
  2296			case tt.err != "" && err != nil && tt.err != err.Error():
  2297				errorf(" error mismatch; got %v, want %v", err, tt.err)
  2298				continue
  2299			}
  2300			if err := enc.Flush(); err != nil {
  2301				errorf(" %v", err)
  2302				continue
  2303			}
  2304			if got := buf.String(); got != tt.want {
  2305				errorf("\ngot  %v\nwant %v", got, tt.want)
  2306				continue
  2307			}
  2308		}
  2309	}
  2310	
  2311	func TestProcInstEncodeToken(t *testing.T) {
  2312		var buf bytes.Buffer
  2313		enc := NewEncoder(&buf)
  2314	
  2315		if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err != nil {
  2316			t.Fatalf("enc.EncodeToken: expected to be able to encode xml target ProcInst as first token, %s", err)
  2317		}
  2318	
  2319		if err := enc.EncodeToken(ProcInst{"Target", []byte("Instruction")}); err != nil {
  2320			t.Fatalf("enc.EncodeToken: expected to be able to add non-xml target ProcInst")
  2321		}
  2322	
  2323		if err := enc.EncodeToken(ProcInst{"xml", []byte("Instruction")}); err == nil {
  2324			t.Fatalf("enc.EncodeToken: expected to not be allowed to encode xml target ProcInst when not first token")
  2325		}
  2326	}
  2327	
  2328	func TestDecodeEncode(t *testing.T) {
  2329		var in, out bytes.Buffer
  2330		in.WriteString(`<?xml version="1.0" encoding="UTF-8"?>
  2331	<?Target Instruction?>
  2332	<root>
  2333	</root>
  2334	`)
  2335		dec := NewDecoder(&in)
  2336		enc := NewEncoder(&out)
  2337		for tok, err := dec.Token(); err == nil; tok, err = dec.Token() {
  2338			err = enc.EncodeToken(tok)
  2339			if err != nil {
  2340				t.Fatalf("enc.EncodeToken: Unable to encode token (%#v), %v", tok, err)
  2341			}
  2342		}
  2343	}
  2344	
  2345	// Issue 9796. Used to fail with GORACE="halt_on_error=1" -race.
  2346	func TestRace9796(t *testing.T) {
  2347		type A struct{}
  2348		type B struct {
  2349			C []A `xml:"X>Y"`
  2350		}
  2351		var wg sync.WaitGroup
  2352		for i := 0; i < 2; i++ {
  2353			wg.Add(1)
  2354			go func() {
  2355				Marshal(B{[]A{{}}})
  2356				wg.Done()
  2357			}()
  2358		}
  2359		wg.Wait()
  2360	}
  2361	
  2362	func TestIsValidDirective(t *testing.T) {
  2363		testOK := []string{
  2364			"<>",
  2365			"< < > >",
  2366			"<!DOCTYPE '<' '>' '>' <!--nothing-->>",
  2367			"<!DOCTYPE doc [ <!ELEMENT doc ANY> <!ELEMENT doc ANY> ]>",
  2368			"<!DOCTYPE doc [ <!ELEMENT doc \"ANY> '<' <!E\" LEMENT '>' doc ANY> ]>",
  2369			"<!DOCTYPE doc <!-- just>>>> a < comment --> [ <!ITEM anything> ] >",
  2370		}
  2371		testKO := []string{
  2372			"<",
  2373			">",
  2374			"<!--",
  2375			"-->",
  2376			"< > > < < >",
  2377			"<!dummy <!-- > -->",
  2378			"<!DOCTYPE doc '>",
  2379			"<!DOCTYPE doc '>'",
  2380			"<!DOCTYPE doc <!--comment>",
  2381		}
  2382		for _, s := range testOK {
  2383			if !isValidDirective(Directive(s)) {
  2384				t.Errorf("Directive %q is expected to be valid", s)
  2385			}
  2386		}
  2387		for _, s := range testKO {
  2388			if isValidDirective(Directive(s)) {
  2389				t.Errorf("Directive %q is expected to be invalid", s)
  2390			}
  2391		}
  2392	}
  2393	
  2394	// Issue 11719. EncodeToken used to silently eat tokens with an invalid type.
  2395	func TestSimpleUseOfEncodeToken(t *testing.T) {
  2396		var buf bytes.Buffer
  2397		enc := NewEncoder(&buf)
  2398		if err := enc.EncodeToken(&StartElement{Name: Name{"", "object1"}}); err == nil {
  2399			t.Errorf("enc.EncodeToken: pointer type should be rejected")
  2400		}
  2401		if err := enc.EncodeToken(&EndElement{Name: Name{"", "object1"}}); err == nil {
  2402			t.Errorf("enc.EncodeToken: pointer type should be rejected")
  2403		}
  2404		if err := enc.EncodeToken(StartElement{Name: Name{"", "object2"}}); err != nil {
  2405			t.Errorf("enc.EncodeToken: StartElement %s", err)
  2406		}
  2407		if err := enc.EncodeToken(EndElement{Name: Name{"", "object2"}}); err != nil {
  2408			t.Errorf("enc.EncodeToken: EndElement %s", err)
  2409		}
  2410		if err := enc.EncodeToken(Universe{}); err == nil {
  2411			t.Errorf("enc.EncodeToken: invalid type not caught")
  2412		}
  2413		if err := enc.Flush(); err != nil {
  2414			t.Errorf("enc.Flush: %s", err)
  2415		}
  2416		if buf.Len() == 0 {
  2417			t.Errorf("enc.EncodeToken: empty buffer")
  2418		}
  2419		want := "<object2></object2>"
  2420		if buf.String() != want {
  2421			t.Errorf("enc.EncodeToken: expected %q; got %q", want, buf.String())
  2422		}
  2423	}
  2424	
  2425	// Issue 16158. Decoder.unmarshalAttr ignores the return value of copyValue.
  2426	func TestIssue16158(t *testing.T) {
  2427		const data = `<foo b="HELLOWORLD"></foo>`
  2428		err := Unmarshal([]byte(data), &struct {
  2429			B byte `xml:"b,attr,omitempty"`
  2430		}{})
  2431		if err == nil {
  2432			t.Errorf("Unmarshal: expected error, got nil")
  2433		}
  2434	}
  2435	

View as plain text