@@ -77,13 +77,32 @@ func TestSameWords(t *testing.T) {
7777 test (f , f , true )
7878}
7979
80+ func testOptionHelper (t * testing.T , cmd * cmds.Command , args string , expectedOpts kvs , expectedWords words , expectErr bool ) {
81+ req := & cmds.Request {}
82+ err := parse (req , strings .Split (args , " " ), cmd )
83+ if err == nil {
84+ err = req .FillDefaults ()
85+ }
86+ if expectErr {
87+ if err == nil {
88+ t .Errorf ("Command line '%v' parsing should have failed" , args )
89+ }
90+ } else if err != nil {
91+ t .Errorf ("Command line '%v' failed to parse: %v" , args , err )
92+ } else if ! sameWords (req .Arguments , expectedWords ) || ! sameKVs (kvs (req .Options ), expectedOpts ) {
93+ t .Errorf ("Command line '%v':\n parsed as %v %v\n instead of %v %v" ,
94+ args , req .Options , req .Arguments , expectedOpts , expectedWords )
95+ }
96+ }
97+
8098func TestOptionParsing (t * testing.T ) {
8199 cmd := & cmds.Command {
82100 Options : []cmds.Option {
83101 cmds .StringOption ("string" , "s" , "a string" ),
84102 cmds .StringOption ("flag" , "alias" , "multiple long" ),
85103 cmds .BoolOption ("bool" , "b" , "a bool" ),
86104 cmds .StringsOption ("strings" , "r" , "strings array" ),
105+ cmds .DelimitedStringsOption ("," , "delimstrings" , "d" , "comma delimited string array" ),
87106 },
88107 Subcommands : map [string ]* cmds.Command {
89108 "test" : & cmds.Command {},
@@ -95,30 +114,12 @@ func TestOptionParsing(t *testing.T) {
95114 },
96115 }
97116
98- testHelper := func (args string , expectedOpts kvs , expectedWords words , expectErr bool ) {
99- req := & cmds.Request {}
100- err := parse (req , strings .Split (args , " " ), cmd )
101- if err == nil {
102- err = req .FillDefaults ()
103- }
104- if expectErr {
105- if err == nil {
106- t .Errorf ("Command line '%v' parsing should have failed" , args )
107- }
108- } else if err != nil {
109- t .Errorf ("Command line '%v' failed to parse: %v" , args , err )
110- } else if ! sameWords (req .Arguments , expectedWords ) || ! sameKVs (kvs (req .Options ), expectedOpts ) {
111- t .Errorf ("Command line '%v':\n parsed as %v %v\n instead of %v %v" ,
112- args , req .Options , req .Arguments , expectedOpts , expectedWords )
113- }
114- }
115-
116117 testFail := func (args string ) {
117- testHelper ( args , kvs {}, words {}, true )
118+ testOptionHelper ( t , cmd , args , kvs {}, words {}, true )
118119 }
119120
120121 test := func (args string , expectedOpts kvs , expectedWords words ) {
121- testHelper ( args , expectedOpts , expectedWords , false )
122+ testOptionHelper ( t , cmd , args , expectedOpts , expectedWords , false )
122123 }
123124
124125 test ("test -" , kvs {}, words {"-" })
@@ -154,6 +155,13 @@ func TestOptionParsing(t *testing.T) {
154155 test ("-b --string foo test bar" , kvs {"bool" : true , "string" : "foo" }, words {"bar" })
155156 test ("-b=false --string bar" , kvs {"bool" : false , "string" : "bar" }, words {})
156157 test ("--strings a --strings b" , kvs {"strings" : []string {"a" , "b" }}, words {})
158+
159+ test ("--delimstrings a,b" , kvs {"delimstrings" : []string {"a" , "b" }}, words {})
160+ test ("--delimstrings=a,b" , kvs {"delimstrings" : []string {"a" , "b" }}, words {})
161+ test ("-d a,b" , kvs {"delimstrings" : []string {"a" , "b" }}, words {})
162+ test ("-d=a,b" , kvs {"delimstrings" : []string {"a" , "b" }}, words {})
163+ test ("-d=a,b -d c --delimstrings d" , kvs {"delimstrings" : []string {"a" , "b" , "c" , "d" }}, words {})
164+
157165 testFail ("foo test" )
158166 test ("defaults" , kvs {"opt" : "def" }, words {})
159167 test ("defaults -o foo" , kvs {"opt" : "foo" }, words {})
@@ -170,6 +178,148 @@ func TestOptionParsing(t *testing.T) {
170178 testFail ("-zz--- --" )
171179}
172180
181+ func TestDefaultOptionParsing (t * testing.T ) {
182+ testPanic := func (f func ()) {
183+ fnFinished := false
184+ defer func () {
185+ if r := recover (); fnFinished == true {
186+ panic (r )
187+ }
188+ }()
189+ f ()
190+ fnFinished = true
191+ t .Error ("expected panic" )
192+ }
193+
194+ testPanic (func () { cmds .StringOption ("string" , "s" , "a string" ).WithDefault (0 ) })
195+ testPanic (func () { cmds .StringOption ("string" , "s" , "a string" ).WithDefault (false ) })
196+ testPanic (func () { cmds .StringOption ("string" , "s" , "a string" ).WithDefault (nil ) })
197+ testPanic (func () { cmds .StringOption ("string" , "s" , "a string" ).WithDefault ([]string {"foo" }) })
198+ testPanic (func () { cmds .StringsOption ("strings" , "a" , "a string array" ).WithDefault (0 ) })
199+ testPanic (func () { cmds .StringsOption ("strings" , "a" , "a string array" ).WithDefault (false ) })
200+ testPanic (func () { cmds .StringsOption ("strings" , "a" , "a string array" ).WithDefault (nil ) })
201+ testPanic (func () { cmds .StringsOption ("strings" , "a" , "a string array" ).WithDefault ("foo" ) })
202+ testPanic (func () { cmds .StringsOption ("strings" , "a" , "a string array" ).WithDefault ([]bool {false }) })
203+ testPanic (func () { cmds .DelimitedStringsOption ("," , "dstrings" , "d" , "delimited string array" ).WithDefault (0 ) })
204+ testPanic (func () { cmds .DelimitedStringsOption ("," , "dstrs" , "d" , "delimited string array" ).WithDefault (false ) })
205+ testPanic (func () { cmds .DelimitedStringsOption ("," , "dstrings" , "d" , "delimited string array" ).WithDefault (nil ) })
206+ testPanic (func () { cmds .DelimitedStringsOption ("," , "dstrs" , "d" , "delimited string array" ).WithDefault ("foo" ) })
207+ testPanic (func () { cmds .DelimitedStringsOption ("," , "dstrs" , "d" , "delimited string array" ).WithDefault ([]int {0 }) })
208+
209+ testPanic (func () { cmds .BoolOption ("bool" , "b" , "a bool" ).WithDefault (0 ) })
210+ testPanic (func () { cmds .BoolOption ("bool" , "b" , "a bool" ).WithDefault (1 ) })
211+ testPanic (func () { cmds .BoolOption ("bool" , "b" , "a bool" ).WithDefault (nil ) })
212+ testPanic (func () { cmds .BoolOption ("bool" , "b" , "a bool" ).WithDefault ([]bool {false }) })
213+ testPanic (func () { cmds .BoolOption ("bool" , "b" , "a bool" ).WithDefault ([]string {"foo" }) })
214+
215+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (int (0 )) })
216+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (int32 (0 )) })
217+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (int64 (0 )) })
218+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (uint64 (0 )) })
219+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (uint32 (0 )) })
220+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (float32 (0 )) })
221+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (float64 (0 )) })
222+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (nil ) })
223+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault ([]uint {0 }) })
224+ testPanic (func () { cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault ([]string {"foo" }) })
225+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (int (0 )) })
226+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (int32 (0 )) })
227+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (int64 (0 )) })
228+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (uint (0 )) })
229+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (uint32 (0 )) })
230+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (float32 (0 )) })
231+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (float64 (0 )) })
232+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (nil ) })
233+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault ([]uint64 {0 }) })
234+ testPanic (func () { cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault ([]string {"foo" }) })
235+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (int32 (0 )) })
236+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (int64 (0 )) })
237+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (uint (0 )) })
238+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (uint32 (0 )) })
239+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (uint64 (0 )) })
240+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (float32 (0 )) })
241+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (float64 (0 )) })
242+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault (nil ) })
243+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault ([]int {0 }) })
244+ testPanic (func () { cmds .IntOption ("int" , "i" , "an int" ).WithDefault ([]string {"foo" }) })
245+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (int (0 )) })
246+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (int32 (0 )) })
247+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (uint (0 )) })
248+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (uint32 (0 )) })
249+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (uint64 (0 )) })
250+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (float32 (0 )) })
251+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (float64 (0 )) })
252+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (nil ) })
253+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault ([]int64 {0 }) })
254+ testPanic (func () { cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault ([]string {"foo" }) })
255+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (int (0 )) })
256+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (int32 (0 )) })
257+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (int64 (0 )) })
258+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (uint (0 )) })
259+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (uint32 (0 )) })
260+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (uint64 (0 )) })
261+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (float32 (0 )) })
262+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (nil ) })
263+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault ([]int {0 }) })
264+ testPanic (func () { cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault ([]string {"foo" }) })
265+
266+ cmd := & cmds.Command {
267+ Subcommands : map [string ]* cmds.Command {
268+ "defaults" : & cmds.Command {
269+ Options : []cmds.Option {
270+ cmds .StringOption ("string" , "s" , "a string" ).WithDefault ("foo" ),
271+ cmds .StringsOption ("strings1" , "a" , "a string array" ).WithDefault ([]string {"foo" }),
272+ cmds .StringsOption ("strings2" , "b" , "a string array" ).WithDefault ([]string {"foo" , "bar" }),
273+ cmds .DelimitedStringsOption ("," , "dstrings1" , "c" , "a delimited string array" ).WithDefault ([]string {"foo" }),
274+ cmds .DelimitedStringsOption ("," , "dstrings2" , "d" , "a delimited string array" ).WithDefault ([]string {"foo" , "bar" }),
275+
276+ cmds .BoolOption ("boolT" , "t" , "a bool" ).WithDefault (true ),
277+ cmds .BoolOption ("boolF" , "a bool" ).WithDefault (false ),
278+
279+ cmds .UintOption ("uint" , "u" , "a uint" ).WithDefault (uint (1 )),
280+ cmds .Uint64Option ("uint64" , "v" , "a uint64" ).WithDefault (uint64 (1 )),
281+ cmds .IntOption ("int" , "i" , "an int" ).WithDefault (int (1 )),
282+ cmds .Int64Option ("int64" , "j" , "an int64" ).WithDefault (int64 (1 )),
283+ cmds .FloatOption ("float" , "f" , "a float64" ).WithDefault (float64 (1 )),
284+ },
285+ },
286+ },
287+ }
288+
289+ test := func (args string , expectedOpts kvs , expectedWords words ) {
290+ testOptionHelper (t , cmd , args , expectedOpts , expectedWords , false )
291+ }
292+
293+ test ("defaults" , kvs {
294+ "string" : "foo" ,
295+ "strings1" : []string {"foo" },
296+ "strings2" : []string {"foo" , "bar" },
297+ "dstrings1" : []string {"foo" },
298+ "dstrings2" : []string {"foo" , "bar" },
299+ "boolT" : true ,
300+ "boolF" : false ,
301+ "uint" : uint (1 ),
302+ "uint64" : uint64 (1 ),
303+ "int" : int (1 ),
304+ "int64" : int64 (1 ),
305+ "float" : float64 (1 ),
306+ }, words {})
307+ test ("defaults --string baz --strings1=baz -b baz -b=foo -c=foo -d=foo,baz,bing -d=zip,zap -d=zorp -t=false --boolF -u=0 -v=10 -i=-5 -j=10 -f=-3.14" , kvs {
308+ "string" : "baz" ,
309+ "strings1" : []string {"baz" },
310+ "strings2" : []string {"baz" , "foo" },
311+ "dstrings1" : []string {"foo" },
312+ "dstrings2" : []string {"foo" , "baz" , "bing" , "zip" , "zap" , "zorp" },
313+ "boolT" : false ,
314+ "boolF" : true ,
315+ "uint" : uint (0 ),
316+ "uint64" : uint64 (10 ),
317+ "int" : int (- 5 ),
318+ "int64" : int64 (10 ),
319+ "float" : float64 (- 3.14 ),
320+ }, words {})
321+ }
322+
173323func TestArgumentParsing (t * testing.T ) {
174324 rootCmd := & cmds.Command {
175325 Subcommands : map [string ]* cmds.Command {
0 commit comments