1package autorest 2 3// Copyright 2017 Microsoft Corporation 4// 5// Licensed under the Apache License, Version 2.0 (the "License"); 6// you may not use this file except in compliance with the License. 7// You may obtain a copy of the License at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, software 12// distributed under the License is distributed on an "AS IS" BASIS, 13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14// See the License for the specific language governing permissions and 15// limitations under the License. 16 17import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "io/ioutil" 22 "net/http" 23 "reflect" 24 "strings" 25 "testing" 26 27 "github.com/Azure/go-autorest/autorest/mocks" 28) 29 30func ExampleWithErrorUnlessOK() { 31 r := mocks.NewResponse() 32 r.Request = mocks.NewRequest() 33 34 // Respond and leave the response body open (for a subsequent responder to close) 35 err := Respond(r, 36 WithErrorUnlessOK(), 37 ByDiscardingBody(), 38 ByClosingIfError()) 39 40 if err == nil { 41 fmt.Printf("%s of %s returned HTTP 200", r.Request.Method, r.Request.URL) 42 43 // Complete handling the response and close the body 44 Respond(r, 45 ByDiscardingBody(), 46 ByClosing()) 47 } 48 // Output: GET of https://microsoft.com/a/b/c/ returned HTTP 200 49} 50 51func TestByUnmarshallingBytes(t *testing.T) { 52 expected := []byte("Lorem Ipsum Dolor") 53 54 // we'll create a fixed-sized array here, since that's the expectation 55 bytes := make([]byte, len(expected)) 56 57 Respond(mocks.NewResponseWithBytes(expected), 58 ByUnmarshallingBytes(&bytes), 59 ByClosing()) 60 61 if len(bytes) != len(expected) { 62 t.Fatalf("Expected Response to be %d bytes but got %d bytes", len(expected), len(bytes)) 63 } 64 65 if !reflect.DeepEqual(expected, bytes) { 66 t.Fatalf("Expected Response to be %s but got %s", expected, bytes) 67 } 68} 69 70func ExampleByUnmarshallingJSON() { 71 c := ` 72 { 73 "name" : "Rob Pike", 74 "age" : 42 75 } 76 ` 77 78 type V struct { 79 Name string `json:"name"` 80 Age int `json:"age"` 81 } 82 83 v := &V{} 84 85 Respond(mocks.NewResponseWithContent(c), 86 ByUnmarshallingJSON(v), 87 ByClosing()) 88 89 fmt.Printf("%s is %d years old\n", v.Name, v.Age) 90 // Output: Rob Pike is 42 years old 91} 92 93func ExampleByUnmarshallingXML() { 94 c := `<?xml version="1.0" encoding="UTF-8"?> 95 <Person> 96 <Name>Rob Pike</Name> 97 <Age>42</Age> 98 </Person>` 99 100 type V struct { 101 Name string `xml:"Name"` 102 Age int `xml:"Age"` 103 } 104 105 v := &V{} 106 107 Respond(mocks.NewResponseWithContent(c), 108 ByUnmarshallingXML(v), 109 ByClosing()) 110 111 fmt.Printf("%s is %d years old\n", v.Name, v.Age) 112 // Output: Rob Pike is 42 years old 113} 114 115func TestCreateResponderDoesNotModify(t *testing.T) { 116 r1 := mocks.NewResponse() 117 r2 := mocks.NewResponse() 118 p := CreateResponder() 119 err := p.Respond(r1) 120 if err != nil { 121 t.Fatalf("autorest: CreateResponder failed (%v)", err) 122 } 123 if !reflect.DeepEqual(r1, r2) { 124 t.Fatalf("autorest: CreateResponder without decorators modified the response") 125 } 126} 127 128func TestCreateResponderRunsDecoratorsInOrder(t *testing.T) { 129 s := "" 130 131 d := func(n int) RespondDecorator { 132 return func(r Responder) Responder { 133 return ResponderFunc(func(resp *http.Response) error { 134 err := r.Respond(resp) 135 if err == nil { 136 s += fmt.Sprintf("%d", n) 137 } 138 return err 139 }) 140 } 141 } 142 143 p := CreateResponder(d(1), d(2), d(3)) 144 err := p.Respond(&http.Response{}) 145 if err != nil { 146 t.Fatalf("autorest: Respond failed (%v)", err) 147 } 148 149 if s != "123" { 150 t.Fatalf("autorest: CreateResponder invoked decorators in an incorrect order; expected '123', received '%s'", s) 151 } 152} 153 154func TestByIgnoring(t *testing.T) { 155 r := mocks.NewResponse() 156 157 Respond(r, 158 (func() RespondDecorator { 159 return func(r Responder) Responder { 160 return ResponderFunc(func(r2 *http.Response) error { 161 r1 := mocks.NewResponse() 162 if !reflect.DeepEqual(r1, r2) { 163 t.Fatalf("autorest: ByIgnoring modified the HTTP Response -- received %v, expected %v", r2, r1) 164 } 165 return nil 166 }) 167 } 168 })(), 169 ByIgnoring(), 170 ByClosing()) 171} 172 173func TestByCopying_Copies(t *testing.T) { 174 r := mocks.NewResponseWithContent(jsonT) 175 b := &bytes.Buffer{} 176 177 err := Respond(r, 178 ByCopying(b), 179 ByUnmarshallingJSON(&mocks.T{}), 180 ByClosing()) 181 if err != nil { 182 t.Fatalf("autorest: ByCopying returned an unexpected error -- %v", err) 183 } 184 if b.String() != jsonT { 185 t.Fatalf("autorest: ByCopying failed to copy the bytes read") 186 } 187} 188 189func TestByCopying_ReturnsNestedErrors(t *testing.T) { 190 r := mocks.NewResponseWithContent(jsonT) 191 192 r.Body.Close() 193 err := Respond(r, 194 ByCopying(&bytes.Buffer{}), 195 ByUnmarshallingJSON(&mocks.T{}), 196 ByClosing()) 197 if err == nil { 198 t.Fatalf("autorest: ByCopying failed to return the expected error") 199 } 200} 201 202func TestByCopying_AcceptsNilReponse(t *testing.T) { 203 r := mocks.NewResponse() 204 205 Respond(r, 206 (func() RespondDecorator { 207 return func(r Responder) Responder { 208 return ResponderFunc(func(resp *http.Response) error { 209 resp.Body.Close() 210 r.Respond(nil) 211 return nil 212 }) 213 } 214 })(), 215 ByCopying(&bytes.Buffer{})) 216} 217 218func TestByCopying_AcceptsNilBody(t *testing.T) { 219 r := mocks.NewResponse() 220 221 Respond(r, 222 (func() RespondDecorator { 223 return func(r Responder) Responder { 224 return ResponderFunc(func(resp *http.Response) error { 225 resp.Body.Close() 226 resp.Body = nil 227 r.Respond(resp) 228 return nil 229 }) 230 } 231 })(), 232 ByCopying(&bytes.Buffer{})) 233} 234 235func TestByClosing(t *testing.T) { 236 r := mocks.NewResponse() 237 err := Respond(r, ByClosing()) 238 if err != nil { 239 t.Fatalf("autorest: ByClosing failed (%v)", err) 240 } 241 if r.Body.(*mocks.Body).IsOpen() { 242 t.Fatalf("autorest: ByClosing did not close the response body") 243 } 244} 245 246func TestByClosingAcceptsNilResponse(t *testing.T) { 247 r := mocks.NewResponse() 248 249 Respond(r, 250 (func() RespondDecorator { 251 return func(r Responder) Responder { 252 return ResponderFunc(func(resp *http.Response) error { 253 resp.Body.Close() 254 r.Respond(nil) 255 return nil 256 }) 257 } 258 })(), 259 ByClosing()) 260} 261 262func TestByClosingAcceptsNilBody(t *testing.T) { 263 r := mocks.NewResponse() 264 265 Respond(r, 266 (func() RespondDecorator { 267 return func(r Responder) Responder { 268 return ResponderFunc(func(resp *http.Response) error { 269 resp.Body.Close() 270 resp.Body = nil 271 r.Respond(resp) 272 return nil 273 }) 274 } 275 })(), 276 ByClosing()) 277} 278 279func TestByClosingClosesEvenAfterErrors(t *testing.T) { 280 var e error 281 282 r := mocks.NewResponse() 283 Respond(r, 284 withErrorRespondDecorator(&e), 285 ByClosing()) 286 287 if r.Body.(*mocks.Body).IsOpen() { 288 t.Fatalf("autorest: ByClosing did not close the response body after an error occurred") 289 } 290} 291 292func TestByClosingClosesReturnsNestedErrors(t *testing.T) { 293 var e error 294 295 r := mocks.NewResponse() 296 err := Respond(r, 297 withErrorRespondDecorator(&e), 298 ByClosing()) 299 300 if err == nil || !reflect.DeepEqual(e, err) { 301 t.Fatalf("autorest: ByClosing failed to return a nested error") 302 } 303} 304 305func TestByClosingIfErrorAcceptsNilResponse(t *testing.T) { 306 var e error 307 308 r := mocks.NewResponse() 309 310 Respond(r, 311 withErrorRespondDecorator(&e), 312 (func() RespondDecorator { 313 return func(r Responder) Responder { 314 return ResponderFunc(func(resp *http.Response) error { 315 resp.Body.Close() 316 r.Respond(nil) 317 return nil 318 }) 319 } 320 })(), 321 ByClosingIfError()) 322} 323 324func TestByClosingIfErrorAcceptsNilBody(t *testing.T) { 325 var e error 326 327 r := mocks.NewResponse() 328 329 Respond(r, 330 withErrorRespondDecorator(&e), 331 (func() RespondDecorator { 332 return func(r Responder) Responder { 333 return ResponderFunc(func(resp *http.Response) error { 334 resp.Body.Close() 335 resp.Body = nil 336 r.Respond(resp) 337 return nil 338 }) 339 } 340 })(), 341 ByClosingIfError()) 342} 343 344func TestByClosingIfErrorClosesIfAnErrorOccurs(t *testing.T) { 345 var e error 346 347 r := mocks.NewResponse() 348 Respond(r, 349 withErrorRespondDecorator(&e), 350 ByClosingIfError()) 351 352 if r.Body.(*mocks.Body).IsOpen() { 353 t.Fatalf("autorest: ByClosingIfError did not close the response body after an error occurred") 354 } 355} 356 357func TestByClosingIfErrorDoesNotClosesIfNoErrorOccurs(t *testing.T) { 358 r := mocks.NewResponse() 359 Respond(r, 360 ByClosingIfError()) 361 362 if !r.Body.(*mocks.Body).IsOpen() { 363 t.Fatalf("autorest: ByClosingIfError closed the response body even though no error occurred") 364 } 365} 366 367func TestByDiscardingBody(t *testing.T) { 368 r := mocks.NewResponse() 369 err := Respond(r, 370 ByDiscardingBody()) 371 if err != nil { 372 t.Fatalf("autorest: ByDiscardingBody failed (%v)", err) 373 } 374 buf, err := ioutil.ReadAll(r.Body) 375 if err != nil { 376 t.Fatalf("autorest: Reading result of ByDiscardingBody failed (%v)", err) 377 } 378 379 if len(buf) != 0 { 380 t.Logf("autorest: Body was not empty after calling ByDiscardingBody.") 381 t.Fail() 382 } 383} 384 385func TestByDiscardingBodyAcceptsNilResponse(t *testing.T) { 386 var e error 387 388 r := mocks.NewResponse() 389 390 Respond(r, 391 withErrorRespondDecorator(&e), 392 (func() RespondDecorator { 393 return func(r Responder) Responder { 394 return ResponderFunc(func(resp *http.Response) error { 395 resp.Body.Close() 396 r.Respond(nil) 397 return nil 398 }) 399 } 400 })(), 401 ByDiscardingBody()) 402} 403 404func TestByDiscardingBodyAcceptsNilBody(t *testing.T) { 405 var e error 406 407 r := mocks.NewResponse() 408 409 Respond(r, 410 withErrorRespondDecorator(&e), 411 (func() RespondDecorator { 412 return func(r Responder) Responder { 413 return ResponderFunc(func(resp *http.Response) error { 414 resp.Body.Close() 415 resp.Body = nil 416 r.Respond(resp) 417 return nil 418 }) 419 } 420 })(), 421 ByDiscardingBody()) 422} 423 424func TestByUnmarshallingJSON(t *testing.T) { 425 v := &mocks.T{} 426 r := mocks.NewResponseWithContent(jsonT) 427 err := Respond(r, 428 ByUnmarshallingJSON(v), 429 ByClosing()) 430 if err != nil { 431 t.Fatalf("autorest: ByUnmarshallingJSON failed (%v)", err) 432 } 433 if v.Name != "Rob Pike" || v.Age != 42 { 434 t.Fatalf("autorest: ByUnmarshallingJSON failed to properly unmarshal") 435 } 436} 437 438func TestByUnmarshallingJSON_HandlesReadErrors(t *testing.T) { 439 v := &mocks.T{} 440 r := mocks.NewResponseWithContent(jsonT) 441 r.Body.(*mocks.Body).Close() 442 443 err := Respond(r, 444 ByUnmarshallingJSON(v), 445 ByClosing()) 446 if err == nil { 447 t.Fatalf("autorest: ByUnmarshallingJSON failed to receive / respond to read error") 448 } 449} 450 451func TestByUnmarshallingJSONIncludesJSONInErrors(t *testing.T) { 452 v := &mocks.T{} 453 j := jsonT[0 : len(jsonT)-2] 454 r := mocks.NewResponseWithContent(j) 455 err := Respond(r, 456 ByUnmarshallingJSON(v), 457 ByClosing()) 458 if err == nil || !strings.Contains(err.Error(), j) { 459 t.Fatalf("autorest: ByUnmarshallingJSON failed to return JSON in error (%v)", err) 460 } 461} 462 463func TestByUnmarshallingJSONEmptyInput(t *testing.T) { 464 v := &mocks.T{} 465 r := mocks.NewResponseWithContent(``) 466 err := Respond(r, 467 ByUnmarshallingJSON(v), 468 ByClosing()) 469 if err != nil { 470 t.Fatalf("autorest: ByUnmarshallingJSON failed to return nil in case of empty JSON (%v)", err) 471 } 472} 473 474func TestByUnmarshallingXML(t *testing.T) { 475 v := &mocks.T{} 476 r := mocks.NewResponseWithContent(xmlT) 477 err := Respond(r, 478 ByUnmarshallingXML(v), 479 ByClosing()) 480 if err != nil { 481 t.Fatalf("autorest: ByUnmarshallingXML failed (%v)", err) 482 } 483 if v.Name != "Rob Pike" || v.Age != 42 { 484 t.Fatalf("autorest: ByUnmarshallingXML failed to properly unmarshal") 485 } 486} 487 488func TestByUnmarshallingXML_HandlesReadErrors(t *testing.T) { 489 v := &mocks.T{} 490 r := mocks.NewResponseWithContent(xmlT) 491 r.Body.(*mocks.Body).Close() 492 493 err := Respond(r, 494 ByUnmarshallingXML(v), 495 ByClosing()) 496 if err == nil { 497 t.Fatalf("autorest: ByUnmarshallingXML failed to receive / respond to read error") 498 } 499} 500 501func TestByUnmarshallingXMLIncludesXMLInErrors(t *testing.T) { 502 v := &mocks.T{} 503 x := xmlT[0 : len(xmlT)-2] 504 r := mocks.NewResponseWithContent(x) 505 err := Respond(r, 506 ByUnmarshallingXML(v), 507 ByClosing()) 508 if err == nil || !strings.Contains(err.Error(), x) { 509 t.Fatalf("autorest: ByUnmarshallingXML failed to return XML in error (%v)", err) 510 } 511} 512 513func TestRespondAcceptsNullResponse(t *testing.T) { 514 err := Respond(nil) 515 if err != nil { 516 t.Fatalf("autorest: Respond returned an unexpected error when given a null Response (%v)", err) 517 } 518} 519 520func TestWithErrorUnlessStatusCodeOKResponse(t *testing.T) { 521 v := &mocks.T{} 522 r := mocks.NewResponseWithContent(jsonT) 523 err := Respond(r, 524 WithErrorUnlessStatusCode(http.StatusOK), 525 ByUnmarshallingJSON(v), 526 ByClosing()) 527 528 if err != nil { 529 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) failed on okay response. (%v)", err) 530 } 531 532 if v.Name != "Rob Pike" || v.Age != 42 { 533 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) corrupted the response body of okay response.") 534 } 535} 536 537func TesWithErrorUnlessStatusCodeErrorResponse(t *testing.T) { 538 v := &mocks.T{} 539 e := &mocks.T{} 540 r := mocks.NewResponseWithContent(jsonT) 541 r.Status = "400 BadRequest" 542 r.StatusCode = http.StatusBadRequest 543 544 err := Respond(r, 545 WithErrorUnlessStatusCode(http.StatusOK), 546 ByUnmarshallingJSON(v), 547 ByClosing()) 548 549 if err == nil { 550 t.Fatal("autorest: WithErrorUnlessStatusCode(http.StatusOK) did not return error, on a response to a bad request.") 551 } 552 553 var errorRespBody []byte 554 if derr, ok := err.(DetailedError); !ok { 555 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) got wrong error type : %T, expected: DetailedError, on a response to a bad request.", err) 556 } else { 557 errorRespBody = derr.ServiceError 558 } 559 560 if errorRespBody == nil { 561 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) ServiceError not returned in DetailedError on a response to a bad request.") 562 } 563 564 err = json.Unmarshal(errorRespBody, e) 565 if err != nil { 566 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK) cannot parse error returned in ServiceError into json. %v", err) 567 } 568 569 expected := &mocks.T{Name: "Rob Pike", Age: 42} 570 if e != expected { 571 t.Fatalf("autorest: WithErrorUnlessStatusCode(http.StatusOK wrong value from parsed ServiceError: got=%#v expected=%#v", e, expected) 572 } 573} 574 575func TestWithErrorUnlessStatusCode(t *testing.T) { 576 r := mocks.NewResponse() 577 r.Request = mocks.NewRequest() 578 r.Status = "400 BadRequest" 579 r.StatusCode = http.StatusBadRequest 580 581 err := Respond(r, 582 WithErrorUnlessStatusCode(http.StatusBadRequest, http.StatusUnauthorized, http.StatusInternalServerError), 583 ByClosingIfError()) 584 585 if err != nil { 586 t.Fatalf("autorest: WithErrorUnlessStatusCode returned an error (%v) for an acceptable status code (%s)", err, r.Status) 587 } 588} 589 590func TestWithErrorUnlessStatusCodeEmitsErrorForUnacceptableStatusCode(t *testing.T) { 591 r := mocks.NewResponse() 592 r.Request = mocks.NewRequest() 593 r.Status = "400 BadRequest" 594 r.StatusCode = http.StatusBadRequest 595 596 err := Respond(r, 597 WithErrorUnlessStatusCode(http.StatusOK, http.StatusUnauthorized, http.StatusInternalServerError), 598 ByClosingIfError()) 599 600 if err == nil { 601 t.Fatalf("autorest: WithErrorUnlessStatusCode failed to return an error for an unacceptable status code (%s)", r.Status) 602 } 603} 604 605func TestWithErrorUnlessOK(t *testing.T) { 606 r := mocks.NewResponse() 607 r.Request = mocks.NewRequest() 608 609 err := Respond(r, 610 WithErrorUnlessOK(), 611 ByClosingIfError()) 612 613 if err != nil { 614 t.Fatalf("autorest: WithErrorUnlessOK returned an error for OK status code (%v)", err) 615 } 616} 617 618func TestWithErrorUnlessOKEmitsErrorIfNotOK(t *testing.T) { 619 r := mocks.NewResponse() 620 r.Request = mocks.NewRequest() 621 r.Status = "400 BadRequest" 622 r.StatusCode = http.StatusBadRequest 623 624 err := Respond(r, 625 WithErrorUnlessOK(), 626 ByClosingIfError()) 627 628 if err == nil { 629 t.Fatalf("autorest: WithErrorUnlessOK failed to return an error for a non-OK status code (%v)", err) 630 } 631} 632 633func TestExtractHeader(t *testing.T) { 634 r := mocks.NewResponse() 635 v := []string{"v1", "v2", "v3"} 636 mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) 637 638 if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { 639 t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", 640 mocks.TestHeader, v, mocks.TestHeader, ExtractHeader(mocks.TestHeader, r)) 641 } 642} 643 644func TestExtractHeaderHandlesMissingHeader(t *testing.T) { 645 var v []string 646 r := mocks.NewResponse() 647 648 if !reflect.DeepEqual(ExtractHeader(mocks.TestHeader, r), v) { 649 t.Fatalf("autorest: ExtractHeader failed to handle a missing header -- expected %v, received %v", 650 v, ExtractHeader(mocks.TestHeader, r)) 651 } 652} 653 654func TestExtractHeaderValue(t *testing.T) { 655 r := mocks.NewResponse() 656 v := "v1" 657 mocks.SetResponseHeader(r, mocks.TestHeader, v) 658 659 if ExtractHeaderValue(mocks.TestHeader, r) != v { 660 t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", 661 mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) 662 } 663} 664 665func TestExtractHeaderValueHandlesMissingHeader(t *testing.T) { 666 r := mocks.NewResponse() 667 v := "" 668 669 if ExtractHeaderValue(mocks.TestHeader, r) != v { 670 t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", 671 mocks.TestHeader, v, mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) 672 } 673} 674 675func TestExtractHeaderValueRetrievesFirstValue(t *testing.T) { 676 r := mocks.NewResponse() 677 v := []string{"v1", "v2", "v3"} 678 mocks.SetResponseHeaderValues(r, mocks.TestHeader, v) 679 680 if ExtractHeaderValue(mocks.TestHeader, r) != v[0] { 681 t.Fatalf("autorest: ExtractHeader failed to retrieve the expected header -- expected [%s]%v, received [%s]%v", 682 mocks.TestHeader, v[0], mocks.TestHeader, ExtractHeaderValue(mocks.TestHeader, r)) 683 } 684} 685