-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsflag_test.go
198 lines (175 loc) · 5.58 KB
/
sflag_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
package sflag
import (
"fmt"
"testing"
)
// TestSflag_1 is minimal
func TestSflag_1(*testing.T) {
var opt = struct {
}{}
Parse(&opt)
}
// TestSflag_2 shows how to parse for a simple int with upcased or lowcase first char of the flag
func TestSflag_2(t *testing.T) {
var opt = struct {
Iq int "Upcased - winuser | 42" // Provide default to the right of Pipe, whitespace is trimmed
Iq_ int "Downcase - linuser | 142" // Underscore to the right of member will parse for --iq instead of --Iq
}{}
Parse(&opt)
fmt.Println("Iq =", opt.Iq)
fmt.Println("iq =", opt.Iq_)
if opt.Iq != 42 || opt.Iq_ != 142 {
t.Fail()
}
}
// TestSflag_3 shows how to retrieve unparsed flags out of os.Args[1:]
func TestSflag_3(t *testing.T) {
var opt = struct {
Args []string
}{}
Parse(&opt)
for ii, aa := range opt.Args {
fmt.Println("arg num", ii, ":", aa)
}
if len(opt.Args) != 0 {
t.Fail()
}
}
// TestSflag_4 shows how to set the []string to be parsed instead of os.Args[1:]
func TestSflag_4(t *testing.T) {
var opt = struct {
Age int "Age | 20"
Bar int "Bar | 150"
GDP int "GDP | 10"
Args []string
}{
Args: []string{"--Age", "10", "--Bar", "7", "--GDP", "2", "hello", "world"}, // One way to set what sflag will parse instead of os.Args[1:]
}
Parse(&opt)
fmt.Println("Age =", opt.Age)
fmt.Println("Bar =", opt.Bar)
fmt.Println("GDP =", opt.GDP)
for ii, aa := range opt.Args {
fmt.Println("arg num", ii, ":", aa)
}
if opt.Age != 10 || opt.Bar != 7 || opt.GDP != 2 || len(opt.Args) != 2 || opt.Args[0] != "hello" || opt.Args[1] != "world" {
t.Fail()
}
}
// TestSflag_5 shows pointer members are ignored if non-nil
func TestSflag_5(t *testing.T) {
var opt = struct {
Foo *int "foo | 200"
}{}
foo := 1
opt.Foo = &foo
Parse(&opt)
fmt.Println("Foo", *opt.Foo)
if foo != 1 {
t.Fail()
}
}
// TestSflag_6 shows nil pointer members remain nil if the corresponding flag was not set, else will point to the set value
func TestSflag_6(t *testing.T) {
var opt1 = struct {
Bar *int "bar" // Bar will remain nil if flag was not not set. Note default makes no sense here
}{}
Parse(&opt1)
if opt1.Bar != nil {
fmt.Println("Bar=", *opt1.Bar)
} else {
fmt.Println("Bar was not set")
}
var opt2 = struct {
Bar *int "bar" // Bar will remain nil if flag was not not set. Note default makes no sense here
Args []string
}{Args: []string{"--Bar", "200"}}
Parse(&opt2)
if opt2.Bar != nil {
fmt.Println("Bar=", *opt2.Bar)
} else {
fmt.Println("Bar was not set")
}
if opt1.Bar != nil || opt2.Bar == nil {
t.Fail()
}
if *(opt2.Bar) != 200 {
t.Fail()
}
}
// TestSflag_7 illustrates how to override the "Default value" delineator. Provide your replacement as the first non-alphabetic of the tag
func TestSflag_7(t *testing.T) {
var opt = struct {
SomeCommand string "! is command that might contain pipe char ! 'yes | head'"
}{}
Parse(&opt)
fmt.Println("SomeCommand=", opt.SomeCommand)
if opt.SomeCommand != "'yes | head'" {
t.Fail()
}
}
// TestSflag_8 illustrates how sflag sets the Usage member to the usage string composed from flag members.
func TestSflag_8(t *testing.T) {
var opt = struct {
Usage string "demonstrates upcase and lowcase flags"
Iq int "Upcased - winuser | 42" // Provide default to the right of Pipe, whitespace is trimmed
Iq_ int "Downcase - linuser | 142" // Underscore to the right of member will parse for --iq instead of --Iq
}{}
var oldUsage = opt.Usage
fmt.Printf("Usage before sflag.Parse(%s)\n", opt.Usage)
Parse(&opt)
fmt.Printf("Usage after sflag.Parse(%s)\n", opt.Usage)
if oldUsage == opt.Usage {
t.Fail()
}
}
// TestSflag_9 is the kitchen sink demo
func TestSflag_9(t *testing.T) {
var opt = struct {
Usage string "sflags demonstrator"
SomeFile string "contains the something | /dev/null"
IQ int "do not inflate | 42"
GDP float64 "in Vietnamese Dong | 42000000000000000000000000.0"
Age int64 "in milliseconds since epoch | 42000000000000"
SomeCommand string "! is command that might contain pipe char ! 'yes | head'"
Verbose bool "Bool flags require use of an equals sign syntax (i.e. \"var=value\") to be unambiguous | false"
OutData string " must be writable | /an/output/file"
Foo *int // sflag will ignore both member and tag since it is initialized to non-nil pointer
Bar *int "bar" // sflag will not look for default value in this tag, since it will be a nil pointer
Args []string
ignoreMe string // sflag will ignore low-case members
}{Args: []string{"--Age", "10", "--Bar", "7", "--GDP", "2", "hello", "world"}} // One way to set what sflag will parse instead of os.Args[1:]
foo := 1
opt.Foo = &foo // sflag will ignore this variable since it is a non-nil pointer
Parse(&opt)
fmt.Println("SomeFile=", opt.SomeFile)
fmt.Println("Age=", opt.Age)
fmt.Println("IQ=", opt.IQ)
fmt.Println("GDP=", opt.GDP)
fmt.Println("SomeCommand=", opt.SomeCommand)
fmt.Println("Verbose=", opt.Verbose)
fmt.Println("OutData=", opt.OutData)
if opt.Bar != nil {
fmt.Println("Bar=", *opt.Bar)
} else {
fmt.Println("Bar was not set")
}
for ii, aa := range opt.Args {
fmt.Println("arg num", ii, ":", aa)
}
if opt.SomeFile != "/dev/null" ||
opt.Age != int64(10) ||
opt.IQ != 42 ||
opt.GDP != 2.0 ||
opt.SomeCommand != "'yes | head'" ||
opt.Verbose != false ||
opt.OutData != "/an/output/file" ||
opt.Bar == nil ||
len(opt.Args) != 2 ||
foo != 1 {
t.Fail()
}
if opt.Args[0] != "hello" || opt.Args[1] != "world" || *(opt.Bar) != 7 {
t.Fail()
}
}