1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
17 "git.arvados.org/arvados.git/sdk/go/ctxlog"
18 "github.com/sirupsen/logrus"
19 check "gopkg.in/check.v1"
22 func Test(t *testing.T) {
26 var _ = check.Suite(&Suite{})
34 func (s *Suite) SetUpTest(c *check.C) {
35 s.logdata = bytes.NewBuffer(nil)
38 s.log.Formatter = &logrus.JSONFormatter{
39 TimestampFormat: time.RFC3339Nano,
41 s.ctx = ctxlog.Context(context.Background(), s.log)
44 func (s *Suite) TestLogRequests(c *check.C) {
45 h := AddRequestIDs(LogRequests(
46 http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
47 w.Write([]byte("hello world"))
50 req, err := http.NewRequest("GET", "https://foo.example/bar", nil)
51 req.Header.Set("X-Forwarded-For", "1.2.3.4:12345")
52 c.Assert(err, check.IsNil)
53 resp := httptest.NewRecorder()
55 HandlerWithContext(s.ctx, h).ServeHTTP(resp, req)
57 dec := json.NewDecoder(s.logdata)
59 gotReq := make(map[string]interface{})
60 err = dec.Decode(&gotReq)
61 c.Check(err, check.IsNil)
63 c.Check(gotReq["RequestID"], check.Matches, "req-[a-z0-9]{20}")
64 c.Check(gotReq["reqForwardedFor"], check.Equals, "1.2.3.4:12345")
65 c.Check(gotReq["msg"], check.Equals, "request")
67 gotResp := make(map[string]interface{})
68 err = dec.Decode(&gotResp)
69 c.Check(err, check.IsNil)
70 c.Logf("%#v", gotResp)
71 c.Check(gotResp["RequestID"], check.Equals, gotReq["RequestID"])
72 c.Check(gotResp["reqForwardedFor"], check.Equals, "1.2.3.4:12345")
73 c.Check(gotResp["msg"], check.Equals, "response")
75 c.Assert(gotResp["time"], check.FitsTypeOf, "")
76 _, err = time.Parse(time.RFC3339Nano, gotResp["time"].(string))
77 c.Check(err, check.IsNil)
79 for _, key := range []string{"timeToStatus", "timeWriteBody", "timeTotal"} {
80 c.Assert(gotResp[key], check.FitsTypeOf, float64(0))
81 c.Check(gotResp[key].(float64), check.Not(check.Equals), float64(0))
85 func (s *Suite) TestLogErrorBody(c *check.C) {
86 dec := json.NewDecoder(s.logdata)
88 for _, trial := range []struct {
95 {"ok", 200, "hello world", false, ""},
96 {"redir", 302, "<a href='http://foo.example/baz'>redir</a>", false, ""},
97 {"4xx short body", 400, "oops", true, "oops"},
98 {"4xx long body", 400, fmt.Sprintf("%0*d", sniffBytes*2, 1), true, fmt.Sprintf("%0*d", sniffBytes, 0)},
99 {"5xx empty body", 500, "", true, ""},
101 comment := check.Commentf("in trial: %q", trial.label)
103 req, err := http.NewRequest("GET", "https://foo.example/bar", nil)
104 c.Assert(err, check.IsNil)
105 resp := httptest.NewRecorder()
107 HandlerWithContext(s.ctx, LogRequests(
108 http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
109 w.WriteHeader(trial.statusCode)
110 w.Write([]byte(trial.sentBody))
112 )).ServeHTTP(resp, req)
114 gotReq := make(map[string]interface{})
115 err = dec.Decode(&gotReq)
116 c.Check(err, check.IsNil)
117 c.Logf("%#v", gotReq)
118 gotResp := make(map[string]interface{})
119 err = dec.Decode(&gotResp)
120 c.Check(err, check.IsNil)
121 c.Logf("%#v", gotResp)
123 c.Check(gotResp["respBody"], check.Equals, trial.expectBody, comment)
125 c.Check(gotResp["respBody"], check.IsNil, comment)