1package azure 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 "encoding/json" 19 "fmt" 20 "io/ioutil" 21 "net/http" 22 "reflect" 23 "strconv" 24 "strings" 25 "testing" 26 "time" 27 28 "github.com/Azure/go-autorest/autorest" 29 "github.com/Azure/go-autorest/autorest/mocks" 30) 31 32const ( 33 headerAuthorization = "Authorization" 34 longDelay = 5 * time.Second 35 retryDelay = 10 * time.Millisecond 36 testLogPrefix = "azure:" 37) 38 39// Use a Client Inspector to set the request identifier. 40func ExampleWithClientID() { 41 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 42 req, _ := autorest.Prepare(&http.Request{}, 43 autorest.AsGet(), 44 autorest.WithBaseURL("https://microsoft.com/a/b/c/")) 45 46 c := autorest.Client{Sender: mocks.NewSender()} 47 c.RequestInspector = WithReturningClientID(uuid) 48 49 autorest.SendWithSender(c, req) 50 fmt.Printf("Inspector added the %s header with the value %s\n", 51 HeaderClientID, req.Header.Get(HeaderClientID)) 52 fmt.Printf("Inspector added the %s header with the value %s\n", 53 HeaderReturnClientID, req.Header.Get(HeaderReturnClientID)) 54 // Output: 55 // Inspector added the x-ms-client-request-id header with the value 71FDB9F4-5E49-4C12-B266-DE7B4FD999A6 56 // Inspector added the x-ms-return-client-request-id header with the value true 57} 58 59func TestWithReturningClientIDReturnsError(t *testing.T) { 60 var errIn error 61 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 62 _, errOut := autorest.Prepare(&http.Request{}, 63 withErrorPrepareDecorator(&errIn), 64 WithReturningClientID(uuid)) 65 66 if errOut == nil || errIn != errOut { 67 t.Fatalf("azure: WithReturningClientID failed to exit early when receiving an error -- expected (%v), received (%v)", 68 errIn, errOut) 69 } 70} 71 72func TestWithClientID(t *testing.T) { 73 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 74 req, _ := autorest.Prepare(&http.Request{}, 75 WithClientID(uuid)) 76 77 if req.Header.Get(HeaderClientID) != uuid { 78 t.Fatalf("azure: WithClientID failed to set %s -- expected %s, received %s", 79 HeaderClientID, uuid, req.Header.Get(HeaderClientID)) 80 } 81} 82 83func TestWithReturnClientID(t *testing.T) { 84 b := false 85 req, _ := autorest.Prepare(&http.Request{}, 86 WithReturnClientID(b)) 87 88 if req.Header.Get(HeaderReturnClientID) != strconv.FormatBool(b) { 89 t.Fatalf("azure: WithReturnClientID failed to set %s -- expected %s, received %s", 90 HeaderClientID, strconv.FormatBool(b), req.Header.Get(HeaderClientID)) 91 } 92} 93 94func TestExtractClientID(t *testing.T) { 95 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 96 resp := mocks.NewResponse() 97 mocks.SetResponseHeader(resp, HeaderClientID, uuid) 98 99 if ExtractClientID(resp) != uuid { 100 t.Fatalf("azure: ExtractClientID failed to extract the %s -- expected %s, received %s", 101 HeaderClientID, uuid, ExtractClientID(resp)) 102 } 103} 104 105func TestExtractRequestID(t *testing.T) { 106 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 107 resp := mocks.NewResponse() 108 mocks.SetResponseHeader(resp, HeaderRequestID, uuid) 109 110 if ExtractRequestID(resp) != uuid { 111 t.Fatalf("azure: ExtractRequestID failed to extract the %s -- expected %s, received %s", 112 HeaderRequestID, uuid, ExtractRequestID(resp)) 113 } 114} 115 116func TestIsAzureError_ReturnsTrueForAzureError(t *testing.T) { 117 if !IsAzureError(&RequestError{}) { 118 t.Fatalf("azure: IsAzureError failed to return true for an Azure Service error") 119 } 120} 121 122func TestIsAzureError_ReturnsFalseForNonAzureError(t *testing.T) { 123 if IsAzureError(fmt.Errorf("An Error")) { 124 t.Fatalf("azure: IsAzureError return true for an non-Azure Service error") 125 } 126} 127 128func TestNewErrorWithError_UsesReponseStatusCode(t *testing.T) { 129 e := NewErrorWithError(fmt.Errorf("Error"), "packageType", "method", mocks.NewResponseWithStatus("Forbidden", http.StatusForbidden), "message") 130 if e.StatusCode != http.StatusForbidden { 131 t.Fatalf("azure: NewErrorWithError failed to use the Status Code of the passed Response -- expected %v, received %v", http.StatusForbidden, e.StatusCode) 132 } 133} 134 135func TestNewErrorWithError_ReturnsUnwrappedError(t *testing.T) { 136 e1 := RequestError{} 137 e1.ServiceError = &ServiceError{Code: "42", Message: "A Message"} 138 e1.StatusCode = 200 139 e1.RequestID = "A RequestID" 140 e2 := NewErrorWithError(&e1, "packageType", "method", nil, "message") 141 142 if !reflect.DeepEqual(e1, e2) { 143 t.Fatalf("azure: NewErrorWithError wrapped an RequestError -- expected %T, received %T", e1, e2) 144 } 145} 146 147func TestNewErrorWithError_WrapsAnError(t *testing.T) { 148 e1 := fmt.Errorf("Inner Error") 149 var e2 interface{} = NewErrorWithError(e1, "packageType", "method", nil, "message") 150 151 if _, ok := e2.(RequestError); !ok { 152 t.Fatalf("azure: NewErrorWithError failed to wrap a standard error -- received %T", e2) 153 } 154} 155 156func TestWithErrorUnlessStatusCode_NotAnAzureError(t *testing.T) { 157 body := `<html> 158 <head> 159 <title>IIS Error page</title> 160 </head> 161 <body>Some non-JSON error page</body> 162 </html>` 163 r := mocks.NewResponseWithContent(body) 164 r.Request = mocks.NewRequest() 165 r.StatusCode = http.StatusBadRequest 166 r.Status = http.StatusText(r.StatusCode) 167 168 err := autorest.Respond(r, 169 WithErrorUnlessStatusCode(http.StatusOK), 170 autorest.ByClosing()) 171 ok, _ := err.(*RequestError) 172 if ok != nil { 173 t.Fatalf("azure: azure.RequestError returned from malformed response: %v", err) 174 } 175 176 // the error body should still be there 177 defer r.Body.Close() 178 b, err := ioutil.ReadAll(r.Body) 179 if err != nil { 180 t.Fatal(err) 181 } 182 if string(b) != body { 183 t.Fatalf("response body is wrong. got=%q exptected=%q", string(b), body) 184 } 185} 186 187func TestWithErrorUnlessStatusCode_FoundAzureErrorWithoutDetails(t *testing.T) { 188 j := `{ 189 "error": { 190 "code": "InternalError", 191 "message": "Azure is having trouble right now." 192 } 193 }` 194 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 195 r := mocks.NewResponseWithContent(j) 196 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 197 r.Request = mocks.NewRequest() 198 r.StatusCode = http.StatusInternalServerError 199 r.Status = http.StatusText(r.StatusCode) 200 201 err := autorest.Respond(r, 202 WithErrorUnlessStatusCode(http.StatusOK), 203 autorest.ByClosing()) 204 205 if err == nil { 206 t.Fatalf("azure: returned nil error for proper error response") 207 } 208 azErr, ok := err.(*RequestError) 209 if !ok { 210 t.Fatalf("azure: returned error is not azure.RequestError: %T", err) 211 } 212 213 expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Azure is having trouble right now.\"" 214 if !reflect.DeepEqual(expected, azErr.Error()) { 215 t.Fatalf("azure: service error is not unmarshaled properly.\nexpected=%v\ngot=%v", expected, azErr.Error()) 216 } 217 218 if expected := http.StatusInternalServerError; azErr.StatusCode != expected { 219 t.Fatalf("azure: got wrong StatusCode=%d Expected=%d", azErr.StatusCode, expected) 220 } 221 if expected := uuid; azErr.RequestID != expected { 222 t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) 223 } 224 225 _ = azErr.Error() 226 227 // the error body should still be there 228 defer r.Body.Close() 229 b, err := ioutil.ReadAll(r.Body) 230 if err != nil { 231 t.Fatal(err) 232 } 233 if string(b) != j { 234 t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) 235 } 236 237} 238 239func TestWithErrorUnlessStatusCode_FoundAzureFullError(t *testing.T) { 240 j := `{ 241 "error": { 242 "code": "InternalError", 243 "message": "Azure is having trouble right now.", 244 "target": "target1", 245 "details": [{"code": "conflict1", "message":"error message1"}, 246 {"code": "conflict2", "message":"error message2"}], 247 "innererror": { "customKey": "customValue" }, 248 "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] 249 } 250 }` 251 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 252 r := mocks.NewResponseWithContent(j) 253 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 254 r.Request = mocks.NewRequest() 255 r.StatusCode = http.StatusInternalServerError 256 r.Status = http.StatusText(r.StatusCode) 257 258 err := autorest.Respond(r, 259 WithErrorUnlessStatusCode(http.StatusOK), 260 autorest.ByClosing()) 261 262 if err == nil { 263 t.Fatalf("azure: returned nil error for proper error response") 264 } 265 azErr, ok := err.(*RequestError) 266 if !ok { 267 t.Fatalf("azure: returned error is not azure.RequestError: %T", err) 268 } 269 270 if expected := "InternalError"; azErr.ServiceError.Code != expected { 271 t.Fatalf("azure: wrong error code. expected=%q; got=%q", expected, azErr.ServiceError.Code) 272 } 273 274 if azErr.ServiceError.Message == "" { 275 t.Fatalf("azure: error message is not unmarshaled properly") 276 } 277 278 if *azErr.ServiceError.Target == "" { 279 t.Fatalf("azure: error target is not unmarshaled properly") 280 } 281 282 d, _ := json.Marshal(azErr.ServiceError.Details) 283 if string(d) != `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` { 284 t.Fatalf("azure: error details is not unmarshaled properly") 285 } 286 287 i, _ := json.Marshal(azErr.ServiceError.InnerError) 288 if string(i) != `{"customKey":"customValue"}` { 289 t.Fatalf("azure: inner error is not unmarshaled properly") 290 } 291 292 a, _ := json.Marshal(azErr.ServiceError.AdditionalInfo) 293 if string(a) != `[{"info":{"someProperty":"someValue"},"type":"someErrorType"}]` { 294 t.Fatalf("azure: error additional info is not unmarshaled properly") 295 } 296 297 if expected := http.StatusInternalServerError; azErr.StatusCode != expected { 298 t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) 299 } 300 if expected := uuid; azErr.RequestID != expected { 301 t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) 302 } 303 304 _ = azErr.Error() 305 306 // the error body should still be there 307 defer r.Body.Close() 308 b, err := ioutil.ReadAll(r.Body) 309 if err != nil { 310 t.Fatal(err) 311 } 312 if string(b) != j { 313 t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) 314 } 315 316} 317 318func TestWithErrorUnlessStatusCode_NoAzureError(t *testing.T) { 319 j := `{ 320 "Status":"NotFound" 321 }` 322 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 323 r := mocks.NewResponseWithContent(j) 324 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 325 r.Request = mocks.NewRequest() 326 r.StatusCode = http.StatusInternalServerError 327 r.Status = http.StatusText(r.StatusCode) 328 329 err := autorest.Respond(r, 330 WithErrorUnlessStatusCode(http.StatusOK), 331 autorest.ByClosing()) 332 if err == nil { 333 t.Fatalf("azure: returned nil error for proper error response") 334 } 335 azErr, ok := err.(*RequestError) 336 if !ok { 337 t.Fatalf("azure: returned error is not azure.RequestError: %T", err) 338 } 339 340 expected := &ServiceError{ 341 Code: "Unknown", 342 Message: "Unknown service error", 343 Details: []map[string]interface{}{ 344 {"Status": "NotFound"}, 345 }, 346 } 347 348 if !reflect.DeepEqual(expected, azErr.ServiceError) { 349 t.Fatalf("azure: service error is not unmarshaled properly. expected=%q\ngot=%q", expected, azErr.ServiceError) 350 } 351 352 if expected := http.StatusInternalServerError; azErr.StatusCode != expected { 353 t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected) 354 } 355 if expected := uuid; azErr.RequestID != expected { 356 t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID) 357 } 358 359 _ = azErr.Error() 360 361 // the error body should still be there 362 defer r.Body.Close() 363 b, err := ioutil.ReadAll(r.Body) 364 if err != nil { 365 t.Fatal(err) 366 } 367 if string(b) != j { 368 t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) 369 } 370 371} 372 373func TestWithErrorUnlessStatusCode_UnwrappedError(t *testing.T) { 374 j := `{ 375 "code": "InternalError", 376 "message": "Azure is having trouble right now.", 377 "target": "target1", 378 "details": [{"code": "conflict1", "message":"error message1"}, 379 {"code": "conflict2", "message":"error message2"}], 380 "innererror": { "customKey": "customValue" }, 381 "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] 382 }` 383 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 384 r := mocks.NewResponseWithContent(j) 385 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 386 r.Request = mocks.NewRequest() 387 r.StatusCode = http.StatusInternalServerError 388 r.Status = http.StatusText(r.StatusCode) 389 390 err := autorest.Respond(r, 391 WithErrorUnlessStatusCode(http.StatusOK), 392 autorest.ByClosing()) 393 394 if err == nil { 395 t.Fatal("azure: returned nil error for proper error response") 396 } 397 398 azErr, ok := err.(*RequestError) 399 if !ok { 400 t.Fatalf("returned error is not azure.RequestError: %T", err) 401 } 402 403 if expected := http.StatusInternalServerError; azErr.StatusCode != expected { 404 t.Logf("Incorrect StatusCode got: %v want: %d", azErr.StatusCode, expected) 405 t.Fail() 406 } 407 408 if expected := "Azure is having trouble right now."; azErr.Message != expected { 409 t.Logf("Incorrect Message\n\tgot: %q\n\twant: %q", azErr.Message, expected) 410 t.Fail() 411 } 412 413 if expected := uuid; azErr.RequestID != expected { 414 t.Logf("Incorrect request ID\n\tgot: %q\n\twant: %q", azErr.RequestID, expected) 415 t.Fail() 416 } 417 418 if azErr.ServiceError == nil { 419 t.Logf("`ServiceError` was nil when it shouldn't have been.") 420 t.Fail() 421 } 422 423 if expected := "target1"; *azErr.ServiceError.Target != expected { 424 t.Logf("Incorrect Target\n\tgot: %q\n\twant: %q", *azErr.ServiceError.Target, expected) 425 t.Fail() 426 } 427 428 expectedServiceErrorDetails := `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]` 429 if azErr.ServiceError.Details == nil { 430 t.Logf("`ServiceError.Details` was nil when it should have been %q", expectedServiceErrorDetails) 431 t.Fail() 432 } else if details, _ := json.Marshal(azErr.ServiceError.Details); expectedServiceErrorDetails != string(details) { 433 t.Logf("Error details was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(details), expectedServiceErrorDetails) 434 t.Fail() 435 } 436 437 expectedServiceErrorInnerError := `{"customKey":"customValue"}` 438 if azErr.ServiceError.InnerError == nil { 439 t.Logf("`ServiceError.InnerError` was nil when it should have been %q", expectedServiceErrorInnerError) 440 t.Fail() 441 } else if innerError, _ := json.Marshal(azErr.ServiceError.InnerError); expectedServiceErrorInnerError != string(innerError) { 442 t.Logf("Inner error was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(innerError), expectedServiceErrorInnerError) 443 t.Fail() 444 } 445 446 expectedServiceErrorAdditionalInfo := `[{"info":{"someProperty":"someValue"},"type":"someErrorType"}]` 447 if azErr.ServiceError.AdditionalInfo == nil { 448 t.Logf("`ServiceError.AdditionalInfo` was nil when it should have been %q", expectedServiceErrorAdditionalInfo) 449 t.Fail() 450 } else if additionalInfo, _ := json.Marshal(azErr.ServiceError.AdditionalInfo); expectedServiceErrorAdditionalInfo != string(additionalInfo) { 451 t.Logf("Additional info was not unmarshaled properly.\n\tgot: %q\n\twant: %q", string(additionalInfo), expectedServiceErrorAdditionalInfo) 452 t.Fail() 453 } 454 455 // the error body should still be there 456 defer r.Body.Close() 457 b, err := ioutil.ReadAll(r.Body) 458 if err != nil { 459 t.Error(err) 460 } 461 if string(b) != j { 462 t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j) 463 } 464 465} 466 467func TestRequestErrorString_WithError(t *testing.T) { 468 j := `{ 469 "error": { 470 "code": "InternalError", 471 "message": "Conflict", 472 "target": "target1", 473 "details": [{"code": "conflict1", "message":"error message1"}], 474 "innererror": { "customKey": "customValue" }, 475 "additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}] 476 } 477 }` 478 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 479 r := mocks.NewResponseWithContent(j) 480 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 481 r.Request = mocks.NewRequest() 482 r.StatusCode = http.StatusInternalServerError 483 r.Status = http.StatusText(r.StatusCode) 484 485 err := autorest.Respond(r, 486 WithErrorUnlessStatusCode(http.StatusOK), 487 autorest.ByClosing()) 488 489 if err == nil { 490 t.Fatalf("azure: returned nil error for proper error response") 491 } 492 azErr, _ := err.(*RequestError) 493 expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Target=\"target1\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"customKey\":\"customValue\"} AdditionalInfo=[{\"info\":{\"someProperty\":\"someValue\"},\"type\":\"someErrorType\"}]" 494 if expected != azErr.Error() { 495 t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error()) 496 } 497} 498 499func TestRequestErrorString_WithErrorNonConforming(t *testing.T) { 500 j := `{ 501 "error": { 502 "code": "InternalError", 503 "message": "Conflict", 504 "details": {"code": "conflict1", "message":"error message1"} 505 } 506 }` 507 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 508 r := mocks.NewResponseWithContent(j) 509 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 510 r.Request = mocks.NewRequest() 511 r.StatusCode = http.StatusInternalServerError 512 r.Status = http.StatusText(r.StatusCode) 513 514 err := autorest.Respond(r, 515 WithErrorUnlessStatusCode(http.StatusOK), 516 autorest.ByClosing()) 517 518 if err == nil { 519 t.Fatalf("azure: returned nil error for proper error response") 520 } 521 azErr, _ := err.(*RequestError) 522 expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}]" 523 if expected != azErr.Error() { 524 t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error()) 525 } 526} 527 528func TestParseResourceID_WithValidBasicResourceID(t *testing.T) { 529 530 basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/testResourceName" 531 want := Resource{ 532 SubscriptionID: "subid-3-3-4", 533 ResourceGroup: "regGroupVladdb", 534 Provider: "Microsoft.Network", 535 ResourceType: "LoadBalancer", 536 ResourceName: "testResourceName", 537 } 538 got, err := ParseResourceID(basicResourceID) 539 540 if err != nil { 541 t.Fatalf("azure: error returned while parsing valid resourceId") 542 } 543 544 if got != want { 545 t.Logf("got: %+v\nwant: %+v", got, want) 546 t.Fail() 547 } 548 549 reGenResourceID := got.String() 550 if !strings.EqualFold(basicResourceID, reGenResourceID) { 551 t.Logf("got: %+v\nwant: %+v", reGenResourceID, basicResourceID) 552 t.Fail() 553 } 554} 555 556func TestParseResourceID_WithValidSubResourceID(t *testing.T) { 557 subresourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/resource/is/a/subresource/actualresourceName" 558 want := Resource{ 559 SubscriptionID: "subid-3-3-4", 560 ResourceGroup: "regGroupVladdb", 561 Provider: "Microsoft.Network", 562 ResourceType: "LoadBalancer", 563 ResourceName: "actualresourceName", 564 } 565 got, err := ParseResourceID(subresourceID) 566 567 if err != nil { 568 t.Fatalf("azure: error returned while parsing valid resourceId") 569 } 570 571 if got != want { 572 t.Logf("got: %+v\nwant: %+v", got, want) 573 t.Fail() 574 } 575} 576 577func TestParseResourceID_WithIncompleteResourceID(t *testing.T) { 578 basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/" 579 want := Resource{} 580 581 got, err := ParseResourceID(basicResourceID) 582 583 if err == nil { 584 t.Fatalf("azure: no error returned on incomplete resource id") 585 } 586 587 if got != want { 588 t.Logf("got: %+v\nwant: %+v", got, want) 589 t.Fail() 590 } 591} 592 593func TestParseResourceID_WithMalformedResourceID(t *testing.T) { 594 malformedResourceID := "/providers/subid-3-3-4/resourceGroups/regGroupVladdb/subscriptions/Microsoft.Network/LoadBalancer/testResourceName" 595 want := Resource{} 596 597 got, err := ParseResourceID(malformedResourceID) 598 599 if err == nil { 600 t.Fatalf("azure: error returned while parsing malformed resourceID") 601 } 602 603 if got != want { 604 t.Logf("got: %+v\nwant: %+v", got, want) 605 t.Fail() 606 } 607} 608 609func TestRequestErrorString_WithXMLError(t *testing.T) { 610 j := `<?xml version="1.0" encoding="utf-8"?> 611 <Error> 612 <Code>InternalError</Code> 613 <Message>Internal service error.</Message> 614 </Error> ` 615 uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6" 616 r := mocks.NewResponseWithContent(j) 617 mocks.SetResponseHeader(r, HeaderRequestID, uuid) 618 r.Request = mocks.NewRequest() 619 r.StatusCode = http.StatusInternalServerError 620 r.Status = http.StatusText(r.StatusCode) 621 r.Header.Add("Content-Type", "text/xml") 622 623 err := autorest.Respond(r, 624 WithErrorUnlessStatusCode(http.StatusOK), 625 autorest.ByClosing()) 626 627 if err == nil { 628 t.Fatalf("azure: returned nil error for proper error response") 629 } 630 azErr, _ := err.(*RequestError) 631 const expected = `autorest/azure: Service returned an error. Status=500 Code="InternalError" Message="Internal service error."` 632 if got := azErr.Error(); expected != got { 633 fmt.Println(got) 634 t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, got) 635 } 636} 637 638func withErrorPrepareDecorator(e *error) autorest.PrepareDecorator { 639 return func(p autorest.Preparer) autorest.Preparer { 640 return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { 641 *e = fmt.Errorf("azure: Faux Prepare Error") 642 return r, *e 643 }) 644 } 645} 646 647func withAsyncResponseDecorator(n int) autorest.SendDecorator { 648 i := 0 649 return func(s autorest.Sender) autorest.Sender { 650 return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) { 651 resp, err := s.Do(r) 652 if err == nil { 653 if i < n { 654 resp.StatusCode = http.StatusCreated 655 resp.Header = http.Header{} 656 resp.Header.Add(http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestURL) 657 i++ 658 } else { 659 resp.StatusCode = http.StatusOK 660 resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation)) 661 } 662 } 663 return resp, err 664 }) 665 } 666} 667 668type mockAuthorizer struct{} 669 670func (ma mockAuthorizer) WithAuthorization() autorest.PrepareDecorator { 671 return autorest.WithHeader(headerAuthorization, mocks.TestAuthorizationHeader) 672} 673 674type mockFailingAuthorizer struct{} 675 676func (mfa mockFailingAuthorizer) WithAuthorization() autorest.PrepareDecorator { 677 return func(p autorest.Preparer) autorest.Preparer { 678 return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { 679 return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error") 680 }) 681 } 682} 683 684type mockInspector struct { 685 wasInvoked bool 686} 687 688func (mi *mockInspector) WithInspection() autorest.PrepareDecorator { 689 return func(p autorest.Preparer) autorest.Preparer { 690 return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) { 691 mi.wasInvoked = true 692 return p.Prepare(r) 693 }) 694 } 695} 696 697func (mi *mockInspector) ByInspecting() autorest.RespondDecorator { 698 return func(r autorest.Responder) autorest.Responder { 699 return autorest.ResponderFunc(func(resp *http.Response) error { 700 mi.wasInvoked = true 701 return r.Respond(resp) 702 }) 703 } 704} 705