-
Notifications
You must be signed in to change notification settings - Fork 30
/
args_test.go
336 lines (288 loc) · 10 KB
/
args_test.go
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
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//go:build unit
// +build unit
package main
import (
"fmt"
"math"
"os"
"reflect"
"testing"
"time"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
"gotest.tools/assert"
)
const (
testContainerID = "test-container-id"
testContainerName = "test-container-name"
testLogDriver = "test-log-driver"
testContainerImageName = "test-container-image-name"
testContainerImageID = "test-container-image-id"
testContainerLabels = "{\"label0\":\"labelValue0\",\"label1\":\"labelValue1\"}"
testContainerEnv = "{\"env0\":\"envValue0\",\"env1\":\"envValue1\"}"
)
var (
testContainerLabelsMap = map[string]string{
"label0": "labelValue0",
"label1": "labelValue1",
}
testContainerEnvSlice = [2]string{
"env0=envValue0",
"env1=envValue1",
}
)
// TestGetGlobalArgs tests getGlobalArgs with/without correct settings of
// flag values.
func TestGetGlobalArgs(t *testing.T) {
t.Run("NoError", testGetGlobalArgsNoError)
t.Run("WithError", testGetGlobalArgsWithError)
}
// testGetGlobalArgsNoError is a sub-test of TestGetGlobalArgs. It tests
// getGlobalArgs function with no returned errors.
func testGetGlobalArgsNoError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
viper.Set(containerIDKey, testContainerID)
viper.Set(containerNameKey, testContainerName)
viper.Set(logDriverTypeKey, testLogDriver)
args, err := getGlobalArgs()
require.NoError(t, err)
assert.Equal(t, args.ContainerID, testContainerID)
assert.Equal(t, args.ContainerName, testContainerName)
assert.Equal(t, args.LogDriver, testLogDriver)
assert.Equal(t, args.Mode, blockingMode)
assert.Equal(t, args.MaxBufferSize, 0)
assert.Equal(t, *args.CleanupTime, 5*time.Second)
}
// testGetGlobalArgsWithError is a sub-test of TestGetGlobalArgs. It tests
// getGlobalArgs function with returned errors when required flag values are
// missed. Since the logic in getGlobalArgs is examining required flag values
// one by one in this order:
//
// container-id, container-name, log-driver,
//
// in this test, we will set flag one by one in the previous order to examine if
// each value check worked as expected.
func testGetGlobalArgsWithError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesWithError := []struct {
keyToSet string
valToSet string
}{
{containerIDKey, testContainerID},
{containerNameKey, testContainerName},
{logDriverTypeKey, testLogDriver},
}
for _, tc := range testCasesWithError {
_, err := getGlobalArgs()
require.Error(t, err)
require.Contains(t,
err.Error(),
fmt.Sprintf("%s is required", tc.keyToSet),
)
viper.Set(tc.keyToSet, tc.valToSet)
}
}
// TestGetModeAndMaxBufferSize tests getModeAndMaxBufferSize with/without correct
// settings of mode.
func TestGetModeAndMaxBufferSize(t *testing.T) {
t.Run("NoError", testGetModeAndMaxBufferSizeNoError)
t.Run("WithError", testGetModeAndMaxBufferSizeWithError)
}
// testGetModeAndMaxBufferSizeNoError is a sub-test of TestGetModeAndMaxBufferSize.
// It tests different valid values set for mode option.
func testGetModeAndMaxBufferSizeNoError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesNoError := []struct {
mode string
expectedMode string
expectedBufferSize int
}{
{"", blockingMode, 0},
{blockingMode, blockingMode, 0},
{nonBlockingMode, nonBlockingMode, int(math.Pow(2, 20))},
}
for _, tc := range testCasesNoError {
viper.Set(modeKey, tc.mode)
mode, maxBufferSize, err := getModeAndMaxBufferSize()
require.NoError(t, err)
require.Equal(t, tc.expectedMode, mode)
require.Equal(t, tc.expectedBufferSize, maxBufferSize)
}
}
// testGetModeAndMaxBufferSizeNoError is a sub-test of TestGetModeAndMaxBufferSize. It
// tests invalid values set for mode option.
func testGetModeAndMaxBufferSizeWithError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
viper.Set(modeKey, "test-mode")
_, _, err := getModeAndMaxBufferSize()
require.Error(t, err)
}
// TestGetMaxBufferSize tests getMaxBufferSize with/without valid setting max buffer
// size options.
func TestGetMaxBufferSize(t *testing.T) {
t.Run("NoError", testGetMaxBufferSizeNoError)
t.Run("WithError", testGetMaxBufferSizeWithError)
}
// testGetMaxBufferSizeNoError is a sub-test of TestGetMaxBufferSize. It tests
// getMaxBufferSize with multiple valid user-set values.
func testGetMaxBufferSizeNoError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesNoError := []struct {
bufferSize string
expectedBufferSize int
}{
{"", int(math.Pow(2, 20))},
{"2m", int(math.Pow(2, 21))},
{"4k", int(math.Pow(2, 12))},
{"1234", 1234},
}
for _, tc := range testCasesNoError {
viper.Set(maxBufferSizeKey, tc.bufferSize)
size, err := getMaxBufferSize()
require.NoError(t, err)
require.Equal(t, tc.expectedBufferSize, size)
}
}
// testGetMaxBufferSizeWithError is a sub-test of TestGetMaxBufferSize. It tests
// getMaxBufferSize with multiple invalid user-set values.
func testGetMaxBufferSizeWithError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesWithError := []struct {
bufferSize string
}{
{"3q"},
{"-1"},
}
for _, tc := range testCasesWithError {
viper.Set(maxBufferSizeKey, tc.bufferSize)
_, err := getMaxBufferSize()
require.Error(t, err)
}
}
// TestGetCleanupTime tests getCleanupTime with/without valid setting cleanup time options.
func TestGetCleanupTime(t *testing.T) {
t.Run("NoError", testGetCleanupTimeNoError)
t.Run("WithError", testGetCleanupTimeWithError)
}
// testGetCleanupTimeNoError is a sub-test of TestGetCleanupTime. It tests getCleanupTime
// with multiple valid user-set values.
func testGetCleanupTimeNoError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesNoError := []struct {
cleanupTime string
expectedCleanupTime time.Duration
}{
{"3s", 3 * time.Second},
{"10s", 10 * time.Second},
{"12s", 12 * time.Second},
}
for _, tc := range testCasesNoError {
viper.Set(cleanupTimeKey, tc.cleanupTime)
cleanupTime, err := getCleanupTime()
require.NoError(t, err)
require.Equal(t, tc.expectedCleanupTime, *cleanupTime)
}
}
// testGetCleanupTimeWithError is a sub-test of TestGetCleanupTime. It tests getCleanupTime
// with multiple invalid user-set values.
func testGetCleanupTimeWithError(t *testing.T) {
// Unset all keys used for this test
defer viper.Reset()
testCasesWithError := []struct {
cleanupTime string
}{
{"3"},
{"15s"},
}
for _, tc := range testCasesWithError {
viper.Set(cleanupTimeKey, tc.cleanupTime)
_, err := getCleanupTime()
require.Error(t, err)
}
}
// TestGetDockerConfigs tests that we can correctly get the docker config input parameters.
func TestGetDockerConfigs(t *testing.T) {
t.Run("NoError", testGetDockerConfigsNoError)
t.Run("Empty", testGetDockerConfigsEmpty)
t.Run("WithError", testGetDockerConfigsWithError)
}
// testGetDockerConfigsNoError tests that the correctly formatted input can be parsed without error.
func testGetDockerConfigsNoError(t *testing.T) {
defer viper.Reset()
viper.Set(ContainerImageNameKey, testContainerImageName)
viper.Set(ContainerImageIDKey, testContainerImageID)
viper.Set(ContainerLabelsKey, testContainerLabels)
viper.Set(ContainerEnvKey, testContainerEnv)
args, err := getDockerConfigs()
require.NoError(t, err)
assert.Equal(t, testContainerImageName, args.ContainerImageName)
assert.Equal(t, testContainerImageID, args.ContainerImageID)
assert.Equal(t, true, reflect.DeepEqual(args.ContainerLabels, testContainerLabelsMap))
// Docker logging use a slice to store the environment variables
// Each item is in the format of "key=value" the unit test should
// convert it back to a map to guarantee content exists but disregard
// the order.
// ref: https://github.com/moby/moby/blob/c833222d54c00d64a0fc44c561a5973ecd414053/daemon/logger/loginfo.go#L60
testContainerEnvMap := make(map[string]struct{})
for _, v := range testContainerEnvSlice {
testContainerEnvMap[v] = struct{}{}
}
argsContainerEnvMap := make(map[string]struct{})
for _, v := range args.ContainerEnv {
argsContainerEnvMap[v] = struct{}{}
}
assert.Equal(t, true, reflect.DeepEqual(testContainerEnvMap, argsContainerEnvMap))
}
// testGetDockerConfigsEmpty tests that empty docker config input parameter generates no error.
func testGetDockerConfigsEmpty(t *testing.T) {
defer viper.Reset()
_, err := getDockerConfigs()
require.NoError(t, err)
}
// testGetDockerConfigsWithError tests that malformat docker config results in an error.
func testGetDockerConfigsWithError(t *testing.T) {
defer viper.Reset()
testCaseWithError := "{invalidJsonMap"
viper.Set(ContainerLabelsKey, testCaseWithError)
viper.Set(ContainerEnvKey, testCaseWithError)
_, err := getDockerConfigs()
require.Error(t, err)
}
// TestIsFlagPassed tests that we are correctly determining whether a flag is passed or not.
// Do not parallelize this test (or any test which interacts with flag parsing and OS args).
func TestIsFlagPassed(t *testing.T) {
t.Run("No", testIsFlagPassedNo)
t.Run("Yes", testIsFlagPassedYes)
}
// testIsFlagPassedNo creates a flag but doesn't pass it, and confirms that we don't interpret it to be set.
func testIsFlagPassedNo(t *testing.T) {
defer func() {
pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
}()
pflag.String("test-flag", "", "test flag description")
pflag.Parse()
require.False(t, isFlagPassed("test-flag"))
}
// testIsFlagPassedYes creates a flag and mimics it being passed. Then, it confirms the flag was passed.
func testIsFlagPassedYes(t *testing.T) {
defer func() {
os.Args = os.Args[:len(os.Args)-1]
pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
}()
testFlag := "test-flag"
pflag.String(testFlag, "", "test flag description")
// pass the flag via os.Args
os.Args = append(os.Args, "--"+testFlag+"=")
pflag.Parse()
require.True(t, isFlagPassed("test-flag"))
}