1 package cli
2
3 import (
4 "context"
5 "flag"
6 "os"
7 "sort"
8 "strings"
9 "testing"
10 "time"
11 )
12
13 func TestNewContext(t *testing.T) {
14 set := flag.NewFlagSet("test", 0)
15 set.Int("myflag", 12, "doc")
16 set.Int64("myflagInt64", int64(12), "doc")
17 set.Uint("myflagUint", uint(93), "doc")
18 set.Uint64("myflagUint64", uint64(93), "doc")
19 set.Float64("myflag64", float64(17), "doc")
20 globalSet := flag.NewFlagSet("test", 0)
21 globalSet.Int("myflag", 42, "doc")
22 globalSet.Int64("myflagInt64", int64(42), "doc")
23 globalSet.Uint("myflagUint", uint(33), "doc")
24 globalSet.Uint64("myflagUint64", uint64(33), "doc")
25 globalSet.Float64("myflag64", float64(47), "doc")
26 globalCtx := NewContext(nil, globalSet, nil)
27 command := &Command{Name: "mycommand"}
28 c := NewContext(nil, set, globalCtx)
29 c.Command = command
30 expect(t, c.Int("myflag"), 12)
31 expect(t, c.Int64("myflagInt64"), int64(12))
32 expect(t, c.Uint("myflagUint"), uint(93))
33 expect(t, c.Uint64("myflagUint64"), uint64(93))
34 expect(t, c.Float64("myflag64"), float64(17))
35 expect(t, c.Command.Name, "mycommand")
36 }
37
38 func TestContext_Int(t *testing.T) {
39 set := flag.NewFlagSet("test", 0)
40 set.Int("myflag", 12, "doc")
41 parentSet := flag.NewFlagSet("test", 0)
42 parentSet.Int("top-flag", 13, "doc")
43 parentCtx := NewContext(nil, parentSet, nil)
44 c := NewContext(nil, set, parentCtx)
45 expect(t, c.Int("myflag"), 12)
46 expect(t, c.Int("top-flag"), 13)
47 }
48
49 func TestContext_Int64(t *testing.T) {
50 set := flag.NewFlagSet("test", 0)
51 set.Int64("myflagInt64", 12, "doc")
52 parentSet := flag.NewFlagSet("test", 0)
53 parentSet.Int64("top-flag", 13, "doc")
54 parentCtx := NewContext(nil, parentSet, nil)
55 c := NewContext(nil, set, parentCtx)
56 expect(t, c.Int64("myflagInt64"), int64(12))
57 expect(t, c.Int64("top-flag"), int64(13))
58 }
59
60 func TestContext_Uint(t *testing.T) {
61 set := flag.NewFlagSet("test", 0)
62 set.Uint("myflagUint", uint(13), "doc")
63 parentSet := flag.NewFlagSet("test", 0)
64 parentSet.Uint("top-flag", uint(14), "doc")
65 parentCtx := NewContext(nil, parentSet, nil)
66 c := NewContext(nil, set, parentCtx)
67 expect(t, c.Uint("myflagUint"), uint(13))
68 expect(t, c.Uint("top-flag"), uint(14))
69 }
70
71 func TestContext_Uint64(t *testing.T) {
72 set := flag.NewFlagSet("test", 0)
73 set.Uint64("myflagUint64", uint64(9), "doc")
74 parentSet := flag.NewFlagSet("test", 0)
75 parentSet.Uint64("top-flag", uint64(10), "doc")
76 parentCtx := NewContext(nil, parentSet, nil)
77 c := NewContext(nil, set, parentCtx)
78 expect(t, c.Uint64("myflagUint64"), uint64(9))
79 expect(t, c.Uint64("top-flag"), uint64(10))
80 }
81
82 func TestContext_Float64(t *testing.T) {
83 set := flag.NewFlagSet("test", 0)
84 set.Float64("myflag", float64(17), "doc")
85 parentSet := flag.NewFlagSet("test", 0)
86 parentSet.Float64("top-flag", float64(18), "doc")
87 parentCtx := NewContext(nil, parentSet, nil)
88 c := NewContext(nil, set, parentCtx)
89 expect(t, c.Float64("myflag"), float64(17))
90 expect(t, c.Float64("top-flag"), float64(18))
91 }
92
93 func TestContext_Duration(t *testing.T) {
94 set := flag.NewFlagSet("test", 0)
95 set.Duration("myflag", 12*time.Second, "doc")
96
97 parentSet := flag.NewFlagSet("test", 0)
98 parentSet.Duration("top-flag", 13*time.Second, "doc")
99 parentCtx := NewContext(nil, parentSet, nil)
100
101 c := NewContext(nil, set, parentCtx)
102 expect(t, c.Duration("myflag"), 12*time.Second)
103 expect(t, c.Duration("top-flag"), 13*time.Second)
104 }
105
106 func TestContext_String(t *testing.T) {
107 set := flag.NewFlagSet("test", 0)
108 set.String("myflag", "hello world", "doc")
109 parentSet := flag.NewFlagSet("test", 0)
110 parentSet.String("top-flag", "hai veld", "doc")
111 parentCtx := NewContext(nil, parentSet, nil)
112 c := NewContext(nil, set, parentCtx)
113 expect(t, c.String("myflag"), "hello world")
114 expect(t, c.String("top-flag"), "hai veld")
115 c = NewContext(nil, nil, parentCtx)
116 expect(t, c.String("top-flag"), "hai veld")
117 }
118
119 func TestContext_Path(t *testing.T) {
120 set := flag.NewFlagSet("test", 0)
121 set.String("path", "path/to/file", "path to file")
122 parentSet := flag.NewFlagSet("test", 0)
123 parentSet.String("top-path", "path/to/top/file", "doc")
124 parentCtx := NewContext(nil, parentSet, nil)
125 c := NewContext(nil, set, parentCtx)
126 expect(t, c.Path("path"), "path/to/file")
127 expect(t, c.Path("top-path"), "path/to/top/file")
128 }
129
130 func TestContext_Bool(t *testing.T) {
131 set := flag.NewFlagSet("test", 0)
132 set.Bool("myflag", false, "doc")
133 parentSet := flag.NewFlagSet("test", 0)
134 parentSet.Bool("top-flag", true, "doc")
135 parentCtx := NewContext(nil, parentSet, nil)
136 c := NewContext(nil, set, parentCtx)
137 expect(t, c.Bool("myflag"), false)
138 expect(t, c.Bool("top-flag"), true)
139 }
140
141 func TestContext_Value(t *testing.T) {
142 set := flag.NewFlagSet("test", 0)
143 set.Int("myflag", 12, "doc")
144 parentSet := flag.NewFlagSet("test", 0)
145 parentSet.Int("top-flag", 13, "doc")
146 parentCtx := NewContext(nil, parentSet, nil)
147 c := NewContext(nil, set, parentCtx)
148 expect(t, c.Value("myflag"), 12)
149 expect(t, c.Value("top-flag"), 13)
150 expect(t, c.Value("unknown-flag"), nil)
151 }
152
153 func TestContext_Value_InvalidFlagAccessHandler(t *testing.T) {
154 var flagName string
155 app := &App{
156 InvalidFlagAccessHandler: func(_ *Context, name string) {
157 flagName = name
158 },
159 Commands: []*Command{
160 {
161 Name: "command",
162 Subcommands: []*Command{
163 {
164 Name: "subcommand",
165 Action: func(ctx *Context) error {
166 ctx.Value("missing")
167 return nil
168 },
169 },
170 },
171 },
172 },
173 }
174 expect(t, app.Run([]string{"run", "command", "subcommand"}), nil)
175 expect(t, flagName, "missing")
176 }
177
178 func TestContext_Args(t *testing.T) {
179 set := flag.NewFlagSet("test", 0)
180 set.Bool("myflag", false, "doc")
181 c := NewContext(nil, set, nil)
182 _ = set.Parse([]string{"--myflag", "bat", "baz"})
183 expect(t, c.Args().Len(), 2)
184 expect(t, c.Bool("myflag"), true)
185 }
186
187 func TestContext_NArg(t *testing.T) {
188 set := flag.NewFlagSet("test", 0)
189 set.Bool("myflag", false, "doc")
190 c := NewContext(nil, set, nil)
191 _ = set.Parse([]string{"--myflag", "bat", "baz"})
192 expect(t, c.NArg(), 2)
193 }
194
195 func TestContext_IsSet(t *testing.T) {
196 set := flag.NewFlagSet("test", 0)
197 set.Bool("one-flag", false, "doc")
198 set.Bool("two-flag", false, "doc")
199 set.String("three-flag", "hello world", "doc")
200 parentSet := flag.NewFlagSet("test", 0)
201 parentSet.Bool("top-flag", true, "doc")
202 parentCtx := NewContext(nil, parentSet, nil)
203 ctx := NewContext(nil, set, parentCtx)
204
205 _ = set.Parse([]string{"--one-flag", "--two-flag", "--three-flag", "frob"})
206 _ = parentSet.Parse([]string{"--top-flag"})
207
208 expect(t, ctx.IsSet("one-flag"), true)
209 expect(t, ctx.IsSet("two-flag"), true)
210 expect(t, ctx.IsSet("three-flag"), true)
211 expect(t, ctx.IsSet("top-flag"), true)
212 expect(t, ctx.IsSet("bogus"), false)
213 }
214
215 func TestContext_IsSet_Aliases(t *testing.T) {
216
217 var fooSet, fSet, tSet, iglooSet bool
218
219 a := App{
220 Flags: []Flag{
221 &Int64Flag{
222 Name: "foo",
223 Aliases: []string{"f", "t", "igloo"},
224 },
225 },
226 Action: func(ctx *Context) error {
227 fooSet = ctx.IsSet("foo")
228 fSet = ctx.IsSet("f")
229 tSet = ctx.IsSet("t")
230 iglooSet = ctx.IsSet("igloo")
231 return nil
232 },
233 }
234
235 _ = a.Run([]string{"run"})
236 expect(t, fooSet, false)
237 expect(t, fSet, false)
238 expect(t, tSet, false)
239 expect(t, iglooSet, false)
240
241 _ = a.Run([]string{"run", "--t", "10"})
242 expect(t, fooSet, true)
243 expect(t, fSet, true)
244 expect(t, tSet, true)
245 expect(t, iglooSet, true)
246 }
247
248
249
250 func TestContext_IsSet_fromEnv(t *testing.T) {
251 var (
252 timeoutIsSet, tIsSet bool
253 noEnvVarIsSet, nIsSet bool
254 passwordIsSet, pIsSet bool
255 unparsableIsSet, uIsSet bool
256 )
257
258 defer resetEnv(os.Environ())
259 os.Clearenv()
260 _ = os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
261 _ = os.Setenv("APP_PASSWORD", "")
262 a := App{
263 Flags: []Flag{
264 &Float64Flag{Name: "timeout", Aliases: []string{"t"}, EnvVars: []string{"APP_TIMEOUT_SECONDS"}},
265 &StringFlag{Name: "password", Aliases: []string{"p"}, EnvVars: []string{"APP_PASSWORD"}},
266 &Float64Flag{Name: "unparsable", Aliases: []string{"u"}, EnvVars: []string{"APP_UNPARSABLE"}},
267 &Float64Flag{Name: "no-env-var", Aliases: []string{"n"}},
268 },
269 Action: func(ctx *Context) error {
270 timeoutIsSet = ctx.IsSet("timeout")
271 tIsSet = ctx.IsSet("t")
272 passwordIsSet = ctx.IsSet("password")
273 pIsSet = ctx.IsSet("p")
274 unparsableIsSet = ctx.IsSet("unparsable")
275 uIsSet = ctx.IsSet("u")
276 noEnvVarIsSet = ctx.IsSet("no-env-var")
277 nIsSet = ctx.IsSet("n")
278 return nil
279 },
280 }
281 _ = a.Run([]string{"run"})
282 expect(t, timeoutIsSet, true)
283 expect(t, tIsSet, true)
284 expect(t, passwordIsSet, true)
285 expect(t, pIsSet, true)
286 expect(t, noEnvVarIsSet, false)
287 expect(t, nIsSet, false)
288
289 _ = os.Setenv("APP_UNPARSABLE", "foobar")
290 _ = a.Run([]string{"run"})
291 expect(t, unparsableIsSet, false)
292 expect(t, uIsSet, false)
293 }
294
295 func TestContext_NumFlags(t *testing.T) {
296 set := flag.NewFlagSet("test", 0)
297 set.Bool("myflag", false, "doc")
298 set.String("otherflag", "hello world", "doc")
299 globalSet := flag.NewFlagSet("test", 0)
300 globalSet.Bool("myflagGlobal", true, "doc")
301 globalCtx := NewContext(nil, globalSet, nil)
302 c := NewContext(nil, set, globalCtx)
303 _ = set.Parse([]string{"--myflag", "--otherflag=foo"})
304 _ = globalSet.Parse([]string{"--myflagGlobal"})
305 expect(t, c.NumFlags(), 2)
306 }
307
308 func TestContext_Set(t *testing.T) {
309 set := flag.NewFlagSet("test", 0)
310 set.Int("int", 5, "an int")
311 c := NewContext(nil, set, nil)
312
313 expect(t, c.IsSet("int"), false)
314 _ = c.Set("int", "1")
315 expect(t, c.Int("int"), 1)
316 expect(t, c.IsSet("int"), true)
317 }
318
319 func TestContext_Set_InvalidFlagAccessHandler(t *testing.T) {
320 set := flag.NewFlagSet("test", 0)
321 var flagName string
322 app := &App{
323 InvalidFlagAccessHandler: func(_ *Context, name string) {
324 flagName = name
325 },
326 }
327 c := NewContext(app, set, nil)
328 expect(t, c.Set("missing", "") != nil, true)
329 expect(t, flagName, "missing")
330 }
331
332 func TestContext_LocalFlagNames(t *testing.T) {
333 set := flag.NewFlagSet("test", 0)
334 set.Bool("one-flag", false, "doc")
335 set.String("two-flag", "hello world", "doc")
336 parentSet := flag.NewFlagSet("test", 0)
337 parentSet.Bool("top-flag", true, "doc")
338 parentCtx := NewContext(nil, parentSet, nil)
339 ctx := NewContext(nil, set, parentCtx)
340 _ = set.Parse([]string{"--one-flag", "--two-flag=foo"})
341 _ = parentSet.Parse([]string{"--top-flag"})
342
343 actualFlags := ctx.LocalFlagNames()
344 sort.Strings(actualFlags)
345
346 expect(t, actualFlags, []string{"one-flag", "two-flag"})
347 }
348
349 func TestContext_FlagNames(t *testing.T) {
350 set := flag.NewFlagSet("test", 0)
351 set.Bool("one-flag", false, "doc")
352 set.String("two-flag", "hello world", "doc")
353 parentSet := flag.NewFlagSet("test", 0)
354 parentSet.Bool("top-flag", true, "doc")
355 parentCtx := NewContext(nil, parentSet, nil)
356 ctx := NewContext(nil, set, parentCtx)
357 _ = set.Parse([]string{"--one-flag", "--two-flag=foo"})
358 _ = parentSet.Parse([]string{"--top-flag"})
359
360 actualFlags := ctx.FlagNames()
361 sort.Strings(actualFlags)
362
363 expect(t, actualFlags, []string{"one-flag", "top-flag", "two-flag"})
364 }
365
366 func TestContext_Lineage(t *testing.T) {
367 set := flag.NewFlagSet("test", 0)
368 set.Bool("local-flag", false, "doc")
369 parentSet := flag.NewFlagSet("test", 0)
370 parentSet.Bool("top-flag", true, "doc")
371 parentCtx := NewContext(nil, parentSet, nil)
372 ctx := NewContext(nil, set, parentCtx)
373 _ = set.Parse([]string{"--local-flag"})
374 _ = parentSet.Parse([]string{"--top-flag"})
375
376 lineage := ctx.Lineage()
377 expect(t, len(lineage), 2)
378 expect(t, lineage[0], ctx)
379 expect(t, lineage[1], parentCtx)
380 }
381
382 func TestContext_lookupFlagSet(t *testing.T) {
383 set := flag.NewFlagSet("test", 0)
384 set.Bool("local-flag", false, "doc")
385 parentSet := flag.NewFlagSet("test", 0)
386 parentSet.Bool("top-flag", true, "doc")
387 parentCtx := NewContext(nil, parentSet, nil)
388 ctx := NewContext(nil, set, parentCtx)
389 _ = set.Parse([]string{"--local-flag"})
390 _ = parentSet.Parse([]string{"--top-flag"})
391
392 fs := ctx.lookupFlagSet("top-flag")
393 expect(t, fs, parentCtx.flagSet)
394
395 fs = ctx.lookupFlagSet("local-flag")
396 expect(t, fs, ctx.flagSet)
397
398 if fs := ctx.lookupFlagSet("frob"); fs != nil {
399 t.Fail()
400 }
401 }
402
403 func TestNonNilContext(t *testing.T) {
404 ctx := NewContext(nil, nil, nil)
405 if ctx.Context == nil {
406 t.Fatal("expected a non nil context when no parent is present")
407 }
408 }
409
410
411
412
413 func TestContextPropagation(t *testing.T) {
414 type testKey struct{}
415
416 parent := NewContext(nil, nil, nil)
417 parent.Context = context.WithValue(context.Background(), testKey{}, "val")
418 ctx := NewContext(nil, nil, parent)
419 val := ctx.Context.Value(testKey{})
420 if val == nil {
421 t.Fatal("expected a parent context to be inherited but got nil")
422 }
423 valstr, _ := val.(string)
424 if valstr != "val" {
425 t.Fatalf("expected the context value to be %q but got %q", "val", valstr)
426 }
427 parent = NewContext(nil, nil, nil)
428 parent.Context = nil
429 ctx = NewContext(nil, nil, parent)
430 if ctx.Context == nil {
431 t.Fatal("expected context to not be nil even if the parent's context is nil")
432 }
433 }
434
435 func TestContextAttributeAccessing(t *testing.T) {
436 tdata := []struct {
437 testCase string
438 setBoolInput string
439 ctxBoolInput string
440 newContextInput *Context
441 }{
442 {
443 testCase: "empty",
444 setBoolInput: "",
445 ctxBoolInput: "",
446 newContextInput: nil,
447 },
448 {
449 testCase: "empty_with_background_context",
450 setBoolInput: "",
451 ctxBoolInput: "",
452 newContextInput: &Context{Context: context.Background()},
453 },
454 {
455 testCase: "empty_set_bool_and_present_ctx_bool",
456 setBoolInput: "",
457 ctxBoolInput: "ctx-bool",
458 newContextInput: nil,
459 },
460 {
461 testCase: "present_set_bool_and_present_ctx_bool_with_background_context",
462 setBoolInput: "",
463 ctxBoolInput: "ctx-bool",
464 newContextInput: &Context{Context: context.Background()},
465 },
466 {
467 testCase: "present_set_bool_and_present_ctx_bool",
468 setBoolInput: "ctx-bool",
469 ctxBoolInput: "ctx-bool",
470 newContextInput: nil,
471 },
472 {
473 testCase: "present_set_bool_and_present_ctx_bool_with_background_context",
474 setBoolInput: "ctx-bool",
475 ctxBoolInput: "ctx-bool",
476 newContextInput: &Context{Context: context.Background()},
477 },
478 {
479 testCase: "present_set_bool_and_different_ctx_bool",
480 setBoolInput: "ctx-bool",
481 ctxBoolInput: "not-ctx-bool",
482 newContextInput: nil,
483 },
484 {
485 testCase: "present_set_bool_and_different_ctx_bool_with_background_context",
486 setBoolInput: "ctx-bool",
487 ctxBoolInput: "not-ctx-bool",
488 newContextInput: &Context{Context: context.Background()},
489 },
490 }
491
492 for _, test := range tdata {
493 t.Run(test.testCase, func(t *testing.T) {
494
495 set := flag.NewFlagSet("some-flag-set-name", 0)
496 set.Bool(test.setBoolInput, false, "usage documentation")
497 ctx := NewContext(nil, set, test.newContextInput)
498
499
500 value := ctx.Bool(test.ctxBoolInput)
501
502
503 if value != false {
504 t.Errorf("expected \"value\" to be false, but it was not")
505 }
506 })
507 }
508 }
509
510 func TestCheckRequiredFlags(t *testing.T) {
511 tdata := []struct {
512 testCase string
513 parseInput []string
514 envVarInput [2]string
515 flags []Flag
516 expectedAnError bool
517 expectedErrorContents []string
518 }{
519 {
520 testCase: "empty",
521 },
522 {
523 testCase: "optional",
524 flags: []Flag{
525 &StringFlag{Name: "optionalFlag"},
526 },
527 },
528 {
529 testCase: "required",
530 flags: []Flag{
531 &StringFlag{Name: "requiredFlag", Required: true},
532 },
533 expectedAnError: true,
534 expectedErrorContents: []string{"requiredFlag"},
535 },
536 {
537 testCase: "required_and_present",
538 flags: []Flag{
539 &StringFlag{Name: "requiredFlag", Required: true},
540 },
541 parseInput: []string{"--requiredFlag", "myinput"},
542 },
543 {
544 testCase: "required_and_present_via_env_var",
545 flags: []Flag{
546 &StringFlag{Name: "requiredFlag", Required: true, EnvVars: []string{"REQUIRED_FLAG"}},
547 },
548 envVarInput: [2]string{"REQUIRED_FLAG", "true"},
549 },
550 {
551 testCase: "required_and_optional",
552 flags: []Flag{
553 &StringFlag{Name: "requiredFlag", Required: true},
554 &StringFlag{Name: "optionalFlag"},
555 },
556 expectedAnError: true,
557 },
558 {
559 testCase: "required_and_optional_and_optional_present",
560 flags: []Flag{
561 &StringFlag{Name: "requiredFlag", Required: true},
562 &StringFlag{Name: "optionalFlag"},
563 },
564 parseInput: []string{"--optionalFlag", "myinput"},
565 expectedAnError: true,
566 },
567 {
568 testCase: "required_and_optional_and_optional_present_via_env_var",
569 flags: []Flag{
570 &StringFlag{Name: "requiredFlag", Required: true},
571 &StringFlag{Name: "optionalFlag", EnvVars: []string{"OPTIONAL_FLAG"}},
572 },
573 envVarInput: [2]string{"OPTIONAL_FLAG", "true"},
574 expectedAnError: true,
575 },
576 {
577 testCase: "required_and_optional_and_required_present",
578 flags: []Flag{
579 &StringFlag{Name: "requiredFlag", Required: true},
580 &StringFlag{Name: "optionalFlag"},
581 },
582 parseInput: []string{"--requiredFlag", "myinput"},
583 },
584 {
585 testCase: "two_required",
586 flags: []Flag{
587 &StringFlag{Name: "requiredFlagOne", Required: true},
588 &StringFlag{Name: "requiredFlagTwo", Required: true},
589 },
590 expectedAnError: true,
591 expectedErrorContents: []string{"requiredFlagOne", "requiredFlagTwo"},
592 },
593 {
594 testCase: "two_required_and_one_present",
595 flags: []Flag{
596 &StringFlag{Name: "requiredFlag", Required: true},
597 &StringFlag{Name: "requiredFlagTwo", Required: true},
598 },
599 parseInput: []string{"--requiredFlag", "myinput"},
600 expectedAnError: true,
601 },
602 {
603 testCase: "two_required_and_both_present",
604 flags: []Flag{
605 &StringFlag{Name: "requiredFlag", Required: true},
606 &StringFlag{Name: "requiredFlagTwo", Required: true},
607 },
608 parseInput: []string{"--requiredFlag", "myinput", "--requiredFlagTwo", "myinput"},
609 },
610 {
611 testCase: "required_flag_with_short_name",
612 flags: []Flag{
613 &StringSliceFlag{Name: "names", Aliases: []string{"N"}, Required: true},
614 },
615 parseInput: []string{"-N", "asd", "-N", "qwe"},
616 },
617 {
618 testCase: "required_flag_with_multiple_short_names",
619 flags: []Flag{
620 &StringSliceFlag{Name: "names", Aliases: []string{"N", "n"}, Required: true},
621 },
622 parseInput: []string{"-n", "asd", "-n", "qwe"},
623 },
624 {
625 testCase: "required_flag_with_short_alias_not_printed_on_error",
626 expectedAnError: true,
627 expectedErrorContents: []string{"Required flag \"names\" not set"},
628 flags: []Flag{
629 &StringSliceFlag{Name: "names, n", Required: true},
630 },
631 },
632 {
633 testCase: "required_flag_with_one_character",
634 expectedAnError: true,
635 expectedErrorContents: []string{"Required flag \"n\" not set"},
636 flags: []Flag{
637 &StringFlag{Name: "n", Required: true},
638 },
639 },
640 {
641 testCase: "required_flag_with_alias_errors_with_actual_name",
642 expectedAnError: true,
643 expectedErrorContents: []string{"Required flag \"collection\" not set"},
644 flags: []Flag{
645 &StringFlag{Name: "collection", Required: true, Aliases: []string{"c"}},
646 },
647 },
648 {
649 testCase: "required_flag_without_name_or_aliases_doesnt_error",
650 expectedAnError: false,
651 flags: []Flag{
652 &StringFlag{Required: true},
653 },
654 },
655 }
656
657 for _, test := range tdata {
658 t.Run(test.testCase, func(t *testing.T) {
659
660 if test.envVarInput[0] != "" {
661 defer resetEnv(os.Environ())
662 os.Clearenv()
663 _ = os.Setenv(test.envVarInput[0], test.envVarInput[1])
664 }
665
666 set := flag.NewFlagSet("test", 0)
667 for _, flags := range test.flags {
668 _ = flags.Apply(set)
669 }
670 _ = set.Parse(test.parseInput)
671
672 c := &Context{}
673 ctx := NewContext(c.App, set, c)
674 ctx.Command.Flags = test.flags
675
676
677 err := ctx.checkRequiredFlags(test.flags)
678
679
680 if test.expectedAnError && err == nil {
681 t.Errorf("expected an error, but there was none")
682 }
683 if !test.expectedAnError && err != nil {
684 t.Errorf("did not expected an error, but there was one: %s", err)
685 }
686 for _, errString := range test.expectedErrorContents {
687 if err != nil {
688 if !strings.Contains(err.Error(), errString) {
689 t.Errorf("expected error %q to contain %q, but it didn't!", err.Error(), errString)
690 }
691 }
692 }
693 })
694 }
695 }
696
697 func TestContext_ParentContext_Set(t *testing.T) {
698 parentSet := flag.NewFlagSet("parent", flag.ContinueOnError)
699 parentSet.String("Name", "", "")
700
701 context := NewContext(
702 nil,
703 flag.NewFlagSet("child", flag.ContinueOnError),
704 NewContext(nil, parentSet, nil),
705 )
706
707 err := context.Set("Name", "aaa")
708 if err != nil {
709 t.Errorf("expect nil. set parent context flag return err: %s", err)
710 }
711 }
712
View as plain text