...

Source file src/go.uber.org/zap/zapcore/core_test.go

Documentation: go.uber.org/zap/zapcore

     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  	"go.uber.org/zap/internal/ztest"
    30  	//revive:disable:dot-imports
    31  	. "go.uber.org/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  }
   167  

View as plain text