Skip to content

Commit 0564106

Browse files
committed
test combinations of args validators
1 parent 7f00a25 commit 0564106

3 files changed

Lines changed: 225 additions & 22 deletions

File tree

args.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ func NoArgs(cmd *Command, args []string) error {
3232
return nil
3333
}
3434

35-
// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
35+
// OnlyValidArgs returns an error if there are any positional args that are not in
36+
// the `ValidArgs` field of `Command`
3637
func OnlyValidArgs(cmd *Command, args []string) error {
3738
if len(cmd.ValidArgs) > 0 {
3839
// Remove any description that may be included in ValidArgs.
@@ -41,7 +42,6 @@ func OnlyValidArgs(cmd *Command, args []string) error {
4142
for _, v := range cmd.ValidArgs {
4243
validArgs = append(validArgs, strings.Split(v, "\t")[0])
4344
}
44-
4545
for _, v := range args {
4646
if !stringInSlice(v, validArgs) {
4747
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))

args_test.go

Lines changed: 215 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func expectSuccess(output string, err error, t *testing.T) {
2727
}
2828
}
2929

30-
func validWithInvalidArgs(err error, t *testing.T) {
30+
func validOnlyWithInvalidArgs(err error, t *testing.T) {
3131
if err == nil {
3232
t.Fatal("Expected an error")
3333
}
@@ -43,7 +43,7 @@ func noArgsWithArgs(err error, t *testing.T) {
4343
t.Fatal("Expected an error")
4444
}
4545
got := err.Error()
46-
expected := `unknown command "illegal" for "c"`
46+
expected := `unknown command "one" for "c"`
4747
if got != expected {
4848
t.Errorf("Expected: %q, got: %q", expected, got)
4949
}
@@ -93,84 +93,280 @@ func rangeArgsWithInvalidCount(err error, t *testing.T) {
9393
}
9494
}
9595

96+
// NoArgs
97+
9698
func TestNoArgs(t *testing.T) {
9799
c := getCommand(NoArgs, false)
98100
output, err := executeCommand(c)
99101
expectSuccess(output, err, t)
100102
}
101103

102-
func TestNoArgsWithArgs(t *testing.T) {
104+
func TestNoArgs_WithArgs(t *testing.T) {
103105
c := getCommand(NoArgs, false)
104-
_, err := executeCommand(c, "illegal")
106+
_, err := executeCommand(c, "one")
107+
noArgsWithArgs(err, t)
108+
}
109+
110+
func TestNoArgs_WithValid_WithArgs(t *testing.T) {
111+
c := getCommand(NoArgs, true)
112+
_, err := executeCommand(c, "one")
113+
noArgsWithArgs(err, t)
114+
}
115+
116+
func TestNoArgs_WithValid_WithInvalidArgs(t *testing.T) {
117+
c := getCommand(NoArgs, true)
118+
_, err := executeCommand(c, "one")
105119
noArgsWithArgs(err, t)
106120
}
107121

122+
func TestNoArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
123+
c := getCommand(MatchAll(OnlyValidArgs, NoArgs), true)
124+
_, err := executeCommand(c, "a")
125+
validOnlyWithInvalidArgs(err, t)
126+
}
127+
128+
// OnlyValidArgs
129+
108130
func TestOnlyValidArgs(t *testing.T) {
109131
c := getCommand(OnlyValidArgs, true)
110132
output, err := executeCommand(c, "one", "two")
111133
expectSuccess(output, err, t)
112134
}
113135

114-
func TestOnlyValidArgsWithInvalidArgs(t *testing.T) {
136+
func TestOnlyValidArgs_WithInvalidArgs(t *testing.T) {
115137
c := getCommand(OnlyValidArgs, true)
116138
_, err := executeCommand(c, "a")
117-
validWithInvalidArgs(err, t)
139+
validOnlyWithInvalidArgs(err, t)
118140
}
119141

142+
// ArbitraryArgs
143+
120144
func TestArbitraryArgs(t *testing.T) {
121145
c := getCommand(ArbitraryArgs, false)
122146
output, err := executeCommand(c, "a", "b")
123147
expectSuccess(output, err, t)
124148
}
125149

150+
func TestArbitraryArgs_WithValid(t *testing.T) {
151+
c := getCommand(ArbitraryArgs, true)
152+
output, err := executeCommand(c, "one", "two")
153+
expectSuccess(output, err, t)
154+
}
155+
156+
func TestArbitraryArgs_WithValid_WithInvalidArgs(t *testing.T) {
157+
c := getCommand(ArbitraryArgs, true)
158+
output, err := executeCommand(c, "a")
159+
expectSuccess(output, err, t)
160+
}
161+
162+
func TestArbitraryArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
163+
c := getCommand(MatchAll(OnlyValidArgs, ArbitraryArgs), true)
164+
_, err := executeCommand(c, "a")
165+
validOnlyWithInvalidArgs(err, t)
166+
}
167+
168+
// MinimumNArgs
169+
126170
func TestMinimumNArgs(t *testing.T) {
127171
c := getCommand(MinimumNArgs(2), false)
128172
output, err := executeCommand(c, "a", "b", "c")
129173
expectSuccess(output, err, t)
130174
}
131175

132-
func TestMinimumNArgsWithLessArgs(t *testing.T) {
176+
func TestMinimumNArgs_WithValid(t *testing.T) {
177+
c := getCommand(MinimumNArgs(2), true)
178+
output, err := executeCommand(c, "one", "three")
179+
expectSuccess(output, err, t)
180+
}
181+
182+
func TestMinimumNArgs_WithValid__WithInvalidArgs(t *testing.T) {
183+
c := getCommand(MinimumNArgs(2), true)
184+
output, err := executeCommand(c, "a", "b")
185+
expectSuccess(output, err, t)
186+
}
187+
188+
func TestMinimumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
189+
c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
190+
_, err := executeCommand(c, "a", "b")
191+
validOnlyWithInvalidArgs(err, t)
192+
}
193+
194+
func TestMinimumNArgs_WithLessArgs(t *testing.T) {
133195
c := getCommand(MinimumNArgs(2), false)
134196
_, err := executeCommand(c, "a")
135197
minimumNArgsWithLessArgs(err, t)
136198
}
137199

200+
func TestMinimumNArgs_WithLessArgs_WithValid(t *testing.T) {
201+
c := getCommand(MinimumNArgs(2), true)
202+
_, err := executeCommand(c, "one")
203+
minimumNArgsWithLessArgs(err, t)
204+
}
205+
206+
func TestMinimumNArgs_WithLessArgs_WithValid_WithInvalidArgs(t *testing.T) {
207+
c := getCommand(MinimumNArgs(2), true)
208+
_, err := executeCommand(c, "a")
209+
minimumNArgsWithLessArgs(err, t)
210+
}
211+
212+
func TestMinimumNArgs_WithLessArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
213+
c := getCommand(MatchAll(OnlyValidArgs, MinimumNArgs(2)), true)
214+
_, err := executeCommand(c, "a")
215+
validOnlyWithInvalidArgs(err, t)
216+
}
217+
218+
// MaximumNArgs
219+
138220
func TestMaximumNArgs(t *testing.T) {
139221
c := getCommand(MaximumNArgs(3), false)
140222
output, err := executeCommand(c, "a", "b")
141223
expectSuccess(output, err, t)
142224
}
143225

144-
func TestMaximumNArgsWithMoreArgs(t *testing.T) {
226+
func TestMaximumNArgs_WithValid(t *testing.T) {
227+
c := getCommand(MaximumNArgs(2), true)
228+
output, err := executeCommand(c, "one", "three")
229+
expectSuccess(output, err, t)
230+
}
231+
232+
func TestMaximumNArgs_WithValid_WithInvalidArgs(t *testing.T) {
233+
c := getCommand(MaximumNArgs(2), true)
234+
output, err := executeCommand(c, "a", "b")
235+
expectSuccess(output, err, t)
236+
}
237+
238+
func TestMaximumNArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
239+
c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
240+
_, err := executeCommand(c, "a", "b")
241+
validOnlyWithInvalidArgs(err, t)
242+
}
243+
244+
func TestMaximumNArgs_WithMoreArgs(t *testing.T) {
145245
c := getCommand(MaximumNArgs(2), false)
146246
_, err := executeCommand(c, "a", "b", "c")
147247
maximumNArgsWithMoreArgs(err, t)
148248
}
149249

250+
func TestMaximumNArgs_WithMoreArgs_WithValid(t *testing.T) {
251+
c := getCommand(MaximumNArgs(2), true)
252+
_, err := executeCommand(c, "one", "three", "two")
253+
maximumNArgsWithMoreArgs(err, t)
254+
}
255+
256+
func TestMaximumNArgs_WithMoreArgs_WithValid_WithInvalidArgs(t *testing.T) {
257+
c := getCommand(MaximumNArgs(2), true)
258+
_, err := executeCommand(c, "a", "b", "c")
259+
maximumNArgsWithMoreArgs(err, t)
260+
}
261+
262+
func TestMaximumNArgs_WithMoreArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
263+
c := getCommand(MatchAll(OnlyValidArgs, MaximumNArgs(2)), true)
264+
_, err := executeCommand(c, "a", "b", "c")
265+
validOnlyWithInvalidArgs(err, t)
266+
}
267+
268+
// ExactArgs
269+
150270
func TestExactArgs(t *testing.T) {
151271
c := getCommand(ExactArgs(3), false)
152272
output, err := executeCommand(c, "a", "b", "c")
153273
expectSuccess(output, err, t)
154274
}
155275

156-
func TestExactArgsWithInvalidCount(t *testing.T) {
276+
func TestExactArgs_WithValid(t *testing.T) {
277+
c := getCommand(ExactArgs(3), true)
278+
output, err := executeCommand(c, "three", "one", "two")
279+
expectSuccess(output, err, t)
280+
}
281+
282+
func TestExactArgs_WithValid_WithInvalidArgs(t *testing.T) {
283+
c := getCommand(ExactArgs(3), true)
284+
output, err := executeCommand(c, "three", "a", "two")
285+
expectSuccess(output, err, t)
286+
}
287+
288+
func TestExactArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
289+
c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(3)), true)
290+
_, err := executeCommand(c, "three", "a", "two")
291+
validOnlyWithInvalidArgs(err, t)
292+
}
293+
294+
func TestExactArgs_WithInvalidCount(t *testing.T) {
157295
c := getCommand(ExactArgs(2), false)
158296
_, err := executeCommand(c, "a", "b", "c")
159297
exactArgsWithInvalidCount(err, t)
160298
}
161299

300+
func TestExactArgs_WithInvalidCount_WithValid(t *testing.T) {
301+
c := getCommand(ExactArgs(2), true)
302+
_, err := executeCommand(c, "three", "one", "two")
303+
exactArgsWithInvalidCount(err, t)
304+
}
305+
306+
func TestExactArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
307+
c := getCommand(ExactArgs(2), true)
308+
_, err := executeCommand(c, "three", "a", "two")
309+
exactArgsWithInvalidCount(err, t)
310+
}
311+
312+
func TestExactArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
313+
c := getCommand(MatchAll(OnlyValidArgs, ExactArgs(2)), true)
314+
_, err := executeCommand(c, "three", "a", "two")
315+
validOnlyWithInvalidArgs(err, t)
316+
}
317+
318+
// RangeArgs
319+
162320
func TestRangeArgs(t *testing.T) {
163321
c := getCommand(RangeArgs(2, 4), false)
164322
output, err := executeCommand(c, "a", "b", "c")
165323
expectSuccess(output, err, t)
166324
}
167325

168-
func TestRangeArgsWithInvalidCount(t *testing.T) {
326+
func TestRangeArgs_WithValid(t *testing.T) {
327+
c := getCommand(RangeArgs(2, 4), true)
328+
output, err := executeCommand(c, "three", "one", "two")
329+
expectSuccess(output, err, t)
330+
}
331+
332+
func TestRangeArgs_WithValid_WithInvalidArgs(t *testing.T) {
333+
c := getCommand(RangeArgs(2, 4), true)
334+
output, err := executeCommand(c, "three", "a", "two")
335+
expectSuccess(output, err, t)
336+
}
337+
338+
func TestRangeArgs_WithValidOnly_WithInvalidArgs(t *testing.T) {
339+
c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
340+
_, err := executeCommand(c, "three", "a", "two")
341+
validOnlyWithInvalidArgs(err, t)
342+
}
343+
344+
func TestRangeArgs_WithInvalidCount(t *testing.T) {
169345
c := getCommand(RangeArgs(2, 4), false)
170346
_, err := executeCommand(c, "a")
171347
rangeArgsWithInvalidCount(err, t)
172348
}
173349

350+
func TestRangeArgs_WithInvalidCount_WithValid(t *testing.T) {
351+
c := getCommand(RangeArgs(2, 4), true)
352+
_, err := executeCommand(c, "two")
353+
rangeArgsWithInvalidCount(err, t)
354+
}
355+
356+
func TestRangeArgs_WithInvalidCount_WithValid_WithInvalidArgs(t *testing.T) {
357+
c := getCommand(RangeArgs(2, 4), true)
358+
_, err := executeCommand(c, "a")
359+
rangeArgsWithInvalidCount(err, t)
360+
}
361+
362+
func TestRangeArgs_WithInvalidCount_WithValidOnly_WithInvalidArgs(t *testing.T) {
363+
c := getCommand(MatchAll(OnlyValidArgs, RangeArgs(2, 4)), true)
364+
_, err := executeCommand(c, "a")
365+
validOnlyWithInvalidArgs(err, t)
366+
}
367+
368+
// Takes(No)Args
369+
174370
func TestRootTakesNoArgs(t *testing.T) {
175371
rootCmd := &Command{Use: "root", Run: emptyRun}
176372
childCmd := &Command{Use: "child", Run: emptyRun}
@@ -283,16 +479,22 @@ func TestExactValidArgs(t *testing.T) {
283479
expectSuccess(output, err, t)
284480
}
285481

286-
func TestExactValidArgsWithInvalidCount(t *testing.T) {
482+
func TestExactValidArgs_WithInvalidCount(t *testing.T) {
287483
c := getCommand(ExactValidArgs(2), false)
288484
_, err := executeCommand(c, "three", "one", "two")
289485
exactArgsWithInvalidCount(err, t)
290486
}
291487

292-
func TestExactValidArgsWithInvalidArgs(t *testing.T) {
488+
func TestExactValidArgs_WithInvalidCount_WithInvalidArgs(t *testing.T) {
293489
c := getCommand(ExactValidArgs(3), true)
294490
_, err := executeCommand(c, "three", "a", "two")
295-
validWithInvalidArgs(err, t)
491+
validOnlyWithInvalidArgs(err, t)
492+
}
493+
494+
func TestExactValidArgs_WithInvalidArgs(t *testing.T) {
495+
c := getCommand(ExactValidArgs(3), true)
496+
_, err := executeCommand(c, "three", "a")
497+
validOnlyWithInvalidArgs(err, t)
296498
}
297499

298500
// This test make sure we keep backwards-compatibility with respect

user_guide.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,9 +326,7 @@ In both of these cases:
326326

327327
## Positional and Custom Arguments
328328

329-
Validation of positional arguments can be specified using the `Args` field
330-
of `Command`.
331-
329+
Validation of positional arguments can be specified using the `Args` field of `Command`.
332330
The following validators are built in:
333331

334332
- Number of arguments:
@@ -339,8 +337,9 @@ The following validators are built in:
339337
- `ExactArgs(int)` - report an error if there are not exactly N positional args.
340338
- `RangeArgs(min, max)` - report an error if the number of args is not between `min` and `max`.
341339
- Content of the arguments:
342-
- `OnlyValidArgs` - report an error if there are any positional args that are not in the `ValidArgs` field of type
343-
`[]string` defined in `Command`.
340+
- `OnlyValidArgs` - report an error if there are any positional args not specified in the `ValidArgs` field of `Command`, which can optionally be set to a list of valid values for positional args.
341+
342+
If `Args` is undefined or `nil`, it defaults to `ArbitraryArgs`.
344343

345344
Moreover, `MatchAll(pargs ...PositionalArgs)` enables combining existing checks with arbitrary other checks.
346345
For instance, if you want to report an error if there are not exactly N positional args OR if there are any positional
@@ -364,9 +363,11 @@ For example:
364363
var cmd = &cobra.Command{
365364
Short: "hello",
366365
Args: func(cmd *cobra.Command, args []string) error {
367-
if len(args) < 1 {
368-
return errors.New("requires a color argument")
366+
// Optionally run one of the validators provided by cobra
367+
if err := cobra.MinimumNArgs(1)(cmd, args); err != nil {
368+
return err
369369
}
370+
// Run the custom validation logic
370371
if myapp.IsValidColor(args[0]) {
371372
return nil
372373
}

0 commit comments

Comments
 (0)