1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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