-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger_test.go
More file actions
249 lines (217 loc) · 6.21 KB
/
logger_test.go
File metadata and controls
249 lines (217 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package comet
import (
"bytes"
"context"
"fmt"
"log/slog"
"strings"
"testing"
)
// TestLogger is a logger implementation for testing that captures output
type TestLogger struct {
level LogLevel
buffer *bytes.Buffer
t *testing.T
}
// NewTestLogger creates a new test logger that captures output
func NewTestLogger(t *testing.T, level LogLevel) *TestLogger {
return &TestLogger{
level: level,
buffer: &bytes.Buffer{},
t: t,
}
}
// Contains checks if the captured output contains the given string
func (tl *TestLogger) Contains(text string) bool {
return strings.Contains(tl.buffer.String(), text)
}
// Reset clears the captured output
func (tl *TestLogger) Reset() {
tl.buffer.Reset()
}
// String returns all captured output
func (tl *TestLogger) String() string {
return tl.buffer.String()
}
// Logger interface implementation
func (tl *TestLogger) Debug(msg string, keysAndValues ...any) {
if tl.level <= LogLevelDebug {
tl.log("DEBUG", msg, keysAndValues...)
}
}
func (tl *TestLogger) Info(msg string, keysAndValues ...any) {
if tl.level <= LogLevelInfo {
tl.log("INFO", msg, keysAndValues...)
}
}
func (tl *TestLogger) Warn(msg string, keysAndValues ...any) {
if tl.level <= LogLevelWarn {
tl.log("WARN", msg, keysAndValues...)
}
}
func (tl *TestLogger) Error(msg string, keysAndValues ...any) {
if tl.level <= LogLevelError {
tl.log("ERROR", msg, keysAndValues...)
}
}
func (tl *TestLogger) WithContext(ctx context.Context) Logger {
return tl // Simple implementation for tests
}
func (tl *TestLogger) WithFields(keysAndValues ...any) Logger {
// For simplicity, return same logger - could be enhanced if needed
return tl
}
func (tl *TestLogger) log(level, msg string, keysAndValues ...any) {
fmt.Fprintf(tl.buffer, "[%s] %s", level, msg)
for i := 0; i < len(keysAndValues); i += 2 {
if i+1 < len(keysAndValues) {
fmt.Fprintf(tl.buffer, " %v=%v", keysAndValues[i], keysAndValues[i+1])
}
}
fmt.Fprintln(tl.buffer)
}
func TestNoOpLogger(t *testing.T) {
logger := NoOpLogger{}
// These should not panic
logger.Debug("debug message")
logger.Info("info message", "key", "value")
logger.Warn("warn message", "count", 42)
logger.Error("error message", "error", "something went wrong")
// Test context and fields
ctxLogger := logger.WithContext(context.Background())
if ctxLogger != logger {
t.Error("WithContext should return same NoOpLogger")
}
fieldLogger := logger.WithFields("field1", "value1")
if fieldLogger != logger {
t.Error("WithFields should return same NoOpLogger")
}
}
func TestStdLogger(t *testing.T) {
var buf bytes.Buffer
logger := &StdLogger{
level: LogLevelInfo,
writer: &buf,
}
// Debug should not output (below level)
logger.Debug("debug message")
if buf.Len() > 0 {
t.Error("Debug message should not be logged at Info level")
}
// Info should output
logger.Info("info message")
output := buf.String()
if !strings.Contains(output, "[INFO] info message") {
t.Errorf("Expected info message, got: %s", output)
}
buf.Reset()
// Test with fields
logger.Warn("warning", "code", 404, "message", "not found")
output = buf.String()
if !strings.Contains(output, "[WARN] warning") {
t.Errorf("Expected warning message, got: %s", output)
}
if !strings.Contains(output, "code=404") {
t.Errorf("Expected code field, got: %s", output)
}
if !strings.Contains(output, "message=not found") {
t.Errorf("Expected message field, got: %s", output)
}
buf.Reset()
// Test WithFields
fieldLogger := logger.WithFields("request_id", "123")
fieldLogger.Error("request failed", "status", 500)
output = buf.String()
if !strings.Contains(output, "request_id=123") {
t.Errorf("Expected request_id field, got: %s", output)
}
if !strings.Contains(output, "status=500") {
t.Errorf("Expected status field, got: %s", output)
}
}
func TestSlogAdapter(t *testing.T) {
var buf bytes.Buffer
handler := slog.NewTextHandler(&buf, &slog.HandlerOptions{
Level: slog.LevelInfo,
})
slogger := slog.New(handler)
adapter := NewSlogAdapter(slogger)
// Test basic logging
adapter.Info("slog test message", "key", "value")
output := buf.String()
if !strings.Contains(output, "slog test message") {
t.Errorf("Expected message in output, got: %s", output)
}
if !strings.Contains(output, "key=value") {
t.Errorf("Expected key=value in output, got: %s", output)
}
buf.Reset()
// Test WithFields
fieldAdapter := adapter.WithFields("service", "comet")
fieldAdapter.Warn("warning from service", "code", 429)
output = buf.String()
if !strings.Contains(output, "service=comet") {
t.Errorf("Expected service field, got: %s", output)
}
if !strings.Contains(output, "code=429") {
t.Errorf("Expected code field, got: %s", output)
}
}
func TestCreateLogger(t *testing.T) {
tests := []struct {
name string
config LogConfig
expectType string
}{
{
name: "none level returns NoOpLogger",
config: LogConfig{Level: "none"},
expectType: "NoOpLogger",
},
{
name: "off level returns NoOpLogger",
config: LogConfig{Level: "off"},
expectType: "NoOpLogger",
},
{
name: "debug level returns StdLogger",
config: LogConfig{Level: "debug"},
expectType: "*StdLogger",
},
{
name: "custom logger",
config: LogConfig{Logger: NoOpLogger{}},
expectType: "NoOpLogger",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
logger := createLogger(tt.config)
typeName := fmt.Sprintf("%T", logger)
if !strings.Contains(typeName, strings.TrimPrefix(tt.expectType, "*")) {
t.Errorf("Expected %s, got %s", tt.expectType, typeName)
}
})
}
}
func TestLoggingIntegration(t *testing.T) {
// This test would verify logging integration with Client
// but requires the full package context to run
t.Skip("Integration test - run with full package tests")
}
func TestDebugMode(t *testing.T) {
// Save original state
originalDebug := IsDebug()
defer SetDebug(originalDebug)
// Test SetDebug
SetDebug(true)
if !IsDebug() {
t.Error("Expected debug mode to be enabled")
}
SetDebug(false)
if IsDebug() {
t.Error("Expected debug mode to be disabled")
}
// Test environment variable (tested in init, so we just verify current state)
// Note: Can't easily test init() behavior in unit tests
}