Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 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. |
| 4 | |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 5 | package flag_test |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 6 | |
| 7 | import ( |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 8 | . "flag" |
Rob Pike | 6431b98 | 2010-04-06 16:46:52 -0700 | [diff] [blame] | 9 | "fmt" |
Russ Cox | ed7c3f3 | 2010-12-07 13:19:01 -0500 | [diff] [blame^] | 10 | "os" |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 11 | "testing" |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 12 | ) |
| 13 | |
| 14 | var ( |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 15 | test_bool = Bool("test_bool", false, "bool value") |
| 16 | test_int = Int("test_int", 0, "int value") |
| 17 | test_int64 = Int64("test_int64", 0, "int64 value") |
| 18 | test_uint = Uint("test_uint", 0, "uint value") |
| 19 | test_uint64 = Uint64("test_uint64", 0, "uint64 value") |
| 20 | test_string = String("test_string", "0", "string value") |
| 21 | test_float = Float("test_float", 0, "float value") |
| 22 | test_float64 = Float("test_float64", 0, "float64 value") |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 23 | ) |
| 24 | |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 25 | func boolString(s string) string { |
| 26 | if s == "0" { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 27 | return "false" |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 28 | } |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 29 | return "true" |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 30 | } |
| 31 | |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 32 | func TestEverything(t *testing.T) { |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 33 | m := make(map[string]*Flag) |
| 34 | desired := "0" |
Russ Cox | 3b864e4 | 2009-08-12 13:18:37 -0700 | [diff] [blame] | 35 | visitor := func(f *Flag) { |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 36 | if len(f.Name) > 5 && f.Name[0:5] == "test_" { |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 37 | m[f.Name] = f |
| 38 | ok := false |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 39 | switch { |
| 40 | case f.Value.String() == desired: |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 41 | ok = true |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 42 | case f.Name == "test_bool" && f.Value.String() == boolString(desired): |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 43 | ok = true |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 44 | } |
| 45 | if !ok { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 46 | t.Error("Visit: bad value", f.Value.String(), "for", f.Name) |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 47 | } |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 48 | } |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 49 | } |
| 50 | VisitAll(visitor) |
Vish Subramanian | 379150c | 2009-11-07 15:52:27 -0800 | [diff] [blame] | 51 | if len(m) != 8 { |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 52 | t.Error("VisitAll misses some flags") |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 53 | for k, v := range m { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 54 | t.Log(k, *v) |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 55 | } |
| 56 | } |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 57 | m = make(map[string]*Flag) |
| 58 | Visit(visitor) |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 59 | if len(m) != 0 { |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 60 | t.Errorf("Visit sees unset flags") |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 61 | for k, v := range m { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 62 | t.Log(k, *v) |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 63 | } |
| 64 | } |
Rob Pike | 575257d | 2009-02-16 21:55:37 -0800 | [diff] [blame] | 65 | // Now set all flags |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 66 | Set("test_bool", "true") |
| 67 | Set("test_int", "1") |
| 68 | Set("test_int64", "1") |
| 69 | Set("test_uint", "1") |
| 70 | Set("test_uint64", "1") |
| 71 | Set("test_string", "1") |
| 72 | Set("test_float", "1") |
| 73 | Set("test_float64", "1") |
| 74 | desired = "1" |
| 75 | Visit(visitor) |
Vish Subramanian | 379150c | 2009-11-07 15:52:27 -0800 | [diff] [blame] | 76 | if len(m) != 8 { |
Robert Griesemer | 1c72959 | 2009-12-15 15:27:16 -0800 | [diff] [blame] | 77 | t.Error("Visit fails after set") |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 78 | for k, v := range m { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 79 | t.Log(k, *v) |
Rob Pike | bbc190b | 2009-02-16 19:43:15 -0800 | [diff] [blame] | 80 | } |
| 81 | } |
| 82 | } |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 83 | |
Rob Pike | 6431b98 | 2010-04-06 16:46:52 -0700 | [diff] [blame] | 84 | func TestUsage(t *testing.T) { |
| 85 | called := false |
| 86 | ResetForTesting(func() { called = true }) |
| 87 | if ParseForTesting([]string{"a.out", "-x"}) { |
| 88 | t.Error("parse did not fail for unknown flag") |
| 89 | } |
| 90 | if !called { |
| 91 | t.Error("did not call Usage for unknown flag") |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | func TestParse(t *testing.T) { |
| 96 | ResetForTesting(func() { t.Error("bad parse") }) |
| 97 | boolFlag := Bool("bool", false, "bool value") |
| 98 | bool2Flag := Bool("bool2", false, "bool2 value") |
| 99 | intFlag := Int("int", 0, "int value") |
| 100 | int64Flag := Int64("int64", 0, "int64 value") |
| 101 | uintFlag := Uint("uint", 0, "uint value") |
| 102 | uint64Flag := Uint64("uint64", 0, "uint64 value") |
| 103 | stringFlag := String("string", "0", "string value") |
| 104 | floatFlag := Float("float", 0, "float value") |
| 105 | float64Flag := Float("float64", 0, "float64 value") |
| 106 | extra := "one-extra-argument" |
| 107 | args := []string{ |
| 108 | "a.out", |
| 109 | "-bool", |
| 110 | "-bool2=true", |
| 111 | "--int", "22", |
| 112 | "--int64", "23", |
| 113 | "-uint", "24", |
| 114 | "--uint64", "25", |
| 115 | "-string", "hello", |
| 116 | "--float", "3141.5", |
| 117 | "-float64", "2718e28", |
| 118 | extra, |
| 119 | } |
| 120 | if !ParseForTesting(args) { |
| 121 | t.Fatal("parse failed") |
| 122 | } |
| 123 | if *boolFlag != true { |
| 124 | t.Error("bool flag should be true, is ", *boolFlag) |
| 125 | } |
| 126 | if *bool2Flag != true { |
| 127 | t.Error("bool2 flag should be true, is ", *bool2Flag) |
| 128 | } |
| 129 | if *intFlag != 22 { |
| 130 | t.Error("int flag should be 22, is ", *intFlag) |
| 131 | } |
| 132 | if *int64Flag != 23 { |
| 133 | t.Error("int64 flag should be 23, is ", *int64Flag) |
| 134 | } |
| 135 | if *uintFlag != 24 { |
| 136 | t.Error("uint flag should be 24, is ", *uintFlag) |
| 137 | } |
| 138 | if *uint64Flag != 25 { |
| 139 | t.Error("uint64 flag should be 25, is ", *uint64Flag) |
| 140 | } |
| 141 | if *stringFlag != "hello" { |
| 142 | t.Error("string flag should be `hello`, is ", *stringFlag) |
| 143 | } |
| 144 | if *floatFlag != 3141.5 { |
| 145 | t.Error("float flag should be 3141.5, is ", *floatFlag) |
| 146 | } |
| 147 | if *float64Flag != 2718e28 { |
| 148 | t.Error("float64 flag should be 2718e28, is ", *float64Flag) |
| 149 | } |
| 150 | if len(Args()) != 1 { |
| 151 | t.Error("expected one argument, got", len(Args())) |
| 152 | } else if Args()[0] != extra { |
| 153 | t.Errorf("expected argument %q got %q", extra, Args()[0]) |
| 154 | } |
| 155 | } |
| 156 | |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 157 | // Declare a user-defined flag. |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 158 | type flagVar []string |
| 159 | |
| 160 | func (f *flagVar) String() string { |
Rob Pike | 6431b98 | 2010-04-06 16:46:52 -0700 | [diff] [blame] | 161 | return fmt.Sprint([]string(*f)) |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 162 | } |
| 163 | |
| 164 | func (f *flagVar) Set(value string) bool { |
Russ Cox | 69c4e93 | 2010-10-27 19:47:23 -0700 | [diff] [blame] | 165 | *f = append(*f, value) |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 166 | return true |
| 167 | } |
| 168 | |
Rob Pike | 6431b98 | 2010-04-06 16:46:52 -0700 | [diff] [blame] | 169 | func TestUserDefined(t *testing.T) { |
| 170 | ResetForTesting(func() { t.Fatal("bad parse") }) |
| 171 | var v flagVar |
| 172 | Var(&v, "v", "usage") |
| 173 | if !ParseForTesting([]string{"a.out", "-v", "1", "-v", "2", "-v=3"}) { |
| 174 | t.Error("parse failed") |
| 175 | } |
| 176 | if len(v) != 3 { |
| 177 | t.Fatal("expected 3 args; got ", len(v)) |
| 178 | } |
| 179 | expect := "[1 2 3]" |
| 180 | if v.String() != expect { |
| 181 | t.Errorf("expected value %q got %q", expect, v.String()) |
| 182 | } |
Rob Pike | 570af81 | 2010-03-29 17:37:22 -0700 | [diff] [blame] | 183 | } |
Russ Cox | ed7c3f3 | 2010-12-07 13:19:01 -0500 | [diff] [blame^] | 184 | |
| 185 | func TestChangingArgs(t *testing.T) { |
| 186 | ResetForTesting(func() { t.Fatal("bad parse") }) |
| 187 | oldArgs := os.Args |
| 188 | defer func() { os.Args = oldArgs }() |
| 189 | os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"} |
| 190 | before := Bool("before", false, "") |
| 191 | Parse() |
| 192 | cmd := Arg(0) |
| 193 | os.Args = Args() |
| 194 | after := Bool("after", false, "") |
| 195 | Parse() |
| 196 | args := Args() |
| 197 | |
| 198 | if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" { |
| 199 | t.Fatal("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args) |
| 200 | } |
| 201 | } |