github.com/Laisky/zap@v1.27.0/zapcore/tee_test.go (about) 1 // Copyright (c) 2016 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 zapcore_test 22 23 import ( 24 "errors" 25 "testing" 26 27 "github.com/Laisky/zap/internal/ztest" 28 //revive:disable:dot-imports 29 . "github.com/Laisky/zap/zapcore" 30 "github.com/Laisky/zap/zaptest/observer" 31 32 "github.com/stretchr/testify/assert" 33 ) 34 35 func withTee(f func(core Core, debugLogs, warnLogs *observer.ObservedLogs)) { 36 debugLogger, debugLogs := observer.New(DebugLevel) 37 warnLogger, warnLogs := observer.New(WarnLevel) 38 tee := NewTee(debugLogger, warnLogger) 39 f(tee, debugLogs, warnLogs) 40 } 41 42 func TestTeeUnusualInput(t *testing.T) { 43 // Verify that Tee handles receiving one and no inputs correctly. 44 t.Run("one input", func(t *testing.T) { 45 obs, _ := observer.New(DebugLevel) 46 assert.Equal(t, obs, NewTee(obs), "Expected to return single inputs unchanged.") 47 }) 48 t.Run("no input", func(t *testing.T) { 49 assert.Equal(t, NewNopCore(), NewTee(), "Expected to return NopCore.") 50 }) 51 } 52 53 func TestLevelOfTee(t *testing.T) { 54 debugLogger, _ := observer.New(DebugLevel) 55 warnLogger, _ := observer.New(WarnLevel) 56 57 tests := []struct { 58 desc string 59 give []Core 60 want Level 61 }{ 62 {desc: "empty", want: InvalidLevel}, 63 { 64 desc: "debug", 65 give: []Core{debugLogger}, 66 want: DebugLevel, 67 }, 68 { 69 desc: "warn", 70 give: []Core{warnLogger}, 71 want: WarnLevel, 72 }, 73 { 74 desc: "debug and warn", 75 give: []Core{warnLogger, debugLogger}, 76 want: DebugLevel, 77 }, 78 } 79 80 for _, tt := range tests { 81 tt := tt 82 t.Run(tt.desc, func(t *testing.T) { 83 t.Parallel() 84 85 core := NewTee(tt.give...) 86 assert.Equal(t, tt.want, LevelOf(core), "Level of Tee core did not match.") 87 }) 88 } 89 } 90 91 func TestTeeCheck(t *testing.T) { 92 withTee(func(tee Core, debugLogs, warnLogs *observer.ObservedLogs) { 93 debugEntry := Entry{Level: DebugLevel, Message: "log-at-debug"} 94 infoEntry := Entry{Level: InfoLevel, Message: "log-at-info"} 95 warnEntry := Entry{Level: WarnLevel, Message: "log-at-warn"} 96 errorEntry := Entry{Level: ErrorLevel, Message: "log-at-error"} 97 for _, ent := range []Entry{debugEntry, infoEntry, warnEntry, errorEntry} { 98 if ce := tee.Check(ent, nil); ce != nil { 99 ce.Write() 100 } 101 } 102 103 assert.Equal(t, []observer.LoggedEntry{ 104 {Entry: debugEntry, Context: []Field{}}, 105 {Entry: infoEntry, Context: []Field{}}, 106 {Entry: warnEntry, Context: []Field{}}, 107 {Entry: errorEntry, Context: []Field{}}, 108 }, debugLogs.All()) 109 110 assert.Equal(t, []observer.LoggedEntry{ 111 {Entry: warnEntry, Context: []Field{}}, 112 {Entry: errorEntry, Context: []Field{}}, 113 }, warnLogs.All()) 114 }) 115 } 116 117 func TestTeeWrite(t *testing.T) { 118 // Calling the tee's Write method directly should always log, regardless of 119 // the configured level. 120 withTee(func(tee Core, debugLogs, warnLogs *observer.ObservedLogs) { 121 debugEntry := Entry{Level: DebugLevel, Message: "log-at-debug"} 122 warnEntry := Entry{Level: WarnLevel, Message: "log-at-warn"} 123 for _, ent := range []Entry{debugEntry, warnEntry} { 124 assert.NoError(t, tee.Write(ent, nil)) 125 } 126 127 for _, logs := range []*observer.ObservedLogs{debugLogs, warnLogs} { 128 assert.Equal(t, []observer.LoggedEntry{ 129 {Entry: debugEntry, Context: []Field{}}, 130 {Entry: warnEntry, Context: []Field{}}, 131 }, logs.All()) 132 } 133 }) 134 } 135 136 func TestTeeWith(t *testing.T) { 137 withTee(func(tee Core, debugLogs, warnLogs *observer.ObservedLogs) { 138 f := makeInt64Field("k", 42) 139 tee = tee.With([]Field{f}) 140 ent := Entry{Level: WarnLevel, Message: "log-at-warn"} 141 if ce := tee.Check(ent, nil); ce != nil { 142 ce.Write() 143 } 144 145 for _, logs := range []*observer.ObservedLogs{debugLogs, warnLogs} { 146 assert.Equal(t, []observer.LoggedEntry{ 147 {Entry: ent, Context: []Field{f}}, 148 }, logs.All()) 149 } 150 }) 151 } 152 153 func TestTeeEnabled(t *testing.T) { 154 infoLogger, _ := observer.New(InfoLevel) 155 warnLogger, _ := observer.New(WarnLevel) 156 tee := NewTee(infoLogger, warnLogger) 157 tests := []struct { 158 lvl Level 159 enabled bool 160 }{ 161 {DebugLevel, false}, 162 {InfoLevel, true}, 163 {WarnLevel, true}, 164 {ErrorLevel, true}, 165 {DPanicLevel, true}, 166 {PanicLevel, true}, 167 {FatalLevel, true}, 168 } 169 170 for _, tt := range tests { 171 assert.Equal(t, tt.enabled, tee.Enabled(tt.lvl), "Unexpected Enabled result for level %s.", tt.lvl) 172 } 173 } 174 175 func TestTeeSync(t *testing.T) { 176 infoLogger, _ := observer.New(InfoLevel) 177 warnLogger, _ := observer.New(WarnLevel) 178 tee := NewTee(infoLogger, warnLogger) 179 assert.NoError(t, tee.Sync(), "Unexpected error from Syncing a tee.") 180 181 sink := &ztest.Discarder{} 182 err := errors.New("failed") 183 sink.SetError(err) 184 185 noSync := NewCore( 186 NewJSONEncoder(testEncoderConfig()), 187 sink, 188 DebugLevel, 189 ) 190 tee = NewTee(tee, noSync) 191 assert.Equal(t, err, tee.Sync(), "Expected an error when part of tee can't Sync.") 192 }