1 package autorest
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import (
18 "bytes"
19 "encoding/json"
20 "encoding/xml"
21 "errors"
22 "fmt"
23 "io"
24 "net/http"
25 "net/url"
26 "reflect"
27 "sort"
28 "strings"
29 "testing"
30
31 "github.com/Azure/go-autorest/autorest/adal"
32 "github.com/Azure/go-autorest/autorest/mocks"
33 )
34
35 const (
36 jsonT = `
37 {
38 "name":"Rob Pike",
39 "age":42
40 }`
41 xmlT = `<?xml version="1.0" encoding="UTF-8"?>
42 <Person>
43 <Name>Rob Pike</Name>
44 <Age>42</Age>
45 </Person>`
46 )
47
48 func TestNewDecoderCreatesJSONDecoder(t *testing.T) {
49 d := NewDecoder(EncodedAsJSON, strings.NewReader(jsonT))
50 _, ok := d.(*json.Decoder)
51 if d == nil || !ok {
52 t.Fatal("autorest: NewDecoder failed to create a JSON decoder when requested")
53 }
54 }
55
56 func TestNewDecoderCreatesXMLDecoder(t *testing.T) {
57 d := NewDecoder(EncodedAsXML, strings.NewReader(xmlT))
58 _, ok := d.(*xml.Decoder)
59 if d == nil || !ok {
60 t.Fatal("autorest: NewDecoder failed to create an XML decoder when requested")
61 }
62 }
63
64 func TestNewDecoderReturnsNilForUnknownEncoding(t *testing.T) {
65 d := NewDecoder("unknown", strings.NewReader(xmlT))
66 if d != nil {
67 t.Fatal("autorest: NewDecoder created a decoder for an unknown encoding")
68 }
69 }
70
71 func TestCopyAndDecodeDecodesJSON(t *testing.T) {
72 _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{})
73 if err != nil {
74 t.Fatalf("autorest: CopyAndDecode returned an error with valid JSON - %v", err)
75 }
76 }
77
78 func TestCopyAndDecodeDecodesXML(t *testing.T) {
79 _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT), &mocks.T{})
80 if err != nil {
81 t.Fatalf("autorest: CopyAndDecode returned an error with valid XML - %v", err)
82 }
83 }
84
85 func TestCopyAndDecodeReturnsJSONDecodingErrors(t *testing.T) {
86 _, err := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT[0:len(jsonT)-2]), &mocks.T{})
87 if err == nil {
88 t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid JSON")
89 }
90 }
91
92 func TestCopyAndDecodeReturnsXMLDecodingErrors(t *testing.T) {
93 _, err := CopyAndDecode(EncodedAsXML, strings.NewReader(xmlT[0:len(xmlT)-2]), &mocks.T{})
94 if err == nil {
95 t.Fatalf("autorest: CopyAndDecode failed to return an error with invalid XML")
96 }
97 }
98
99 func TestCopyAndDecodeAlwaysReturnsACopy(t *testing.T) {
100 b, _ := CopyAndDecode(EncodedAsJSON, strings.NewReader(jsonT), &mocks.T{})
101 if b.String() != jsonT {
102 t.Fatalf("autorest: CopyAndDecode failed to return a valid copy of the data - %v", b.String())
103 }
104 }
105
106 func TestTeeReadCloser_Copies(t *testing.T) {
107 v := &mocks.T{}
108 r := mocks.NewResponseWithContent(jsonT)
109 b := &bytes.Buffer{}
110
111 r.Body = TeeReadCloser(r.Body, b)
112
113 err := Respond(r,
114 ByUnmarshallingJSON(v),
115 ByClosing())
116 if err != nil {
117 t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err)
118 }
119 if b.String() != jsonT {
120 t.Fatalf("autorest: TeeReadCloser failed to copy the bytes read")
121 }
122 }
123
124 func TestTeeReadCloser_PassesReadErrors(t *testing.T) {
125 v := &mocks.T{}
126 r := mocks.NewResponseWithContent(jsonT)
127
128 r.Body.(*mocks.Body).Close()
129 r.Body = TeeReadCloser(r.Body, &bytes.Buffer{})
130
131 err := Respond(r,
132 ByUnmarshallingJSON(v),
133 ByClosing())
134 if err == nil {
135 t.Fatalf("autorest: TeeReadCloser failed to return the expected error")
136 }
137 }
138
139 func TestTeeReadCloser_ClosesWrappedReader(t *testing.T) {
140 v := &mocks.T{}
141 r := mocks.NewResponseWithContent(jsonT)
142
143 b := r.Body.(*mocks.Body)
144 r.Body = TeeReadCloser(r.Body, &bytes.Buffer{})
145 err := Respond(r,
146 ByUnmarshallingJSON(v),
147 ByClosing())
148 if err != nil {
149 t.Fatalf("autorest: TeeReadCloser returned an unexpected error -- %v", err)
150 }
151 if b.IsOpen() {
152 t.Fatalf("autorest: TeeReadCloser failed to close the nested io.ReadCloser")
153 }
154 }
155
156 func TestContainsIntFindsValue(t *testing.T) {
157 ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
158 v := 5
159 if !containsInt(ints, v) {
160 t.Fatalf("autorest: containsInt failed to find %v in %v", v, ints)
161 }
162 }
163
164 func TestContainsIntDoesNotFindValue(t *testing.T) {
165 ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
166 v := 42
167 if containsInt(ints, v) {
168 t.Fatalf("autorest: containsInt unexpectedly found %v in %v", v, ints)
169 }
170 }
171
172 func TestContainsIntAcceptsEmptyList(t *testing.T) {
173 ints := make([]int, 10)
174 if containsInt(ints, 42) {
175 t.Fatalf("autorest: containsInt failed to handle an empty list")
176 }
177 }
178
179 func TestContainsIntAcceptsNilList(t *testing.T) {
180 var ints []int
181 if containsInt(ints, 42) {
182 t.Fatalf("autorest: containsInt failed to handle an nil list")
183 }
184 }
185
186 func TestEscapeStrings(t *testing.T) {
187 m := map[string]string{
188 "string": "a long string with = odd characters",
189 "int": "42",
190 "nil": "",
191 }
192 r := map[string]string{
193 "string": "a+long+string+with+%3D+odd+characters",
194 "int": "42",
195 "nil": "",
196 }
197 v := escapeValueStrings(m)
198 if !reflect.DeepEqual(v, r) {
199 t.Fatalf("autorest: ensureValueStrings returned %v\n", v)
200 }
201 }
202
203 func TestEnsureStrings(t *testing.T) {
204 m := map[string]interface{}{
205 "string": "string",
206 "int": 42,
207 "nil": nil,
208 "bytes": []byte{255, 254, 253},
209 }
210 r := map[string]string{
211 "string": "string",
212 "int": "42",
213 "nil": "",
214 "bytes": string([]byte{255, 254, 253}),
215 }
216 v := ensureValueStrings(m)
217 if !reflect.DeepEqual(v, r) {
218 t.Fatalf("autorest: ensureValueStrings returned %v\n", v)
219 }
220 }
221
222 func ExampleString() {
223 m := []string{
224 "string1",
225 "string2",
226 "string3",
227 }
228
229 fmt.Println(String(m, ","))
230
231 }
232
233 func TestStringWithValidString(t *testing.T) {
234 i := 123
235 if got, want := String(i), "123"; got != want {
236 t.Logf("got: %q\nwant: %q", got, want)
237 t.Fail()
238 }
239 }
240
241 func TestStringWithStringSlice(t *testing.T) {
242 s := []string{"string1", "string2"}
243 if got, want := String(s, ","), "string1,string2"; got != want {
244 t.Logf("got: %q\nwant: %q", got, want)
245 t.Fail()
246 }
247 }
248
249 func TestStringWithEnum(t *testing.T) {
250 type TestEnumType string
251 s := TestEnumType("string1")
252 if got, want := String(s), "string1"; got != want {
253 t.Logf("got: %q\nwant: %q", got, want)
254 t.Fail()
255 }
256 }
257
258 func TestStringWithEnumSlice(t *testing.T) {
259 type TestEnumType string
260 s := []TestEnumType{"string1", "string2"}
261 if got, want := String(s, ","), "string1,string2"; got != want {
262 t.Logf("got: %q\nwant: %q", got, want)
263 t.Fail()
264 }
265 }
266
267 func TestStringWithIntegerSlice(t *testing.T) {
268 type TestEnumType int32
269 s := []TestEnumType{1, 2}
270 if got, want := String(s, ","), "1,2"; got != want {
271 t.Logf("got: %q\nwant: %q", got, want)
272 t.Fail()
273 }
274 }
275
276 func ExampleAsStringSlice() {
277 type TestEnumType string
278
279 a := []TestEnumType{"value1", "value2"}
280 b, _ := AsStringSlice(a)
281 for _, c := range b {
282 fmt.Println(c)
283 }
284
285
286
287 }
288
289 func TestEncodeWithValidPath(t *testing.T) {
290 s := Encode("Path", "Hello Gopher")
291 if s != "Hello%20Gopher" {
292 t.Fatalf("autorest: Encode method failed for valid path encoding. Got: %v; Want: %v", s, "Hello%20Gopher")
293 }
294 }
295
296 func TestEncodeWithValidQuery(t *testing.T) {
297 s := Encode("Query", "Hello Gopher")
298 if s != "Hello+Gopher" {
299 t.Fatalf("autorest: Encode method failed for valid query encoding. Got: '%v'; Want: 'Hello+Gopher'", s)
300 }
301 }
302
303 func TestEncodeWithValidNotPathQuery(t *testing.T) {
304 s := Encode("Host", "Hello Gopher")
305 if s != "Hello Gopher" {
306 t.Fatalf("autorest: Encode method failed for parameter not query or path. Got: '%v'; Want: 'Hello Gopher'", s)
307 }
308 }
309
310 func TestMapToValues(t *testing.T) {
311 m := map[string]interface{}{
312 "a": "a",
313 "b": 2,
314 }
315 v := url.Values{}
316 v.Add("a", "a")
317 v.Add("b", "2")
318 if !isEqual(v, MapToValues(m)) {
319 t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m))
320 }
321 }
322
323 func TestMapToValuesWithArrayValues(t *testing.T) {
324 m := map[string]interface{}{
325 "a": []string{"a", "b"},
326 "b": 2,
327 "c": []int{3, 4},
328 }
329 v := url.Values{}
330 v.Add("a", "a")
331 v.Add("a", "b")
332 v.Add("b", "2")
333 v.Add("c", "3")
334 v.Add("c", "4")
335
336 if !isEqual(v, MapToValues(m)) {
337 t.Fatalf("autorest: MapToValues method failed to return correct values - expected(%v) got(%v)", v, MapToValues(m))
338 }
339 }
340
341 type someTempError struct{}
342
343 func (s someTempError) Error() string {
344 return "temporary error"
345 }
346 func (s someTempError) Timeout() bool {
347 return true
348 }
349 func (s someTempError) Temporary() bool {
350 return true
351 }
352
353 func TestIsTemporaryNetworkErrorTrue(t *testing.T) {
354 if !IsTemporaryNetworkError(someTempError{}) {
355 t.Fatal("expected someTempError to be a temporary network error")
356 }
357 if !IsTemporaryNetworkError(errors.New("non-temporary network error")) {
358 t.Fatal("expected random error to be a temporary network error")
359 }
360 }
361
362 type someFatalError struct{}
363
364 func (s someFatalError) Error() string {
365 return "fatal error"
366 }
367 func (s someFatalError) Timeout() bool {
368 return false
369 }
370 func (s someFatalError) Temporary() bool {
371 return false
372 }
373
374 func TestIsTemporaryNetworkErrorFalse(t *testing.T) {
375 if IsTemporaryNetworkError(someFatalError{}) {
376 t.Fatal("expected someFatalError to be a fatal network error")
377 }
378 }
379
380 type tokenRefreshError struct{}
381
382 func (t tokenRefreshError) Error() string {
383 return "empty"
384 }
385
386 func (t tokenRefreshError) Response() *http.Response {
387 return nil
388 }
389
390 var _ adal.TokenRefreshError = (*tokenRefreshError)(nil)
391
392 func TestIsTokenRefreshError(t *testing.T) {
393 err := errors.New("not a TRE")
394 if IsTokenRefreshError(err) {
395 t.Fatal("string error shouldn't be a TokenRefreshError")
396 }
397 err = tokenRefreshError{}
398 if !IsTokenRefreshError(err) {
399 t.Fatal("expected a TokenRefreshError")
400 }
401 err = NewError("package", "method", "failed")
402 if IsTokenRefreshError(err) {
403 t.Fatal("DetailedError shouldn't be a TokenRefreshError")
404 }
405 err = NewErrorWithError(tokenRefreshError{}, "package", "method", nil, "failed")
406 if !IsTokenRefreshError(err) {
407 t.Fatal("expected a wrapped TokenRefreshError")
408 }
409 }
410
411 func isEqual(v, u url.Values) bool {
412 for key, value := range v {
413 if len(u[key]) == 0 {
414 return false
415 }
416 sort.Strings(value)
417 sort.Strings(u[key])
418 for i := range value {
419 if value[i] != u[key][i] {
420 return false
421 }
422 }
423 u.Del(key)
424 }
425 if len(u) > 0 {
426 return false
427 }
428 return true
429 }
430
431 func doEnsureBodyClosed(t *testing.T) SendDecorator {
432 return func(s Sender) Sender {
433 return SenderFunc(func(r *http.Request) (*http.Response, error) {
434 resp, err := s.Do(r)
435 if resp != nil && resp.Body != nil && resp.Body.(*mocks.Body).IsOpen() {
436 t.Fatal("autorest: Expected Body to be closed -- it was left open")
437 }
438 return resp, err
439 })
440 }
441 }
442
443 type mockAuthorizer struct{}
444
445 func (ma mockAuthorizer) WithAuthorization() PrepareDecorator {
446 return WithHeader(headerAuthorization, mocks.TestAuthorizationHeader)
447 }
448
449 type mockFailingAuthorizer struct{}
450
451 func (mfa mockFailingAuthorizer) WithAuthorization() PrepareDecorator {
452 return func(p Preparer) Preparer {
453 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
454 return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error")
455 })
456 }
457 }
458
459 type mockInspector struct {
460 wasInvoked bool
461 }
462
463 func (mi *mockInspector) WithInspection() PrepareDecorator {
464 return func(p Preparer) Preparer {
465 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
466 mi.wasInvoked = true
467 return p.Prepare(r)
468 })
469 }
470 }
471
472 func (mi *mockInspector) ByInspecting() RespondDecorator {
473 return func(r Responder) Responder {
474 return ResponderFunc(func(resp *http.Response) error {
475 mi.wasInvoked = true
476 return r.Respond(resp)
477 })
478 }
479 }
480
481 func withMessage(output *string, msg string) SendDecorator {
482 return func(s Sender) Sender {
483 return SenderFunc(func(r *http.Request) (*http.Response, error) {
484 resp, err := s.Do(r)
485 if err == nil {
486 *output += msg
487 }
488 return resp, err
489 })
490 }
491 }
492
493 func withErrorRespondDecorator(e *error) RespondDecorator {
494 return func(r Responder) Responder {
495 return ResponderFunc(func(resp *http.Response) error {
496 err := r.Respond(resp)
497 if err != nil {
498 return err
499 }
500 *e = fmt.Errorf("autorest: Faux Respond Error")
501 return *e
502 })
503 }
504 }
505
506 type mockDrain struct {
507 read bool
508 closed bool
509 }
510
511 func (md *mockDrain) Read(b []byte) (int, error) {
512 md.read = true
513 b = append(b, 0xff)
514 return 1, io.EOF
515 }
516
517 func (md *mockDrain) Close() error {
518 md.closed = true
519 return nil
520 }
521
522 func TestDrainResponseBody(t *testing.T) {
523 err := DrainResponseBody(nil)
524 if err != nil {
525 t.Fatalf("expected nil error, got %v", err)
526 }
527 err = DrainResponseBody(&http.Response{})
528 if err != nil {
529 t.Fatalf("expected nil error, got %v", err)
530 }
531 md := &mockDrain{}
532 err = DrainResponseBody(&http.Response{Body: md})
533 if err != nil {
534 t.Fatalf("expected nil error, got %v", err)
535 }
536 if !md.closed {
537 t.Fatal("mockDrain wasn't closed")
538 }
539 if !md.read {
540 t.Fatal("mockDrain wasn't read")
541 }
542 }
543
View as plain text