...

Source file src/github.com/Azure/go-autorest/autorest/azure/azure_test.go

Documentation: github.com/Azure/go-autorest/autorest/azure

     1  package 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  
    17  import (
    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  
    32  const (
    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.
    40  func 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  
    59  func 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  
    72  func 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  
    83  func 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  
    94  func 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  
   105  func 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  
   116  func 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  
   122  func 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  
   128  func 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  
   135  func 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  
   147  func 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  
   156  func 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  
   187  func 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  
   239  func 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  
   318  func TestWithErrorUnlessStatusCode_LiteralNullValueInResponse(t *testing.T) {
   319  	// As found in the Log Analytics Cluster API
   320  	// API Bug: https://github.com/Azure/azure-rest-api-specs/issues/12331
   321  	j := `null`
   322  	r := mocks.NewResponseWithContent(j)
   323  	mocks.SetResponseHeader(r, HeaderContentType, "application/json; charset=utf-8")
   324  	r.Request = mocks.NewRequest()
   325  	r.StatusCode = http.StatusInternalServerError
   326  	r.Status = http.StatusText(r.StatusCode)
   327  
   328  	err := autorest.Respond(r,
   329  		WithErrorUnlessStatusCode(http.StatusOK),
   330  		autorest.ByClosing())
   331  	if err == nil {
   332  		t.Fatalf("azure: returned nil error for proper error response")
   333  	}
   334  	azErr, ok := err.(*RequestError)
   335  	if !ok {
   336  		t.Fatalf("azure: returned error is not azure.RequestError: %T", err)
   337  	}
   338  
   339  	expected := &ServiceError{
   340  		Code:    "Unknown",
   341  		Message: "Unknown service error",
   342  		Details: []map[string]interface{}{
   343  			{"HttpResponse.Body": "null"},
   344  		},
   345  	}
   346  
   347  	if !reflect.DeepEqual(expected, azErr.ServiceError) {
   348  		t.Fatalf("azure: service error is not unmarshaled properly. expected=%q\ngot=%q", expected, azErr.ServiceError)
   349  	}
   350  }
   351  
   352  func TestWithErrorUnlessStatusCode_NoAzureError(t *testing.T) {
   353  	j := `{
   354  		"Status":"NotFound"
   355  	}`
   356  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   357  	r := mocks.NewResponseWithContent(j)
   358  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   359  	r.Request = mocks.NewRequest()
   360  	r.StatusCode = http.StatusInternalServerError
   361  	r.Status = http.StatusText(r.StatusCode)
   362  
   363  	err := autorest.Respond(r,
   364  		WithErrorUnlessStatusCode(http.StatusOK),
   365  		autorest.ByClosing())
   366  	if err == nil {
   367  		t.Fatalf("azure: returned nil error for proper error response")
   368  	}
   369  	azErr, ok := err.(*RequestError)
   370  	if !ok {
   371  		t.Fatalf("azure: returned error is not azure.RequestError: %T", err)
   372  	}
   373  
   374  	expected := &ServiceError{
   375  		Code:    "Unknown",
   376  		Message: "Unknown service error",
   377  		Details: []map[string]interface{}{
   378  			{"Status": "NotFound"},
   379  		},
   380  	}
   381  
   382  	if !reflect.DeepEqual(expected, azErr.ServiceError) {
   383  		t.Fatalf("azure: service error is not unmarshaled properly. expected=%q\ngot=%q", expected, azErr.ServiceError)
   384  	}
   385  
   386  	if expected := http.StatusInternalServerError; azErr.StatusCode != expected {
   387  		t.Fatalf("azure: got wrong StatusCode=%v Expected=%d", azErr.StatusCode, expected)
   388  	}
   389  	if expected := uuid; azErr.RequestID != expected {
   390  		t.Fatalf("azure: wrong request ID in error. expected=%q; got=%q", expected, azErr.RequestID)
   391  	}
   392  
   393  	_ = azErr.Error()
   394  
   395  	// the error body should still be there
   396  	defer r.Body.Close()
   397  	b, err := ioutil.ReadAll(r.Body)
   398  	if err != nil {
   399  		t.Fatal(err)
   400  	}
   401  	if string(b) != j {
   402  		t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j)
   403  	}
   404  
   405  }
   406  
   407  func TestWithErrorUnlessStatusCode_UnwrappedError(t *testing.T) {
   408  	j := `{
   409  		"code": "InternalError",
   410  		"message": "Azure is having trouble right now.",
   411  		"target": "target1",
   412  		"details": [{"code": "conflict1", "message":"error message1"},
   413  					{"code": "conflict2", "message":"error message2"}],
   414  		"innererror": { "customKey": "customValue" },
   415  		"additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}]
   416      }`
   417  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   418  	r := mocks.NewResponseWithContent(j)
   419  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   420  	r.Request = mocks.NewRequest()
   421  	r.StatusCode = http.StatusInternalServerError
   422  	r.Status = http.StatusText(r.StatusCode)
   423  
   424  	err := autorest.Respond(r,
   425  		WithErrorUnlessStatusCode(http.StatusOK),
   426  		autorest.ByClosing())
   427  
   428  	if err == nil {
   429  		t.Fatal("azure: returned nil error for proper error response")
   430  	}
   431  
   432  	azErr, ok := err.(*RequestError)
   433  	if !ok {
   434  		t.Fatalf("returned error is not azure.RequestError: %T", err)
   435  	}
   436  
   437  	if expected := http.StatusInternalServerError; azErr.StatusCode != expected {
   438  		t.Logf("Incorrect StatusCode got: %v want: %d", azErr.StatusCode, expected)
   439  		t.Fail()
   440  	}
   441  
   442  	if expected := "Azure is having trouble right now."; azErr.Message != expected {
   443  		t.Logf("Incorrect Message\n\tgot:  %q\n\twant: %q", azErr.Message, expected)
   444  		t.Fail()
   445  	}
   446  
   447  	if expected := uuid; azErr.RequestID != expected {
   448  		t.Logf("Incorrect request ID\n\tgot:  %q\n\twant: %q", azErr.RequestID, expected)
   449  		t.Fail()
   450  	}
   451  
   452  	if azErr.ServiceError == nil {
   453  		t.Logf("`ServiceError` was nil when it shouldn't have been.")
   454  		t.Fail()
   455  	}
   456  
   457  	if expected := "target1"; *azErr.ServiceError.Target != expected {
   458  		t.Logf("Incorrect Target\n\tgot:  %q\n\twant: %q", *azErr.ServiceError.Target, expected)
   459  		t.Fail()
   460  	}
   461  
   462  	expectedServiceErrorDetails := `[{"code":"conflict1","message":"error message1"},{"code":"conflict2","message":"error message2"}]`
   463  	if azErr.ServiceError.Details == nil {
   464  		t.Logf("`ServiceError.Details` was nil when it should have been %q", expectedServiceErrorDetails)
   465  		t.Fail()
   466  	} else if details, _ := json.Marshal(azErr.ServiceError.Details); expectedServiceErrorDetails != string(details) {
   467  		t.Logf("Error details was not unmarshaled properly.\n\tgot:  %q\n\twant: %q", string(details), expectedServiceErrorDetails)
   468  		t.Fail()
   469  	}
   470  
   471  	expectedServiceErrorInnerError := `{"customKey":"customValue"}`
   472  	if azErr.ServiceError.InnerError == nil {
   473  		t.Logf("`ServiceError.InnerError` was nil when it should have been %q", expectedServiceErrorInnerError)
   474  		t.Fail()
   475  	} else if innerError, _ := json.Marshal(azErr.ServiceError.InnerError); expectedServiceErrorInnerError != string(innerError) {
   476  		t.Logf("Inner error was not unmarshaled properly.\n\tgot:  %q\n\twant: %q", string(innerError), expectedServiceErrorInnerError)
   477  		t.Fail()
   478  	}
   479  
   480  	expectedServiceErrorAdditionalInfo := `[{"info":{"someProperty":"someValue"},"type":"someErrorType"}]`
   481  	if azErr.ServiceError.AdditionalInfo == nil {
   482  		t.Logf("`ServiceError.AdditionalInfo` was nil when it should have been %q", expectedServiceErrorAdditionalInfo)
   483  		t.Fail()
   484  	} else if additionalInfo, _ := json.Marshal(azErr.ServiceError.AdditionalInfo); expectedServiceErrorAdditionalInfo != string(additionalInfo) {
   485  		t.Logf("Additional info was not unmarshaled properly.\n\tgot:  %q\n\twant: %q", string(additionalInfo), expectedServiceErrorAdditionalInfo)
   486  		t.Fail()
   487  	}
   488  
   489  	// the error body should still be there
   490  	defer r.Body.Close()
   491  	b, err := ioutil.ReadAll(r.Body)
   492  	if err != nil {
   493  		t.Error(err)
   494  	}
   495  	if string(b) != j {
   496  		t.Fatalf("response body is wrong. got=%q expected=%q", string(b), j)
   497  	}
   498  
   499  }
   500  
   501  func TestRequestErrorString_WithError(t *testing.T) {
   502  	j := `{
   503  		"error": {
   504  			"code": "InternalError",
   505  			"message": "Conflict",
   506  			"target": "target1",
   507  			"details": [{"code": "conflict1", "message":"error message1"}],
   508  			"innererror": { "customKey": "customValue" },
   509  			"additionalInfo": [{"type": "someErrorType", "info": {"someProperty": "someValue"}}]
   510  		}
   511  	}`
   512  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   513  	r := mocks.NewResponseWithContent(j)
   514  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   515  	r.Request = mocks.NewRequest()
   516  	r.StatusCode = http.StatusInternalServerError
   517  	r.Status = http.StatusText(r.StatusCode)
   518  
   519  	err := autorest.Respond(r,
   520  		WithErrorUnlessStatusCode(http.StatusOK),
   521  		autorest.ByClosing())
   522  
   523  	if err == nil {
   524  		t.Fatalf("azure: returned nil error for proper error response")
   525  	}
   526  	azErr, _ := err.(*RequestError)
   527  	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\"}]"
   528  	if expected != azErr.Error() {
   529  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   530  	}
   531  }
   532  
   533  func TestRequestErrorString_WithErrorNonConforming(t *testing.T) {
   534  	// here details is an object, it should be an array of objects
   535  	// and innererror is an array of objects (should be one object)
   536  	j := `{
   537  		"error": {
   538  			"code": "InternalError",
   539  			"message": "Conflict",
   540  			"details": {"code": "conflict1", "message":"error message1"},
   541  			"innererror": [{ "customKey": "customValue" }]
   542  		}
   543  	}`
   544  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   545  	r := mocks.NewResponseWithContent(j)
   546  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   547  	r.Request = mocks.NewRequest()
   548  	r.StatusCode = http.StatusInternalServerError
   549  	r.Status = http.StatusText(r.StatusCode)
   550  
   551  	err := autorest.Respond(r,
   552  		WithErrorUnlessStatusCode(http.StatusOK),
   553  		autorest.ByClosing())
   554  
   555  	if err == nil {
   556  		t.Fatalf("azure: returned nil error for proper error response")
   557  	}
   558  	azErr, _ := err.(*RequestError)
   559  	expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"customKey\":\"customValue\"}"
   560  	if expected != azErr.Error() {
   561  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   562  	}
   563  }
   564  
   565  func TestRequestErrorString_WithErrorNonConforming2(t *testing.T) {
   566  	// here innererror is a string (it should be a JSON object)
   567  	j := `{
   568  		"error": {
   569  			"code": "InternalError",
   570  			"message": "Conflict",
   571  			"details": {"code": "conflict1", "message":"error message1"},
   572  			"innererror": "something bad happened"
   573  		}
   574  	}`
   575  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   576  	r := mocks.NewResponseWithContent(j)
   577  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   578  	r.Request = mocks.NewRequest()
   579  	r.StatusCode = http.StatusInternalServerError
   580  	r.Status = http.StatusText(r.StatusCode)
   581  
   582  	err := autorest.Respond(r,
   583  		WithErrorUnlessStatusCode(http.StatusOK),
   584  		autorest.ByClosing())
   585  
   586  	if err == nil {
   587  		t.Fatalf("azure: returned nil error for proper error response")
   588  	}
   589  	azErr, _ := err.(*RequestError)
   590  	expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"error\":\"something bad happened\"}"
   591  	if expected != azErr.Error() {
   592  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   593  	}
   594  }
   595  
   596  func TestRequestErrorString_WithErrorNonConforming3(t *testing.T) {
   597  	// here details is an object, it should be an array of objects
   598  	// and innererror is an array of objects (should be one object)
   599  	j := `{
   600  		"error": {
   601  			"code": "InternalError",
   602  			"message": "Conflict",
   603  			"details": {"code": "conflict1", "message":"error message1"},
   604  			"innererror": [{ "customKey": "customValue" }, { "customKey2": "customValue2" }]
   605  		}
   606  	}`
   607  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   608  	r := mocks.NewResponseWithContent(j)
   609  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   610  	r.Request = mocks.NewRequest()
   611  	r.StatusCode = http.StatusInternalServerError
   612  	r.Status = http.StatusText(r.StatusCode)
   613  
   614  	err := autorest.Respond(r,
   615  		WithErrorUnlessStatusCode(http.StatusOK),
   616  		autorest.ByClosing())
   617  
   618  	if err == nil {
   619  		t.Fatalf("azure: returned nil error for proper error response")
   620  	}
   621  	azErr, _ := err.(*RequestError)
   622  	expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"multi\":[{\"customKey\":\"customValue\"},{\"customKey2\":\"customValue2\"}]}"
   623  	if expected != azErr.Error() {
   624  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   625  	}
   626  }
   627  
   628  func TestRequestErrorString_WithErrorNonConforming4(t *testing.T) {
   629  	// here details is a string, it should be an array of objects
   630  	j := `{
   631  		"error": {
   632  			"code": "InternalError",
   633  			"message": "Conflict",
   634  			"details": "something bad happened"
   635  		}
   636  	}`
   637  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   638  	r := mocks.NewResponseWithContent(j)
   639  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   640  	r.Request = mocks.NewRequest()
   641  	r.StatusCode = http.StatusInternalServerError
   642  	r.Status = http.StatusText(r.StatusCode)
   643  
   644  	err := autorest.Respond(r,
   645  		WithErrorUnlessStatusCode(http.StatusOK),
   646  		autorest.ByClosing())
   647  
   648  	if err == nil {
   649  		t.Fatalf("azure: returned nil error for proper error response")
   650  	}
   651  	azErr, _ := err.(*RequestError)
   652  	expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"raw\":\"something bad happened\"}]"
   653  	if expected != azErr.Error() {
   654  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   655  	}
   656  }
   657  
   658  func TestRequestErrorString_WithErrorNonConforming5(t *testing.T) {
   659  	// here innererror is a number (it should be a JSON object)
   660  	j := `{
   661  		"error": {
   662  			"code": "InternalError",
   663  			"message": "Conflict",
   664  			"details": {"code": "conflict1", "message":"error message1"},
   665  			"innererror": 500
   666  		}
   667  	}`
   668  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   669  	r := mocks.NewResponseWithContent(j)
   670  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   671  	r.Request = mocks.NewRequest()
   672  	r.StatusCode = http.StatusInternalServerError
   673  	r.Status = http.StatusText(r.StatusCode)
   674  
   675  	err := autorest.Respond(r,
   676  		WithErrorUnlessStatusCode(http.StatusOK),
   677  		autorest.ByClosing())
   678  
   679  	if err == nil {
   680  		t.Fatalf("azure: returned nil error for proper error response")
   681  	}
   682  	azErr, _ := err.(*RequestError)
   683  	expected := "autorest/azure: Service returned an error. Status=500 Code=\"InternalError\" Message=\"Conflict\" Details=[{\"code\":\"conflict1\",\"message\":\"error message1\"}] InnerError={\"raw\":500}"
   684  	if expected != azErr.Error() {
   685  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, azErr.Error())
   686  	}
   687  }
   688  
   689  func TestRequestErrorString_WithErrorNonConforming6(t *testing.T) {
   690  	// here code is a number, it should be a string
   691  	j := `{
   692  			"code": 409,
   693  			"message": "Conflict",
   694  			"details": "something bad happened"
   695  		}`
   696  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   697  	r := mocks.NewResponseWithContent(j)
   698  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   699  	r.Request = mocks.NewRequest()
   700  	r.StatusCode = http.StatusInternalServerError
   701  	r.Status = http.StatusText(r.StatusCode)
   702  
   703  	err := autorest.Respond(r,
   704  		WithErrorUnlessStatusCode(http.StatusOK),
   705  		autorest.ByClosing())
   706  
   707  	if err == nil {
   708  		t.Fatalf("azure: returned nil error for proper error response")
   709  	}
   710  	if _, ok := err.(*RequestError); ok {
   711  		t.Fatal("unexpected RequestError when unmarshalling fails")
   712  	}
   713  }
   714  
   715  func TestParseResourceID_WithValidBasicResourceID(t *testing.T) {
   716  
   717  	basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/testResourceName"
   718  	want := Resource{
   719  		SubscriptionID: "subid-3-3-4",
   720  		ResourceGroup:  "regGroupVladdb",
   721  		Provider:       "Microsoft.Network",
   722  		ResourceType:   "LoadBalancer",
   723  		ResourceName:   "testResourceName",
   724  	}
   725  	got, err := ParseResourceID(basicResourceID)
   726  
   727  	if err != nil {
   728  		t.Fatalf("azure: error returned while parsing valid resourceId")
   729  	}
   730  
   731  	if got != want {
   732  		t.Logf("got:  %+v\nwant: %+v", got, want)
   733  		t.Fail()
   734  	}
   735  
   736  	reGenResourceID := got.String()
   737  	if !strings.EqualFold(basicResourceID, reGenResourceID) {
   738  		t.Logf("got:  %+v\nwant: %+v", reGenResourceID, basicResourceID)
   739  		t.Fail()
   740  	}
   741  }
   742  
   743  func TestParseResourceID_WithValidSubResourceID(t *testing.T) {
   744  	subresourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/LoadBalancer/resource/is/a/subresource/actualresourceName"
   745  	want := Resource{
   746  		SubscriptionID: "subid-3-3-4",
   747  		ResourceGroup:  "regGroupVladdb",
   748  		Provider:       "Microsoft.Network",
   749  		ResourceType:   "LoadBalancer",
   750  		ResourceName:   "actualresourceName",
   751  	}
   752  	got, err := ParseResourceID(subresourceID)
   753  
   754  	if err != nil {
   755  		t.Fatalf("azure: error returned while parsing valid resourceId")
   756  	}
   757  
   758  	if got != want {
   759  		t.Logf("got:  %+v\nwant: %+v", got, want)
   760  		t.Fail()
   761  	}
   762  }
   763  
   764  func TestParseResourceID_WithIncompleteResourceID(t *testing.T) {
   765  	basicResourceID := "/subscriptions/subid-3-3-4/resourceGroups/regGroupVladdb/providers/Microsoft.Network/"
   766  	want := Resource{}
   767  
   768  	got, err := ParseResourceID(basicResourceID)
   769  
   770  	if err == nil {
   771  		t.Fatalf("azure: no error returned on incomplete resource id")
   772  	}
   773  
   774  	if got != want {
   775  		t.Logf("got:  %+v\nwant: %+v", got, want)
   776  		t.Fail()
   777  	}
   778  }
   779  
   780  func TestParseResourceID_WithMalformedResourceID(t *testing.T) {
   781  	malformedResourceID := "/providers/subid-3-3-4/resourceGroups/regGroupVladdb/subscriptions/Microsoft.Network/LoadBalancer/testResourceName"
   782  	want := Resource{}
   783  
   784  	got, err := ParseResourceID(malformedResourceID)
   785  
   786  	if err == nil {
   787  		t.Fatalf("azure: error returned while parsing malformed resourceID")
   788  	}
   789  
   790  	if got != want {
   791  		t.Logf("got:  %+v\nwant: %+v", got, want)
   792  		t.Fail()
   793  	}
   794  }
   795  
   796  func TestRequestErrorString_WithXMLError(t *testing.T) {
   797  	j := `<?xml version="1.0" encoding="utf-8"?>  
   798  	<Error>  
   799  	  <Code>InternalError</Code>  
   800  	  <Message>Internal service error.</Message>  
   801  	</Error> `
   802  	uuid := "71FDB9F4-5E49-4C12-B266-DE7B4FD999A6"
   803  	r := mocks.NewResponseWithContent(j)
   804  	mocks.SetResponseHeader(r, HeaderRequestID, uuid)
   805  	r.Request = mocks.NewRequest()
   806  	r.StatusCode = http.StatusInternalServerError
   807  	r.Status = http.StatusText(r.StatusCode)
   808  	r.Header.Add("Content-Type", "text/xml")
   809  
   810  	err := autorest.Respond(r,
   811  		WithErrorUnlessStatusCode(http.StatusOK),
   812  		autorest.ByClosing())
   813  
   814  	if err == nil {
   815  		t.Fatalf("azure: returned nil error for proper error response")
   816  	}
   817  	azErr, _ := err.(*RequestError)
   818  	const expected = `autorest/azure: Service returned an error. Status=500 Code="InternalError" Message="Internal service error."`
   819  	if got := azErr.Error(); expected != got {
   820  		fmt.Println(got)
   821  		t.Fatalf("azure: send wrong RequestError.\nexpected=%v\ngot=%v", expected, got)
   822  	}
   823  }
   824  
   825  func withErrorPrepareDecorator(e *error) autorest.PrepareDecorator {
   826  	return func(p autorest.Preparer) autorest.Preparer {
   827  		return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
   828  			*e = fmt.Errorf("azure: Faux Prepare Error")
   829  			return r, *e
   830  		})
   831  	}
   832  }
   833  
   834  func withAsyncResponseDecorator(n int) autorest.SendDecorator {
   835  	i := 0
   836  	return func(s autorest.Sender) autorest.Sender {
   837  		return autorest.SenderFunc(func(r *http.Request) (*http.Response, error) {
   838  			resp, err := s.Do(r)
   839  			if err == nil {
   840  				if i < n {
   841  					resp.StatusCode = http.StatusCreated
   842  					resp.Header = http.Header{}
   843  					resp.Header.Add(http.CanonicalHeaderKey(headerAsyncOperation), mocks.TestURL)
   844  					i++
   845  				} else {
   846  					resp.StatusCode = http.StatusOK
   847  					resp.Header.Del(http.CanonicalHeaderKey(headerAsyncOperation))
   848  				}
   849  			}
   850  			return resp, err
   851  		})
   852  	}
   853  }
   854  
   855  type mockAuthorizer struct{}
   856  
   857  func (ma mockAuthorizer) WithAuthorization() autorest.PrepareDecorator {
   858  	return autorest.WithHeader(headerAuthorization, mocks.TestAuthorizationHeader)
   859  }
   860  
   861  type mockFailingAuthorizer struct{}
   862  
   863  func (mfa mockFailingAuthorizer) WithAuthorization() autorest.PrepareDecorator {
   864  	return func(p autorest.Preparer) autorest.Preparer {
   865  		return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
   866  			return r, fmt.Errorf("ERROR: mockFailingAuthorizer returned expected error")
   867  		})
   868  	}
   869  }
   870  
   871  type mockInspector struct {
   872  	wasInvoked bool
   873  }
   874  
   875  func (mi *mockInspector) WithInspection() autorest.PrepareDecorator {
   876  	return func(p autorest.Preparer) autorest.Preparer {
   877  		return autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
   878  			mi.wasInvoked = true
   879  			return p.Prepare(r)
   880  		})
   881  	}
   882  }
   883  
   884  func (mi *mockInspector) ByInspecting() autorest.RespondDecorator {
   885  	return func(r autorest.Responder) autorest.Responder {
   886  		return autorest.ResponderFunc(func(resp *http.Response) error {
   887  			mi.wasInvoked = true
   888  			return r.Respond(resp)
   889  		})
   890  	}
   891  }
   892  

View as plain text