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 "bytes" 10 "context" 11 "errors" 12 "net/http" 13 "strings" 14 "testing" 15 16 "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" 17) 18 19func TestPolicyLoggingSuccess(t *testing.T) { 20 log := map[LogClassification]string{} 21 Log().SetListener(func(cls LogClassification, s string) { 22 log[cls] = s 23 }) 24 srv, close := mock.NewServer() 25 defer close() 26 srv.SetResponse() 27 pl := NewPipeline(srv, NewLogPolicy(nil)) 28 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 29 if err != nil { 30 t.Fatalf("unexpected error: %v", err) 31 } 32 qp := req.URL.Query() 33 qp.Set("one", "fish") 34 qp.Set("sig", "redact") 35 req.URL.RawQuery = qp.Encode() 36 resp, err := pl.Do(req) 37 if err != nil { 38 t.Fatalf("unexpected error: %v", err) 39 } 40 if resp.StatusCode != http.StatusOK { 41 t.Fatalf("unexpected status code: %d", resp.StatusCode) 42 } 43 if logReq, ok := log[LogRequest]; ok { 44 // Request ==> OUTGOING REQUEST (Try=1) 45 // GET http://127.0.0.1:49475?one=fish&sig=REDACTED 46 // (no headers) 47 if !strings.Contains(logReq, "(no headers)") { 48 t.Fatal("missing (no headers)") 49 } 50 } else { 51 t.Fatal("missing LogRequest") 52 } 53 if logResp, ok := log[LogResponse]; ok { 54 // Response ==> REQUEST/RESPONSE (Try=1/1.0034ms, OpTime=1.0034ms) -- RESPONSE SUCCESSFULLY RECEIVED 55 // GET http://127.0.0.1:49475?one=fish&sig=REDACTED 56 // (no headers) 57 // -------------------------------------------------------------------------------- 58 // RESPONSE Status: 200 OK 59 // Content-Length: [0] 60 // Date: [Fri, 22 Nov 2019 23:48:02 GMT] 61 if !strings.Contains(logResp, "RESPONSE Status: 200 OK") { 62 t.Fatal("missing response status") 63 } 64 } else { 65 t.Fatal("missing LogResponse") 66 } 67} 68 69func TestPolicyLoggingError(t *testing.T) { 70 log := map[LogClassification]string{} 71 Log().SetListener(func(cls LogClassification, s string) { 72 log[cls] = s 73 }) 74 srv, close := mock.NewServer() 75 defer close() 76 srv.SetError(errors.New("bogus error")) 77 pl := NewPipeline(srv, NewLogPolicy(nil)) 78 req, err := NewRequest(context.Background(), http.MethodGet, srv.URL()) 79 if err != nil { 80 t.Fatalf("unexpected error: %v", err) 81 } 82 req.Header.Add("header", "one") 83 req.Header.Add("Authorization", "redact") 84 resp, err := pl.Do(req) 85 if err == nil { 86 t.Fatal("unexpected nil error") 87 } 88 if resp != nil { 89 t.Fatal("unexpected respose") 90 } 91 if logReq, ok := log[LogRequest]; ok { 92 // Request ==> OUTGOING REQUEST (Try=1) 93 // GET http://127.0.0.1:50057 94 // Authorization: REDACTED 95 // Header: [one] 96 if !strings.Contains(logReq, "Authorization: REDACTED") { 97 t.Fatal("missing redacted authorization header") 98 } 99 } else { 100 t.Fatal("missing LogRequest") 101 } 102 if logResponse, ok := log[LogResponse]; ok { 103 // Response ==> REQUEST/RESPONSE (Try=1/0s, OpTime=0s) -- REQUEST ERROR 104 // GET http://127.0.0.1:50057 105 // Authorization: REDACTED 106 // Header: [one] 107 // -------------------------------------------------------------------------------- 108 // ERROR: 109 // bogus error 110 // ...stack track... 111 if !strings.Contains(logResponse, "Authorization: REDACTED") { 112 t.Fatal("missing redacted authorization header") 113 } 114 if !strings.Contains(logResponse, "bogus error") { 115 t.Fatal("missing error message") 116 } 117 } else { 118 t.Fatal("missing LogResponse") 119 } 120} 121 122func TestShouldLogBody(t *testing.T) { 123 b := bytes.NewBuffer(make([]byte, 64)) 124 if shouldLogBody(b, "application/octet-stream") { 125 t.Fatal("shouldn't log for application/octet-stream") 126 } else if b.Len() == 0 { 127 t.Fatal("skip logging should write skip message to buffer") 128 } 129 b.Reset() 130 if !shouldLogBody(b, "application/json") { 131 t.Fatal("should log for application/json") 132 } else if b.Len() != 0 { 133 t.Fatal("logging shouldn't write message") 134 } 135 if !shouldLogBody(b, "application/xml") { 136 t.Fatal("should log for application/xml") 137 } else if b.Len() != 0 { 138 t.Fatal("logging shouldn't write message") 139 } 140 if !shouldLogBody(b, "text/plain") { 141 t.Fatal("should log for text/plain") 142 } else if b.Len() != 0 { 143 t.Fatal("logging shouldn't write message") 144 } 145} 146