1 package xml
2
3 import (
4 "bytes"
5 "encoding/xml"
6 "io"
7 "reflect"
8 "strings"
9 "testing"
10 )
11
12 func TestXMLNodeDecoder_Token(t *testing.T) {
13 cases := map[string]struct {
14 responseBody io.Reader
15 expectedStartElement xml.StartElement
16 expectedDone bool
17 expectedError string
18 }{
19 "simple success case": {
20 responseBody: bytes.NewReader([]byte(`<Response>abc</Response>`)),
21 expectedStartElement: xml.StartElement{
22 Name: xml.Name{
23 Local: "",
24 },
25 },
26 expectedDone: true,
27 },
28 "no value": {
29 responseBody: bytes.NewReader([]byte(`<Response></Response>`)),
30 expectedDone: true,
31 },
32 "empty body": {
33 responseBody: bytes.NewReader([]byte(``)),
34 expectedError: "EOF",
35 },
36 "with indentation": {
37 responseBody: bytes.NewReader([]byte(` <Response><Struct>abc</Struct></Response>`)),
38 expectedStartElement: xml.StartElement{
39 Name: xml.Name{
40 Local: "Struct",
41 },
42 Attr: []xml.Attr{},
43 },
44 },
45 "with comment and indentation": {
46 responseBody: bytes.NewReader([]byte(`<!--comment--> <Response><Struct>abc</Struct></Response>`)),
47 expectedStartElement: xml.StartElement{
48 Name: xml.Name{
49 Local: "Struct",
50 },
51 Attr: []xml.Attr{},
52 },
53 },
54 "attr with namespace": {
55 responseBody: bytes.NewReader([]byte(`<Response><Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"></Grantee></Response>`)),
56 expectedStartElement: xml.StartElement{
57 Name: xml.Name{
58 Local: "Grantee",
59 },
60 Attr: []xml.Attr{
61 {
62 Name: xml.Name{
63 Space: "xmlns",
64 Local: "xsi",
65 },
66 Value: "http://www.w3.org/2001/XMLSchema-instance",
67 },
68 {
69 Name: xml.Name{
70 Space: "xsi",
71 Local: "type",
72 },
73 Value: "CanonicalUser",
74 },
75 },
76 },
77 },
78 }
79
80 for name, c := range cases {
81 t.Run(name, func(t *testing.T) {
82 xmlDecoder := xml.NewDecoder(c.responseBody)
83 st, err := FetchRootElement(xmlDecoder)
84 if err != nil {
85 if len(c.expectedError) == 0 {
86 t.Fatalf("Expected no error, got %v", err)
87 }
88
89 if e, a := c.expectedError, err; !strings.Contains(err.Error(), c.expectedError) {
90 t.Fatalf("expected error to contain %v, found %v", e, a.Error())
91 }
92 }
93 nodeDecoder := WrapNodeDecoder(xmlDecoder, st)
94 token, done, err := nodeDecoder.Token()
95 if err != nil {
96 if len(c.expectedError) == 0 {
97 t.Fatalf("Expected no error, got %v", err)
98 }
99
100 if e, a := c.expectedError, err; !strings.Contains(err.Error(), c.expectedError) {
101 t.Fatalf("expected error to contain %v, found %v", e, a.Error())
102 }
103 }
104
105 if e, a := c.expectedDone, done; e != a {
106 t.Fatalf("expected a valid end element token for the xml document, got none")
107 }
108
109 if !reflect.DeepEqual(c.expectedStartElement, token) {
110 t.Fatalf("Found diff : %v != %v", c.expectedStartElement, token)
111 }
112 })
113 }
114 }
115
116 func TestXMLNodeDecoder_TokenExample(t *testing.T) {
117 responseBody := bytes.NewReader([]byte(`<Struct><Response>abc</Response></Struct>`))
118
119 xmlDecoder := xml.NewDecoder(responseBody)
120
121 st, err := FetchRootElement(xmlDecoder)
122 if err != nil {
123 t.Fatalf("Expected no error, got %v", err)
124 }
125
126
127 nodeDecoder := WrapNodeDecoder(xmlDecoder, st)
128
129
130 token, done, err := nodeDecoder.Token()
131 if err != nil {
132 t.Fatalf("Expected no error, got %v", err)
133
134 }
135
136 expect := xml.StartElement{Name: xml.Name{Local: "Response"}, Attr: []xml.Attr{}}
137 if !reflect.DeepEqual(expect, token) {
138 t.Fatalf("Found diff : %v != %v", expect, token)
139 }
140 if done {
141 t.Fatalf("expected decoding to not be done yet")
142 }
143
144
145
146
147
148 token, done, err = nodeDecoder.Token()
149 if err != nil {
150 t.Fatalf("Expected no error, got %v", err)
151
152 }
153
154 expect = xml.StartElement{Name: xml.Name{Local: ""}, Attr: nil}
155 if !reflect.DeepEqual(expect, token) {
156 t.Fatalf("Found diff : %v != %v", expect, token)
157 }
158 if done {
159 t.Fatalf("expected decoding to not be done yet")
160 }
161
162
163
164 token, done, err = nodeDecoder.Token()
165 if err != nil {
166 t.Fatalf("Expected no error, got %v", err)
167
168 }
169
170 if !reflect.DeepEqual(expect, token) {
171 t.Fatalf("%v != %v", expect, token)
172 }
173 if !done {
174 t.Fatalf("expected decoding to be done as we fetched the end element </Struct>")
175 }
176 }
177
178 func TestXMLNodeDecoder_Value(t *testing.T) {
179 cases := map[string]struct {
180 responseBody io.Reader
181 expectedValue []byte
182 expectedDone bool
183 expectedError string
184 }{
185 "simple success case": {
186 responseBody: bytes.NewReader([]byte(`<Response>abc</Response>`)),
187 expectedValue: []byte(`abc`),
188 },
189 "no value": {
190 responseBody: bytes.NewReader([]byte(`<Response></Response>`)),
191 expectedValue: []byte{},
192 },
193 "self-closing": {
194 responseBody: bytes.NewReader([]byte(`<Response />`)),
195 expectedValue: []byte{},
196 },
197 "empty body": {
198 responseBody: bytes.NewReader([]byte(``)),
199 expectedError: "EOF",
200 },
201 "start element retrieved": {
202 responseBody: bytes.NewReader([]byte(`<Response><Struct>abc</Struct></Response>`)),
203 expectedError: "expected value for Response element, got xml.StartElement type",
204 },
205 }
206
207 for name, c := range cases {
208 t.Run(name, func(t *testing.T) {
209 xmlDecoder := xml.NewDecoder(c.responseBody)
210 st, err := FetchRootElement(xmlDecoder)
211 if err != nil {
212 if len(c.expectedError) == 0 {
213 t.Fatalf("Expected no error, got %v", err)
214 }
215
216 if e, a := c.expectedError, err; !strings.Contains(err.Error(), c.expectedError) {
217 t.Fatalf("expected error to contain %v, found %v", e, a.Error())
218 }
219 }
220 nodeDecoder := WrapNodeDecoder(xmlDecoder, st)
221 token, err := nodeDecoder.Value()
222 if err != nil {
223 if len(c.expectedError) == 0 {
224 t.Fatalf("Expected no error, got %v", err)
225 }
226
227 if e, a := c.expectedError, err; !strings.Contains(err.Error(), c.expectedError) {
228 t.Fatalf("expected error to contain %v, found %v", e, a.Error())
229 }
230 }
231
232 if !reflect.DeepEqual(c.expectedValue, token) {
233 t.Fatalf("%v != %v", c.expectedValue, token)
234 }
235 })
236 }
237 }
238
239 func Test_FetchXMLRootElement(t *testing.T) {
240 cases := map[string]struct {
241 responseBody io.Reader
242 expectedStartElement xml.StartElement
243 expectedError string
244 }{
245 "simple success case": {
246 responseBody: bytes.NewReader([]byte(`<Response><Struct>abc</Struct></Response>`)),
247 expectedStartElement: xml.StartElement{
248 Name: xml.Name{
249 Local: "Response",
250 },
251 Attr: []xml.Attr{},
252 },
253 },
254 "empty body": {
255 responseBody: bytes.NewReader([]byte(``)),
256 expectedError: "EOF",
257 },
258 "with indentation": {
259 responseBody: bytes.NewReader([]byte(` <ErrorResponse>
260 <Error>
261 <Type>Sender</Type>
262 <Code>InvalidGreeting</Code>
263 <Message>Hi</Message>
264 <AnotherSetting>setting</AnotherSetting>
265 </Error>
266 <RequestId>foo-id</RequestId>
267 </ErrorResponse>`)),
268 expectedStartElement: xml.StartElement{
269 Name: xml.Name{
270 Local: "ErrorResponse",
271 },
272 Attr: []xml.Attr{},
273 },
274 },
275 "with preamble": {
276 responseBody: bytes.NewReader([]byte(`<?xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
277 <ErrorResponse>
278 <Error>
279 <Type>Sender</Type>
280 <Code>InvalidGreeting</Code>
281 <Message>Hi</Message>
282 <AnotherSetting>setting</AnotherSetting>
283 </Error>
284 <RequestId>foo-id</RequestId>
285 </ErrorResponse>`)),
286 expectedStartElement: xml.StartElement{
287 Name: xml.Name{
288 Local: "ErrorResponse",
289 },
290 Attr: []xml.Attr{},
291 },
292 },
293 "with comments": {
294 responseBody: bytes.NewReader([]byte(`<!--Sample comment for testing-->
295 <?xml version = "1.0" encoding = "UTF-8" standalone = "no" ?>
296 <ErrorResponse>
297 <Error>
298 <Type>Sender</Type>
299 <Code>InvalidGreeting</Code>
300 <Message>Hi</Message>
301 <AnotherSetting>setting</AnotherSetting>
302 </Error>
303 <RequestId>foo-id</RequestId>
304 </ErrorResponse>`)),
305 expectedStartElement: xml.StartElement{
306 Name: xml.Name{
307 Local: "ErrorResponse",
308 },
309 Attr: []xml.Attr{},
310 },
311 },
312 }
313
314 for name, c := range cases {
315 t.Run(name, func(t *testing.T) {
316 decoder := xml.NewDecoder(c.responseBody)
317 st, err := FetchRootElement(decoder)
318 if err != nil {
319 if len(c.expectedError) == 0 {
320 t.Fatalf("Expected no error, got %v", err)
321 }
322
323 if e, a := c.expectedError, err; !strings.Contains(err.Error(), c.expectedError) {
324 t.Fatalf("expected error to contain %v, found %v", e, a.Error())
325 }
326 }
327
328 if !reflect.DeepEqual(c.expectedStartElement, st) {
329 t.Fatalf("Found diff : %v != %v", c.expectedStartElement, st)
330 }
331 })
332 }
333 }
334
View as plain text