1package autorest 2 3// Copyright 2017 Microsoft Corporation 4// 5// Licensed under the Apache License, Version 2.0 (the "License"); 6// you may not use this file except in compliance with the License. 7// You may obtain a copy of the License at 8// 9// http://www.apache.org/licenses/LICENSE-2.0 10// 11// Unless required by applicable law or agreed to in writing, software 12// distributed under the License is distributed on an "AS IS" BASIS, 13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14// See the License for the specific language governing permissions and 15// limitations under the License. 16 17import ( 18 "bytes" 19 "context" 20 "crypto/tls" 21 "fmt" 22 "io/ioutil" 23 "log" 24 "math/rand" 25 "net/http" 26 "net/http/httptest" 27 "reflect" 28 "testing" 29 "time" 30 31 "github.com/Azure/go-autorest/autorest/mocks" 32) 33 34func TestLoggingInspectorWithInspection(t *testing.T) { 35 b := bytes.Buffer{} 36 c := Client{} 37 li := LoggingInspector{Logger: log.New(&b, "", 0)} 38 c.RequestInspector = li.WithInspection() 39 40 Prepare(mocks.NewRequestWithContent("Content"), 41 c.WithInspection()) 42 43 if len(b.String()) <= 0 { 44 t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") 45 } 46} 47 48func TestLoggingInspectorWithInspectionEmitsErrors(t *testing.T) { 49 b := bytes.Buffer{} 50 c := Client{} 51 r := mocks.NewRequestWithContent("Content") 52 li := LoggingInspector{Logger: log.New(&b, "", 0)} 53 c.RequestInspector = li.WithInspection() 54 55 if _, err := Prepare(r, 56 c.WithInspection()); err != nil { 57 t.Error(err) 58 } 59 60 if len(b.String()) <= 0 { 61 t.Fatal("autorest: LoggingInspector#WithInspection did not record Request to the log") 62 } 63} 64 65func TestLoggingInspectorWithInspectionRestoresBody(t *testing.T) { 66 b := bytes.Buffer{} 67 c := Client{} 68 r := mocks.NewRequestWithContent("Content") 69 li := LoggingInspector{Logger: log.New(&b, "", 0)} 70 c.RequestInspector = li.WithInspection() 71 72 Prepare(r, 73 c.WithInspection()) 74 75 s, _ := ioutil.ReadAll(r.Body) 76 if len(s) <= 0 { 77 t.Fatal("autorest: LoggingInspector#WithInspection did not restore the Request body") 78 } 79} 80 81func TestLoggingInspectorByInspecting(t *testing.T) { 82 b := bytes.Buffer{} 83 c := Client{} 84 li := LoggingInspector{Logger: log.New(&b, "", 0)} 85 c.ResponseInspector = li.ByInspecting() 86 87 Respond(mocks.NewResponseWithContent("Content"), 88 c.ByInspecting()) 89 90 if len(b.String()) <= 0 { 91 t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") 92 } 93} 94 95func TestLoggingInspectorByInspectingEmitsErrors(t *testing.T) { 96 b := bytes.Buffer{} 97 c := Client{} 98 r := mocks.NewResponseWithContent("Content") 99 li := LoggingInspector{Logger: log.New(&b, "", 0)} 100 c.ResponseInspector = li.ByInspecting() 101 102 if err := Respond(r, 103 c.ByInspecting()); err != nil { 104 t.Fatal(err) 105 } 106 107 if len(b.String()) <= 0 { 108 t.Fatal("autorest: LoggingInspector#ByInspection did not record Response to the log") 109 } 110} 111 112func TestLoggingInspectorByInspectingRestoresBody(t *testing.T) { 113 b := bytes.Buffer{} 114 c := Client{} 115 r := mocks.NewResponseWithContent("Content") 116 li := LoggingInspector{Logger: log.New(&b, "", 0)} 117 c.ResponseInspector = li.ByInspecting() 118 119 Respond(r, 120 c.ByInspecting()) 121 122 s, _ := ioutil.ReadAll(r.Body) 123 if len(s) <= 0 { 124 t.Fatal("autorest: LoggingInspector#ByInspecting did not restore the Response body") 125 } 126} 127 128func TestNewClientWithUserAgent(t *testing.T) { 129 ua := "UserAgent" 130 c := NewClientWithUserAgent(ua) 131 completeUA := fmt.Sprintf("%s %s", UserAgent(), ua) 132 if c.UserAgent != completeUA { 133 t.Fatalf("autorest: NewClientWithUserAgent failed to set the UserAgent -- expected %s, received %s", 134 completeUA, c.UserAgent) 135 } 136 r := c.Sender.(*http.Client).Transport.(*http.Transport).TLSClientConfig.Renegotiation 137 if r != tls.RenegotiateNever { 138 t.Fatal("autorest: TestNewClientWithUserAgentTLSRenegotiation expected RenegotiateNever") 139 } 140} 141 142func TestNewClientWithOptions(t *testing.T) { 143 const ua = "UserAgent" 144 c1 := NewClientWithOptions(ClientOptions{ 145 UserAgent: ua, 146 Renegotiation: tls.RenegotiateFreelyAsClient, 147 }) 148 r1 := c1.Sender.(*http.Client).Transport.(*http.Transport).TLSClientConfig.Renegotiation 149 if r1 != tls.RenegotiateFreelyAsClient { 150 t.Fatal("autorest: TestNewClientWithUserAgentTLSRenegotiation expected RenegotiateFreelyAsClient") 151 } 152 // ensure default value doesn't stomp over previous value 153 c2 := NewClientWithUserAgent(ua) 154 r2 := c2.Sender.(*http.Client).Transport.(*http.Transport).TLSClientConfig.Renegotiation 155 if r2 != tls.RenegotiateNever { 156 t.Fatal("autorest: TestNewClientWithUserAgentTLSRenegotiation expected RenegotiateNever") 157 } 158 r1 = c1.Sender.(*http.Client).Transport.(*http.Transport).TLSClientConfig.Renegotiation 159 if r1 != tls.RenegotiateFreelyAsClient { 160 t.Fatal("autorest: TestNewClientWithUserAgentTLSRenegotiation expected RenegotiateFreelyAsClient (overwritten)") 161 } 162 r2 = c2.Sender.(*http.Client).Transport.(*http.Transport).TLSClientConfig.Renegotiation 163 if r2 != tls.RenegotiateNever { 164 t.Fatal("autorest: TestNewClientWithUserAgentTLSRenegotiation expected RenegotiateNever (overwritten)") 165 } 166} 167 168func TestAddToUserAgent(t *testing.T) { 169 ua := "UserAgent" 170 c := NewClientWithUserAgent(ua) 171 ext := "extension" 172 err := c.AddToUserAgent(ext) 173 if err != nil { 174 t.Fatalf("autorest: AddToUserAgent returned error -- expected nil, received %s", err) 175 } 176 completeUA := fmt.Sprintf("%s %s %s", UserAgent(), ua, ext) 177 178 if c.UserAgent != completeUA { 179 t.Fatalf("autorest: AddToUserAgent failed to add an extension to the UserAgent -- expected %s, received %s", 180 completeUA, c.UserAgent) 181 } 182 183 err = c.AddToUserAgent("") 184 if err == nil { 185 t.Fatalf("autorest: AddToUserAgent didn't return error -- expected %s, received nil", 186 fmt.Errorf("Extension was empty, User Agent stayed as %s", c.UserAgent)) 187 } 188 if c.UserAgent != completeUA { 189 t.Fatalf("autorest: AddToUserAgent failed to not add an empty extension to the UserAgent -- expected %s, received %s", 190 completeUA, c.UserAgent) 191 } 192} 193 194func TestClientSenderReturnsHttpClientByDefault(t *testing.T) { 195 c := Client{} 196 197 if fmt.Sprintf("%T", c.sender(tls.RenegotiateNever)) != "*http.Client" { 198 t.Fatal("autorest: Client#sender failed to return http.Client by default") 199 } 200} 201 202func TestClientSenderReturnsSetSender(t *testing.T) { 203 c := Client{} 204 205 s := mocks.NewSender() 206 c.Sender = s 207 208 if c.sender(tls.RenegotiateNever) != s { 209 t.Fatal("autorest: Client#sender failed to return set Sender") 210 } 211} 212 213func TestClientDoInvokesSender(t *testing.T) { 214 c := Client{} 215 216 s := mocks.NewSender() 217 c.Sender = s 218 219 c.Do(&http.Request{}) 220 if s.Attempts() != 1 { 221 t.Fatal("autorest: Client#Do failed to invoke the Sender") 222 } 223} 224 225func TestClientDoSetsUserAgent(t *testing.T) { 226 ua := "UserAgent" 227 c := Client{UserAgent: ua} 228 r := mocks.NewRequest() 229 s := mocks.NewSender() 230 c.Sender = s 231 232 c.Do(r) 233 234 if r.UserAgent() != ua { 235 t.Fatalf("autorest: Client#Do failed to correctly set User-Agent header: %s=%s", 236 http.CanonicalHeaderKey(headerUserAgent), r.UserAgent()) 237 } 238} 239 240func TestClientDoSetsAuthorization(t *testing.T) { 241 r := mocks.NewRequest() 242 s := mocks.NewSender() 243 c := Client{Authorizer: mockAuthorizer{}, Sender: s} 244 245 c.Do(r) 246 if len(r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) <= 0 { 247 t.Fatalf("autorest: Client#Send failed to set Authorization header -- %s=%s", 248 http.CanonicalHeaderKey(headerAuthorization), 249 r.Header.Get(http.CanonicalHeaderKey(headerAuthorization))) 250 } 251} 252 253func TestClientDoInvokesRequestInspector(t *testing.T) { 254 r := mocks.NewRequest() 255 s := mocks.NewSender() 256 i := &mockInspector{} 257 c := Client{RequestInspector: i.WithInspection(), Sender: s} 258 259 c.Do(r) 260 if !i.wasInvoked { 261 t.Fatal("autorest: Client#Send failed to invoke the RequestInspector") 262 } 263} 264 265func TestClientDoInvokesResponseInspector(t *testing.T) { 266 r := mocks.NewRequest() 267 s := mocks.NewSender() 268 i := &mockInspector{} 269 c := Client{ResponseInspector: i.ByInspecting(), Sender: s} 270 271 c.Do(r) 272 if !i.wasInvoked { 273 t.Fatal("autorest: Client#Send failed to invoke the ResponseInspector") 274 } 275} 276 277func TestClientDoReturnsErrorIfPrepareFails(t *testing.T) { 278 c := Client{} 279 s := mocks.NewSender() 280 c.Authorizer = mockFailingAuthorizer{} 281 c.Sender = s 282 283 _, err := c.Do(&http.Request{}) 284 if err == nil { 285 t.Fatalf("autorest: Client#Do failed to return an error when Prepare failed") 286 } 287} 288 289func TestClientDoDoesNotSendIfPrepareFails(t *testing.T) { 290 c := Client{} 291 s := mocks.NewSender() 292 c.Authorizer = mockFailingAuthorizer{} 293 c.Sender = s 294 295 c.Do(&http.Request{}) 296 if s.Attempts() > 0 { 297 t.Fatal("autorest: Client#Do failed to invoke the Sender") 298 } 299} 300 301func TestClientAuthorizerReturnsNullAuthorizerByDefault(t *testing.T) { 302 c := Client{} 303 304 if fmt.Sprintf("%T", c.authorizer()) != "autorest.NullAuthorizer" { 305 t.Fatal("autorest: Client#authorizer failed to return the NullAuthorizer by default") 306 } 307} 308 309func TestClientAuthorizerReturnsSetAuthorizer(t *testing.T) { 310 c := Client{} 311 c.Authorizer = mockAuthorizer{} 312 313 if fmt.Sprintf("%T", c.authorizer()) != "autorest.mockAuthorizer" { 314 t.Fatal("autorest: Client#authorizer failed to return the set Authorizer") 315 } 316} 317 318func TestClientWithAuthorizer(t *testing.T) { 319 c := Client{} 320 c.Authorizer = mockAuthorizer{} 321 322 req, _ := Prepare(&http.Request{}, 323 c.WithAuthorization()) 324 325 if req.Header.Get(headerAuthorization) == "" { 326 t.Fatal("autorest: Client#WithAuthorizer failed to return the WithAuthorizer from the active Authorizer") 327 } 328} 329 330func TestClientWithInspection(t *testing.T) { 331 c := Client{} 332 r := &mockInspector{} 333 c.RequestInspector = r.WithInspection() 334 335 Prepare(&http.Request{}, 336 c.WithInspection()) 337 338 if !r.wasInvoked { 339 t.Fatal("autorest: Client#WithInspection failed to invoke RequestInspector") 340 } 341} 342 343func TestClientWithInspectionSetsDefault(t *testing.T) { 344 c := Client{} 345 346 r1 := &http.Request{} 347 r2, _ := Prepare(r1, 348 c.WithInspection()) 349 350 if !reflect.DeepEqual(r1, r2) { 351 t.Fatal("autorest: Client#WithInspection failed to provide a default RequestInspector") 352 } 353} 354 355func TestClientByInspecting(t *testing.T) { 356 c := Client{} 357 r := &mockInspector{} 358 c.ResponseInspector = r.ByInspecting() 359 360 Respond(&http.Response{}, 361 c.ByInspecting()) 362 363 if !r.wasInvoked { 364 t.Fatal("autorest: Client#ByInspecting failed to invoke ResponseInspector") 365 } 366} 367 368func TestClientByInspectingSetsDefault(t *testing.T) { 369 c := Client{} 370 371 r := &http.Response{} 372 Respond(r, 373 c.ByInspecting()) 374 375 if !reflect.DeepEqual(r, &http.Response{}) { 376 t.Fatal("autorest: Client#ByInspecting failed to provide a default ResponseInspector") 377 } 378} 379 380func TestCookies(t *testing.T) { 381 second := "second" 382 expected := http.Cookie{ 383 Name: "tastes", 384 Value: "delicious", 385 } 386 387 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 388 http.SetCookie(w, &expected) 389 b, err := ioutil.ReadAll(r.Body) 390 if err != nil { 391 t.Fatalf("autorest: ioutil.ReadAll failed reading request body: %s", err) 392 } 393 if string(b) == second { 394 cookie, err := r.Cookie(expected.Name) 395 if err != nil { 396 t.Fatalf("autorest: r.Cookie could not get request cookie: %s", err) 397 } 398 if cookie == nil { 399 t.Fatalf("autorest: got nil cookie, expecting %v", expected) 400 } 401 if cookie.Value != expected.Value { 402 t.Fatalf("autorest: got cookie value '%s', expecting '%s'", cookie.Value, expected.Name) 403 } 404 } 405 })) 406 defer server.Close() 407 408 client := NewClientWithUserAgent("") 409 _, err := SendWithSender(client, mocks.NewRequestForURL(server.URL)) 410 if err != nil { 411 t.Fatalf("autorest: first request failed: %s", err) 412 } 413 414 r2, err := http.NewRequest(http.MethodGet, server.URL, mocks.NewBody(second)) 415 if err != nil { 416 t.Fatalf("autorest: failed creating second request: %s", err) 417 } 418 419 _, err = SendWithSender(client, r2) 420 if err != nil { 421 t.Fatalf("autorest: second request failed: %s", err) 422 } 423} 424 425func TestResponseIsHTTPStatus(t *testing.T) { 426 r := Response{} 427 if r.IsHTTPStatus(http.StatusBadRequest) { 428 t.Fatal("autorest: expected false for nil response") 429 } 430 r.Response = &http.Response{StatusCode: http.StatusOK} 431 if r.IsHTTPStatus(http.StatusBadRequest) { 432 t.Fatal("autorest: expected false") 433 } 434 if !r.IsHTTPStatus(http.StatusOK) { 435 t.Fatal("autorest: expected true") 436 } 437} 438 439func TestResponseHasHTTPStatus(t *testing.T) { 440 r := Response{} 441 if r.HasHTTPStatus(http.StatusBadRequest, http.StatusInternalServerError) { 442 t.Fatal("autorest: expected false for nil response") 443 } 444 r.Response = &http.Response{StatusCode: http.StatusAccepted} 445 if r.HasHTTPStatus(http.StatusBadRequest, http.StatusInternalServerError) { 446 t.Fatal("autorest: expected false") 447 } 448 if !r.HasHTTPStatus(http.StatusOK, http.StatusCreated, http.StatusAccepted) { 449 t.Fatal("autorest: expected true") 450 } 451 if r.HasHTTPStatus() { 452 t.Fatal("autorest: expected false for no status codes") 453 } 454} 455 456func randomString(n int) string { 457 const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 458 r := rand.New(rand.NewSource(time.Now().UTC().UnixNano())) 459 s := make([]byte, n) 460 for i := range s { 461 s[i] = chars[r.Intn(len(chars))] 462 } 463 return string(s) 464} 465 466func TestClientSendMethod(t *testing.T) { 467 sender := mocks.NewSender() 468 sender.AppendResponse(newAcceptedResponse()) 469 client := Client{ 470 Sender: sender, 471 } 472 req, err := http.NewRequest(http.MethodGet, mocks.TestURL, nil) 473 req = req.WithContext(context.Background()) 474 if err != nil { 475 t.Fatal(err) 476 } 477 // no SendDecorators 478 resp, err := client.Send(req) 479 if err != nil { 480 t.Fatal(err) 481 } 482 if resp.StatusCode != http.StatusAccepted { 483 t.Fatalf("expected status code %d, got %d", http.StatusAccepted, resp.StatusCode) 484 } 485 // default SendDecorators 486 sender.AppendResponse(newAcceptedResponse()) 487 resp, err = client.Send(req, DefaultSendDecorator()) 488 if err != nil { 489 t.Fatal(err) 490 } 491 if v := resp.Header.Get("default-decorator"); v != "true" { 492 t.Fatal("didn't find default-decorator header in response") 493 } 494 // using client SendDecorators 495 sender.AppendResponse(newAcceptedResponse()) 496 client.SendDecorators = []SendDecorator{ClientSendDecorator()} 497 resp, err = client.Send(req, DefaultSendDecorator()) 498 if err != nil { 499 t.Fatal(err) 500 } 501 if v := resp.Header.Get("client-decorator"); v != "true" { 502 t.Fatal("didn't find client-decorator header in response") 503 } 504 if v := resp.Header.Get("default-decorator"); v == "true" { 505 t.Fatal("unexpected default-decorator header in response") 506 } 507 // using context SendDecorators 508 sender.AppendResponse(newAcceptedResponse()) 509 req = req.WithContext(WithSendDecorators(req.Context(), []SendDecorator{ContextSendDecorator()})) 510 resp, err = client.Send(req, DefaultSendDecorator()) 511 if err != nil { 512 t.Fatal(err) 513 } 514 if v := resp.Header.Get("context-decorator"); v != "true" { 515 t.Fatal("didn't find context-decorator header in response") 516 } 517 if v := resp.Header.Get("client-decorator"); v == "true" { 518 t.Fatal("unexpected client-decorator header in response") 519 } 520 if v := resp.Header.Get("default-decorator"); v == "true" { 521 t.Fatal("unexpected default-decorator header in response") 522 } 523} 524 525func DefaultSendDecorator() SendDecorator { 526 return func(s Sender) Sender { 527 return SenderFunc(func(r *http.Request) (*http.Response, error) { 528 resp, err := s.Do(r) 529 resp.Header.Set("default-decorator", "true") 530 return resp, err 531 }) 532 } 533} 534 535func ClientSendDecorator() SendDecorator { 536 return func(s Sender) Sender { 537 return SenderFunc(func(r *http.Request) (*http.Response, error) { 538 resp, err := s.Do(r) 539 resp.Header.Set("client-decorator", "true") 540 return resp, err 541 }) 542 } 543} 544 545func ContextSendDecorator() SendDecorator { 546 return func(s Sender) Sender { 547 return SenderFunc(func(r *http.Request) (*http.Response, error) { 548 resp, err := s.Do(r) 549 resp.Header.Set("context-decorator", "true") 550 return resp, err 551 }) 552 } 553} 554