...

Source file src/github.com/aws/smithy-go/encoding/xml/encoder_test.go

Documentation: github.com/aws/smithy-go/encoding/xml

     1  package xml_test
     2  
     3  import (
     4  	"bytes"
     5  	"log"
     6  	"sort"
     7  	"testing"
     8  
     9  	"github.com/aws/smithy-go/encoding/xml"
    10  )
    11  
    12  var root = xml.StartElement{Name: xml.Name{Local: "root"}}
    13  
    14  func TestEncoder(t *testing.T) {
    15  	b := bytes.NewBuffer(nil)
    16  	encoder := xml.NewEncoder(b)
    17  
    18  	func() {
    19  		root := encoder.RootElement(root)
    20  		defer root.Close()
    21  
    22  		stringKey := xml.StartElement{Name: xml.Name{Local: "stringKey"}}
    23  		integerKey := xml.StartElement{Name: xml.Name{Local: "integerKey"}}
    24  		floatKey := xml.StartElement{Name: xml.Name{Local: "floatKey"}}
    25  		foo := xml.StartElement{Name: xml.Name{Local: "foo"}}
    26  		byteSlice := xml.StartElement{Name: xml.Name{Local: "byteSlice"}}
    27  
    28  		root.MemberElement(stringKey).String("stringValue")
    29  		root.MemberElement(integerKey).Integer(1024)
    30  		root.MemberElement(floatKey).Float(3.14)
    31  
    32  		ns := root.MemberElement(foo)
    33  		defer ns.Close()
    34  		ns.MemberElement(byteSlice).String("Zm9vIGJhcg==")
    35  	}()
    36  
    37  	e := []byte(`<root><stringKey>stringValue</stringKey><integerKey>1024</integerKey><floatKey>3.14</floatKey><foo><byteSlice>Zm9vIGJhcg==</byteSlice></foo></root>`)
    38  	verify(t, encoder, e)
    39  }
    40  
    41  func TestEncodeAttribute(t *testing.T) {
    42  	b := bytes.NewBuffer(nil)
    43  	encoder := xml.NewEncoder(b)
    44  
    45  	func() {
    46  		r := xml.StartElement{
    47  			Name: xml.Name{Local: "payload", Space: "baz"},
    48  			Attr: []xml.Attr{
    49  				xml.NewAttribute("attrkey", "value"),
    50  			},
    51  		}
    52  
    53  		obj := encoder.RootElement(r)
    54  		obj.String("")
    55  	}()
    56  
    57  	expect := `<baz:payload attrkey="value"></baz:payload>`
    58  
    59  	verify(t, encoder, []byte(expect))
    60  }
    61  
    62  func TestEncodeNamespace(t *testing.T) {
    63  	b := bytes.NewBuffer(nil)
    64  	encoder := xml.NewEncoder(b)
    65  
    66  	func() {
    67  		root := encoder.RootElement(root)
    68  		defer root.Close()
    69  
    70  		key := xml.StartElement{
    71  			Name: xml.Name{Local: "namespace"},
    72  			Attr: []xml.Attr{
    73  				xml.NewNamespaceAttribute("prefix", "https://example.com"),
    74  			},
    75  		}
    76  
    77  		n := root.MemberElement(key)
    78  		defer n.Close()
    79  
    80  		prefix := xml.StartElement{Name: xml.Name{Local: "user"}}
    81  		n.MemberElement(prefix).String("abc")
    82  	}()
    83  
    84  	e := []byte(`<root><namespace xmlns:prefix="https://example.com"><user>abc</user></namespace></root>`)
    85  	verify(t, encoder, e)
    86  }
    87  
    88  func TestEncodeEmptyNamespacePrefix(t *testing.T) {
    89  	b := bytes.NewBuffer(nil)
    90  	encoder := xml.NewEncoder(b)
    91  	func() {
    92  		root := encoder.RootElement(root)
    93  		defer root.Close()
    94  
    95  		key := xml.StartElement{
    96  			Name: xml.Name{Local: "namespace"},
    97  			Attr: []xml.Attr{
    98  				xml.NewNamespaceAttribute("", "https://example.com"),
    99  			},
   100  		}
   101  
   102  		n := root.MemberElement(key)
   103  		defer n.Close()
   104  
   105  		prefix := xml.StartElement{Name: xml.Name{Local: "user"}}
   106  		n.MemberElement(prefix).String("abc")
   107  	}()
   108  
   109  	e := []byte(`<root><namespace xmlns="https://example.com"><user>abc</user></namespace></root>`)
   110  	verify(t, encoder, e)
   111  }
   112  
   113  func verify(t *testing.T, encoder *xml.Encoder, e []byte) {
   114  	if a := encoder.Bytes(); bytes.Compare(e, a) != 0 {
   115  		t.Errorf("expected %+q, but got %+q", e, a)
   116  	}
   117  
   118  	if a := encoder.String(); string(encoder.Bytes()) != a {
   119  		t.Errorf("expected %s, but got %s", e, a)
   120  	}
   121  }
   122  
   123  func TestEncodeNestedShape(t *testing.T) {
   124  	b := bytes.NewBuffer(nil)
   125  	encoder := xml.NewEncoder(b)
   126  
   127  	func() {
   128  		r := encoder.RootElement(root)
   129  		defer r.Close()
   130  
   131  		// nested `nested` shape
   132  		nested := xml.StartElement{Name: xml.Name{Local: "nested"}}
   133  		n1 := r.MemberElement(nested)
   134  		defer n1.Close()
   135  
   136  		// nested `value` shape
   137  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   138  		n1.MemberElement(value).String("expected value")
   139  	}()
   140  
   141  	e := []byte(`<root><nested><value>expected value</value></nested></root>`)
   142  	defer verify(t, encoder, e)
   143  }
   144  
   145  func TestEncodeMapString(t *testing.T) {
   146  	b := bytes.NewBuffer(nil)
   147  	encoder := xml.NewEncoder(b)
   148  	func() {
   149  		r := encoder.RootElement(root)
   150  		defer r.Close()
   151  
   152  		// nested `mapStr` shape
   153  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}}
   154  		mapElement := r.MemberElement(mapstr)
   155  		defer mapElement.Close()
   156  
   157  		m := mapElement.Map()
   158  
   159  		key := xml.StartElement{Name: xml.Name{Local: "key"}}
   160  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   161  
   162  		e := m.Entry()
   163  		defer e.Close()
   164  		e.MemberElement(key).String("abc")
   165  		e.MemberElement(value).Integer(123)
   166  	}()
   167  
   168  	ex := []byte(`<root><mapstr><entry><key>abc</key><value>123</value></entry></mapstr></root>`)
   169  	verify(t, encoder, ex)
   170  }
   171  
   172  func TestEncodeMapFlatten(t *testing.T) {
   173  	b := bytes.NewBuffer(nil)
   174  	encoder := xml.NewEncoder(b)
   175  
   176  	func() {
   177  		r := encoder.RootElement(root)
   178  		defer r.Close()
   179  		// nested `mapStr` shape
   180  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapstr"}}
   181  		flatElement := r.FlattenedElement(mapstr)
   182  
   183  		m := flatElement.Map()
   184  		e := m.Entry()
   185  		defer e.Close()
   186  
   187  		key := xml.StartElement{Name: xml.Name{Local: "key"}}
   188  		e.MemberElement(key).String("abc")
   189  
   190  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   191  		e.MemberElement(value).Integer(123)
   192  	}()
   193  
   194  	ex := []byte(`<root><mapstr><key>abc</key><value>123</value></mapstr></root>`)
   195  	verify(t, encoder, ex)
   196  }
   197  
   198  func TestEncodeMapNamed(t *testing.T) {
   199  	b := bytes.NewBuffer(nil)
   200  	encoder := xml.NewEncoder(b)
   201  
   202  	func() {
   203  		r := encoder.RootElement(root)
   204  		defer r.Close()
   205  		// nested `mapStr` shape
   206  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamed"}}
   207  		mapElement := r.MemberElement(mapstr)
   208  		defer mapElement.Close()
   209  
   210  		m := mapElement.Map()
   211  		e := m.Entry()
   212  		defer e.Close()
   213  
   214  		key := xml.StartElement{Name: xml.Name{Local: "namedKey"}}
   215  		e.MemberElement(key).String("abc")
   216  
   217  		value := xml.StartElement{Name: xml.Name{Local: "namedValue"}}
   218  		e.MemberElement(value).Integer(123)
   219  	}()
   220  
   221  	ex := []byte(`<root><mapNamed><entry><namedKey>abc</namedKey><namedValue>123</namedValue></entry></mapNamed></root>`)
   222  	verify(t, encoder, ex)
   223  }
   224  
   225  func TestEncodeMapShape(t *testing.T) {
   226  	b := bytes.NewBuffer(nil)
   227  	encoder := xml.NewEncoder(b)
   228  
   229  	func() {
   230  		r := encoder.RootElement(root)
   231  		defer r.Close()
   232  
   233  		// nested `mapStr` shape
   234  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}}
   235  		mapElement := r.MemberElement(mapstr)
   236  		defer mapElement.Close()
   237  
   238  		m := mapElement.Map()
   239  
   240  		e := m.Entry()
   241  		defer e.Close()
   242  
   243  		key := xml.StartElement{Name: xml.Name{Local: "key"}}
   244  		e.MemberElement(key).String("abc")
   245  
   246  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   247  		n1 := e.MemberElement(value)
   248  		defer n1.Close()
   249  
   250  		shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
   251  		n1.MemberElement(shapeVal).Integer(1)
   252  	}()
   253  
   254  	ex := []byte(`<root><mapShape><entry><key>abc</key><value><shapeVal>1</shapeVal></value></entry></mapShape></root>`)
   255  	verify(t, encoder, ex)
   256  }
   257  
   258  func TestEncodeMapFlattenShape(t *testing.T) {
   259  	b := bytes.NewBuffer(nil)
   260  	encoder := xml.NewEncoder(b)
   261  
   262  	func() {
   263  		r := encoder.RootElement(root)
   264  		defer r.Close()
   265  		// nested `mapStr` shape
   266  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapShape"}}
   267  		flatElement := r.FlattenedElement(mapstr)
   268  		m := flatElement.Map()
   269  
   270  		e := m.Entry()
   271  		defer e.Close()
   272  
   273  		key := xml.StartElement{Name: xml.Name{Local: "key"}}
   274  		e.MemberElement(key).String("abc")
   275  
   276  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   277  		n1 := e.MemberElement(value)
   278  		defer n1.Close()
   279  
   280  		shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
   281  		n1.MemberElement(shapeVal).Integer(1)
   282  	}()
   283  	ex := []byte(`<root><mapShape><key>abc</key><value><shapeVal>1</shapeVal></value></mapShape></root>`)
   284  	verify(t, encoder, ex)
   285  }
   286  
   287  func TestEncodeMapNamedShape(t *testing.T) {
   288  	b := bytes.NewBuffer(nil)
   289  	encoder := xml.NewEncoder(b)
   290  
   291  	func() {
   292  		r := encoder.RootElement(root)
   293  		defer r.Close()
   294  
   295  		// nested `mapStr` shape
   296  		mapstr := xml.StartElement{Name: xml.Name{Local: "mapNamedShape"}}
   297  		mapElement := r.MemberElement(mapstr)
   298  		defer mapElement.Close()
   299  
   300  		m := mapElement.Map()
   301  		e := m.Entry()
   302  		defer e.Close()
   303  
   304  		key := xml.StartElement{Name: xml.Name{Local: "namedKey"}}
   305  		e.MemberElement(key).String("abc")
   306  
   307  		value := xml.StartElement{Name: xml.Name{Local: "namedValue"}}
   308  		n1 := e.MemberElement(value)
   309  		defer n1.Close()
   310  
   311  		shapeVal := xml.StartElement{Name: xml.Name{Local: "shapeVal"}}
   312  		n1.MemberElement(shapeVal).Integer(1)
   313  	}()
   314  
   315  	ex := []byte(`<root><mapNamedShape><entry><namedKey>abc</namedKey><namedValue><shapeVal>1</shapeVal></namedValue></entry></mapNamedShape></root>`)
   316  	verify(t, encoder, ex)
   317  }
   318  
   319  func TestEncodeListString(t *testing.T) {
   320  	b := bytes.NewBuffer(nil)
   321  	encoder := xml.NewEncoder(b)
   322  
   323  	func() {
   324  		r := encoder.RootElement(root)
   325  		defer r.Close()
   326  
   327  		// Object key `liststr`
   328  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   329  		m := r.MemberElement(liststr)
   330  		defer m.Close()
   331  
   332  		a := m.Array()
   333  		a.Member().String("abc")
   334  		a.Member().Integer(123)
   335  	}()
   336  
   337  	ex := []byte(`<root><liststr><member>abc</member><member>123</member></liststr></root>`)
   338  	verify(t, encoder, ex)
   339  }
   340  
   341  func TestEncodeListFlatten(t *testing.T) {
   342  	b := bytes.NewBuffer(nil)
   343  	encoder := xml.NewEncoder(b)
   344  
   345  	func() {
   346  		r := encoder.RootElement(root)
   347  		defer r.Close()
   348  
   349  		// Object key `liststr`
   350  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   351  		m := r.FlattenedElement(liststr)
   352  
   353  		a := m.Array()
   354  		a.Member().String("abc")
   355  		a.Member().Integer(123)
   356  	}()
   357  
   358  	ex := []byte(`<root><liststr>abc</liststr><liststr>123</liststr></root>`)
   359  	verify(t, encoder, ex)
   360  }
   361  
   362  func TestEncodeListNamed(t *testing.T) {
   363  	b := bytes.NewBuffer(nil)
   364  	encoder := xml.NewEncoder(b)
   365  
   366  	func() {
   367  		r := encoder.RootElement(root)
   368  		defer r.Close()
   369  
   370  		// Object key `liststr`
   371  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   372  
   373  		namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
   374  		m := r.MemberElement(liststr)
   375  		defer m.Close()
   376  
   377  		a := m.ArrayWithCustomName(namedMember)
   378  		a.Member().String("abc")
   379  		a.Member().Integer(123)
   380  	}()
   381  
   382  	ex := []byte(`<root><liststr><namedMember>abc</namedMember><namedMember>123</namedMember></liststr></root>`)
   383  	verify(t, encoder, ex)
   384  }
   385  
   386  //
   387  func TestEncodeListShape(t *testing.T) {
   388  	b := bytes.NewBuffer(nil)
   389  	encoder := xml.NewEncoder(b)
   390  
   391  	func() {
   392  		r := encoder.RootElement(root)
   393  		defer r.Close()
   394  
   395  		// Object key `liststr`
   396  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   397  
   398  		m := r.MemberElement(liststr)
   399  		defer m.Close()
   400  
   401  		a := m.Array()
   402  
   403  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   404  
   405  		m1 := a.Member()
   406  		m1.MemberElement(value).String("abc")
   407  		m1.Close()
   408  
   409  		m2 := a.Member()
   410  		m2.MemberElement(value).Integer(123)
   411  		m2.Close()
   412  	}()
   413  
   414  	ex := []byte(`<root><liststr><member><value>abc</value></member><member><value>123</value></member></liststr></root>`)
   415  	verify(t, encoder, ex)
   416  }
   417  
   418  //
   419  func TestEncodeListFlattenShape(t *testing.T) {
   420  	b := bytes.NewBuffer(nil)
   421  	encoder := xml.NewEncoder(b)
   422  
   423  	func() {
   424  		r := encoder.RootElement(root)
   425  		defer r.Close()
   426  
   427  		// Object key `liststr`
   428  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   429  
   430  		m := r.FlattenedElement(liststr)
   431  
   432  		a := m.Array()
   433  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   434  
   435  		m1 := a.Member()
   436  		m1.MemberElement(value).String("abc")
   437  		m1.Close()
   438  
   439  		m2 := a.Member()
   440  		m2.MemberElement(value).Integer(123)
   441  		m2.Close()
   442  	}()
   443  
   444  	ex := []byte(`<root><liststr><value>abc</value></liststr><liststr><value>123</value></liststr></root>`)
   445  	verify(t, encoder, ex)
   446  }
   447  
   448  //
   449  func TestEncodeListNamedShape(t *testing.T) {
   450  	b := bytes.NewBuffer(nil)
   451  	encoder := xml.NewEncoder(b)
   452  
   453  	func() {
   454  		r := encoder.RootElement(root)
   455  		defer r.Close()
   456  
   457  		// Object key `liststr`
   458  		liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   459  		namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
   460  
   461  		// member element
   462  		m := r.MemberElement(liststr)
   463  		defer m.Close()
   464  
   465  		// Build array
   466  		a := m.ArrayWithCustomName(namedMember)
   467  
   468  		value := xml.StartElement{Name: xml.Name{Local: "value"}}
   469  		m1 := a.Member()
   470  		m1.MemberElement(value).String("abc")
   471  		m1.Close()
   472  
   473  		m2 := a.Member()
   474  		m2.MemberElement(value).Integer(123)
   475  		m2.Close()
   476  	}()
   477  
   478  	ex := []byte(`<root><liststr><namedMember><value>abc</value></namedMember><namedMember><value>123</value></namedMember></liststr></root>`)
   479  	verify(t, encoder, ex)
   480  }
   481  
   482  func TestEncodeEscaping(t *testing.T) {
   483  	b := bytes.NewBuffer(nil)
   484  	encoder := xml.NewEncoder(b)
   485  
   486  	func() {
   487  		r := encoder.RootElement(root)
   488  		defer r.Close()
   489  
   490  		cases := map[string]rune{
   491  			"quote":          '"',
   492  			"apos":           '\'',
   493  			"amp":            '&',
   494  			"lt":             '<',
   495  			"gt":             '>',
   496  			"tab":            '\t',
   497  			"newLine":        '\n',
   498  			"carriageReturn": '\r',
   499  			"nextLine":       '\u0085',
   500  			"lineSeparator":  '\u2028',
   501  		}
   502  
   503  		var sortedKeys []string
   504  		for name := range cases {
   505  			sortedKeys = append(sortedKeys, name)
   506  		}
   507  
   508  		sort.Strings(sortedKeys)
   509  
   510  		for _, name := range sortedKeys {
   511  			rr := cases[name]
   512  
   513  			st := xml.StartElement{Name: xml.Name{Local: name}}
   514  			st.Attr = append(st.Attr, xml.Attr{
   515  				Name: xml.Name{
   516  					Local: "key",
   517  				},
   518  				Value: name + string(rr) + name,
   519  			})
   520  			value := r.MemberElement(st)
   521  			value.String(name + string(rr) + name)
   522  		}
   523  	}()
   524  
   525  	ex := []byte(`<root><amp key="amp&amp;amp">amp&amp;amp</amp><apos key="apos&#39;apos">apos&#39;apos</apos><carriageReturn key="carriageReturn&#xD;carriageReturn">carriageReturn&#xD;carriageReturn</carriageReturn><gt key="gt&gt;gt">gt&gt;gt</gt><lineSeparator key="lineSeparator&#x2028;lineSeparator">lineSeparator&#x2028;lineSeparator</lineSeparator><lt key="lt&lt;lt">lt&lt;lt</lt><newLine key="newLine&#xA;newLine">newLine&#xA;newLine</newLine><nextLine key="nextLine&#x85;nextLine">nextLine&#x85;nextLine</nextLine><quote key="quote&#34;quote">quote&#34;quote</quote><tab key="tab&#x9;tab">tab&#x9;tab</tab></root>`)
   526  	verify(t, encoder, ex)
   527  }
   528  
   529  // ExampleEncoder is the example function on how to use an encoder
   530  func ExampleEncoder() {
   531  	b := bytes.NewBuffer(nil)
   532  	encoder := xml.NewEncoder(b)
   533  
   534  	// expected encoded xml document is :
   535  	// `<root><liststr><namedMember><value>abc</value></namedMember><namedMember><value>123</value></namedMember></liststr></root>`
   536  	defer log.Printf("Encoded xml document: %v", encoder.String())
   537  
   538  	r := encoder.RootElement(root)
   539  	defer r.Close()
   540  
   541  	// Object key `liststr`
   542  	liststr := xml.StartElement{Name: xml.Name{Local: "liststr"}}
   543  	namedMember := xml.StartElement{Name: xml.Name{Local: "namedMember"}}
   544  
   545  	// member element
   546  	m := r.MemberElement(liststr)
   547  	defer m.Close()
   548  
   549  	// Build array
   550  	a := m.ArrayWithCustomName(namedMember)
   551  
   552  	value := xml.StartElement{Name: xml.Name{Local: "value"}}
   553  	m1 := a.Member()
   554  	m1.MemberElement(value).String("abc")
   555  	m1.Close()
   556  
   557  	m2 := a.Member()
   558  	m2.MemberElement(value).Integer(123)
   559  	m2.Close()
   560  }
   561  

View as plain text