1 package rags
2
3 import (
4 "flag"
5 "fmt"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9 )
10
11 func TestValue_IsBoolFlag(t *testing.T) {
12 t.Parallel()
13
14 tcs := []struct {
15 val flag.Getter
16 isBool bool
17 }{
18 {&Value[bool]{}, true},
19 {&Value[bool]{Var: new(bool)}, true},
20 {&Value[bool]{Default: true}, true},
21 {&Value[int]{}, false},
22 {&Value[int]{Var: new(int)}, false},
23 {&Value[int]{Default: 100}, false},
24 }
25
26 for i, tc := range tcs {
27 i := i
28 tc := tc
29 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) {
30 t.Parallel()
31
32 b, ok := tc.val.(interface{ IsBoolFlag() bool })
33 assert.True(t, ok, "value was expected to implement IsBoolFlag()")
34 if tc.isBool {
35 assert.True(t, b.IsBoolFlag())
36 } else {
37 assert.False(t, b.IsBoolFlag())
38 }
39 })
40 }
41 }
42
43 func TestValue(t *testing.T) {
44 t.Parallel()
45
46 tcs := []struct {
47 ptr *int
48 def int
49 set string
50 }{
51 {},
52 {ptr: new(int)},
53 {def: 100},
54 {ptr: new(int), def: 100},
55 }
56
57 for i, tc := range tcs {
58 i := i
59 tc := tc
60 t.Run(fmt.Sprintf("%s-%d", t.Name(), i), func(t *testing.T) {
61 t.Parallel()
62
63
64 v := NewValueDefault(tc.ptr, tc.def)
65 assert.True(t, v.initialized)
66 assert.NotNil(t, v.Parse)
67 if tc.ptr != nil {
68 assert.Same(t, tc.ptr, v.Var)
69 assert.Equal(t, *tc.ptr, tc.def)
70 }
71 assert.Equal(t, tc.def, *v.Var)
72 assert.Equal(t, tc.def, v.Default)
73
74
75 if tc.set != "" {
76 assert.NoError(t, v.Set(tc.set))
77 assert.Equal(t, tc.set, v.String())
78 parsedVal, _ := v.Parse(tc.set)
79 assert.Equal(t, parsedVal, v.Get())
80 assert.Equal(t, parsedVal, v.Var)
81
82
83 if tc.ptr != nil {
84 assert.Same(t, tc.ptr, v.Var,
85 "pointer used to instantiate flag value is different than values current pointer")
86 assert.Equalf(t, tc.ptr, v.Get(),
87 "pointer used to instantiate flag value references different value than "+
88 "returned by value: want %v, got %v", *tc.ptr, v.Get())
89 }
90 }
91 })
92 }
93 }
94
95 func TestCollections(t *testing.T) {
96 t.Parallel()
97
98 tcs := map[string]struct {
99 def []string
100 set []string
101 expList []string
102 expSet []string
103 }{
104 "one": {
105 set: []string{"prometheus"},
106 expList: []string{"prometheus"},
107 expSet: []string{"prometheus"},
108 },
109 "two": {
110 set: []string{"prometheus", "linkerd"},
111 expList: []string{"prometheus", "linkerd"},
112 expSet: []string{"prometheus", "linkerd"},
113 },
114 "trailing multivalue comma": {
115 set: []string{"prometheus,linkerd,"},
116 expList: []string{"prometheus", "linkerd"},
117 expSet: []string{"prometheus", "linkerd"},
118 },
119 "leading multivalue comma": {
120 set: []string{",prometheus"},
121 expList: []string{"prometheus"},
122 expSet: []string{"prometheus"},
123 },
124 "dupes": {
125 set: []string{"prometheus", "prometheus"},
126 expList: []string{"prometheus", "prometheus"},
127 expSet: []string{"prometheus"},
128 },
129 "blank": {
130 set: []string{""},
131 expList: []string{""},
132 expSet: []string{""},
133 },
134 "blank comma": {
135 set: []string{","},
136 expList: []string{""},
137 expSet: []string{""},
138 },
139 "defaults": {
140 set: []string{"prometheus"},
141 expList: []string{"linkerd", "prometheus"},
142 expSet: []string{"linkerd", "prometheus"},
143 def: []string{"linkerd"},
144 },
145 "defaults duped": {
146 set: []string{"prometheus"},
147 expList: []string{"prometheus", "prometheus"},
148 expSet: []string{"prometheus"},
149 def: []string{"prometheus"},
150 },
151 }
152
153 testCollection := func(t *testing.T, v flag.Getter, set, exp []string) {
154 t.Helper()
155
156 for _, s := range set {
157 assert.NoErrorf(t, v.Set(s), "setting valid value %s should not error", s)
158 }
159 assert.Equalf(t, collectionStringFn(exp), v.String(),
160 "incorrect value after Set(): want %s, got %s",
161 collectionStringFn(exp), v.String(),
162 )
163
164 assert.Equalf(t, exp, v.Get(),
165 "incorrect value after Set(): want %s, got %s",
166 exp, v.Get(),
167 )
168 }
169
170 testPtr := func(t *testing.T, v flag.Getter, ptr, valPtr *[]string) {
171 t.Helper()
172
173 assert.Same(t, ptr, valPtr,
174 "pointer used to instantiate flag value is different than values current pointer")
175
176 vals := v.Get()
177 for i := range *ptr {
178 assert.Equalf(t, (*ptr)[i], (vals.([]string))[i],
179 "pointer used to instantiate flag value references different value than "+
180 "returned by value: want %v, got %v", *ptr, v.Get())
181 }
182 }
183
184 for name, tc := range tcs {
185 tc := tc
186 name := name
187 t.Run(name, func(t *testing.T) {
188 t.Parallel()
189
190
191 t.Run(fmt.Sprintf("%s-List", name), func(t *testing.T) {
192 t.Parallel()
193
194 ptr := &([]string{})
195 v := &StringList{Var: ptr, Default: tc.def}
196 assert.NotPanics(t, func() { v.initialize() },
197 "initializing List should not panic")
198 assert.True(t, v.initialized)
199
200 testCollection(t, v, tc.set, tc.expList)
201 testPtr(t, v, ptr, v.Var)
202 })
203
204
205 t.Run(fmt.Sprintf("%s-Set", name), func(t *testing.T) {
206 t.Parallel()
207
208 ptr := &([]string{})
209 v := &StringSet{Var: ptr, Default: tc.def}
210 assert.NotPanics(t, func() { v.initialize() },
211 "initializing Set should not panic")
212 assert.True(t, v.initialized)
213
214 testCollection(t, v, tc.set, tc.expSet)
215 testPtr(t, v, ptr, v.Var)
216 })
217 })
218 }
219 }
220
221 func TestEnum(t *testing.T) {
222 t.Parallel()
223
224 var s string
225 assert.Panics(t, func() { NewEnum(&s) },
226 "Enum value without any valid values specified should panic")
227 v := NewEnum(&s, "foo", "bar")
228 assert.Equalf(t, "foo", v.Default,
229 "when default value isnt set, default should be first valid value: "+
230 "wanted %s, got %s",
231 "foo", v.Default,
232 )
233
234 v = &StringEnum{Var: &s, Default: "bar", Valid: []string{"foo", "bar"}}
235 v.initialize()
236 assert.Equalf(t, "bar", v.Default,
237 "when default value is set explicitly, it should be honored if it is valid: "+
238 "wanted %s, got %s",
239 "bar", v.Default,
240 )
241
242 v = &StringEnum{Var: &s, Default: "baz", Valid: []string{"foo", "bar"}}
243 v.initialize()
244 assert.Equalf(t, "foo", v.Default,
245 "when default value is set explicitly to an invalid value, it should be "+
246 "replaced with first valid value: wanted %s, got %s",
247 "foo", v.Default,
248 )
249
250 assert.Error(t, v.Set("baz"), "invalid value should cause an error")
251 assert.NoError(t, v.Set("bar"), "setting a valid value should not cause an error")
252 assert.Equal(t, "bar", v.Get(), "enum value should reflect updates after Set()")
253 }
254
View as plain text