github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/httpsnoop/capture_metrics_test.go (about) 1 package httpsnoop 2 3 import ( 4 "io" 5 "io/ioutil" 6 "log" 7 "os" 8 "strings" 9 "testing" 10 "time" 11 12 http "github.com/hxx258456/ccgo/gmhttp" 13 "github.com/hxx258456/ccgo/gmhttp/httptest" 14 ) 15 16 func TestCaptureMetrics(t *testing.T) { 17 // Some of the edge cases tested below cause the net/http pkg to log some 18 // messages that add a lot of noise to the `go test -v` output, so we discard 19 // the log here. 20 log.SetOutput(ioutil.Discard) 21 defer log.SetOutput(os.Stderr) 22 23 tests := []struct { 24 Handler http.Handler 25 WantDuration time.Duration 26 WantWritten int64 27 WantCode int 28 WantErr string 29 }{ 30 { 31 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}), 32 WantCode: http.StatusOK, 33 }, 34 { 35 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 36 w.WriteHeader(http.StatusBadRequest) 37 w.WriteHeader(http.StatusNotFound) 38 w.Write([]byte("foo")) 39 w.Write([]byte("bar")) 40 time.Sleep(25 * time.Millisecond) 41 }), 42 WantCode: http.StatusBadRequest, 43 WantWritten: 6, 44 WantDuration: 25 * time.Millisecond, 45 }, 46 { 47 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 48 w.Write([]byte("foo")) 49 w.WriteHeader(http.StatusNotFound) 50 }), 51 WantCode: http.StatusOK, 52 }, 53 { 54 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 55 rrf := w.(io.ReaderFrom) 56 rrf.ReadFrom(strings.NewReader("reader from is ok")) 57 }), 58 WantWritten: 17, 59 WantCode: http.StatusOK, 60 }, 61 { 62 Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 63 panic("oh no") 64 }), 65 WantErr: "EOF", 66 }, 67 } 68 69 for i, test := range tests { 70 func() { 71 ch := make(chan Metrics, 1) 72 h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 73 ch <- CaptureMetrics(test.Handler, w, r) 74 }) 75 s := httptest.NewServer(h) 76 defer s.Close() 77 res, err := http.Get(s.URL) 78 if !errContains(err, test.WantErr) { 79 t.Errorf("test %d: got=%s want=%s", i, err, test.WantErr) 80 } 81 if err != nil { 82 return 83 } 84 defer res.Body.Close() 85 m := <-ch 86 if m.Code != test.WantCode { 87 t.Errorf("test %d: got=%d want=%d", i, m.Code, test.WantCode) 88 } else if m.Duration < test.WantDuration { 89 t.Errorf("test %d: got=%s want=%s", i, m.Duration, test.WantDuration) 90 } else if m.Written < test.WantWritten { 91 t.Errorf("test %d: got=%d want=%d", i, m.Written, test.WantWritten) 92 } 93 }() 94 } 95 } 96 97 func errContains(err error, s string) bool { 98 var errS string 99 if err == nil { 100 errS = "" 101 } else { 102 errS = err.Error() 103 } 104 return strings.Contains(errS, s) 105 }