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