github.com/x04/go/src@v0.0.0-20200202162449-3d481ceb3525/encoding/xml/marshal_test.go (about)

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