github.com/Laisky/zap@v1.27.0/zapcore/core_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 "os" 26 "testing" 27 "time" 28 29 "github.com/Laisky/zap/internal/ztest" 30 //revive:disable:dot-imports 31 . "github.com/Laisky/zap/zapcore" 32 33 "github.com/stretchr/testify/assert" 34 "github.com/stretchr/testify/require" 35 ) 36 37 func makeInt64Field(key string, val int) Field { 38 return Field{Type: Int64Type, Integer: int64(val), Key: key} 39 } 40 41 func TestNopCore(t *testing.T) { 42 entry := Entry{ 43 Message: "test", 44 Level: InfoLevel, 45 Time: time.Now(), 46 LoggerName: "main", 47 Stack: "fake-stack", 48 } 49 ce := &CheckedEntry{} 50 51 allLevels := []Level{ 52 DebugLevel, 53 InfoLevel, 54 WarnLevel, 55 ErrorLevel, 56 DPanicLevel, 57 PanicLevel, 58 FatalLevel, 59 } 60 core := NewNopCore() 61 assert.Equal(t, core, core.With([]Field{makeInt64Field("k", 42)}), "Expected no-op With.") 62 for _, level := range allLevels { 63 assert.False(t, core.Enabled(level), "Expected all levels to be disabled in no-op core.") 64 assert.Equal(t, ce, core.Check(entry, ce), "Expected no-op Check to return checked entry unchanged.") 65 assert.NoError(t, core.Write(entry, nil), "Expected no-op Writes to always succeed.") 66 assert.NoError(t, core.Sync(), "Expected no-op Syncs to always succeed.") 67 } 68 } 69 70 func TestIOCore(t *testing.T) { 71 temp, err := os.CreateTemp(t.TempDir(), "test.log") 72 require.NoError(t, err) 73 74 // Drop timestamps for simpler assertions (timestamp encoding is tested 75 // elsewhere). 76 cfg := testEncoderConfig() 77 cfg.TimeKey = "" 78 79 core := NewCore( 80 NewJSONEncoder(cfg), 81 temp, 82 InfoLevel, 83 ).With([]Field{makeInt64Field("k", 1)}) 84 defer assert.NoError(t, core.Sync(), "Expected Syncing a temp file to succeed.") 85 86 t.Run("LevelOf", func(t *testing.T) { 87 assert.Equal(t, InfoLevel, LevelOf(core), "Incorrect Core Level") 88 }) 89 90 if ce := core.Check(Entry{Level: DebugLevel, Message: "debug"}, nil); ce != nil { 91 ce.Write(makeInt64Field("k", 2)) 92 } 93 if ce := core.Check(Entry{Level: InfoLevel, Message: "info"}, nil); ce != nil { 94 ce.Write(makeInt64Field("k", 3)) 95 } 96 if ce := core.Check(Entry{Level: WarnLevel, Message: "warn"}, nil); ce != nil { 97 ce.Write(makeInt64Field("k", 4)) 98 } 99 100 logged, err := os.ReadFile(temp.Name()) 101 require.NoError(t, err, "Failed to read from temp file.") 102 require.Equal( 103 t, 104 `{"level":"info","msg":"info","k":1,"k":3}`+"\n"+ 105 `{"level":"warn","msg":"warn","k":1,"k":4}`+"\n", 106 string(logged), 107 "Unexpected log output.", 108 ) 109 } 110 111 func TestIOCoreSyncFail(t *testing.T) { 112 sink := &ztest.Discarder{} 113 err := errors.New("failed") 114 sink.SetError(err) 115 116 core := NewCore( 117 NewJSONEncoder(testEncoderConfig()), 118 sink, 119 DebugLevel, 120 ) 121 122 assert.Equal( 123 t, 124 err, 125 core.Sync(), 126 "Expected core.Sync to return errors from underlying WriteSyncer.", 127 ) 128 } 129 130 func TestIOCoreSyncsOutput(t *testing.T) { 131 tests := []struct { 132 entry Entry 133 shouldSync bool 134 }{ 135 {Entry{Level: DebugLevel}, false}, 136 {Entry{Level: InfoLevel}, false}, 137 {Entry{Level: WarnLevel}, false}, 138 {Entry{Level: ErrorLevel}, false}, 139 {Entry{Level: DPanicLevel}, true}, 140 {Entry{Level: PanicLevel}, true}, 141 {Entry{Level: FatalLevel}, true}, 142 } 143 144 for _, tt := range tests { 145 sink := &ztest.Discarder{} 146 core := NewCore( 147 NewJSONEncoder(testEncoderConfig()), 148 sink, 149 DebugLevel, 150 ) 151 152 assert.NoError(t, core.Write(tt.entry, nil), "Unexpected error writing entry.") 153 assert.Equal(t, tt.shouldSync, sink.Called(), "Incorrect Sync behavior.") 154 } 155 } 156 157 func TestIOCoreWriteFailure(t *testing.T) { 158 core := NewCore( 159 NewJSONEncoder(testEncoderConfig()), 160 Lock(&ztest.FailWriter{}), 161 DebugLevel, 162 ) 163 err := core.Write(Entry{}, nil) 164 // Should log the error. 165 assert.Error(t, err, "Expected writing Entry to fail.") 166 }