1// +build go1.13 2 3// Copyright (c) Microsoft Corporation. All rights reserved. 4// Licensed under the MIT License. 5 6package azcore 7 8import ( 9 "context" 10 "net/http" 11 "testing" 12 "time" 13 14 "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" 15) 16 17func TestResponseUnmarshalXML(t *testing.T) { 18 srv, close := mock.NewServer() 19 defer close() 20 // include UTF8 BOM 21 srv.SetResponse(mock.WithBody([]byte("\xef\xbb\xbf<testXML><SomeInt>1</SomeInt><SomeString>s</SomeString></testXML>"))) 22 pl := NewPipeline(srv) 23 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 24 if err != nil { 25 t.Fatalf("unexpected error: %v", err) 26 } 27 resp, err := pl.Do(req) 28 if err != nil { 29 t.Fatalf("unexpected error: %v", err) 30 } 31 if !resp.HasStatusCode(http.StatusOK) { 32 t.Fatalf("unexpected status code: %d", resp.StatusCode) 33 } 34 var tx testXML 35 if err := resp.UnmarshalAsXML(&tx); err != nil { 36 t.Fatalf("unexpected error unmarshalling: %v", err) 37 } 38 if tx.SomeInt != 1 || tx.SomeString != "s" { 39 t.Fatal("unexpected value") 40 } 41} 42 43func TestResponseFailureStatusCode(t *testing.T) { 44 srv, close := mock.NewServer() 45 defer close() 46 srv.SetResponse(mock.WithStatusCode(http.StatusForbidden)) 47 pl := NewPipeline(srv) 48 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 49 if err != nil { 50 t.Fatalf("unexpected error: %v", err) 51 } 52 resp, err := pl.Do(req) 53 if err != nil { 54 t.Fatalf("unexpected error: %v", err) 55 } 56 if resp.HasStatusCode(http.StatusOK) { 57 t.Fatalf("unexpected status code: %d", resp.StatusCode) 58 } 59} 60 61func TestResponseUnmarshalJSON(t *testing.T) { 62 srv, close := mock.NewServer() 63 defer close() 64 srv.SetResponse(mock.WithBody([]byte(`{ "someInt": 1, "someString": "s" }`))) 65 pl := NewPipeline(srv) 66 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 67 if err != nil { 68 t.Fatalf("unexpected error: %v", err) 69 } 70 resp, err := pl.Do(req) 71 if err != nil { 72 t.Fatalf("unexpected error: %v", err) 73 } 74 if !resp.HasStatusCode(http.StatusOK) { 75 t.Fatalf("unexpected status code: %d", resp.StatusCode) 76 } 77 var tx testJSON 78 if err := resp.UnmarshalAsJSON(&tx); err != nil { 79 t.Fatalf("unexpected error unmarshalling: %v", err) 80 } 81 if tx.SomeInt != 1 || tx.SomeString != "s" { 82 t.Fatal("unexpected value") 83 } 84} 85 86func TestResponseUnmarshalJSONskipDownload(t *testing.T) { 87 srv, close := mock.NewServer() 88 defer close() 89 srv.SetResponse(mock.WithBody([]byte(`{ "someInt": 1, "someString": "s" }`))) 90 pl := NewPipeline(srv) 91 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 92 if err != nil { 93 t.Fatalf("unexpected error: %v", err) 94 } 95 req.SkipBodyDownload() 96 resp, err := pl.Do(req) 97 if err != nil { 98 t.Fatalf("unexpected error: %v", err) 99 } 100 if !resp.HasStatusCode(http.StatusOK) { 101 t.Fatalf("unexpected status code: %d", resp.StatusCode) 102 } 103 var tx testJSON 104 if err := resp.UnmarshalAsJSON(&tx); err != nil { 105 t.Fatalf("unexpected error unmarshalling: %v", err) 106 } 107 if tx.SomeInt != 1 || tx.SomeString != "s" { 108 t.Fatal("unexpected value") 109 } 110} 111 112func TestResponseUnmarshalJSONNoBody(t *testing.T) { 113 srv, close := mock.NewServer() 114 defer close() 115 srv.SetResponse(mock.WithBody([]byte{})) 116 pl := NewPipeline(srv) 117 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 118 if err != nil { 119 t.Fatalf("unexpected error: %v", err) 120 } 121 resp, err := pl.Do(req) 122 if err != nil { 123 t.Fatalf("unexpected error: %v", err) 124 } 125 if !resp.HasStatusCode(http.StatusOK) { 126 t.Fatalf("unexpected status code: %d", resp.StatusCode) 127 } 128 if err := resp.UnmarshalAsJSON(nil); err != nil { 129 t.Fatalf("unexpected error unmarshalling: %v", err) 130 } 131} 132 133func TestResponseUnmarshalXMLNoBody(t *testing.T) { 134 srv, close := mock.NewServer() 135 defer close() 136 srv.SetResponse(mock.WithBody([]byte{})) 137 pl := NewPipeline(srv) 138 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 139 if err != nil { 140 t.Fatalf("unexpected error: %v", err) 141 } 142 resp, err := pl.Do(req) 143 if err != nil { 144 t.Fatalf("unexpected error: %v", err) 145 } 146 if !resp.HasStatusCode(http.StatusOK) { 147 t.Fatalf("unexpected status code: %d", resp.StatusCode) 148 } 149 if err := resp.UnmarshalAsXML(nil); err != nil { 150 t.Fatalf("unexpected error unmarshalling: %v", err) 151 } 152} 153 154func TestRetryAfter(t *testing.T) { 155 raw := &http.Response{ 156 Header: http.Header{}, 157 } 158 resp := Response{raw} 159 if d := resp.retryAfter(); d > 0 { 160 t.Fatalf("unexpected retry-after value %d", d) 161 } 162 raw.Header.Set(HeaderRetryAfter, "300") 163 d := resp.retryAfter() 164 if d <= 0 { 165 t.Fatal("expected retry-after value from seconds") 166 } 167 if d != 300*time.Second { 168 t.Fatalf("expected 300 seconds, got %d", d/time.Second) 169 } 170 atDate := time.Now().Add(600 * time.Second) 171 raw.Header.Set(HeaderRetryAfter, atDate.Format(time.RFC1123)) 172 d = resp.retryAfter() 173 if d <= 0 { 174 t.Fatal("expected retry-after value from date") 175 } 176 // d will not be exactly 600 seconds but it will be close 177 if s := d / time.Second; s < 598 || s > 602 { 178 t.Fatalf("expected ~600 seconds, got %d", s) 179 } 180} 181 182func TestResponseUnmarshalAsByteArrayURLFormat(t *testing.T) { 183 srv, close := mock.NewServer() 184 defer close() 185 srv.SetResponse(mock.WithBody([]byte(`"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw"`))) 186 pl := NewPipeline(srv) 187 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 188 if err != nil { 189 t.Fatalf("unexpected error: %v", err) 190 } 191 resp, err := pl.Do(req) 192 if err != nil { 193 t.Fatalf("unexpected error: %v", err) 194 } 195 if !resp.HasStatusCode(http.StatusOK) { 196 t.Fatalf("unexpected status code: %d", resp.StatusCode) 197 } 198 var ba *[]byte 199 if err := resp.UnmarshalAsByteArray(&ba, Base64URLFormat); err != nil { 200 t.Fatalf("unexpected error unmarshalling: %v", err) 201 } 202 if string(*ba) != "a string that gets encoded with base64url" { 203 t.Fatalf("bad payload, got %s", string(*ba)) 204 } 205} 206 207func TestResponseUnmarshalAsByteArrayStdFormat(t *testing.T) { 208 srv, close := mock.NewServer() 209 defer close() 210 srv.SetResponse(mock.WithBody([]byte(`"YSBzdHJpbmcgdGhhdCBnZXRzIGVuY29kZWQgd2l0aCBiYXNlNjR1cmw="`))) 211 pl := NewPipeline(srv) 212 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 213 if err != nil { 214 t.Fatalf("unexpected error: %v", err) 215 } 216 resp, err := pl.Do(req) 217 if err != nil { 218 t.Fatalf("unexpected error: %v", err) 219 } 220 if !resp.HasStatusCode(http.StatusOK) { 221 t.Fatalf("unexpected status code: %d", resp.StatusCode) 222 } 223 var ba *[]byte 224 if err := resp.UnmarshalAsByteArray(&ba, Base64StdFormat); err != nil { 225 t.Fatalf("unexpected error unmarshalling: %v", err) 226 } 227 if string(*ba) != "a string that gets encoded with base64url" { 228 t.Fatalf("bad payload, got %s", string(*ba)) 229 } 230} 231