Skip to content

Commit b95603e

Browse files
authored
test coverage for internal/logger (#229)
* test coverage for internal/logger Signed-off-by: Geoff Flarity <gflarity@nvidia.com>
1 parent 22a9b7e commit b95603e

File tree

1 file changed

+306
-0
lines changed

1 file changed

+306
-0
lines changed
Lines changed: 306 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,306 @@
1+
// /*
2+
// Copyright 2024 The Grove Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
// */
16+
17+
package logger
18+
19+
import (
20+
"testing"
21+
22+
configv1alpha1 "github.com/ai-dynamo/grove/operator/api/config/v1alpha1"
23+
24+
"go.uber.org/zap/zapcore"
25+
)
26+
27+
// TestCreateLogLevelOpts verifies that log level configurations are correctly
28+
// converted to Zap logger options.
29+
func TestCreateLogLevelOpts(t *testing.T) {
30+
tests := []struct {
31+
// name is the test case identifier
32+
name string
33+
// level is the input log level to convert
34+
level configv1alpha1.LogLevel
35+
// wantErr indicates whether an error is expected
36+
wantErr bool
37+
// expectedLevel is the expected Zap level (only checked when wantErr is false)
38+
expectedLevel zapcore.Level
39+
}{
40+
{
41+
// Debug level should map to zapcore.DebugLevel
42+
name: "debug level",
43+
level: configv1alpha1.DebugLevel,
44+
wantErr: false,
45+
expectedLevel: zapcore.DebugLevel,
46+
},
47+
{
48+
// Info level should map to zapcore.InfoLevel
49+
name: "info level",
50+
level: configv1alpha1.InfoLevel,
51+
wantErr: false,
52+
expectedLevel: zapcore.InfoLevel,
53+
},
54+
{
55+
// Empty string should default to info level
56+
name: "empty level defaults to info",
57+
level: "",
58+
wantErr: false,
59+
expectedLevel: zapcore.InfoLevel,
60+
},
61+
{
62+
// Error level should map to zapcore.ErrorLevel
63+
name: "error level",
64+
level: configv1alpha1.ErrorLevel,
65+
wantErr: false,
66+
expectedLevel: zapcore.ErrorLevel,
67+
},
68+
{
69+
// Invalid log level should return an error
70+
name: "invalid level",
71+
level: "invalid",
72+
wantErr: true,
73+
},
74+
}
75+
76+
for _, tt := range tests {
77+
t.Run(tt.name, func(t *testing.T) {
78+
opts, err := createLogLevelOpts(tt.level)
79+
if (err != nil) != tt.wantErr {
80+
t.Errorf("createLogLevelOpts() error = %v, wantErr %v", err, tt.wantErr)
81+
return
82+
}
83+
if !tt.wantErr && opts == nil {
84+
t.Errorf("createLogLevelOpts() returned nil opts without error")
85+
}
86+
})
87+
}
88+
}
89+
90+
// TestCreateLogFormatOpts verifies that log format configurations are correctly
91+
// converted to Zap logger options.
92+
func TestCreateLogFormatOpts(t *testing.T) {
93+
tests := []struct {
94+
// name is the test case identifier
95+
name string
96+
// format is the input log format to convert
97+
format configv1alpha1.LogFormat
98+
// wantErr indicates whether an error is expected
99+
wantErr bool
100+
}{
101+
{
102+
// JSON format should return JSON encoder options
103+
name: "json format",
104+
format: configv1alpha1.LogFormatJSON,
105+
wantErr: false,
106+
},
107+
{
108+
// Empty string should default to JSON format
109+
name: "empty format defaults to json",
110+
format: "",
111+
wantErr: false,
112+
},
113+
{
114+
// Text format should return console encoder options
115+
name: "text format",
116+
format: configv1alpha1.LogFormatText,
117+
wantErr: false,
118+
},
119+
{
120+
// Invalid log format should return an error
121+
name: "invalid format",
122+
format: "invalid",
123+
wantErr: true,
124+
},
125+
}
126+
127+
for _, tt := range tests {
128+
t.Run(tt.name, func(t *testing.T) {
129+
opts, err := createLogFormatOpts(tt.format)
130+
if (err != nil) != tt.wantErr {
131+
t.Errorf("createLogFormatOpts() error = %v, wantErr %v", err, tt.wantErr)
132+
return
133+
}
134+
if !tt.wantErr && opts == nil {
135+
t.Errorf("createLogFormatOpts() returned nil opts without error")
136+
}
137+
})
138+
}
139+
}
140+
141+
// TestBuildDefaultLoggerOpts verifies that logger options are correctly built
142+
// from configuration parameters.
143+
func TestBuildDefaultLoggerOpts(t *testing.T) {
144+
tests := []struct {
145+
// name is the test case identifier
146+
name string
147+
// devMode specifies whether development mode is enabled
148+
devMode bool
149+
// level is the log level configuration
150+
level configv1alpha1.LogLevel
151+
// format is the log format configuration
152+
format configv1alpha1.LogFormat
153+
// wantErr indicates whether an error is expected
154+
wantErr bool
155+
}{
156+
{
157+
// Production configuration with info level and JSON format
158+
name: "production mode with info level and json format",
159+
devMode: false,
160+
level: configv1alpha1.InfoLevel,
161+
format: configv1alpha1.LogFormatJSON,
162+
wantErr: false,
163+
},
164+
{
165+
// Development configuration with debug level and text format
166+
name: "dev mode with debug level and text format",
167+
devMode: true,
168+
level: configv1alpha1.DebugLevel,
169+
format: configv1alpha1.LogFormatText,
170+
wantErr: false,
171+
},
172+
{
173+
// Configuration with error level
174+
name: "error level configuration",
175+
devMode: false,
176+
level: configv1alpha1.ErrorLevel,
177+
format: configv1alpha1.LogFormatJSON,
178+
wantErr: false,
179+
},
180+
{
181+
// Default values (empty strings) should work
182+
name: "default values",
183+
devMode: false,
184+
level: "",
185+
format: "",
186+
wantErr: false,
187+
},
188+
{
189+
// Invalid log level should cause an error
190+
name: "invalid log level",
191+
devMode: false,
192+
level: "invalid",
193+
format: configv1alpha1.LogFormatJSON,
194+
wantErr: true,
195+
},
196+
{
197+
// Invalid log format should cause an error
198+
name: "invalid log format",
199+
devMode: false,
200+
level: configv1alpha1.InfoLevel,
201+
format: "invalid",
202+
wantErr: true,
203+
},
204+
}
205+
206+
for _, tt := range tests {
207+
t.Run(tt.name, func(t *testing.T) {
208+
opts, err := buildDefaultLoggerOpts(tt.devMode, tt.level, tt.format)
209+
if (err != nil) != tt.wantErr {
210+
t.Errorf("buildDefaultLoggerOpts() error = %v, wantErr %v", err, tt.wantErr)
211+
return
212+
}
213+
if !tt.wantErr {
214+
if opts == nil {
215+
t.Errorf("buildDefaultLoggerOpts() returned nil opts without error")
216+
}
217+
// Verify that we get the expected number of options (3: devMode, format, level)
218+
if len(opts) != 3 {
219+
t.Errorf("buildDefaultLoggerOpts() returned %d opts, expected 3", len(opts))
220+
}
221+
}
222+
})
223+
}
224+
}
225+
226+
// TestMustNewLogger verifies that MustNewLogger correctly creates a logger
227+
// with valid inputs and panics with invalid inputs.
228+
func TestMustNewLogger(t *testing.T) {
229+
tests := []struct {
230+
// name is the test case identifier
231+
name string
232+
// devMode specifies whether development mode is enabled
233+
devMode bool
234+
// level is the log level configuration
235+
level configv1alpha1.LogLevel
236+
// format is the log format configuration
237+
format configv1alpha1.LogFormat
238+
// wantPanic indicates whether a panic is expected
239+
wantPanic bool
240+
}{
241+
{
242+
// Valid production configuration should create logger successfully
243+
name: "valid production configuration",
244+
devMode: false,
245+
level: configv1alpha1.InfoLevel,
246+
format: configv1alpha1.LogFormatJSON,
247+
wantPanic: false,
248+
},
249+
{
250+
// Valid development configuration should create logger successfully
251+
name: "valid development configuration",
252+
devMode: true,
253+
level: configv1alpha1.DebugLevel,
254+
format: configv1alpha1.LogFormatText,
255+
wantPanic: false,
256+
},
257+
{
258+
// Valid configuration with error level
259+
name: "valid configuration with error level",
260+
devMode: false,
261+
level: configv1alpha1.ErrorLevel,
262+
format: configv1alpha1.LogFormatJSON,
263+
wantPanic: false,
264+
},
265+
{
266+
// Default values should work
267+
name: "default values",
268+
devMode: false,
269+
level: "",
270+
format: "",
271+
wantPanic: false,
272+
},
273+
{
274+
// Invalid log level should cause panic
275+
name: "invalid log level causes panic",
276+
devMode: false,
277+
level: "invalid",
278+
format: configv1alpha1.LogFormatJSON,
279+
wantPanic: true,
280+
},
281+
{
282+
// Invalid log format should cause panic
283+
name: "invalid log format causes panic",
284+
devMode: false,
285+
level: configv1alpha1.InfoLevel,
286+
format: "invalid",
287+
wantPanic: true,
288+
},
289+
}
290+
291+
for _, tt := range tests {
292+
t.Run(tt.name, func(t *testing.T) {
293+
defer func() {
294+
r := recover()
295+
if (r != nil) != tt.wantPanic {
296+
t.Errorf("MustNewLogger() panic = %v, wantPanic %v", r != nil, tt.wantPanic)
297+
}
298+
}()
299+
300+
logger := MustNewLogger(tt.devMode, tt.level, tt.format)
301+
if !tt.wantPanic && logger.GetSink() == nil {
302+
t.Errorf("MustNewLogger() returned logger with nil sink")
303+
}
304+
})
305+
}
306+
}

0 commit comments

Comments
 (0)