1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 func boolString(s
string) string {
26 func TestEverything(t
*testing
.T
) {
28 Bool("test_bool", false, "bool value")
29 Int("test_int", 0, "int value")
30 Int64("test_int64", 0, "int64 value")
31 Uint("test_uint", 0, "uint value")
32 Uint64("test_uint64", 0, "uint64 value")
33 String("test_string", "0", "string value")
34 Float64("test_float64", 0, "float64 value")
35 Duration("test_duration", 0, "time.Duration value")
37 m
:= make(map[string]*Flag
)
39 visitor
:= func(f
*Flag
) {
40 if len(f
.Name
) > 5 && f
.Name
[0:5] == "test_" {
44 case f
.Value
.String() == desired
:
46 case f
.Name
== "test_bool" && f
.Value
.String() == boolString(desired
):
48 case f
.Name
== "test_duration" && f
.Value
.String() == desired
+"s":
52 t
.Error("Visit: bad value", f
.Value
.String(), "for", f
.Name
)
58 t
.Error("VisitAll misses some flags")
63 m
= make(map[string]*Flag
)
66 t
.Errorf("Visit sees unset flags")
72 Set("test_bool", "true")
74 Set("test_int64", "1")
76 Set("test_uint64", "1")
77 Set("test_string", "1")
78 Set("test_float64", "1")
79 Set("test_duration", "1s")
83 t
.Error("Visit fails after set")
88 // Now test they're visited in sort order.
89 var flagNames
[]string
90 Visit(func(f
*Flag
) { flagNames
= append(flagNames
, f
.Name
) })
91 if !sort
.StringsAreSorted(flagNames
) {
92 t
.Errorf("flag names not sorted: %v", flagNames
)
96 func TestGet(t
*testing
.T
) {
98 Bool("test_bool", true, "bool value")
99 Int("test_int", 1, "int value")
100 Int64("test_int64", 2, "int64 value")
101 Uint("test_uint", 3, "uint value")
102 Uint64("test_uint64", 4, "uint64 value")
103 String("test_string", "5", "string value")
104 Float64("test_float64", 6, "float64 value")
105 Duration("test_duration", 7, "time.Duration value")
107 visitor
:= func(f
*Flag
) {
108 if len(f
.Name
) > 5 && f
.Name
[0:5] == "test_" {
109 g
, ok
:= f
.Value
.(Getter
)
111 t
.Errorf("Visit: value does not satisfy Getter: %T", f
.Value
)
118 ok
= g
.Get() == int(1)
120 ok
= g
.Get() == int64(2)
122 ok
= g
.Get() == uint(3)
124 ok
= g
.Get() == uint64(4)
128 ok
= g
.Get() == float64(6)
129 case "test_duration":
130 ok
= g
.Get() == time
.Duration(7)
133 t
.Errorf("Visit: bad value %T(%v) for %s", g
.Get(), g
.Get(), f
.Name
)
140 func TestUsage(t
*testing
.T
) {
142 ResetForTesting(func() { called
= true })
143 if CommandLine
.Parse([]string{"-x"}) == nil {
144 t
.Error("parse did not fail for unknown flag")
147 t
.Error("did not call Usage for unknown flag")
151 func testParse(f
*FlagSet
, t
*testing
.T
) {
153 t
.Error("f.Parse() = true before Parse")
155 boolFlag
:= f
.Bool("bool", false, "bool value")
156 bool2Flag
:= f
.Bool("bool2", false, "bool2 value")
157 intFlag
:= f
.Int("int", 0, "int value")
158 int64Flag
:= f
.Int64("int64", 0, "int64 value")
159 uintFlag
:= f
.Uint("uint", 0, "uint value")
160 uint64Flag
:= f
.Uint64("uint64", 0, "uint64 value")
161 stringFlag
:= f
.String("string", "0", "string value")
162 float64Flag
:= f
.Float64("float64", 0, "float64 value")
163 durationFlag
:= f
.Duration("duration", 5*time
.Second
, "time.Duration value")
164 extra
:= "one-extra-argument"
173 "-float64", "2718e28",
177 if err
:= f
.Parse(args
); err
!= nil {
181 t
.Error("f.Parse() = false after Parse")
183 if *boolFlag
!= true {
184 t
.Error("bool flag should be true, is ", *boolFlag
)
186 if *bool2Flag
!= true {
187 t
.Error("bool2 flag should be true, is ", *bool2Flag
)
190 t
.Error("int flag should be 22, is ", *intFlag
)
192 if *int64Flag
!= 0x23 {
193 t
.Error("int64 flag should be 0x23, is ", *int64Flag
)
196 t
.Error("uint flag should be 24, is ", *uintFlag
)
198 if *uint64Flag
!= 25 {
199 t
.Error("uint64 flag should be 25, is ", *uint64Flag
)
201 if *stringFlag
!= "hello" {
202 t
.Error("string flag should be `hello`, is ", *stringFlag
)
204 if *float64Flag
!= 2718e28
{
205 t
.Error("float64 flag should be 2718e28, is ", *float64Flag
)
207 if *durationFlag
!= 2*time
.Minute
{
208 t
.Error("duration flag should be 2m, is ", *durationFlag
)
210 if len(f
.Args()) != 1 {
211 t
.Error("expected one argument, got", len(f
.Args()))
212 } else if f
.Args()[0] != extra
{
213 t
.Errorf("expected argument %q got %q", extra
, f
.Args()[0])
217 func TestParse(t
*testing
.T
) {
218 ResetForTesting(func() { t
.Error("bad parse") })
219 testParse(CommandLine
, t
)
222 func TestFlagSetParse(t
*testing
.T
) {
223 testParse(NewFlagSet("test", ContinueOnError
), t
)
226 // Declare a user-defined flag type.
227 type flagVar
[]string
229 func (f
*flagVar
) String() string {
230 return fmt
.Sprint([]string(*f
))
233 func (f
*flagVar
) Set(value
string) error
{
234 *f
= append(*f
, value
)
238 func TestUserDefined(t
*testing
.T
) {
240 flags
.Init("test", ContinueOnError
)
242 flags
.Var(&v
, "v", "usage")
243 if err
:= flags
.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err
!= nil {
247 t
.Fatal("expected 3 args; got ", len(v
))
250 if v
.String() != expect
{
251 t
.Errorf("expected value %q got %q", expect
, v
.String())
255 func TestUserDefinedForCommandLine(t
*testing
.T
) {
258 ResetForTesting(func() { result
= help
})
261 t
.Fatalf("got %q; expected %q", result
, help
)
265 // Declare a user-defined boolean flag type.
266 type boolFlagVar
struct {
270 func (b
*boolFlagVar
) String() string {
271 return fmt
.Sprintf("%d", b
.count
)
274 func (b
*boolFlagVar
) Set(value
string) error
{
281 func (b
*boolFlagVar
) IsBoolFlag() bool {
285 func TestUserDefinedBool(t
*testing
.T
) {
287 flags
.Init("test", ContinueOnError
)
290 flags
.Var(&b
, "b", "usage")
291 if err
= flags
.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err
!= nil {
298 t
.Errorf("want: %d; got: %d", 4, b
.count
)
302 t
.Error("expected error; got none")
306 func TestSetOutput(t
*testing
.T
) {
309 flags
.SetOutput(&buf
)
310 flags
.Init("test", ContinueOnError
)
311 flags
.Parse([]string{"-unknown"})
312 if out
:= buf
.String(); !strings
.Contains(out
, "-unknown") {
313 t
.Logf("expected output mentioning unknown; got %q", out
)
317 // This tests that one can reset the flags. This still works but not well, and is
318 // superseded by FlagSet.
319 func TestChangingArgs(t
*testing
.T
) {
320 ResetForTesting(func() { t
.Fatal("bad parse") })
322 defer func() { os
.Args
= oldArgs
}()
323 os
.Args
= []string{"cmd", "-before", "subcmd", "-after", "args"}
324 before
:= Bool("before", false, "")
325 if err
:= CommandLine
.Parse(os
.Args
[1:]); err
!= nil {
330 after
:= Bool("after", false, "")
334 if !*before || cmd
!= "subcmd" ||
!*after ||
len(args
) != 1 || args
[0] != "args" {
335 t
.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before
, cmd
, *after
, args
)
339 // Test that -help invokes the usage message and returns ErrHelp.
340 func TestHelp(t
*testing
.T
) {
341 var helpCalled
= false
342 fs
:= NewFlagSet("help test", ContinueOnError
)
343 fs
.Usage
= func() { helpCalled
= true }
345 fs
.BoolVar(&flag
, "flag", false, "regular flag")
346 // Regular flag invocation should work
347 err
:= fs
.Parse([]string{"-flag=true"})
349 t
.Fatal("expected no error; got ", err
)
352 t
.Error("flag was not set by -flag")
355 t
.Error("help called for regular flag")
356 helpCalled
= false // reset for next test
358 // Help flag should work as expected.
359 err
= fs
.Parse([]string{"-help"})
361 t
.Fatal("error expected")
364 t
.Fatal("expected ErrHelp; got ", err
)
367 t
.Fatal("help was not called")
369 // If we define a help flag, that should override.
371 fs
.BoolVar(&help
, "help", false, "help flag")
373 err
= fs
.Parse([]string{"-help"})
375 t
.Fatal("expected no error for defined -help; got ", err
)
378 t
.Fatal("help was called; should not have been for defined help flag")
382 const defaultOutput
= ` -A for bootstrapping, allow 'any' type
384 disable bounds checking
385 -C a boolean defaulting to true (default true)
387 set relative path for local imports
389 a non-zero number (default 2.7)
391 a float that defaults to zero
393 a non-zero int (default 27)
395 an int that defaults to zero
400 func TestPrintDefaults(t
*testing
.T
) {
401 fs
:= NewFlagSet("print defaults test", ContinueOnError
)
404 fs
.Bool("A", false, "for bootstrapping, allow 'any' type")
405 fs
.Bool("Alongflagname", false, "disable bounds checking")
406 fs
.Bool("C", true, "a boolean defaulting to true")
407 fs
.String("D", "", "set relative `path` for local imports")
408 fs
.Float64("F", 2.7, "a non-zero `number`")
409 fs
.Float64("G", 0, "a float that defaults to zero")
410 fs
.Int("N", 27, "a non-zero int")
411 fs
.Int("Z", 0, "an int that defaults to zero")
412 fs
.Duration("maxT", 0, "set `timeout` for dial")
415 if got
!= defaultOutput
{
416 t
.Errorf("got %q want %q\n", got
, defaultOutput
)
420 // Issue 19230: validate range of Int and Uint flag values.
421 func TestIntFlagOverflow(t
*testing
.T
) {
422 if strconv
.IntSize
!= 32 {
428 if err
:= Set("i", "2147483648"); err
== nil {
429 t
.Error("unexpected success setting Int")
431 if err
:= Set("u", "4294967296"); err
== nil {
432 t
.Error("unexpected success setting Uint")