1
16
17 package v1
18
19 import (
20 "bytes"
21 "context"
22 "flag"
23 "testing"
24
25 "github.com/go-logr/logr"
26 "github.com/spf13/pflag"
27 "github.com/stretchr/testify/assert"
28 "github.com/stretchr/testify/require"
29
30 "k8s.io/apimachinery/pkg/util/validation/field"
31 "k8s.io/component-base/featuregate"
32 "k8s.io/klog/v2"
33 )
34
35 func TestReapply(t *testing.T) {
36 oldReapplyHandling := ReapplyHandling
37 defer func() {
38 ReapplyHandling = oldReapplyHandling
39 if err := ResetForTest(nil ); err != nil {
40 t.Errorf("Unexpected error resetting the logging configuration: %v", err)
41 }
42 }()
43
44 newOptions := NewLoggingConfiguration()
45 if err := ValidateAndApply(newOptions, nil); err != nil {
46 t.Errorf("unexpected error for first ValidateAndApply: %v", err)
47 }
48 ReapplyHandling = ReapplyHandlingError
49 if err := ValidateAndApply(newOptions, nil); err == nil {
50 t.Error("did not get expected error for second ValidateAndApply")
51 }
52 ReapplyHandling = ReapplyHandlingIgnoreUnchanged
53 if err := ValidateAndApply(newOptions, nil); err != nil {
54 t.Errorf("unexpected error for third ValidateAndApply: %v", err)
55 }
56 modifiedOptions := newOptions.DeepCopy()
57 modifiedOptions.Verbosity = 100
58 if err := ValidateAndApply(modifiedOptions, nil); err == nil {
59 t.Errorf("unexpected success for forth ValidateAndApply, should have complained about modified config")
60 }
61 }
62
63 func TestOptions(t *testing.T) {
64 newOptions := NewLoggingConfiguration()
65 testcases := []struct {
66 name string
67 args []string
68 want *LoggingConfiguration
69 errs field.ErrorList
70 }{
71 {
72 name: "Default log format",
73 want: newOptions.DeepCopy(),
74 },
75 {
76 name: "Text log format",
77 args: []string{"--logging-format=text"},
78 want: newOptions.DeepCopy(),
79 },
80 {
81 name: "Unsupported log format",
82 args: []string{"--logging-format=test"},
83 want: func() *LoggingConfiguration {
84 c := newOptions.DeepCopy()
85 c.Format = "test"
86 return c
87 }(),
88 errs: field.ErrorList{&field.Error{
89 Type: "FieldValueInvalid",
90 Field: "format",
91 BadValue: "test",
92 Detail: "Unsupported log format",
93 }},
94 },
95 }
96
97 for _, tc := range testcases {
98 t.Run(tc.name, func(t *testing.T) {
99 c := NewLoggingConfiguration()
100 fs := pflag.NewFlagSet("addflagstest", pflag.ContinueOnError)
101 AddFlags(c, fs)
102 fs.Parse(tc.args)
103 if !assert.Equal(t, tc.want, c) {
104 t.Errorf("Wrong Validate() result for %q. expect %v, got %v", tc.name, tc.want, c)
105 }
106 defer func() {
107 if err := ResetForTest(nil ); err != nil {
108 t.Errorf("Unexpected error resetting the logging configuration: %v", err)
109 }
110 }()
111 errs := ValidateAndApply(c, nil )
112 defer klog.StopFlushDaemon()
113 if !assert.ElementsMatch(t, tc.errs, errs) {
114 t.Errorf("Wrong Validate() result for %q.\n expect:\t%+v\n got:\t%+v", tc.name, tc.errs, errs)
115 }
116 })
117 }
118 }
119
120 func TestFlagSet(t *testing.T) {
121 t.Run("pflag", func(t *testing.T) {
122 newOptions := NewLoggingConfiguration()
123 var fs pflag.FlagSet
124 AddFlags(newOptions, &fs)
125 var buffer bytes.Buffer
126 fs.SetOutput(&buffer)
127 fs.PrintDefaults()
128
129
130
131
132
133
134
135 assert.Regexp(t, `^.*--logging-format.*default.*text.*
136 .*--log-flush-frequency.*default 5s.*
137 .*-v.*--v.*
138 .*--vmodule.*pattern=N.*
139 .*--log-text-split-stream.*
140 .*--log-text-info-buffer-size quantity.*
141 $`, buffer.String())
142 })
143
144 t.Run("flag", func(t *testing.T) {
145 newOptions := NewLoggingConfiguration()
146 var pfs pflag.FlagSet
147 AddFlags(newOptions, &pfs)
148 var fs flag.FlagSet
149 pfs.VisitAll(func(f *pflag.Flag) {
150 fs.Var(f.Value, f.Name, f.Usage)
151 })
152 var buffer bytes.Buffer
153 fs.SetOutput(&buffer)
154 fs.PrintDefaults()
155
156
157
158
159
160
161
162
163
164
165
166
167
168 assert.Regexp(t, `^.*-log-flush-frequency.*
169 .*default 5s.*
170 .*-log-text-info-buffer-size.*
171 .*
172 .*-log-text-split-stream.*
173 .*
174 .*-logging-format.*
175 .*default.*text.*
176 .*-v.*
177 .*
178 .*-vmodule.*
179 .*
180 $`, buffer.String())
181 })
182
183 t.Run("AddGoFlags", func(t *testing.T) {
184 newOptions := NewLoggingConfiguration()
185 var fs flag.FlagSet
186 var buffer bytes.Buffer
187 AddGoFlags(newOptions, &fs)
188 fs.SetOutput(&buffer)
189 fs.PrintDefaults()
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 assert.Regexp(t, `^.*-log-flush-frequency.*duration.*
205 .*default 5s.*
206 .*-log-text-info-buffer-size.*
207 .*
208 .*-log-text-split-stream.*
209 .*
210 .*-logging-format.*string.*
211 .*default.*text.*
212 .*-v.*
213 .*
214 .*-vmodule.*
215 .*
216 $`, buffer.String())
217 })
218 }
219
220 func TestContextualLogging(t *testing.T) {
221 t.Run("enabled", func(t *testing.T) {
222 testContextualLogging(t, true)
223 })
224
225 t.Run("disabled", func(t *testing.T) {
226 testContextualLogging(t, false)
227 })
228 }
229
230 func testContextualLogging(t *testing.T, enabled bool) {
231 var err error
232
233 c := NewLoggingConfiguration()
234 featureGate := featuregate.NewFeatureGate()
235 AddFeatureGates(featureGate)
236 err = featureGate.SetFromMap(map[string]bool{string(ContextualLogging): enabled})
237 require.NoError(t, err)
238 defer func() {
239 if err := ResetForTest(nil ); err != nil {
240 t.Errorf("Unexpected error resetting the logging configuration: %v", err)
241 }
242 }()
243 err = ValidateAndApply(c, featureGate)
244 require.NoError(t, err)
245 defer klog.StopFlushDaemon()
246 defer klog.EnableContextualLogging(true)
247
248 ctx := context.Background()
249
250 logger := klog.NewKlogr().WithName("contextual")
251
252 ctx = logr.NewContext(ctx, logger)
253 if enabled {
254 assert.Equal(t, logger, klog.FromContext(ctx), "FromContext")
255 assert.NotEqual(t, ctx, klog.NewContext(ctx, logger), "NewContext")
256 assert.NotEqual(t, logger, klog.LoggerWithName(logger, "foo"), "LoggerWithName")
257 assert.NotEqual(t, logger, klog.LoggerWithValues(logger, "x", "y"), "LoggerWithValues")
258 } else {
259 assert.NotEqual(t, logger, klog.FromContext(ctx), "FromContext")
260 assert.Equal(t, ctx, klog.NewContext(ctx, logger), "NewContext")
261 assert.Equal(t, logger, klog.LoggerWithName(logger, "foo"), "LoggerWithName")
262 assert.Equal(t, logger, klog.LoggerWithValues(logger, "x", "y"), "LoggerWithValues")
263 }
264 }
265
View as plain text