• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clap::{error::ErrorKind, Arg, ArgAction, Command};
2 
3 #[test]
option_long()4 fn option_long() {
5     let m = Command::new("multiple_values")
6         .arg(
7             Arg::new("option")
8                 .long("option")
9                 .help("multiple options")
10                 .action(ArgAction::Set)
11                 .num_args(1..)
12                 .action(ArgAction::Append),
13         )
14         .try_get_matches_from(vec![
15             "", "--option", "val1", "--option", "val2", "--option", "val3",
16         ]);
17 
18     assert!(m.is_ok(), "{}", m.unwrap_err());
19     let m = m.unwrap();
20 
21     assert!(m.contains_id("option"));
22     assert_eq!(
23         m.get_many::<String>("option")
24             .unwrap()
25             .map(|v| v.as_str())
26             .collect::<Vec<_>>(),
27         ["val1", "val2", "val3"]
28     );
29 }
30 
31 #[test]
option_short()32 fn option_short() {
33     let m = Command::new("multiple_values")
34         .arg(
35             Arg::new("option")
36                 .short('o')
37                 .help("multiple options")
38                 .action(ArgAction::Set)
39                 .num_args(1..)
40                 .action(ArgAction::Append),
41         )
42         .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2", "-o", "val3"]);
43 
44     assert!(m.is_ok(), "{}", m.unwrap_err());
45     let m = m.unwrap();
46 
47     assert!(m.contains_id("option"));
48     assert_eq!(
49         m.get_many::<String>("option")
50             .unwrap()
51             .map(|v| v.as_str())
52             .collect::<Vec<_>>(),
53         ["val1", "val2", "val3"]
54     );
55 }
56 
57 #[test]
option_mixed()58 fn option_mixed() {
59     let m = Command::new("multiple_values")
60         .arg(
61             Arg::new("option")
62                 .long("option")
63                 .short('o')
64                 .help("multiple options")
65                 .action(ArgAction::Set)
66                 .num_args(1..)
67                 .action(ArgAction::Append),
68         )
69         .try_get_matches_from(vec![
70             "", "-o", "val1", "--option", "val2", "--option", "val3", "-o", "val4",
71         ]);
72 
73     assert!(m.is_ok(), "{}", m.unwrap_err());
74     let m = m.unwrap();
75 
76     assert!(m.contains_id("option"));
77     assert_eq!(
78         m.get_many::<String>("option")
79             .unwrap()
80             .map(|v| v.as_str())
81             .collect::<Vec<_>>(),
82         ["val1", "val2", "val3", "val4"]
83     );
84 }
85 
86 #[test]
option_exact_exact()87 fn option_exact_exact() {
88     let m = Command::new("multiple_values")
89         .arg(
90             Arg::new("option")
91                 .short('o')
92                 .help("multiple options")
93                 .num_args(3)
94                 .action(ArgAction::Append),
95         )
96         .try_get_matches_from(vec![
97             "", "-o", "val1", "val2", "val3", "-o", "val4", "val5", "val6",
98         ]);
99 
100     assert!(m.is_ok(), "{}", m.unwrap_err());
101     let m = m.unwrap();
102 
103     assert!(m.contains_id("option"));
104     assert_eq!(
105         m.get_many::<String>("option")
106             .unwrap()
107             .map(|v| v.as_str())
108             .collect::<Vec<_>>(),
109         ["val1", "val2", "val3", "val4", "val5", "val6"]
110     );
111 }
112 
113 #[test]
option_exact_exact_not_mult()114 fn option_exact_exact_not_mult() {
115     let m = Command::new("multiple_values")
116         .arg(
117             Arg::new("option")
118                 .short('o')
119                 .help("multiple options")
120                 .num_args(3),
121         )
122         .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
123 
124     assert!(m.is_ok(), "{}", m.unwrap_err());
125     let m = m.unwrap();
126 
127     assert!(m.contains_id("option"));
128     assert_eq!(
129         m.get_many::<String>("option")
130             .unwrap()
131             .map(|v| v.as_str())
132             .collect::<Vec<_>>(),
133         ["val1", "val2", "val3"]
134     );
135 }
136 
137 #[test]
option_exact_exact_mult()138 fn option_exact_exact_mult() {
139     let m = Command::new("multiple_values")
140         .arg(
141             Arg::new("option")
142                 .short('o')
143                 .help("multiple options")
144                 .num_args(3)
145                 .action(ArgAction::Append),
146         )
147         .try_get_matches_from(vec![
148             "", "-o", "val1", "val2", "val3", "-o", "val4", "val5", "val6",
149         ]);
150 
151     assert!(m.is_ok(), "{}", m.unwrap_err());
152     let m = m.unwrap();
153 
154     assert!(m.contains_id("option"));
155     assert_eq!(
156         m.get_many::<String>("option")
157             .unwrap()
158             .map(|v| v.as_str())
159             .collect::<Vec<_>>(),
160         ["val1", "val2", "val3", "val4", "val5", "val6"]
161     );
162 }
163 
164 #[test]
option_exact_less()165 fn option_exact_less() {
166     let m = Command::new("multiple_values")
167         .arg(
168             Arg::new("option")
169                 .short('o')
170                 .help("multiple options")
171                 .num_args(3)
172                 .action(ArgAction::Append),
173         )
174         .try_get_matches_from(vec!["", "-o", "val1", "-o", "val2"]);
175 
176     assert!(m.is_err());
177     assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
178 }
179 
180 #[test]
option_exact_more()181 fn option_exact_more() {
182     let m = Command::new("multiple_values")
183         .arg(
184             Arg::new("option")
185                 .short('o')
186                 .help("multiple options")
187                 .num_args(3)
188                 .action(ArgAction::Append),
189         )
190         .try_get_matches_from(vec![
191             "", "-o", "val1", "-o", "val2", "-o", "val3", "-o", "val4",
192         ]);
193 
194     assert!(m.is_err());
195     assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
196 }
197 
198 #[test]
option_min_exact()199 fn option_min_exact() {
200     let m = Command::new("multiple_values")
201         .arg(
202             Arg::new("option")
203                 .short('o')
204                 .help("multiple options")
205                 .num_args(3..)
206                 .action(ArgAction::Set),
207         )
208         .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
209 
210     assert!(m.is_ok(), "{}", m.unwrap_err());
211     let m = m.unwrap();
212 
213     assert!(m.contains_id("option"));
214     assert_eq!(
215         m.get_many::<String>("option")
216             .unwrap()
217             .map(|v| v.as_str())
218             .collect::<Vec<_>>(),
219         ["val1", "val2", "val3"]
220     );
221 }
222 
223 #[test]
option_min_less()224 fn option_min_less() {
225     let m = Command::new("multiple_values")
226         .arg(
227             Arg::new("option")
228                 .short('o')
229                 .help("multiple options")
230                 .num_args(3..)
231                 .action(ArgAction::Set),
232         )
233         .try_get_matches_from(vec!["", "-o", "val1", "val2"]);
234 
235     assert!(m.is_err());
236     assert_eq!(m.unwrap_err().kind(), ErrorKind::TooFewValues);
237 }
238 
239 #[test]
option_short_min_more_mult_occurs()240 fn option_short_min_more_mult_occurs() {
241     let m = Command::new("multiple_values")
242         .arg(Arg::new("arg").required(true))
243         .arg(
244             Arg::new("option")
245                 .short('o')
246                 .help("multiple options")
247                 .num_args(3..)
248                 .action(ArgAction::Set),
249         )
250         .try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]);
251 
252     assert!(m.is_ok(), "{}", m.unwrap_err());
253     let m = m.unwrap();
254 
255     assert!(m.contains_id("option"));
256     assert!(m.contains_id("arg"));
257     assert_eq!(
258         m.get_many::<String>("option")
259             .unwrap()
260             .map(|v| v.as_str())
261             .collect::<Vec<_>>(),
262         ["val1", "val2", "val3", "val4"]
263     );
264     assert_eq!(m.get_one::<String>("arg").map(|v| v.as_str()), Some("pos"));
265 }
266 
267 #[test]
option_short_min_more_single_occur()268 fn option_short_min_more_single_occur() {
269     let m = Command::new("multiple_values")
270         .arg(Arg::new("arg").required(true))
271         .arg(
272             Arg::new("option")
273                 .short('o')
274                 .help("multiple options")
275                 .num_args(3..),
276         )
277         .try_get_matches_from(vec!["", "pos", "-o", "val1", "val2", "val3", "val4"]);
278 
279     assert!(m.is_ok(), "{}", m.unwrap_err());
280     let m = m.unwrap();
281 
282     assert!(m.contains_id("option"));
283     assert!(m.contains_id("arg"));
284     assert_eq!(
285         m.get_many::<String>("option")
286             .unwrap()
287             .map(|v| v.as_str())
288             .collect::<Vec<_>>(),
289         ["val1", "val2", "val3", "val4"]
290     );
291     assert_eq!(m.get_one::<String>("arg").map(|v| v.as_str()), Some("pos"));
292 }
293 
294 #[test]
option_max_exact()295 fn option_max_exact() {
296     let m = Command::new("multiple_values")
297         .arg(
298             Arg::new("option")
299                 .short('o')
300                 .help("multiple options")
301                 .num_args(1..=3)
302                 .action(ArgAction::Set),
303         )
304         .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
305 
306     assert!(m.is_ok(), "{}", m.unwrap_err());
307     let m = m.unwrap();
308 
309     assert!(m.contains_id("option"));
310     assert_eq!(
311         m.get_many::<String>("option")
312             .unwrap()
313             .map(|v| v.as_str())
314             .collect::<Vec<_>>(),
315         ["val1", "val2", "val3"]
316     );
317 }
318 
319 #[test]
option_max_less()320 fn option_max_less() {
321     let m = Command::new("multiple_values")
322         .arg(
323             Arg::new("option")
324                 .short('o')
325                 .help("multiple options")
326                 .num_args(1..=3)
327                 .action(ArgAction::Set),
328         )
329         .try_get_matches_from(vec!["", "-o", "val1", "val2"]);
330 
331     assert!(m.is_ok(), "{}", m.unwrap_err());
332     let m = m.unwrap();
333 
334     assert!(m.contains_id("option"));
335     assert_eq!(
336         m.get_many::<String>("option")
337             .unwrap()
338             .map(|v| v.as_str())
339             .collect::<Vec<_>>(),
340         ["val1", "val2"]
341     );
342 }
343 
344 #[test]
option_max_zero()345 fn option_max_zero() {
346     let m = Command::new("multiple_values")
347         .arg(
348             Arg::new("option")
349                 .short('o')
350                 .help("multiple options")
351                 .num_args(1..=3)
352                 .action(ArgAction::Set),
353         )
354         .try_get_matches_from(vec!["", "-o"]);
355 
356     assert!(m.is_err());
357     assert_eq!(m.unwrap_err().kind(), ErrorKind::InvalidValue);
358 }
359 
360 #[test]
option_max_zero_eq()361 fn option_max_zero_eq() {
362     let m = Command::new("multiple_values")
363         .arg(
364             Arg::new("option")
365                 .short('o')
366                 .help("multiple options")
367                 .num_args(1..=3)
368                 .action(ArgAction::Set),
369         )
370         .try_get_matches_from(vec!["", "-o="]);
371 
372     assert!(m.is_ok(), "{}", m.unwrap_err());
373     let m = m.unwrap();
374 
375     assert!(m.contains_id("option"));
376     assert_eq!(
377         m.get_many::<String>("option")
378             .unwrap()
379             .map(|v| v.as_str())
380             .collect::<Vec<_>>(),
381         [""]
382     );
383 }
384 
385 #[test]
option_max_more()386 fn option_max_more() {
387     let m = Command::new("multiple_values")
388         .arg(
389             Arg::new("option")
390                 .short('o')
391                 .help("multiple options")
392                 .num_args(1..=3)
393                 .action(ArgAction::Set),
394         )
395         .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3", "val4"]);
396 
397     assert!(m.is_err());
398     // Can end up being TooManyValues or UnknownArgument
399     assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
400 }
401 
402 #[test]
optional_value()403 fn optional_value() {
404     let mut cmd = Command::new("test").args_override_self(true).arg(
405         Arg::new("port")
406             .short('p')
407             .value_name("NUM")
408             .num_args(0..=1),
409     );
410 
411     let r = cmd.try_get_matches_from_mut(["test", "-p42"]);
412     assert!(r.is_ok(), "{}", r.unwrap_err());
413     let m = r.unwrap();
414     assert!(m.contains_id("port"));
415     assert_eq!(m.get_one::<String>("port").unwrap(), "42");
416 
417     let r = cmd.try_get_matches_from_mut(["test", "-p"]);
418     assert!(r.is_ok(), "{}", r.unwrap_err());
419     let m = r.unwrap();
420     assert!(m.contains_id("port"));
421     assert!(m.get_one::<String>("port").is_none());
422 
423     let r = cmd.try_get_matches_from_mut(["test", "-p", "24", "-p", "42"]);
424     assert!(r.is_ok(), "{}", r.unwrap_err());
425     let m = r.unwrap();
426     assert!(m.contains_id("port"));
427     assert_eq!(m.get_one::<String>("port").unwrap(), "42");
428 
429     let help = cmd.render_help().to_string();
430     const HELP: &str = "\
431 Usage: test [OPTIONS]
432 
433 Options:
434   -p [<NUM>]
435   -h, --help      Print help
436 ";
437     snapbox::assert_eq(HELP, help);
438 }
439 
440 #[test]
positional()441 fn positional() {
442     let m = Command::new("multiple_values")
443         .arg(
444             Arg::new("pos")
445                 .help("multiple positionals")
446                 .action(ArgAction::Set)
447                 .num_args(1..),
448         )
449         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
450 
451     assert!(m.is_ok(), "{}", m.unwrap_err());
452     let m = m.unwrap();
453 
454     assert!(m.contains_id("pos"));
455     assert_eq!(
456         m.get_many::<String>("pos")
457             .unwrap()
458             .map(|v| v.as_str())
459             .collect::<Vec<_>>(),
460         ["val1", "val2", "val3"]
461     );
462 }
463 
464 #[test]
positional_exact_exact()465 fn positional_exact_exact() {
466     let m = Command::new("multiple_values")
467         .arg(Arg::new("pos").help("multiple positionals").num_args(3))
468         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
469 
470     assert!(m.is_ok(), "{}", m.unwrap_err());
471     let m = m.unwrap();
472 
473     assert!(m.contains_id("pos"));
474     assert_eq!(
475         m.get_many::<String>("pos")
476             .unwrap()
477             .map(|v| v.as_str())
478             .collect::<Vec<_>>(),
479         ["val1", "val2", "val3"]
480     );
481 }
482 
483 #[test]
positional_exact_less()484 fn positional_exact_less() {
485     let m = Command::new("multiple_values")
486         .arg(Arg::new("pos").help("multiple positionals").num_args(3))
487         .try_get_matches_from(vec!["myprog", "val1", "val2"]);
488 
489     assert!(m.is_err());
490     assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
491 }
492 
493 #[test]
positional_exact_more()494 fn positional_exact_more() {
495     let m = Command::new("multiple_values")
496         .arg(Arg::new("pos").help("multiple positionals").num_args(3))
497         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]);
498 
499     assert!(m.is_err());
500     assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
501 }
502 
503 #[test]
positional_min_exact()504 fn positional_min_exact() {
505     let m = Command::new("multiple_values")
506         .arg(Arg::new("pos").help("multiple positionals").num_args(3..))
507         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
508 
509     assert!(m.is_ok(), "{}", m.unwrap_err());
510     let m = m.unwrap();
511 
512     assert!(m.contains_id("pos"));
513     assert_eq!(
514         m.get_many::<String>("pos")
515             .unwrap()
516             .map(|v| v.as_str())
517             .collect::<Vec<_>>(),
518         ["val1", "val2", "val3"]
519     );
520 }
521 
522 #[test]
positional_min_less()523 fn positional_min_less() {
524     let m = Command::new("multiple_values")
525         .arg(Arg::new("pos").help("multiple positionals").num_args(3..))
526         .try_get_matches_from(vec!["myprog", "val1", "val2"]);
527 
528     assert!(m.is_err());
529     assert_eq!(m.unwrap_err().kind(), ErrorKind::TooFewValues);
530 }
531 
532 #[test]
positional_min_more()533 fn positional_min_more() {
534     let m = Command::new("multiple_values")
535         .arg(Arg::new("pos").help("multiple positionals").num_args(3..))
536         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]);
537 
538     assert!(m.is_ok(), "{}", m.unwrap_err());
539     let m = m.unwrap();
540 
541     assert!(m.contains_id("pos"));
542     assert_eq!(
543         m.get_many::<String>("pos")
544             .unwrap()
545             .map(|v| v.as_str())
546             .collect::<Vec<_>>(),
547         ["val1", "val2", "val3", "val4"]
548     );
549 }
550 
551 #[test]
positional_max_exact()552 fn positional_max_exact() {
553     let m = Command::new("multiple_values")
554         .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3))
555         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
556 
557     assert!(m.is_ok(), "{}", m.unwrap_err());
558     let m = m.unwrap();
559 
560     assert!(m.contains_id("pos"));
561     assert_eq!(
562         m.get_many::<String>("pos")
563             .unwrap()
564             .map(|v| v.as_str())
565             .collect::<Vec<_>>(),
566         ["val1", "val2", "val3"]
567     );
568 }
569 
570 #[test]
positional_max_less()571 fn positional_max_less() {
572     let m = Command::new("multiple_values")
573         .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3))
574         .try_get_matches_from(vec!["myprog", "val1", "val2"]);
575 
576     assert!(m.is_ok(), "{}", m.unwrap_err());
577     let m = m.unwrap();
578 
579     assert!(m.contains_id("pos"));
580     assert_eq!(
581         m.get_many::<String>("pos")
582             .unwrap()
583             .map(|v| v.as_str())
584             .collect::<Vec<_>>(),
585         ["val1", "val2"]
586     );
587 }
588 
589 #[test]
positional_max_more()590 fn positional_max_more() {
591     let m = Command::new("multiple_values")
592         .arg(Arg::new("pos").help("multiple positionals").num_args(1..=3))
593         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3", "val4"]);
594 
595     assert!(m.is_err());
596     assert_eq!(m.unwrap_err().kind(), ErrorKind::TooManyValues);
597 }
598 
599 #[test]
sep_long_equals()600 fn sep_long_equals() {
601     let m = Command::new("multiple_values")
602         .arg(
603             Arg::new("option")
604                 .long("option")
605                 .help("multiple options")
606                 .value_delimiter(','),
607         )
608         .try_get_matches_from(vec!["", "--option=val1,val2,val3"]);
609 
610     assert!(m.is_ok(), "{}", m.unwrap_err());
611     let m = m.unwrap();
612 
613     assert!(m.contains_id("option"));
614     assert_eq!(
615         m.get_many::<String>("option")
616             .unwrap()
617             .map(|v| v.as_str())
618             .collect::<Vec<_>>(),
619         ["val1", "val2", "val3"]
620     );
621 }
622 
623 #[test]
sep_long_space()624 fn sep_long_space() {
625     let m = Command::new("multiple_values")
626         .arg(
627             Arg::new("option")
628                 .long("option")
629                 .help("multiple options")
630                 .value_delimiter(','),
631         )
632         .try_get_matches_from(vec!["", "--option", "val1,val2,val3"]);
633 
634     assert!(m.is_ok(), "{}", m.unwrap_err());
635     let m = m.unwrap();
636 
637     assert!(m.contains_id("option"));
638     assert_eq!(
639         m.get_many::<String>("option")
640             .unwrap()
641             .map(|v| v.as_str())
642             .collect::<Vec<_>>(),
643         ["val1", "val2", "val3"]
644     );
645 }
646 
647 #[test]
sep_short_equals()648 fn sep_short_equals() {
649     let m = Command::new("multiple_values")
650         .arg(
651             Arg::new("option")
652                 .short('o')
653                 .help("multiple options")
654                 .value_delimiter(','),
655         )
656         .try_get_matches_from(vec!["", "-o=val1,val2,val3"]);
657 
658     assert!(m.is_ok(), "{}", m.unwrap_err());
659     let m = m.unwrap();
660 
661     assert!(m.contains_id("option"));
662     assert_eq!(
663         m.get_many::<String>("option")
664             .unwrap()
665             .map(|v| v.as_str())
666             .collect::<Vec<_>>(),
667         ["val1", "val2", "val3"]
668     );
669 }
670 
671 #[test]
sep_short_space()672 fn sep_short_space() {
673     let m = Command::new("multiple_values")
674         .arg(
675             Arg::new("option")
676                 .short('o')
677                 .help("multiple options")
678                 .value_delimiter(','),
679         )
680         .try_get_matches_from(vec!["", "-o", "val1,val2,val3"]);
681 
682     assert!(m.is_ok(), "{}", m.unwrap_err());
683     let m = m.unwrap();
684 
685     assert!(m.contains_id("option"));
686     assert_eq!(
687         m.get_many::<String>("option")
688             .unwrap()
689             .map(|v| v.as_str())
690             .collect::<Vec<_>>(),
691         ["val1", "val2", "val3"]
692     );
693 }
694 
695 #[test]
sep_short_no_space()696 fn sep_short_no_space() {
697     let m = Command::new("multiple_values")
698         .arg(
699             Arg::new("option")
700                 .short('o')
701                 .help("multiple options")
702                 .value_delimiter(','),
703         )
704         .try_get_matches_from(vec!["", "-oval1,val2,val3"]);
705 
706     assert!(m.is_ok(), "{}", m.unwrap_err());
707     let m = m.unwrap();
708 
709     assert!(m.contains_id("option"));
710     assert_eq!(
711         m.get_many::<String>("option")
712             .unwrap()
713             .map(|v| v.as_str())
714             .collect::<Vec<_>>(),
715         ["val1", "val2", "val3"]
716     );
717 }
718 
719 #[test]
sep_positional()720 fn sep_positional() {
721     let m = Command::new("multiple_values")
722         .arg(
723             Arg::new("option")
724                 .help("multiple options")
725                 .value_delimiter(','),
726         )
727         .try_get_matches_from(vec!["", "val1,val2,val3"]);
728 
729     assert!(m.is_ok(), "{}", m.unwrap_err());
730     let m = m.unwrap();
731 
732     assert!(m.contains_id("option"));
733     assert_eq!(
734         m.get_many::<String>("option")
735             .unwrap()
736             .map(|v| v.as_str())
737             .collect::<Vec<_>>(),
738         ["val1", "val2", "val3"]
739     );
740 }
741 
742 #[test]
different_sep()743 fn different_sep() {
744     let m = Command::new("multiple_values")
745         .arg(
746             Arg::new("option")
747                 .long("option")
748                 .help("multiple options")
749                 .value_delimiter(';'),
750         )
751         .try_get_matches_from(vec!["", "--option=val1;val2;val3"]);
752 
753     assert!(m.is_ok(), "{}", m.unwrap_err());
754     let m = m.unwrap();
755 
756     assert!(m.contains_id("option"));
757     assert_eq!(
758         m.get_many::<String>("option")
759             .unwrap()
760             .map(|v| v.as_str())
761             .collect::<Vec<_>>(),
762         ["val1", "val2", "val3"]
763     );
764 }
765 
766 #[test]
different_sep_positional()767 fn different_sep_positional() {
768     let m = Command::new("multiple_values")
769         .arg(
770             Arg::new("option")
771                 .help("multiple options")
772                 .value_delimiter(';'),
773         )
774         .try_get_matches_from(vec!["", "val1;val2;val3"]);
775 
776     assert!(m.is_ok(), "{}", m.unwrap_err());
777     let m = m.unwrap();
778 
779     assert!(m.contains_id("option"));
780     assert_eq!(
781         m.get_many::<String>("option")
782             .unwrap()
783             .map(|v| v.as_str())
784             .collect::<Vec<_>>(),
785         ["val1", "val2", "val3"]
786     );
787 }
788 
789 #[test]
no_sep()790 fn no_sep() {
791     let m = Command::new("multiple_values")
792         .arg(
793             Arg::new("option")
794                 .long("option")
795                 .help("multiple options")
796                 .action(ArgAction::Set),
797         )
798         .try_get_matches_from(vec!["", "--option=val1,val2,val3"]);
799 
800     assert!(m.is_ok(), "{}", m.unwrap_err());
801     let m = m.unwrap();
802 
803     assert!(m.contains_id("option"));
804     assert_eq!(
805         m.get_one::<String>("option").map(|v| v.as_str()).unwrap(),
806         "val1,val2,val3"
807     );
808 }
809 
810 #[test]
no_sep_positional()811 fn no_sep_positional() {
812     let m = Command::new("multiple_values")
813         .arg(
814             Arg::new("option")
815                 .help("multiple options")
816                 .action(ArgAction::Set),
817         )
818         .try_get_matches_from(vec!["", "val1,val2,val3"]);
819 
820     assert!(m.is_ok(), "{}", m.unwrap_err());
821     let m = m.unwrap();
822 
823     assert!(m.contains_id("option"));
824     assert_eq!(
825         m.get_one::<String>("option").map(|v| v.as_str()).unwrap(),
826         "val1,val2,val3"
827     );
828 }
829 
830 #[test]
req_delimiter_long()831 fn req_delimiter_long() {
832     let m = Command::new("multiple_values")
833         .arg(
834             Arg::new("option")
835                 .long("option")
836                 .num_args(1)
837                 .value_delimiter(','),
838         )
839         .arg(
840             Arg::new("args")
841                 .action(ArgAction::Set)
842                 .num_args(1..)
843                 .index(1),
844         )
845         .try_get_matches_from(vec!["", "--option", "val1", "val2", "val3"]);
846 
847     assert!(m.is_ok(), "{}", m.unwrap_err());
848     let m = m.unwrap();
849 
850     assert!(m.contains_id("option"));
851     assert_eq!(
852         m.get_many::<String>("option")
853             .unwrap()
854             .map(|v| v.as_str())
855             .collect::<Vec<_>>(),
856         ["val1"]
857     );
858     assert_eq!(
859         m.get_many::<String>("args")
860             .unwrap()
861             .map(|v| v.as_str())
862             .collect::<Vec<_>>(),
863         ["val2", "val3"]
864     );
865 }
866 
867 #[test]
req_delimiter_long_with_equal()868 fn req_delimiter_long_with_equal() {
869     let m = Command::new("multiple_values")
870         .arg(
871             Arg::new("option")
872                 .long("option")
873                 .num_args(1)
874                 .value_delimiter(','),
875         )
876         .arg(
877             Arg::new("args")
878                 .action(ArgAction::Set)
879                 .num_args(1..)
880                 .index(1),
881         )
882         .try_get_matches_from(vec!["", "--option=val1", "val2", "val3"]);
883 
884     assert!(m.is_ok(), "{}", m.unwrap_err());
885     let m = m.unwrap();
886 
887     assert!(m.contains_id("option"));
888     assert_eq!(
889         m.get_many::<String>("option")
890             .unwrap()
891             .map(|v| v.as_str())
892             .collect::<Vec<_>>(),
893         ["val1"]
894     );
895     assert_eq!(
896         m.get_many::<String>("args")
897             .unwrap()
898             .map(|v| v.as_str())
899             .collect::<Vec<_>>(),
900         ["val2", "val3"]
901     );
902 }
903 
904 #[test]
req_delimiter_short_with_space()905 fn req_delimiter_short_with_space() {
906     let m = Command::new("multiple_values")
907         .arg(
908             Arg::new("option")
909                 .short('o')
910                 .num_args(1)
911                 .value_delimiter(','),
912         )
913         .arg(
914             Arg::new("args")
915                 .action(ArgAction::Set)
916                 .num_args(1..)
917                 .index(1),
918         )
919         .try_get_matches_from(vec!["", "-o", "val1", "val2", "val3"]);
920 
921     assert!(m.is_ok(), "{}", m.unwrap_err());
922     let m = m.unwrap();
923 
924     assert!(m.contains_id("option"));
925     assert_eq!(
926         m.get_many::<String>("option")
927             .unwrap()
928             .map(|v| v.as_str())
929             .collect::<Vec<_>>(),
930         ["val1"]
931     );
932     assert_eq!(
933         m.get_many::<String>("args")
934             .unwrap()
935             .map(|v| v.as_str())
936             .collect::<Vec<_>>(),
937         ["val2", "val3"]
938     );
939 }
940 
941 #[test]
req_delimiter_short_with_no_space()942 fn req_delimiter_short_with_no_space() {
943     let m = Command::new("multiple_values")
944         .arg(
945             Arg::new("option")
946                 .short('o')
947                 .num_args(1)
948                 .value_delimiter(','),
949         )
950         .arg(
951             Arg::new("args")
952                 .action(ArgAction::Set)
953                 .num_args(1..)
954                 .index(1),
955         )
956         .try_get_matches_from(vec!["", "-oval1", "val2", "val3"]);
957 
958     assert!(m.is_ok(), "{}", m.unwrap_err());
959     let m = m.unwrap();
960 
961     assert!(m.contains_id("option"));
962     assert_eq!(
963         m.get_many::<String>("option")
964             .unwrap()
965             .map(|v| v.as_str())
966             .collect::<Vec<_>>(),
967         ["val1"]
968     );
969     assert_eq!(
970         m.get_many::<String>("args")
971             .unwrap()
972             .map(|v| v.as_str())
973             .collect::<Vec<_>>(),
974         ["val2", "val3"]
975     );
976 }
977 
978 #[test]
req_delimiter_short_with_equal()979 fn req_delimiter_short_with_equal() {
980     let m = Command::new("multiple_values")
981         .arg(
982             Arg::new("option")
983                 .short('o')
984                 .num_args(1)
985                 .value_delimiter(','),
986         )
987         .arg(
988             Arg::new("args")
989                 .action(ArgAction::Set)
990                 .num_args(1..)
991                 .index(1),
992         )
993         .try_get_matches_from(vec!["", "-o=val1", "val2", "val3"]);
994 
995     assert!(m.is_ok(), "{}", m.unwrap_err());
996     let m = m.unwrap();
997 
998     assert!(m.contains_id("option"));
999     assert_eq!(
1000         m.get_many::<String>("option")
1001             .unwrap()
1002             .map(|v| v.as_str())
1003             .collect::<Vec<_>>(),
1004         ["val1"]
1005     );
1006     assert_eq!(
1007         m.get_many::<String>("args")
1008             .unwrap()
1009             .map(|v| v.as_str())
1010             .collect::<Vec<_>>(),
1011         ["val2", "val3"]
1012     );
1013 }
1014 
1015 #[test]
req_delimiter_complex()1016 fn req_delimiter_complex() {
1017     let m = Command::new("multiple_values")
1018         .arg(
1019             Arg::new("option")
1020                 .long("option")
1021                 .short('o')
1022                 .num_args(1)
1023                 .action(ArgAction::Append)
1024                 .value_delimiter(','),
1025         )
1026         .arg(Arg::new("args").num_args(1..).index(1))
1027         .try_get_matches_from(vec![
1028             "",
1029             "val1",
1030             "-oval2",
1031             "val3",
1032             "-o",
1033             "val4",
1034             "val5",
1035             "-o=val6",
1036             "val7",
1037             "--option=val8",
1038             "val9",
1039             "--option",
1040             "val10",
1041             "val11",
1042             "-oval12,val13",
1043             "val14",
1044             "-o",
1045             "val15,val16",
1046             "val17",
1047             "-o=val18,val19",
1048             "val20",
1049             "--option=val21,val22",
1050             "val23",
1051             "--option",
1052             "val24,val25",
1053             "val26",
1054         ]);
1055 
1056     assert!(m.is_ok(), "{}", m.unwrap_err());
1057     let m = m.unwrap();
1058 
1059     assert!(m.contains_id("option"));
1060     assert_eq!(
1061         m.get_many::<String>("option")
1062             .unwrap()
1063             .map(|v| v.as_str())
1064             .collect::<Vec<_>>(),
1065         [
1066             "val2", "val4", "val6", "val8", "val10", "val12", "val13", "val15", "val16", "val18",
1067             "val19", "val21", "val22", "val24", "val25",
1068         ]
1069     );
1070     assert_eq!(
1071         m.get_many::<String>("args")
1072             .unwrap()
1073             .map(|v| v.as_str())
1074             .collect::<Vec<_>>(),
1075         [
1076             "val1", "val3", "val5", "val7", "val9", "val11", "val14", "val17", "val20", "val23",
1077             "val26",
1078         ]
1079     );
1080 }
1081 
1082 // This tests a programmer error and will only succeed with debug_assertions
1083 #[cfg(debug_assertions)]
1084 #[test]
1085 #[should_panic = "When using a positional argument with \
1086 `.num_args(1..)` that is *not the last* positional argument, the last \
1087 positional argument (i.e. the one with the highest index) *must* have \
1088 .required(true) or .last(true) set."]
low_index_positional_not_required()1089 fn low_index_positional_not_required() {
1090     let _ = Command::new("lip")
1091         .arg(
1092             Arg::new("files")
1093                 .index(1)
1094                 .action(ArgAction::Set)
1095                 .required(true)
1096                 .num_args(1..),
1097         )
1098         .arg(Arg::new("target").index(2))
1099         .try_get_matches_from(vec![""]);
1100 }
1101 
1102 // This tests a programmer error and will only succeed with debug_assertions
1103 #[cfg(debug_assertions)]
1104 #[test]
1105 #[should_panic = "Only one positional argument with `.num_args(1..)` \
1106 set is allowed per command, unless the second one also has .last(true) set"]
low_index_positional_last_multiple_too()1107 fn low_index_positional_last_multiple_too() {
1108     let _ = Command::new("lip")
1109         .arg(
1110             Arg::new("files")
1111                 .index(1)
1112                 .action(ArgAction::Set)
1113                 .required(true)
1114                 .num_args(1..),
1115         )
1116         .arg(
1117             Arg::new("target")
1118                 .index(2)
1119                 .action(ArgAction::Set)
1120                 .required(true)
1121                 .num_args(1..),
1122         )
1123         .try_get_matches_from(vec![""]);
1124 }
1125 
1126 // This tests a programmer error and will only succeed with debug_assertions
1127 #[cfg(debug_assertions)]
1128 #[test]
1129 #[should_panic = "Only the last positional argument, or second to \
1130 last positional argument may be set to `.num_args(1..)`"]
low_index_positional_too_far_back()1131 fn low_index_positional_too_far_back() {
1132     let _ = Command::new("lip")
1133         .arg(
1134             Arg::new("files")
1135                 .index(1)
1136                 .action(ArgAction::Set)
1137                 .required(true)
1138                 .num_args(1..),
1139         )
1140         .arg(Arg::new("target").required(true).index(2))
1141         .arg(Arg::new("target2").required(true).index(3))
1142         .try_get_matches_from(vec![""]);
1143 }
1144 
1145 #[test]
low_index_positional()1146 fn low_index_positional() {
1147     let m = Command::new("lip")
1148         .arg(
1149             Arg::new("files")
1150                 .index(1)
1151                 .action(ArgAction::Set)
1152                 .required(true)
1153                 .num_args(1..),
1154         )
1155         .arg(Arg::new("target").index(2).required(true))
1156         .try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target"]);
1157 
1158     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1159     let m = m.unwrap();
1160 
1161     assert!(m.contains_id("files"));
1162     assert_eq!(
1163         m.get_many::<String>("files")
1164             .unwrap()
1165             .map(|v| v.as_str())
1166             .collect::<Vec<_>>(),
1167         ["file1", "file2", "file3"]
1168     );
1169     assert!(m.contains_id("target"));
1170     assert_eq!(
1171         m.get_one::<String>("target").map(|v| v.as_str()).unwrap(),
1172         "target"
1173     );
1174 }
1175 
1176 #[test]
low_index_positional_in_subcmd()1177 fn low_index_positional_in_subcmd() {
1178     let m = Command::new("lip")
1179         .subcommand(
1180             Command::new("test")
1181                 .arg(
1182                     Arg::new("files")
1183                         .index(1)
1184                         .action(ArgAction::Set)
1185                         .required(true)
1186                         .num_args(1..),
1187                 )
1188                 .arg(Arg::new("target").index(2).required(true)),
1189         )
1190         .try_get_matches_from(vec!["lip", "test", "file1", "file2", "file3", "target"]);
1191 
1192     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1193     let m = m.unwrap();
1194     let sm = m.subcommand_matches("test").unwrap();
1195 
1196     assert!(sm.contains_id("files"));
1197     assert_eq!(
1198         sm.get_many::<String>("files")
1199             .unwrap()
1200             .map(|v| v.as_str())
1201             .collect::<Vec<_>>(),
1202         ["file1", "file2", "file3"]
1203     );
1204     assert!(sm.contains_id("target"));
1205     assert_eq!(
1206         sm.get_one::<String>("target").map(|v| v.as_str()).unwrap(),
1207         "target"
1208     );
1209 }
1210 
1211 #[test]
low_index_positional_with_option()1212 fn low_index_positional_with_option() {
1213     let m = Command::new("lip")
1214         .arg(
1215             Arg::new("files")
1216                 .required(true)
1217                 .index(1)
1218                 .action(ArgAction::Set)
1219                 .num_args(1..),
1220         )
1221         .arg(Arg::new("target").index(2).required(true))
1222         .arg(Arg::new("opt").long("option").action(ArgAction::Set))
1223         .try_get_matches_from(vec![
1224             "lip", "file1", "file2", "file3", "target", "--option", "test",
1225         ]);
1226 
1227     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1228     let m = m.unwrap();
1229 
1230     assert!(m.contains_id("files"));
1231     assert_eq!(
1232         m.get_many::<String>("files")
1233             .unwrap()
1234             .map(|v| v.as_str())
1235             .collect::<Vec<_>>(),
1236         ["file1", "file2", "file3"]
1237     );
1238     assert!(m.contains_id("target"));
1239     assert_eq!(
1240         m.get_one::<String>("target").map(|v| v.as_str()).unwrap(),
1241         "target"
1242     );
1243     assert_eq!(
1244         m.get_one::<String>("opt").map(|v| v.as_str()).unwrap(),
1245         "test"
1246     );
1247 }
1248 
1249 #[test]
low_index_positional_with_flag()1250 fn low_index_positional_with_flag() {
1251     let m = Command::new("lip")
1252         .arg(
1253             Arg::new("files")
1254                 .index(1)
1255                 .action(ArgAction::Set)
1256                 .required(true)
1257                 .num_args(1..),
1258         )
1259         .arg(Arg::new("target").index(2).required(true))
1260         .arg(Arg::new("flg").long("flag").action(ArgAction::SetTrue))
1261         .try_get_matches_from(vec!["lip", "file1", "file2", "file3", "target", "--flag"]);
1262 
1263     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1264     let m = m.unwrap();
1265 
1266     assert!(m.contains_id("files"));
1267     assert_eq!(
1268         m.get_many::<String>("files")
1269             .unwrap()
1270             .map(|v| v.as_str())
1271             .collect::<Vec<_>>(),
1272         ["file1", "file2", "file3"]
1273     );
1274     assert!(m.contains_id("target"));
1275     assert_eq!(
1276         m.get_one::<String>("target").map(|v| v.as_str()).unwrap(),
1277         "target"
1278     );
1279     assert!(*m.get_one::<bool>("flg").expect("defaulted by clap"));
1280 }
1281 
1282 #[test]
low_index_positional_with_extra_flags()1283 fn low_index_positional_with_extra_flags() {
1284     let cmd = Command::new("test")
1285         .arg(Arg::new("yes").long("yes").action(ArgAction::SetTrue))
1286         .arg(Arg::new("one").long("one").action(ArgAction::Set))
1287         .arg(Arg::new("two").long("two").action(ArgAction::Set))
1288         .arg(Arg::new("input").num_args(1..).required(true))
1289         .arg(Arg::new("output").required(true));
1290     let m = cmd.try_get_matches_from([
1291         "test", "--one", "1", "--two", "2", "3", "4", "5", "6", "7", "8",
1292     ]);
1293 
1294     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1295     let m = m.unwrap();
1296 
1297     assert_eq!(
1298         m.get_many::<String>("input")
1299             .unwrap()
1300             .into_iter()
1301             .map(String::from)
1302             .collect::<Vec<_>>(),
1303         vec![
1304             "3".to_owned(),
1305             "4".to_owned(),
1306             "5".to_owned(),
1307             "6".to_owned(),
1308             "7".to_owned()
1309         ],
1310     );
1311     assert_eq!(m.get_one::<String>("output").unwrap(), "8");
1312     assert_eq!(m.get_one::<String>("one").unwrap(), "1");
1313     assert_eq!(m.get_one::<String>("two").unwrap(), "2");
1314     assert!(!m.get_flag("yes"));
1315 }
1316 
1317 #[test]
multiple_value_terminator_option()1318 fn multiple_value_terminator_option() {
1319     let m = Command::new("lip")
1320         .arg(
1321             Arg::new("files")
1322                 .short('f')
1323                 .value_terminator(";")
1324                 .action(ArgAction::Set)
1325                 .num_args(1..),
1326         )
1327         .arg(Arg::new("other"))
1328         .try_get_matches_from(vec!["lip", "-f", "val1", "val2", ";", "otherval"]);
1329 
1330     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1331     let m = m.unwrap();
1332 
1333     assert!(m.contains_id("other"));
1334     assert!(m.contains_id("files"));
1335     assert_eq!(
1336         m.get_many::<String>("files")
1337             .unwrap()
1338             .map(|v| v.as_str())
1339             .collect::<Vec<_>>(),
1340         ["val1", "val2"]
1341     );
1342     assert_eq!(
1343         m.get_one::<String>("other").map(|v| v.as_str()),
1344         Some("otherval")
1345     );
1346 }
1347 
1348 #[test]
multiple_value_terminator_option_other_arg()1349 fn multiple_value_terminator_option_other_arg() {
1350     let m = Command::new("lip")
1351         .arg(
1352             Arg::new("files")
1353                 .short('f')
1354                 .value_terminator(";")
1355                 .action(ArgAction::Set)
1356                 .num_args(1..),
1357         )
1358         .arg(Arg::new("other"))
1359         .arg(Arg::new("flag").short('F').action(ArgAction::SetTrue))
1360         .try_get_matches_from(vec!["lip", "-f", "val1", "val2", "-F", "otherval"]);
1361 
1362     assert!(m.is_ok(), "{:?}", m.unwrap_err().kind());
1363     let m = m.unwrap();
1364 
1365     assert!(m.contains_id("other"));
1366     assert!(m.contains_id("files"));
1367     assert_eq!(
1368         m.get_many::<String>("files")
1369             .unwrap()
1370             .map(|v| v.as_str())
1371             .collect::<Vec<_>>(),
1372         ["val1", "val2"]
1373     );
1374     assert_eq!(
1375         m.get_one::<String>("other").map(|v| v.as_str()),
1376         Some("otherval")
1377     );
1378     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
1379 }
1380 
1381 #[test]
multiple_vals_with_hyphen()1382 fn multiple_vals_with_hyphen() {
1383     let res = Command::new("do")
1384         .arg(
1385             Arg::new("cmds")
1386                 .action(ArgAction::Set)
1387                 .num_args(1..)
1388                 .allow_hyphen_values(true)
1389                 .value_terminator(";"),
1390         )
1391         .arg(Arg::new("location"))
1392         .try_get_matches_from(vec![
1393             "do",
1394             "find",
1395             "-type",
1396             "f",
1397             "-name",
1398             "special",
1399             ";",
1400             "/home/clap",
1401         ]);
1402     assert!(res.is_ok(), "{:?}", res.unwrap_err().kind());
1403 
1404     let m = res.unwrap();
1405     let cmds: Vec<_> = m
1406         .get_many::<String>("cmds")
1407         .unwrap()
1408         .map(|v| v.as_str())
1409         .collect();
1410     assert_eq!(&cmds, &["find", "-type", "f", "-name", "special"]);
1411     assert_eq!(
1412         m.get_one::<String>("location").map(|v| v.as_str()),
1413         Some("/home/clap")
1414     );
1415 }
1416 
1417 #[test]
issue_1480_max_values_consumes_extra_arg_1()1418 fn issue_1480_max_values_consumes_extra_arg_1() {
1419     let res = Command::new("prog")
1420         .arg(Arg::new("field").num_args(..=1).long("field"))
1421         .arg(Arg::new("positional").required(true).index(1))
1422         .try_get_matches_from(vec!["prog", "--field", "1", "file"]);
1423 
1424     assert!(res.is_ok(), "{}", res.unwrap_err());
1425 }
1426 
1427 #[test]
issue_1480_max_values_consumes_extra_arg_2()1428 fn issue_1480_max_values_consumes_extra_arg_2() {
1429     let res = Command::new("prog")
1430         .arg(Arg::new("field").num_args(..=1).long("field"))
1431         .try_get_matches_from(vec!["prog", "--field", "1", "2"]);
1432 
1433     assert!(res.is_err());
1434     assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1435 }
1436 
1437 #[test]
issue_1480_max_values_consumes_extra_arg_3()1438 fn issue_1480_max_values_consumes_extra_arg_3() {
1439     let res = Command::new("prog")
1440         .arg(Arg::new("field").num_args(..=1).long("field"))
1441         .try_get_matches_from(vec!["prog", "--field", "1", "2", "3"]);
1442 
1443     assert!(res.is_err());
1444     assert_eq!(res.unwrap_err().kind(), ErrorKind::UnknownArgument);
1445 }
1446 
1447 #[test]
value_names_building_num_vals()1448 fn value_names_building_num_vals() {
1449     let m = Command::new("test")
1450         .arg(
1451             Arg::new("pos")
1452                 .long("pos")
1453                 .value_names(["who", "what", "why"]),
1454         )
1455         .try_get_matches_from(vec!["myprog", "--pos", "val1", "val2", "val3"]);
1456 
1457     assert!(m.is_ok(), "{}", m.unwrap_err());
1458     let m = m.unwrap();
1459 
1460     assert_eq!(
1461         m.get_many::<String>("pos")
1462             .unwrap()
1463             .map(|v| v.as_str())
1464             .collect::<Vec<_>>(),
1465         ["val1", "val2", "val3"]
1466     );
1467 }
1468 
1469 #[test]
value_names_building_num_vals_for_positional()1470 fn value_names_building_num_vals_for_positional() {
1471     let m = Command::new("test")
1472         .arg(Arg::new("pos").value_names(["who", "what", "why"]))
1473         .try_get_matches_from(vec!["myprog", "val1", "val2", "val3"]);
1474 
1475     assert!(m.is_ok(), "{}", m.unwrap_err());
1476     let m = m.unwrap();
1477 
1478     assert_eq!(
1479         m.get_many::<String>("pos")
1480             .unwrap()
1481             .map(|v| v.as_str())
1482             .collect::<Vec<_>>(),
1483         ["val1", "val2", "val3"]
1484     );
1485 }
1486 
1487 #[test]
num_args_preferred_over_value_names()1488 fn num_args_preferred_over_value_names() {
1489     let m = Command::new("test")
1490         .arg(
1491             Arg::new("pos")
1492                 .long("pos")
1493                 .num_args(4)
1494                 .value_names(["who", "what", "why"]),
1495         )
1496         .try_get_matches_from(vec!["myprog", "--pos", "val1", "val2", "val3", "val4"]);
1497 
1498     assert!(m.is_ok(), "{}", m.unwrap_err());
1499     let m = m.unwrap();
1500 
1501     assert_eq!(
1502         m.get_many::<String>("pos")
1503             .unwrap()
1504             .map(|v| v.as_str())
1505             .collect::<Vec<_>>(),
1506         ["val1", "val2", "val3", "val4"]
1507     );
1508 }
1509 
1510 #[test]
values_per_occurrence_named()1511 fn values_per_occurrence_named() {
1512     let mut a = Command::new("test").arg(
1513         Arg::new("pos")
1514             .long("pos")
1515             .num_args(2)
1516             .action(ArgAction::Append),
1517     );
1518 
1519     let m = a.try_get_matches_from_mut(vec!["myprog", "--pos", "val1", "val2"]);
1520     assert!(m.is_ok(), "{}", m.unwrap_err());
1521     let m = m.unwrap();
1522     assert_eq!(
1523         m.get_many::<String>("pos")
1524             .unwrap()
1525             .map(|v| v.as_str())
1526             .collect::<Vec<_>>(),
1527         ["val1", "val2"]
1528     );
1529 
1530     let m = a.try_get_matches_from_mut(vec![
1531         "myprog", "--pos", "val1", "val2", "--pos", "val3", "val4",
1532     ]);
1533     let m = match m {
1534         Ok(m) => m,
1535         Err(err) => panic!("{}", err),
1536     };
1537     assert_eq!(
1538         m.get_many::<String>("pos")
1539             .unwrap()
1540             .map(|v| v.as_str())
1541             .collect::<Vec<_>>(),
1542         ["val1", "val2", "val3", "val4"]
1543     );
1544 }
1545 
1546 #[test]
values_per_occurrence_positional()1547 fn values_per_occurrence_positional() {
1548     let mut a = Command::new("test").arg(Arg::new("pos").num_args(2).action(ArgAction::Append));
1549 
1550     let m = a.try_get_matches_from_mut(vec!["myprog", "val1", "val2"]);
1551     assert!(m.is_ok(), "{}", m.unwrap_err());
1552     let m = m.unwrap();
1553     assert_eq!(
1554         m.get_many::<String>("pos")
1555             .unwrap()
1556             .map(|v| v.as_str())
1557             .collect::<Vec<_>>(),
1558         ["val1", "val2"]
1559     );
1560 }
1561 
1562 #[test]
issue_2229()1563 fn issue_2229() {
1564     let m = Command::new("multiple_values")
1565         .arg(Arg::new("pos").help("multiple positionals").num_args(3))
1566         .try_get_matches_from(vec![
1567             "myprog", "val1", "val2", "val3", "val4", "val5", "val6",
1568         ]);
1569 
1570     assert!(m.is_err());
1571     assert_eq!(m.unwrap_err().kind(), ErrorKind::WrongNumberOfValues);
1572 }
1573 
1574 #[test]
1575 #[should_panic = "Argument 'pos` is positional, it must take a value"]
disallow_positionals_without_values()1576 fn disallow_positionals_without_values() {
1577     let cmd = Command::new("test").arg(Arg::new("pos").num_args(0));
1578     cmd.debug_assert();
1579 }
1580