...

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

Documentation: go.uber.org/zap/zapcore

     1  // Copyright (c) 2023 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  	"sync/atomic"
    25  	"testing"
    26  
    27  	"github.com/stretchr/testify/assert"
    28  	"go.uber.org/zap/zapcore"
    29  	"go.uber.org/zap/zaptest/observer"
    30  )
    31  
    32  type proxyCore struct {
    33  	zapcore.Core
    34  
    35  	withCount  atomic.Int64
    36  	checkCount atomic.Int64
    37  }
    38  
    39  func newProxyCore(inner zapcore.Core) *proxyCore {
    40  	return &proxyCore{Core: inner}
    41  }
    42  
    43  func (p *proxyCore) With(fields []zapcore.Field) zapcore.Core {
    44  	p.withCount.Add(1)
    45  	return p.Core.With(fields)
    46  }
    47  
    48  func (p *proxyCore) Check(e zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
    49  	p.checkCount.Add(1)
    50  	return p.Core.Check(e, ce)
    51  }
    52  
    53  func withLazyCore(f func(zapcore.Core, *proxyCore, *observer.ObservedLogs), initialFields ...zapcore.Field) {
    54  	infoLogger, infoLogs := observer.New(zapcore.InfoLevel)
    55  	proxyCore := newProxyCore(infoLogger)
    56  	lazyCore := zapcore.NewLazyWith(proxyCore, initialFields)
    57  	f(lazyCore, proxyCore, infoLogs)
    58  }
    59  
    60  func TestLazyCore(t *testing.T) {
    61  	tests := []struct {
    62  		name          string
    63  		entries       []zapcore.Entry
    64  		initialFields []zapcore.Field
    65  		withChains    [][]zapcore.Field
    66  		wantLogs      []observer.LoggedEntry
    67  	}{
    68  		{
    69  			name:     "no logging, no with, inner core with never called, inner core check never called",
    70  			wantLogs: []observer.LoggedEntry{},
    71  		},
    72  		{
    73  			name: "2 logs, 1 dropped, no with, inner core with called once, inner core check never called",
    74  			entries: []zapcore.Entry{
    75  				{Level: zapcore.DebugLevel, Message: "log-at-debug"},
    76  				{Level: zapcore.WarnLevel, Message: "log-at-warn"},
    77  			},
    78  			wantLogs: []observer.LoggedEntry{
    79  				{
    80  					Entry: zapcore.Entry{
    81  						Level:   zapcore.WarnLevel,
    82  						Message: "log-at-warn",
    83  					},
    84  					Context: []zapcore.Field{},
    85  				},
    86  			},
    87  		},
    88  		{
    89  			name: "no logs, 2-chained with, inner core with called once, inner core check never called",
    90  			withChains: [][]zapcore.Field{
    91  				{makeInt64Field("a", 11), makeInt64Field("b", 22)},
    92  				{makeInt64Field("c", 33), makeInt64Field("d", 44)},
    93  			},
    94  			wantLogs: []observer.LoggedEntry{},
    95  		},
    96  		{
    97  			name: "2 logs, 1 dropped, 2-chained with, inner core with called once, inner core check never called",
    98  			entries: []zapcore.Entry{
    99  				{Level: zapcore.DebugLevel, Message: "log-at-debug"},
   100  				{Level: zapcore.WarnLevel, Message: "log-at-warn"},
   101  			},
   102  			withChains: [][]zapcore.Field{
   103  				{makeInt64Field("a", 11), makeInt64Field("b", 22)},
   104  				{makeInt64Field("c", 33), makeInt64Field("d", 44)},
   105  			},
   106  			wantLogs: []observer.LoggedEntry{
   107  				{
   108  					Entry: zapcore.Entry{
   109  						Level:   zapcore.WarnLevel,
   110  						Message: "log-at-warn",
   111  					},
   112  					Context: []zapcore.Field{
   113  						makeInt64Field("a", 11),
   114  						makeInt64Field("b", 22),
   115  						makeInt64Field("c", 33),
   116  						makeInt64Field("d", 44),
   117  					},
   118  				},
   119  			},
   120  		},
   121  	}
   122  	for _, tt := range tests {
   123  		t.Run(tt.name, func(t *testing.T) {
   124  			withLazyCore(func(lazy zapcore.Core, proxy *proxyCore, logs *observer.ObservedLogs) {
   125  				checkCounts := func(withCount int64, msg string) {
   126  					assert.Equal(t, withCount, proxy.withCount.Load(), msg)
   127  				}
   128  				checkCounts(0, "expected no with calls because the logger is not used yet")
   129  
   130  				for _, chain := range tt.withChains {
   131  					lazy = lazy.With(chain)
   132  				}
   133  				if len(tt.withChains) > 0 {
   134  					checkCounts(1, "expected with calls because the logger was with-chained")
   135  				} else {
   136  					checkCounts(0, "expected no with calls because the logger is not used yet")
   137  				}
   138  
   139  				for _, ent := range tt.entries {
   140  					if ce := lazy.Check(ent, nil); ce != nil {
   141  						ce.Write()
   142  					}
   143  				}
   144  				if len(tt.entries) > 0 || len(tt.withChains) > 0 {
   145  					checkCounts(1, "expected with calls because the logger had entries or with chains")
   146  				} else {
   147  					checkCounts(0, "expected no with calls because the logger is not used yet")
   148  				}
   149  				assert.Zero(t, proxy.checkCount.Load(), "expected no check calls because the inner core is copied")
   150  				assert.Equal(t, tt.wantLogs, logs.AllUntimed())
   151  			}, tt.initialFields...)
   152  		})
   153  	}
   154  }
   155  

View as plain text