diff options
Diffstat (limited to '')
-rw-r--r-- | dependencies/pkg/mod/go.uber.org/zap@v1.23.0/writer_test.go | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/dependencies/pkg/mod/go.uber.org/zap@v1.23.0/writer_test.go b/dependencies/pkg/mod/go.uber.org/zap@v1.23.0/writer_test.go new file mode 100644 index 0000000..c2f4392 --- /dev/null +++ b/dependencies/pkg/mod/go.uber.org/zap@v1.23.0/writer_test.go @@ -0,0 +1,266 @@ +// Copyright (c) 2016-2022 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package zap + +import ( + "errors" + "io" + "io/fs" + "net/url" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.uber.org/multierr" + "go.uber.org/zap/zapcore" +) + +func TestOpenNoPaths(t *testing.T) { + ws, cleanup, err := Open() + defer cleanup() + + assert.NoError(t, err, "Expected opening no paths to succeed.") + assert.Equal( + t, + zapcore.AddSync(io.Discard), + ws, + "Expected opening no paths to return a no-op WriteSyncer.", + ) +} + +func TestOpen(t *testing.T) { + tempName := filepath.Join(t.TempDir(), "test.log") + assert.False(t, fileExists(tempName)) + require.True(t, filepath.IsAbs(tempName), "Expected absolute temp file path.") + + tests := []struct { + msg string + paths []string + }{ + { + msg: "stdout", + paths: []string{"stdout"}, + }, + { + msg: "stderr", + paths: []string{"stderr"}, + }, + { + msg: "temp file path only", + paths: []string{tempName}, + }, + { + msg: "temp file file scheme", + paths: []string{"file://" + tempName}, + }, + { + msg: "temp file with file scheme and host localhost", + paths: []string{"file://localhost" + tempName}, + }, + } + + for _, tt := range tests { + t.Run(tt.msg, func(t *testing.T) { + _, cleanup, err := Open(tt.paths...) + if err == nil { + defer cleanup() + } + + assert.NoError(t, err, "Unexpected error opening paths %v.", tt.paths) + }) + } + + assert.True(t, fileExists(tempName)) + os.Remove(tempName) +} + +func TestOpenPathsNotFound(t *testing.T) { + tempName := filepath.Join(t.TempDir(), "test.log") + + tests := []struct { + msg string + paths []string + wantNotFoundPaths []string + }{ + { + msg: "missing path", + paths: []string{"/foo/bar/baz"}, + wantNotFoundPaths: []string{"/foo/bar/baz"}, + }, + { + msg: "missing file scheme url with host localhost", + paths: []string{"file://localhost/foo/bar/baz"}, + wantNotFoundPaths: []string{"/foo/bar/baz"}, + }, + { + msg: "multiple paths", + paths: []string{"stdout", "/foo/bar/baz", tempName, "file:///baz/quux"}, + wantNotFoundPaths: []string{ + "/foo/bar/baz", + "/baz/quux", + }, + }, + } + + for _, tt := range tests { + t.Run(tt.msg, func(t *testing.T) { + _, cleanup, err := Open(tt.paths...) + if !assert.Error(t, err, "Open must fail.") { + cleanup() + return + } + + errs := multierr.Errors(err) + require.Len(t, errs, len(tt.wantNotFoundPaths)) + for i, err := range errs { + assert.ErrorIs(t, err, fs.ErrNotExist) + assert.ErrorContains(t, err, tt.wantNotFoundPaths[i], "missing path in error") + } + }) + } +} + +func TestOpenRelativePath(t *testing.T) { + const name = "test-relative-path.txt" + + require.False(t, fileExists(name), "Test file already exists.") + s, cleanup, err := Open(name) + require.NoError(t, err, "Open failed.") + defer func() { + err := os.Remove(name) + if !t.Failed() { + // If the test has already failed, we probably didn't create this file. + require.NoError(t, err, "Deleting test file failed.") + } + }() + defer cleanup() + + _, err = s.Write([]byte("test")) + assert.NoError(t, err, "Write failed.") + assert.True(t, fileExists(name), "Didn't create file for relative path.") +} + +func TestOpenFails(t *testing.T) { + tests := []struct { + paths []string + }{ + {paths: []string{"./non-existent-dir/file"}}, // directory doesn't exist + {paths: []string{"stdout", "./non-existent-dir/file"}}, // directory doesn't exist + {paths: []string{"://foo.log"}}, // invalid URL, scheme can't begin with colon + {paths: []string{"mem://somewhere"}}, // scheme not registered + } + + for _, tt := range tests { + _, cleanup, err := Open(tt.paths...) + require.Nil(t, cleanup, "Cleanup function should never be nil") + assert.Error(t, err, "Open with invalid URL should fail.") + } +} + +func TestOpenOtherErrors(t *testing.T) { + tempName := filepath.Join(t.TempDir(), "test.log") + + tests := []struct { + msg string + paths []string + wantErr string + }{ + { + msg: "file with unexpected host", + paths: []string{"file://host01.test.com" + tempName}, + wantErr: "empty or use localhost", + }, + { + msg: "file with user on localhost", + paths: []string{"file://rms@localhost" + tempName}, + wantErr: "user and password not allowed", + }, + { + msg: "file url with fragment", + paths: []string{"file://localhost" + tempName + "#foo"}, + wantErr: "fragments not allowed", + }, + { + msg: "file url with query", + paths: []string{"file://localhost" + tempName + "?foo=bar"}, + wantErr: "query parameters not allowed", + }, + { + msg: "file with port", + paths: []string{"file://localhost:8080" + tempName}, + wantErr: "ports not allowed", + }, + } + + for _, tt := range tests { + t.Run(tt.msg, func(t *testing.T) { + _, cleanup, err := Open(tt.paths...) + if !assert.Error(t, err, "Open must fail.") { + cleanup() + return + } + + assert.ErrorContains(t, err, tt.wantErr, "Unexpected error opening paths %v.", tt.paths) + }) + } +} + +type testWriter struct { + expected string + t testing.TB +} + +func (w *testWriter) Write(actual []byte) (int, error) { + assert.Equal(w.t, []byte(w.expected), actual, "Unexpected write error.") + return len(actual), nil +} + +func (w *testWriter) Sync() error { + return nil +} + +func TestOpenWithErroringSinkFactory(t *testing.T) { + defer resetSinkRegistry() + + msg := "expected factory error" + factory := func(_ *url.URL) (Sink, error) { + return nil, errors.New(msg) + } + + assert.NoError(t, RegisterSink("test", factory), "Failed to register sink factory.") + _, _, err := Open("test://some/path") + assert.Contains(t, err.Error(), msg, "Unexpected error.") +} + +func TestCombineWriteSyncers(t *testing.T) { + tw := &testWriter{"test", t} + w := CombineWriteSyncers(tw) + w.Write([]byte("test")) +} + +func fileExists(name string) bool { + if _, err := os.Stat(name); os.IsNotExist(err) { + return false + } + return true +} |