github.com/Laisky/zap@v1.27.0/zaptest/logger_test.go (about) 1 // Copyright (c) 2017 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package zaptest 22 23 import ( 24 "errors" 25 "fmt" 26 "io" 27 "strings" 28 "testing" 29 30 "github.com/Laisky/zap" 31 "github.com/Laisky/zap/internal/ztest" 32 "github.com/Laisky/zap/zapcore" 33 34 "github.com/stretchr/testify/assert" 35 ) 36 37 func TestTestLogger(t *testing.T) { 38 ts := newTestLogSpy(t) 39 defer ts.AssertPassed() 40 41 log := NewLogger(ts) 42 43 log.Info("received work order") 44 log.Debug("starting work") 45 log.Warn("work may fail") 46 log.Error("work failed", zap.Error(errors.New("great sadness"))) 47 48 assert.Panics(t, func() { 49 log.Panic("failed to do work") 50 }, "log.Panic should panic") 51 52 ts.AssertMessages( 53 "INFO received work order", 54 "DEBUG starting work", 55 "WARN work may fail", 56 `ERROR work failed {"error": "great sadness"}`, 57 "PANIC failed to do work", 58 ) 59 } 60 61 func TestTestLoggerSupportsLevels(t *testing.T) { 62 ts := newTestLogSpy(t) 63 defer ts.AssertPassed() 64 65 log := NewLogger(ts, Level(zap.WarnLevel)) 66 67 log.Info("received work order") 68 log.Debug("starting work") 69 log.Warn("work may fail") 70 log.Error("work failed", zap.Error(errors.New("great sadness"))) 71 72 assert.Panics(t, func() { 73 log.Panic("failed to do work") 74 }, "log.Panic should panic") 75 76 ts.AssertMessages( 77 "WARN work may fail", 78 `ERROR work failed {"error": "great sadness"}`, 79 "PANIC failed to do work", 80 ) 81 } 82 83 func TestTestLoggerSupportsWrappedZapOptions(t *testing.T) { 84 ts := newTestLogSpy(t) 85 defer ts.AssertPassed() 86 87 log := NewLogger(ts, WrapOptions(zap.AddCaller(), zap.Fields(zap.String("k1", "v1")))) 88 89 log.Info("received work order") 90 log.Debug("starting work") 91 log.Warn("work may fail") 92 log.Error("work failed", zap.Error(errors.New("great sadness"))) 93 94 assert.Panics(t, func() { 95 log.Panic("failed to do work") 96 }, "log.Panic should panic") 97 98 ts.AssertMessages( 99 `INFO zaptest/logger_test.go:89 received work order {"k1": "v1"}`, 100 `DEBUG zaptest/logger_test.go:90 starting work {"k1": "v1"}`, 101 `WARN zaptest/logger_test.go:91 work may fail {"k1": "v1"}`, 102 `ERROR zaptest/logger_test.go:92 work failed {"k1": "v1", "error": "great sadness"}`, 103 `PANIC zaptest/logger_test.go:95 failed to do work {"k1": "v1"}`, 104 ) 105 } 106 107 func TestTestingWriter(t *testing.T) { 108 ts := newTestLogSpy(t) 109 w := NewTestingWriter(ts) 110 111 n, err := io.WriteString(w, "hello\n\n") 112 assert.NoError(t, err, "WriteString must not fail") 113 assert.Equal(t, 7, n) 114 } 115 116 func TestTestLoggerErrorOutput(t *testing.T) { 117 // This test verifies that the test logger logs internal messages to the 118 // testing.T and marks the test as failed. 119 120 ts := newTestLogSpy(t) 121 defer ts.AssertFailed() 122 123 log := NewLogger(ts) 124 125 // Replace with a core that fails. 126 log = log.WithOptions(zap.WrapCore(func(zapcore.Core) zapcore.Core { 127 return zapcore.NewCore( 128 zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig()), 129 zapcore.Lock(zapcore.AddSync(ztest.FailWriter{})), 130 zapcore.DebugLevel, 131 ) 132 })) 133 134 log.Info("foo") // this fails 135 136 if assert.Len(t, ts.Messages, 1, "expected a log message") { 137 assert.Regexp(t, `write error: failed`, ts.Messages[0]) 138 } 139 } 140 141 // testLogSpy is a testing.TB that captures logged messages. 142 type testLogSpy struct { 143 testing.TB 144 145 failed bool 146 Messages []string 147 } 148 149 func newTestLogSpy(t testing.TB) *testLogSpy { 150 return &testLogSpy{TB: t} 151 } 152 153 func (t *testLogSpy) Fail() { 154 t.failed = true 155 } 156 157 func (t *testLogSpy) Failed() bool { 158 return t.failed 159 } 160 161 func (t *testLogSpy) FailNow() { 162 t.Fail() 163 t.TB.FailNow() 164 } 165 166 func (t *testLogSpy) Logf(format string, args ...interface{}) { 167 // Log messages are in the format, 168 // 169 // 2017-10-27T13:03:01.000-0700 DEBUG your message here {data here} 170 // 171 // We strip the first part of these messages because we can't really test 172 // for the timestamp from these tests. 173 m := fmt.Sprintf(format, args...) 174 m = m[strings.IndexByte(m, '\t')+1:] 175 t.Messages = append(t.Messages, m) 176 t.TB.Log(m) 177 } 178 179 func (t *testLogSpy) AssertMessages(msgs ...string) { 180 assert.Equal(t.TB, msgs, t.Messages, "logged messages did not match") 181 } 182 183 func (t *testLogSpy) AssertPassed() { 184 t.assertFailed(false, "expected test to pass") 185 } 186 187 func (t *testLogSpy) AssertFailed() { 188 t.assertFailed(true, "expected test to fail") 189 } 190 191 func (t *testLogSpy) assertFailed(v bool, msg string) { 192 assert.Equal(t.TB, v, t.failed, msg) 193 }