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