1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package zapcore
22
23 import (
24 "sync"
25 "testing"
26
27 "go.uber.org/zap/internal/exit"
28
29 "github.com/stretchr/testify/assert"
30 )
31
32 func assertGoexit(t *testing.T, f func()) {
33 var finished bool
34 recovered := make(chan interface{})
35 go func() {
36 defer func() {
37 recovered <- recover()
38 }()
39
40 f()
41 finished = true
42 }()
43
44 assert.Nil(t, <-recovered, "Goexit should cause recover to return nil")
45 assert.False(t, finished, "Goroutine should not finish after Goexit")
46 }
47
48 func TestPutNilEntry(t *testing.T) {
49
50 var wg sync.WaitGroup
51 wg.Add(2)
52
53 go func() {
54 defer wg.Done()
55 for i := 0; i < 1000; i++ {
56 putCheckedEntry(nil)
57 }
58 }()
59
60 go func() {
61 defer wg.Done()
62 for i := 0; i < 1000; i++ {
63 ce := getCheckedEntry()
64 assert.NotNil(t, ce, "Expected only non-nil CheckedEntries in pool.")
65 assert.False(t, ce.dirty, "Unexpected dirty bit set.")
66 assert.Nil(t, ce.ErrorOutput, "Non-nil ErrorOutput.")
67 assert.Nil(t, ce.after, "Unexpected terminal behavior.")
68 assert.Equal(t, 0, len(ce.cores), "Expected empty slice of cores.")
69 assert.True(t, cap(ce.cores) > 0, "Expected pooled CheckedEntries to pre-allocate slice of Cores.")
70 }
71 }()
72
73 wg.Wait()
74 }
75
76 func TestEntryCaller(t *testing.T) {
77 tests := []struct {
78 caller EntryCaller
79 full string
80 short string
81 }{
82 {
83 caller: NewEntryCaller(100, "/path/to/foo.go", 42, false),
84 full: "undefined",
85 short: "undefined",
86 },
87 {
88 caller: NewEntryCaller(100, "/path/to/foo.go", 42, true),
89 full: "/path/to/foo.go:42",
90 short: "to/foo.go:42",
91 },
92 {
93 caller: NewEntryCaller(100, "to/foo.go", 42, true),
94 full: "to/foo.go:42",
95 short: "to/foo.go:42",
96 },
97 }
98
99 for _, tt := range tests {
100 assert.Equal(t, tt.full, tt.caller.String(), "Unexpected string from EntryCaller.")
101 assert.Equal(t, tt.full, tt.caller.FullPath(), "Unexpected FullPath from EntryCaller.")
102 assert.Equal(t, tt.short, tt.caller.TrimmedPath(), "Unexpected TrimmedPath from EntryCaller.")
103 }
104 }
105
106 func TestCheckedEntryWrite(t *testing.T) {
107 t.Run("nil is safe", func(t *testing.T) {
108 var ce *CheckedEntry
109 assert.NotPanics(t, func() { ce.Write() }, "Unexpected panic writing nil CheckedEntry.")
110 })
111
112 t.Run("WriteThenPanic", func(t *testing.T) {
113 var ce *CheckedEntry
114 ce = ce.After(Entry{}, WriteThenPanic)
115 assert.Panics(t, func() { ce.Write() }, "Expected to panic when WriteThenPanic is set.")
116 })
117
118 t.Run("WriteThenGoexit", func(t *testing.T) {
119 var ce *CheckedEntry
120 ce = ce.After(Entry{}, WriteThenGoexit)
121 assertGoexit(t, func() { ce.Write() })
122 })
123
124 t.Run("WriteThenFatal", func(t *testing.T) {
125 var ce *CheckedEntry
126 ce = ce.After(Entry{}, WriteThenFatal)
127 stub := exit.WithStub(func() {
128 ce.Write()
129 })
130 assert.True(t, stub.Exited, "Expected to exit when WriteThenFatal is set.")
131 assert.Equal(t, 1, stub.Code, "Expected to exit when WriteThenFatal is set.")
132 })
133
134 t.Run("After", func(t *testing.T) {
135 var ce *CheckedEntry
136 hook := &customHook{}
137 ce = ce.After(Entry{}, hook)
138 ce.Write()
139 assert.True(t, hook.called, "Expected to call custom action after Write.")
140 })
141 }
142
143 type customHook struct {
144 called bool
145 }
146
147 func (c *customHook) OnWrite(_ *CheckedEntry, _ []Field) {
148 c.called = true
149 }
150
View as plain text