github.com/cornelk/go-cloud@v0.17.1/server/requestlog/requestlog_test.go (about) 1 // Copyright 2018 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package requestlog 16 17 import ( 18 "fmt" 19 "io" 20 "net/http" 21 "net/http/httptest" 22 "strings" 23 "testing" 24 25 "go.opencensus.io/trace" 26 ) 27 28 func TestHandler(t *testing.T) { 29 const requestMsg = "Hello, World!" 30 const responseMsg = "I see you." 31 const userAgent = "Request Log Test UA" 32 const referer = "http://www.example.com/" 33 r, err := http.NewRequest("POST", "http://localhost/foo", strings.NewReader(requestMsg)) 34 if err != nil { 35 t.Fatal("NewRequest:", err) 36 } 37 r.Header.Set("User-Agent", userAgent) 38 r.Header.Set("Referer", referer) 39 requestHdrSize := len(fmt.Sprintf("User-Agent: %s\r\nReferer: %s\r\nContent-Length: %v\r\n", userAgent, referer, len(requestMsg))) 40 responseHdrSize := len(fmt.Sprintf("Content-Length: %v\r\n", len(responseMsg))) 41 ent, spanCtx, err := roundTrip(r, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 42 w.Header().Set("Content-Length", fmt.Sprint(len(responseMsg))) 43 w.WriteHeader(http.StatusOK) 44 io.WriteString(w, responseMsg) 45 })) 46 if err != nil { 47 t.Fatal("Could not get entry:", err) 48 } 49 if want := "POST"; ent.RequestMethod != want { 50 t.Errorf("RequestMethod = %q; want %q", ent.RequestMethod, want) 51 } 52 if want := "/foo"; ent.RequestURL != want { 53 t.Errorf("RequestURL = %q; want %q", ent.RequestURL, want) 54 } 55 if ent.RequestHeaderSize < int64(requestHdrSize) { 56 t.Errorf("RequestHeaderSize = %d; want >=%d", ent.RequestHeaderSize, requestHdrSize) 57 } 58 if ent.RequestBodySize != int64(len(requestMsg)) { 59 t.Errorf("RequestBodySize = %d; want %d", ent.RequestBodySize, len(requestMsg)) 60 } 61 if ent.UserAgent != userAgent { 62 t.Errorf("UserAgent = %q; want %q", ent.UserAgent, userAgent) 63 } 64 if ent.Referer != referer { 65 t.Errorf("Referer = %q; want %q", ent.Referer, referer) 66 } 67 if want := "HTTP/1.1"; ent.Proto != want { 68 t.Errorf("Proto = %q; want %q", ent.Proto, want) 69 } 70 if ent.Status != http.StatusOK { 71 t.Errorf("Status = %d; want %d", ent.Status, http.StatusOK) 72 } 73 if ent.ResponseHeaderSize < int64(responseHdrSize) { 74 t.Errorf("ResponseHeaderSize = %d; want >=%d", ent.ResponseHeaderSize, responseHdrSize) 75 } 76 if ent.ResponseBodySize != int64(len(responseMsg)) { 77 t.Errorf("ResponseBodySize = %d; want %d", ent.ResponseBodySize, len(responseMsg)) 78 } 79 if ent.TraceID != spanCtx.TraceID { 80 t.Errorf("TraceID = %v; want %v", ent.TraceID, spanCtx.TraceID) 81 } 82 if ent.SpanID != spanCtx.SpanID { 83 t.Errorf("SpanID = %v; want %v", ent.SpanID, spanCtx.SpanID) 84 } 85 } 86 87 type testSpanHandler struct { 88 h http.Handler 89 spanCtx *trace.SpanContext 90 } 91 92 func (sh *testSpanHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 93 ctx, span := trace.StartSpan(r.Context(), "test") 94 defer span.End() 95 r = r.WithContext(ctx) 96 sc := trace.FromContext(ctx).SpanContext() 97 sh.spanCtx = &sc 98 sh.h.ServeHTTP(w, r) 99 } 100 101 func roundTrip(r *http.Request, h http.Handler) (*Entry, *trace.SpanContext, error) { 102 capture := new(captureLogger) 103 hh := NewHandler(capture, h) 104 handler := &testSpanHandler{h: hh} 105 s := httptest.NewServer(handler) 106 defer s.Close() 107 r.URL.Host = s.URL[len("http://"):] 108 resp, err := http.DefaultClient.Do(r) 109 if err != nil { 110 return nil, nil, err 111 } 112 resp.Body.Close() 113 return &capture.ent, handler.spanCtx, nil 114 } 115 116 type captureLogger struct { 117 ent Entry 118 } 119 120 func (cl *captureLogger) Log(ent *Entry) { 121 cl.ent = *ent 122 }