github.com/Laisky/zap@v1.27.0/zapcore/write_syncer_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 22 23 import ( 24 "bytes" 25 "errors" 26 "io" 27 "testing" 28 29 "github.com/Laisky/zap/internal/ztest" 30 "github.com/stretchr/testify/assert" 31 "github.com/stretchr/testify/require" 32 ) 33 34 type writeSyncSpy struct { 35 io.Writer 36 ztest.Syncer 37 } 38 39 func requireWriteWorks(t testing.TB, ws WriteSyncer) { 40 n, err := ws.Write([]byte("foo")) 41 require.NoError(t, err, "Unexpected error writing to WriteSyncer.") 42 require.Equal(t, 3, n, "Wrote an unexpected number of bytes.") 43 } 44 45 func TestAddSyncWriteSyncer(t *testing.T) { 46 buf := &bytes.Buffer{} 47 concrete := &writeSyncSpy{Writer: buf} 48 ws := AddSync(concrete) 49 requireWriteWorks(t, ws) 50 51 require.NoError(t, ws.Sync(), "Unexpected error syncing a WriteSyncer.") 52 require.True(t, concrete.Called(), "Expected to dispatch to concrete type's Sync method.") 53 54 concrete.SetError(errors.New("fail")) 55 assert.Error(t, ws.Sync(), "Expected to propagate errors from concrete type's Sync method.") 56 } 57 58 func TestAddSyncWriter(t *testing.T) { 59 // If we pass a plain io.Writer, make sure that we still get a WriteSyncer 60 // with a no-op Sync. 61 buf := &bytes.Buffer{} 62 ws := AddSync(buf) 63 requireWriteWorks(t, ws) 64 assert.NoError(t, ws.Sync(), "Unexpected error calling a no-op Sync method.") 65 } 66 67 func TestNewMultiWriteSyncerWorksForSingleWriter(t *testing.T) { 68 w := &ztest.Buffer{} 69 70 ws := NewMultiWriteSyncer(w) 71 assert.Equal(t, w, ws, "Expected NewMultiWriteSyncer to return the same WriteSyncer object for a single argument.") 72 73 assert.NoError(t, ws.Sync(), "Expected Sync to succeed.") 74 assert.True(t, w.Called(), "Expected Sync to be called on the created WriteSyncer") 75 } 76 77 func TestMultiWriteSyncerWritesBoth(t *testing.T) { 78 first := &bytes.Buffer{} 79 second := &bytes.Buffer{} 80 ws := NewMultiWriteSyncer(AddSync(first), AddSync(second)) 81 82 msg := []byte("dumbledore") 83 n, err := ws.Write(msg) 84 require.NoError(t, err, "Expected successful buffer write") 85 assert.Equal(t, len(msg), n) 86 87 assert.Equal(t, msg, first.Bytes()) 88 assert.Equal(t, msg, second.Bytes()) 89 } 90 91 func TestMultiWriteSyncerFailsWrite(t *testing.T) { 92 ws := NewMultiWriteSyncer(AddSync(&ztest.FailWriter{})) 93 _, err := ws.Write([]byte("test")) 94 assert.Error(t, err, "Write error should propagate") 95 } 96 97 func TestMultiWriteSyncerFailsShortWrite(t *testing.T) { 98 ws := NewMultiWriteSyncer(AddSync(&ztest.ShortWriter{})) 99 n, err := ws.Write([]byte("test")) 100 assert.NoError(t, err, "Expected fake-success from short write") 101 assert.Equal(t, 3, n, "Expected byte count to return from underlying writer") 102 } 103 104 func TestWritestoAllSyncs_EvenIfFirstErrors(t *testing.T) { 105 failer := &ztest.FailWriter{} 106 second := &bytes.Buffer{} 107 ws := NewMultiWriteSyncer(AddSync(failer), AddSync(second)) 108 109 _, err := ws.Write([]byte("fail")) 110 assert.Error(t, err, "Expected error from call to a writer that failed") 111 assert.Equal(t, []byte("fail"), second.Bytes(), "Expected second sink to be written after first error") 112 } 113 114 func TestMultiWriteSyncerSync_PropagatesErrors(t *testing.T) { 115 badsink := &ztest.Buffer{} 116 badsink.SetError(errors.New("sink is full")) 117 ws := NewMultiWriteSyncer(&ztest.Discarder{}, badsink) 118 119 assert.Error(t, ws.Sync(), "Expected sync error to propagate") 120 } 121 122 func TestMultiWriteSyncerSync_NoErrorsOnDiscard(t *testing.T) { 123 ws := NewMultiWriteSyncer(&ztest.Discarder{}) 124 assert.NoError(t, ws.Sync(), "Expected error-free sync to /dev/null") 125 } 126 127 func TestMultiWriteSyncerSync_AllCalled(t *testing.T) { 128 failed, second := &ztest.Buffer{}, &ztest.Buffer{} 129 130 failed.SetError(errors.New("disposal broken")) 131 ws := NewMultiWriteSyncer(failed, second) 132 133 assert.Error(t, ws.Sync(), "Expected first sink to fail") 134 assert.True(t, failed.Called(), "Expected first sink to have Sync method called.") 135 assert.True(t, second.Called(), "Expected call to Sync even with first failure.") 136 }