1package flags
2
3import (
4	"fmt"
5	"testing"
6)
7
8func TestCommandInline(t *testing.T) {
9	var opts = struct {
10		Value bool `short:"v"`
11
12		Command struct {
13			G bool `short:"g"`
14		} `command:"cmd"`
15	}{}
16
17	p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g")
18
19	assertStringArray(t, ret, []string{})
20
21	if p.Active == nil {
22		t.Errorf("Expected active command")
23	}
24
25	if !opts.Value {
26		t.Errorf("Expected Value to be true")
27	}
28
29	if !opts.Command.G {
30		t.Errorf("Expected Command.G to be true")
31	}
32
33	if p.Command.Find("cmd") != p.Active {
34		t.Errorf("Expected to find command `cmd' to be active")
35	}
36}
37
38func TestCommandInlineMulti(t *testing.T) {
39	var opts = struct {
40		Value bool `short:"v"`
41
42		C1 struct {
43		} `command:"c1"`
44
45		C2 struct {
46			G bool `short:"g"`
47		} `command:"c2"`
48	}{}
49
50	p, ret := assertParserSuccess(t, &opts, "-v", "c2", "-g")
51
52	assertStringArray(t, ret, []string{})
53
54	if p.Active == nil {
55		t.Errorf("Expected active command")
56	}
57
58	if !opts.Value {
59		t.Errorf("Expected Value to be true")
60	}
61
62	if !opts.C2.G {
63		t.Errorf("Expected C2.G to be true")
64	}
65
66	if p.Command.Find("c1") == nil {
67		t.Errorf("Expected to find command `c1'")
68	}
69
70	if c2 := p.Command.Find("c2"); c2 == nil {
71		t.Errorf("Expected to find command `c2'")
72	} else if c2 != p.Active {
73		t.Errorf("Expected to find command `c2' to be active")
74	}
75}
76
77func TestCommandFlagOrder1(t *testing.T) {
78	var opts = struct {
79		Value bool `short:"v"`
80
81		Command struct {
82			G bool `short:"g"`
83		} `command:"cmd"`
84	}{}
85
86	assertParseFail(t, ErrUnknownFlag, "unknown flag `g'", &opts, "-v", "-g", "cmd")
87}
88
89func TestCommandFlagOrder2(t *testing.T) {
90	var opts = struct {
91		Value bool `short:"v"`
92
93		Command struct {
94			G bool `short:"g"`
95		} `command:"cmd"`
96	}{}
97
98	assertParseSuccess(t, &opts, "cmd", "-v", "-g")
99
100	if !opts.Value {
101		t.Errorf("Expected Value to be true")
102	}
103
104	if !opts.Command.G {
105		t.Errorf("Expected Command.G to be true")
106	}
107}
108
109func TestCommandFlagOrderSub(t *testing.T) {
110	var opts = struct {
111		Value bool `short:"v"`
112
113		Command struct {
114			G bool `short:"g"`
115
116			SubCommand struct {
117				B bool `short:"b"`
118			} `command:"sub"`
119		} `command:"cmd"`
120	}{}
121
122	assertParseSuccess(t, &opts, "cmd", "sub", "-v", "-g", "-b")
123
124	if !opts.Value {
125		t.Errorf("Expected Value to be true")
126	}
127
128	if !opts.Command.G {
129		t.Errorf("Expected Command.G to be true")
130	}
131
132	if !opts.Command.SubCommand.B {
133		t.Errorf("Expected Command.SubCommand.B to be true")
134	}
135}
136
137func TestCommandFlagOverride1(t *testing.T) {
138	var opts = struct {
139		Value bool `short:"v"`
140
141		Command struct {
142			Value bool `short:"v"`
143		} `command:"cmd"`
144	}{}
145
146	assertParseSuccess(t, &opts, "-v", "cmd")
147
148	if !opts.Value {
149		t.Errorf("Expected Value to be true")
150	}
151
152	if opts.Command.Value {
153		t.Errorf("Expected Command.Value to be false")
154	}
155}
156
157func TestCommandFlagOverride2(t *testing.T) {
158	var opts = struct {
159		Value bool `short:"v"`
160
161		Command struct {
162			Value bool `short:"v"`
163		} `command:"cmd"`
164	}{}
165
166	assertParseSuccess(t, &opts, "cmd", "-v")
167
168	if opts.Value {
169		t.Errorf("Expected Value to be false")
170	}
171
172	if !opts.Command.Value {
173		t.Errorf("Expected Command.Value to be true")
174	}
175}
176
177func TestCommandFlagOverrideSub(t *testing.T) {
178	var opts = struct {
179		Value bool `short:"v"`
180
181		Command struct {
182			Value bool `short:"v"`
183
184			SubCommand struct {
185				Value bool `short:"v"`
186			} `command:"sub"`
187		} `command:"cmd"`
188	}{}
189
190	assertParseSuccess(t, &opts, "cmd", "sub", "-v")
191
192	if opts.Value {
193		t.Errorf("Expected Value to be false")
194	}
195
196	if opts.Command.Value {
197		t.Errorf("Expected Command.Value to be false")
198	}
199
200	if !opts.Command.SubCommand.Value {
201		t.Errorf("Expected Command.Value to be true")
202	}
203}
204
205func TestCommandFlagOverrideSub2(t *testing.T) {
206	var opts = struct {
207		Value bool `short:"v"`
208
209		Command struct {
210			Value bool `short:"v"`
211
212			SubCommand struct {
213				G bool `short:"g"`
214			} `command:"sub"`
215		} `command:"cmd"`
216	}{}
217
218	assertParseSuccess(t, &opts, "cmd", "sub", "-v")
219
220	if opts.Value {
221		t.Errorf("Expected Value to be false")
222	}
223
224	if !opts.Command.Value {
225		t.Errorf("Expected Command.Value to be true")
226	}
227}
228
229func TestCommandEstimate(t *testing.T) {
230	var opts = struct {
231		Value bool `short:"v"`
232
233		Cmd1 struct {
234		} `command:"remove"`
235
236		Cmd2 struct {
237		} `command:"add"`
238	}{}
239
240	p := NewParser(&opts, None)
241	_, err := p.ParseArgs([]string{})
242
243	assertError(t, err, ErrCommandRequired, "Please specify one command of: add or remove")
244}
245
246func TestCommandEstimate2(t *testing.T) {
247	var opts = struct {
248		Value bool `short:"v"`
249
250		Cmd1 struct {
251		} `command:"remove"`
252
253		Cmd2 struct {
254		} `command:"add"`
255	}{}
256
257	p := NewParser(&opts, None)
258	_, err := p.ParseArgs([]string{"rmive"})
259
260	assertError(t, err, ErrUnknownCommand, "Unknown command `rmive', did you mean `remove'?")
261}
262
263type testCommand struct {
264	G        bool `short:"g"`
265	Executed bool
266	EArgs    []string
267}
268
269func (c *testCommand) Execute(args []string) error {
270	c.Executed = true
271	c.EArgs = args
272
273	return nil
274}
275
276func TestCommandExecute(t *testing.T) {
277	var opts = struct {
278		Value bool `short:"v"`
279
280		Command testCommand `command:"cmd"`
281	}{}
282
283	assertParseSuccess(t, &opts, "-v", "cmd", "-g", "a", "b")
284
285	if !opts.Value {
286		t.Errorf("Expected Value to be true")
287	}
288
289	if !opts.Command.Executed {
290		t.Errorf("Did not execute command")
291	}
292
293	if !opts.Command.G {
294		t.Errorf("Expected Command.C to be true")
295	}
296
297	assertStringArray(t, opts.Command.EArgs, []string{"a", "b"})
298}
299
300func TestCommandClosest(t *testing.T) {
301	var opts = struct {
302		Value bool `short:"v"`
303
304		Cmd1 struct {
305		} `command:"remove"`
306
307		Cmd2 struct {
308		} `command:"add"`
309	}{}
310
311	args := assertParseFail(t, ErrUnknownCommand, "Unknown command `addd', did you mean `add'?", &opts, "-v", "addd")
312
313	assertStringArray(t, args, []string{"addd"})
314}
315
316func TestCommandAdd(t *testing.T) {
317	var opts = struct {
318		Value bool `short:"v"`
319	}{}
320
321	var cmd = struct {
322		G bool `short:"g"`
323	}{}
324
325	p := NewParser(&opts, Default)
326	c, err := p.AddCommand("cmd", "", "", &cmd)
327
328	if err != nil {
329		t.Fatalf("Unexpected error: %v", err)
330		return
331	}
332
333	ret, err := p.ParseArgs([]string{"-v", "cmd", "-g", "rest"})
334
335	if err != nil {
336		t.Fatalf("Unexpected error: %v", err)
337		return
338	}
339
340	assertStringArray(t, ret, []string{"rest"})
341
342	if !opts.Value {
343		t.Errorf("Expected Value to be true")
344	}
345
346	if !cmd.G {
347		t.Errorf("Expected Command.G to be true")
348	}
349
350	if p.Command.Find("cmd") != c {
351		t.Errorf("Expected to find command `cmd'")
352	}
353
354	if p.Commands()[0] != c {
355		t.Errorf("Expected command %#v, but got %#v", c, p.Commands()[0])
356	}
357
358	if c.Options()[0].ShortName != 'g' {
359		t.Errorf("Expected short name `g' but got %v", c.Options()[0].ShortName)
360	}
361}
362
363func TestCommandNestedInline(t *testing.T) {
364	var opts = struct {
365		Value bool `short:"v"`
366
367		Command struct {
368			G bool `short:"g"`
369
370			Nested struct {
371				N string `long:"n"`
372			} `command:"nested"`
373		} `command:"cmd"`
374	}{}
375
376	p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g", "nested", "--n", "n", "rest")
377
378	assertStringArray(t, ret, []string{"rest"})
379
380	if !opts.Value {
381		t.Errorf("Expected Value to be true")
382	}
383
384	if !opts.Command.G {
385		t.Errorf("Expected Command.G to be true")
386	}
387
388	assertString(t, opts.Command.Nested.N, "n")
389
390	if c := p.Command.Find("cmd"); c == nil {
391		t.Errorf("Expected to find command `cmd'")
392	} else {
393		if c != p.Active {
394			t.Errorf("Expected `cmd' to be the active parser command")
395		}
396
397		if nested := c.Find("nested"); nested == nil {
398			t.Errorf("Expected to find command `nested'")
399		} else if nested != c.Active {
400			t.Errorf("Expected to find command `nested' to be the active `cmd' command")
401		}
402	}
403}
404
405func TestRequiredOnCommand(t *testing.T) {
406	var opts = struct {
407		Value bool `short:"v" required:"true"`
408
409		Command struct {
410			G bool `short:"g"`
411		} `command:"cmd"`
412	}{}
413
414	assertParseFail(t, ErrRequired, fmt.Sprintf("the required flag `%cv' was not specified", defaultShortOptDelimiter), &opts, "cmd")
415}
416
417func TestRequiredAllOnCommand(t *testing.T) {
418	var opts = struct {
419		Value   bool `short:"v" required:"true"`
420		Missing bool `long:"missing" required:"true"`
421
422		Command struct {
423			G bool `short:"g"`
424		} `command:"cmd"`
425	}{}
426
427	assertParseFail(t, ErrRequired, fmt.Sprintf("the required flags `%smissing' and `%cv' were not specified", defaultLongOptDelimiter, defaultShortOptDelimiter), &opts, "cmd")
428}
429
430func TestDefaultOnCommand(t *testing.T) {
431	var opts = struct {
432		Command struct {
433			G bool `short:"g" default:"true"`
434		} `command:"cmd"`
435	}{}
436
437	assertParseSuccess(t, &opts, "cmd")
438
439	if !opts.Command.G {
440		t.Errorf("Expected G to be true")
441	}
442}
443
444func TestSubcommandsOptional(t *testing.T) {
445	var opts = struct {
446		Value bool `short:"v"`
447
448		Cmd1 struct {
449		} `command:"remove"`
450
451		Cmd2 struct {
452		} `command:"add"`
453	}{}
454
455	p := NewParser(&opts, None)
456	p.SubcommandsOptional = true
457
458	_, err := p.ParseArgs([]string{"-v"})
459
460	if err != nil {
461		t.Fatalf("Unexpected error: %v", err)
462		return
463	}
464
465	if !opts.Value {
466		t.Errorf("Expected Value to be true")
467	}
468}
469
470func TestCommandAlias(t *testing.T) {
471	var opts = struct {
472		Command struct {
473			G bool `short:"g" default:"true"`
474		} `command:"cmd" alias:"cm"`
475	}{}
476
477	assertParseSuccess(t, &opts, "cm")
478
479	if !opts.Command.G {
480		t.Errorf("Expected G to be true")
481	}
482}
483
484func TestSubCommandFindOptionByLongFlag(t *testing.T) {
485	var opts struct {
486		Testing bool `long:"testing" description:"Testing"`
487	}
488
489	var cmd struct {
490		Other bool `long:"other" description:"Other"`
491	}
492
493	p := NewParser(&opts, Default)
494	c, _ := p.AddCommand("command", "Short", "Long", &cmd)
495
496	opt := c.FindOptionByLongName("other")
497
498	if opt == nil {
499		t.Errorf("Expected option, but found none")
500	}
501
502	assertString(t, opt.LongName, "other")
503
504	opt = c.FindOptionByLongName("testing")
505
506	if opt == nil {
507		t.Errorf("Expected option, but found none")
508	}
509
510	assertString(t, opt.LongName, "testing")
511}
512
513func TestSubCommandFindOptionByShortFlag(t *testing.T) {
514	var opts struct {
515		Testing bool `short:"t" description:"Testing"`
516	}
517
518	var cmd struct {
519		Other bool `short:"o" description:"Other"`
520	}
521
522	p := NewParser(&opts, Default)
523	c, _ := p.AddCommand("command", "Short", "Long", &cmd)
524
525	opt := c.FindOptionByShortName('o')
526
527	if opt == nil {
528		t.Errorf("Expected option, but found none")
529	}
530
531	if opt.ShortName != 'o' {
532		t.Errorf("Expected 'o', but got %v", opt.ShortName)
533	}
534
535	opt = c.FindOptionByShortName('t')
536
537	if opt == nil {
538		t.Errorf("Expected option, but found none")
539	}
540
541	if opt.ShortName != 't' {
542		t.Errorf("Expected 'o', but got %v", opt.ShortName)
543	}
544}
545