github.com/go-kit/log@v0.2.1/json_logger_test.go (about) 1 package log_test 2 3 import ( 4 "bytes" 5 "errors" 6 "io/ioutil" 7 "testing" 8 9 "github.com/go-kit/log" 10 ) 11 12 func TestJSONLoggerCaller(t *testing.T) { 13 t.Parallel() 14 buf := &bytes.Buffer{} 15 logger := log.NewJSONLogger(buf) 16 logger = log.With(logger, "caller", log.DefaultCaller) 17 18 if err := logger.Log(); err != nil { 19 t.Fatal(err) 20 } 21 if want, have := `{"caller":"json_logger_test.go:18"}`+"\n", buf.String(); want != have { 22 t.Errorf("\nwant %#v\nhave %#v", want, have) 23 } 24 } 25 26 func TestJSONLogger(t *testing.T) { 27 t.Parallel() 28 buf := &bytes.Buffer{} 29 logger := log.NewJSONLogger(buf) 30 if err := logger.Log("err", errors.New("err"), "m", map[string]int{"0": 0}, "a", []int{1, 2, 3}); err != nil { 31 t.Fatal(err) 32 } 33 if want, have := `{"a":[1,2,3],"err":"err","m":{"0":0}}`+"\n", buf.String(); want != have { 34 t.Errorf("\nwant %#v\nhave %#v", want, have) 35 } 36 } 37 38 func TestJSONLoggerMissingValue(t *testing.T) { 39 t.Parallel() 40 buf := &bytes.Buffer{} 41 logger := log.NewJSONLogger(buf) 42 if err := logger.Log("k"); err != nil { 43 t.Fatal(err) 44 } 45 if want, have := `{"k":"(MISSING)"}`+"\n", buf.String(); want != have { 46 t.Errorf("\nwant %#v\nhave %#v", want, have) 47 } 48 } 49 50 func TestJSONLoggerNilStringerKey(t *testing.T) { 51 t.Parallel() 52 53 buf := &bytes.Buffer{} 54 logger := log.NewJSONLogger(buf) 55 if err := logger.Log((*stringer)(nil), "v"); err != nil { 56 t.Fatal(err) 57 } 58 if want, have := `{"NULL":"v"}`+"\n", buf.String(); want != have { 59 t.Errorf("\nwant %#v\nhave %#v", want, have) 60 } 61 } 62 63 func TestJSONLoggerPanicStringerValue(t *testing.T) { 64 t.Parallel() 65 66 buf := &bytes.Buffer{} 67 logger := log.NewJSONLogger(buf) 68 if err := logger.Log("k", unsafeStringer{}); err != nil { 69 t.Fatal(err) 70 } 71 if want, have := `{"k":"PANIC in String method: error"}`+"\n", buf.String(); want != have { 72 t.Errorf("\nwant %#v\nhave %#v", want, have) 73 } 74 } 75 76 func TestJSONLoggerNilErrorValue(t *testing.T) { 77 t.Parallel() 78 79 buf := &bytes.Buffer{} 80 logger := log.NewJSONLogger(buf) 81 if err := logger.Log("err", (*stringError)(nil)); err != nil { 82 t.Fatal(err) 83 } 84 if want, have := `{"err":null}`+"\n", buf.String(); want != have { 85 t.Errorf("\nwant %#v\nhave %#v", want, have) 86 } 87 } 88 89 func TestJSONLoggerPanicErrorValue(t *testing.T) { 90 t.Parallel() 91 92 buf := &bytes.Buffer{} 93 logger := log.NewJSONLogger(buf) 94 if err := logger.Log("err", unsafeError{}); err != nil { 95 t.Fatal(err) 96 } 97 if want, have := `{"err":"PANIC in Error method: error"}`+"\n", buf.String(); want != have { 98 t.Errorf("\nwant %#v\nhave %#v", want, have) 99 } 100 } 101 102 func TestJSONLoggerNoHTMLEscape(t *testing.T) { 103 t.Parallel() 104 buf := &bytes.Buffer{} 105 logger := log.NewJSONLogger(buf) 106 if err := logger.Log("k", "<&>"); err != nil { 107 t.Fatal(err) 108 } 109 if want, have := `{"k":"<&>"}`+"\n", buf.String(); want != have { 110 t.Errorf("\nwant %#v\nhave%#v", want, have) 111 } 112 } 113 114 // aller implements json.Marshaler, encoding.TextMarshaler, and fmt.Stringer. 115 type aller struct{} 116 117 func (aller) MarshalJSON() ([]byte, error) { 118 return []byte("\"json\""), nil 119 } 120 121 func (aller) MarshalText() ([]byte, error) { 122 return []byte("text"), nil 123 } 124 125 func (aller) String() string { 126 return "string" 127 } 128 129 func (aller) Error() string { 130 return "error" 131 } 132 133 // textstringer implements encoding.TextMarshaler and fmt.Stringer. 134 type textstringer struct{} 135 136 func (textstringer) MarshalText() ([]byte, error) { 137 return []byte("text"), nil 138 } 139 140 func (textstringer) String() string { 141 return "string" 142 } 143 144 func TestJSONLoggerStringValue(t *testing.T) { 145 t.Parallel() 146 tests := []struct { 147 v interface{} 148 expected string 149 }{ 150 { 151 v: aller{}, 152 expected: `{"v":"json"}`, 153 }, 154 { 155 v: textstringer{}, 156 expected: `{"v":"text"}`, 157 }, 158 { 159 v: stringer("string"), 160 expected: `{"v":"string"}`, 161 }, 162 } 163 164 for _, test := range tests { 165 buf := &bytes.Buffer{} 166 logger := log.NewJSONLogger(buf) 167 if err := logger.Log("v", test.v); err != nil { 168 t.Fatal(err) 169 } 170 171 if want, have := test.expected+"\n", buf.String(); want != have { 172 t.Errorf("\nwant %#v\nhave %#v", want, have) 173 } 174 } 175 } 176 177 type stringer string 178 179 func (s stringer) String() string { 180 return string(s) 181 } 182 183 type stringError string 184 185 func (s stringError) Error() string { 186 return string(s) 187 } 188 189 type unsafeStringer struct{} 190 191 func (s unsafeStringer) String() string { 192 panic("error") 193 } 194 195 type unsafeError struct{} 196 197 func (s unsafeError) Error() string { 198 panic("error") 199 } 200 201 func BenchmarkJSONLoggerSimple(b *testing.B) { 202 benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), baseMessage) 203 } 204 205 func BenchmarkJSONLoggerContextual(b *testing.B) { 206 benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), withMessage) 207 } 208 209 func TestJSONLoggerConcurrency(t *testing.T) { 210 t.Parallel() 211 testConcurrency(t, log.NewJSONLogger(ioutil.Discard), 10000) 212 }