...

Source file src/go.uber.org/zap/zapcore/tee_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  	"testing"
    26  
    27  	"go.uber.org/zap/internal/ztest"
    28  	//revive:disable:dot-imports
    29  	. "go.uber.org/zap/zapcore"
    30  	"go.uber.org/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  }
   193  

View as plain text