• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clap::{arg, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
2 
3 #[cfg(feature = "error-context")]
4 use super::utils;
5 
6 #[test]
flag_conflict()7 fn flag_conflict() {
8     let result = Command::new("flag_conflict")
9         .arg(arg!(-f --flag "some flag").conflicts_with("other"))
10         .arg(arg!(-o --other "some flag"))
11         .try_get_matches_from(vec!["myprog", "-f", "-o"]);
12     assert!(result.is_err());
13     let err = result.err().unwrap();
14     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
15 }
16 
17 #[test]
flag_conflict_2()18 fn flag_conflict_2() {
19     let result = Command::new("flag_conflict")
20         .arg(arg!(-f --flag "some flag").conflicts_with("other"))
21         .arg(arg!(-o --other "some flag"))
22         .try_get_matches_from(vec!["myprog", "-o", "-f"]);
23     assert!(result.is_err());
24     let err = result.err().unwrap();
25     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
26 }
27 
28 #[test]
flag_conflict_with_all()29 fn flag_conflict_with_all() {
30     let result = Command::new("flag_conflict")
31         .arg(arg!(-f --flag "some flag").conflicts_with_all(["other"]))
32         .arg(arg!(-o --other "some flag"))
33         .try_get_matches_from(vec!["myprog", "-o", "-f"]);
34     assert!(result.is_err());
35     let err = result.err().unwrap();
36     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
37 }
38 
39 #[test]
exclusive_flag()40 fn exclusive_flag() {
41     let cmd = Command::new("flag_conflict")
42         .arg(arg!(-f --flag "some flag").exclusive(true))
43         .arg(arg!(-o --other "some flag"));
44     let result = cmd.clone().try_get_matches_from(vec!["myprog", "-f"]);
45     assert!(result.is_ok(), "{}", result.unwrap_err());
46 
47     let result = cmd.clone().try_get_matches_from(vec!["myprog", "-o", "-f"]);
48     assert!(result.is_err());
49     let err = result.err().unwrap();
50     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
51 }
52 
53 #[test]
exclusive_option()54 fn exclusive_option() {
55     let result = Command::new("flag_conflict")
56         .arg(arg!(-f --flag <VALUE> "some flag").exclusive(true))
57         .arg(arg!(-o --other <VALUE> "some flag"))
58         .try_get_matches_from(vec!["myprog", "-o=val1", "-f=val2"]);
59     assert!(result.is_err());
60     let err = result.err().unwrap();
61     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
62 }
63 
64 #[test]
not_exclusive_with_defaults()65 fn not_exclusive_with_defaults() {
66     let result = Command::new("flag_conflict")
67         .arg(arg!(-f --flag <VALUE> "some flag").exclusive(true))
68         .arg(
69             arg!(-o --other <VALUE> "some flag")
70                 .required(false)
71                 .default_value("val1"),
72         )
73         .try_get_matches_from(vec!["myprog", "-f=val2"]);
74     assert!(result.is_ok(), "{}", result.unwrap_err());
75 }
76 
77 #[test]
not_exclusive_with_group()78 fn not_exclusive_with_group() {
79     let cmd = Command::new("test")
80         .group(clap::ArgGroup::new("test").arg("foo"))
81         .arg(
82             clap::Arg::new("foo")
83                 .long("foo")
84                 .exclusive(true)
85                 .action(clap::ArgAction::SetTrue),
86         );
87     let result = cmd.try_get_matches_from(vec!["test", "--foo"]);
88     assert!(result.is_ok(), "{}", result.unwrap_err());
89 }
90 
91 #[test]
default_doesnt_activate_exclusive()92 fn default_doesnt_activate_exclusive() {
93     let result = Command::new("flag_conflict")
94         .arg(
95             arg!(-f --flag <VALUE> "some flag")
96                 .exclusive(true)
97                 .default_value("val2"),
98         )
99         .arg(arg!(-o --other <VALUE> "some flag").default_value("val1"))
100         .try_get_matches_from(vec!["myprog"]);
101     assert!(result.is_ok(), "{}", result.unwrap_err());
102 }
103 
104 #[test]
arg_conflicts_with_group()105 fn arg_conflicts_with_group() {
106     let mut cmd = Command::new("group_conflict")
107         .arg(arg!(-f --flag "some flag").conflicts_with("gr"))
108         .group(ArgGroup::new("gr").arg("some").arg("other"))
109         .arg(arg!(--some "some arg"))
110         .arg(arg!(--other "other arg"));
111 
112     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
113     assert!(result.is_err());
114     let err = result.err().unwrap();
115     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
116 
117     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
118     assert!(result.is_err());
119     let err = result.err().unwrap();
120     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
121 
122     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
123     if let Err(err) = result {
124         panic!("{}", err);
125     }
126 
127     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
128     if let Err(err) = result {
129         panic!("{}", err);
130     }
131 
132     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--flag"]);
133     if let Err(err) = result {
134         panic!("{}", err);
135     }
136 }
137 
138 #[test]
arg_conflicts_with_group_with_multiple_sources()139 fn arg_conflicts_with_group_with_multiple_sources() {
140     let mut cmd = clap::Command::new("group_conflict")
141         .arg(clap::arg!(-f --flag "some flag").conflicts_with("gr"))
142         .group(clap::ArgGroup::new("gr").multiple(true))
143         .arg(clap::arg!(--some <name> "some arg").group("gr"))
144         .arg(
145             clap::arg!(--other <secs> "other arg")
146                 .default_value("1000")
147                 .group("gr"),
148         );
149 
150     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f"]);
151     if let Err(err) = result {
152         panic!("{}", err);
153     }
154 
155     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some", "usb1"]);
156     if let Err(err) = result {
157         panic!("{}", err);
158     }
159 
160     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some", "usb1", "--other", "40"]);
161     if let Err(err) = result {
162         panic!("{}", err);
163     }
164 
165     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some", "usb1"]);
166     let err = result.err().unwrap();
167     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
168 }
169 
170 #[test]
group_conflicts_with_arg()171 fn group_conflicts_with_arg() {
172     let mut cmd = Command::new("group_conflict")
173         .arg(arg!(-f --flag "some flag"))
174         .group(
175             ArgGroup::new("gr")
176                 .arg("some")
177                 .arg("other")
178                 .conflicts_with("flag"),
179         )
180         .arg(arg!(--some "some arg"))
181         .arg(arg!(--other "other arg"));
182 
183     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
184     assert!(result.is_err());
185     let err = result.err().unwrap();
186     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
187 
188     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
189     assert!(result.is_err());
190     let err = result.err().unwrap();
191     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
192 
193     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
194     if let Err(err) = result {
195         panic!("{}", err);
196     }
197 
198     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
199     if let Err(err) = result {
200         panic!("{}", err);
201     }
202 
203     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--flag"]);
204     if let Err(err) = result {
205         panic!("{}", err);
206     }
207 }
208 
209 #[test]
arg_conflicts_with_required_group()210 fn arg_conflicts_with_required_group() {
211     let mut cmd = Command::new("group_conflict")
212         .arg(arg!(-f --flag "some flag").conflicts_with("gr"))
213         .group(ArgGroup::new("gr").required(true).arg("some").arg("other"))
214         .arg(arg!(--some "some arg"))
215         .arg(arg!(--other "other arg"));
216 
217     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
218     assert!(result.is_err());
219     let err = result.err().unwrap();
220     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
221 
222     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
223     assert!(result.is_err());
224     let err = result.err().unwrap();
225     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
226 
227     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
228     if let Err(err) = result {
229         panic!("{}", err);
230     }
231 
232     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
233     if let Err(err) = result {
234         panic!("{}", err);
235     }
236 }
237 
238 #[test]
arg_conflicts_with_group_with_required_memeber()239 fn arg_conflicts_with_group_with_required_memeber() {
240     let mut cmd = Command::new("group_conflict")
241         .arg(arg!(-f --flag "some flag").conflicts_with("gr"))
242         .group(ArgGroup::new("gr").arg("some").arg("other"))
243         .arg(arg!(--some "some arg").required(true))
244         .arg(arg!(--other "other arg"));
245 
246     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
247     assert!(result.is_err());
248     let err = result.err().unwrap();
249     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
250 
251     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
252     assert!(result.is_err());
253     let err = result.err().unwrap();
254     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
255 
256     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
257     if let Err(err) = result {
258         panic!("{}", err);
259     }
260 
261     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--flag"]);
262     if let Err(err) = result {
263         panic!("{}", err);
264     }
265 }
266 
267 #[test]
required_group_conflicts_with_arg()268 fn required_group_conflicts_with_arg() {
269     let mut cmd = Command::new("group_conflict")
270         .arg(arg!(-f --flag "some flag"))
271         .group(
272             ArgGroup::new("gr")
273                 .required(true)
274                 .arg("some")
275                 .arg("other")
276                 .conflicts_with("flag"),
277         )
278         .arg(arg!(--some "some arg"))
279         .arg(arg!(--other "other arg"));
280 
281     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other", "-f"]);
282     assert!(result.is_err());
283     let err = result.err().unwrap();
284     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
285 
286     let result = cmd.try_get_matches_from_mut(vec!["myprog", "-f", "--some"]);
287     assert!(result.is_err());
288     let err = result.err().unwrap();
289     assert_eq!(err.kind(), ErrorKind::ArgumentConflict);
290 
291     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--some"]);
292     if let Err(err) = result {
293         panic!("{}", err);
294     }
295 
296     let result = cmd.try_get_matches_from_mut(vec!["myprog", "--other"]);
297     if let Err(err) = result {
298         panic!("{}", err);
299     }
300 }
301 
302 #[test]
get_arg_conflicts_with_group()303 fn get_arg_conflicts_with_group() {
304     let flag = arg!(--flag).conflicts_with("gr");
305     let mut cmd = Command::new("group_conflict")
306         .arg(&flag)
307         .group(ArgGroup::new("gr").arg("some").arg("other"))
308         .arg(arg!(--some))
309         .arg(arg!(--other));
310 
311     cmd.build();
312 
313     let result = cmd.get_arg_conflicts_with(&flag);
314 
315     assert_eq!(result.len(), 2);
316     assert_eq!(result[0].get_id(), "some");
317     assert_eq!(result[1].get_id(), "other");
318 }
319 
320 #[test]
321 #[cfg(feature = "error-context")]
conflict_output()322 fn conflict_output() {
323     static CONFLICT_ERR: &str = "\
324 error: the argument '--flag...' cannot be used with '-F'
325 
326 Usage: clap-test --flag... --long-option-2 <option2> <positional> <positional2> [positional3]...
327 
328 For more information, try '--help'.
329 ";
330 
331     utils::assert_output(
332         utils::complex_app(),
333         "clap-test val1 fa --flag --long-option-2 val2 -F",
334         CONFLICT_ERR,
335         true,
336     );
337 }
338 
339 #[test]
340 #[cfg(feature = "error-context")]
conflict_output_rev()341 fn conflict_output_rev() {
342     static CONFLICT_ERR_REV: &str = "\
343 error: the argument '-F' cannot be used with '--flag...'
344 
345 Usage: clap-test -F --long-option-2 <option2> <positional> <positional2> [positional3]...
346 
347 For more information, try '--help'.
348 ";
349 
350     utils::assert_output(
351         utils::complex_app(),
352         "clap-test val1 fa -F --long-option-2 val2 --flag",
353         CONFLICT_ERR_REV,
354         true,
355     );
356 }
357 
358 #[test]
359 #[cfg(feature = "error-context")]
conflict_output_repeat()360 fn conflict_output_repeat() {
361     static ERR: &str = "\
362 error: the argument '-F' cannot be used multiple times
363 
364 Usage: clap-test [OPTIONS] [positional] [positional2] [positional3]... [COMMAND]
365 
366 For more information, try '--help'.
367 ";
368 
369     utils::assert_output(utils::complex_app(), "clap-test -F -F", ERR, true);
370 }
371 
372 #[test]
373 #[cfg(feature = "error-context")]
conflict_output_with_required()374 fn conflict_output_with_required() {
375     static CONFLICT_ERR: &str = "\
376 error: the argument '--flag...' cannot be used with '-F'
377 
378 Usage: clap-test --flag... --long-option-2 <option2> <positional> <positional2> [positional3]...
379 
380 For more information, try '--help'.
381 ";
382 
383     utils::assert_output(
384         utils::complex_app(),
385         "clap-test val1 --flag --long-option-2 val2 -F",
386         CONFLICT_ERR,
387         true,
388     );
389 }
390 
391 #[test]
392 #[cfg(feature = "error-context")]
conflict_output_rev_with_required()393 fn conflict_output_rev_with_required() {
394     static CONFLICT_ERR_REV: &str = "\
395 error: the argument '-F' cannot be used with '--flag...'
396 
397 Usage: clap-test -F --long-option-2 <option2> <positional> <positional2> [positional3]...
398 
399 For more information, try '--help'.
400 ";
401 
402     utils::assert_output(
403         utils::complex_app(),
404         "clap-test val1 -F --long-option-2 val2 --flag",
405         CONFLICT_ERR_REV,
406         true,
407     );
408 }
409 
410 #[test]
411 #[cfg(feature = "error-context")]
conflict_output_three_conflicting()412 fn conflict_output_three_conflicting() {
413     static CONFLICT_ERR_THREE: &str = "\
414 error: the argument '--one' cannot be used with:
415   --two
416   --three
417 
418 Usage: three_conflicting_arguments --one
419 
420 For more information, try '--help'.
421 ";
422 
423     let cmd = Command::new("three_conflicting_arguments")
424         .arg(
425             Arg::new("one")
426                 .long("one")
427                 .action(ArgAction::SetTrue)
428                 .conflicts_with_all(["two", "three"]),
429         )
430         .arg(
431             Arg::new("two")
432                 .long("two")
433                 .action(ArgAction::SetTrue)
434                 .conflicts_with_all(["one", "three"]),
435         )
436         .arg(
437             Arg::new("three")
438                 .long("three")
439                 .action(ArgAction::SetTrue)
440                 .conflicts_with_all(["one", "two"]),
441         );
442     utils::assert_output(
443         cmd,
444         "three_conflicting_arguments --one --two --three",
445         CONFLICT_ERR_THREE,
446         true,
447     );
448 }
449 
450 #[test]
451 #[cfg(feature = "error-context")]
two_conflicting_arguments()452 fn two_conflicting_arguments() {
453     let a = Command::new("two_conflicting_arguments")
454         .arg(
455             Arg::new("develop")
456                 .long("develop")
457                 .action(ArgAction::SetTrue)
458                 .conflicts_with("production"),
459         )
460         .arg(
461             Arg::new("production")
462                 .long("production")
463                 .action(ArgAction::SetTrue)
464                 .conflicts_with("develop"),
465         )
466         .try_get_matches_from(vec!["", "--develop", "--production"]);
467 
468     assert!(a.is_err());
469     let a = a.unwrap_err();
470     assert!(
471         a.to_string()
472             .contains("the argument \'--develop\' cannot be used with \'--production\'"),
473         "{}",
474         a
475     );
476 }
477 
478 #[test]
479 #[cfg(feature = "error-context")]
three_conflicting_arguments()480 fn three_conflicting_arguments() {
481     let a = Command::new("three_conflicting_arguments")
482         .arg(
483             Arg::new("one")
484                 .long("one")
485                 .action(ArgAction::SetTrue)
486                 .conflicts_with_all(["two", "three"]),
487         )
488         .arg(
489             Arg::new("two")
490                 .long("two")
491                 .action(ArgAction::SetTrue)
492                 .conflicts_with_all(["one", "three"]),
493         )
494         .arg(
495             Arg::new("three")
496                 .long("three")
497                 .action(ArgAction::SetTrue)
498                 .conflicts_with_all(["one", "two"]),
499         )
500         .try_get_matches_from(vec!["", "--one", "--two", "--three"]);
501 
502     assert!(a.is_err());
503     let a = a.unwrap_err();
504     assert!(
505         a.to_string()
506             .contains("the argument \'--one\' cannot be used with:"),
507         "{}",
508         a
509     );
510 }
511 
512 #[cfg(debug_assertions)]
513 #[test]
514 #[should_panic = "Argument 'config' cannot conflict with itself"]
self_conflicting_arg()515 fn self_conflicting_arg() {
516     let _ = Command::new("prog")
517         .arg(Arg::new("config").long("config").conflicts_with("config"))
518         .try_get_matches_from(vec!["", "--config"]);
519 }
520 
521 #[cfg(debug_assertions)]
522 #[test]
523 #[should_panic = "Argument or group 'extra' specified in 'conflicts_with*' for 'config' does not exist"]
conflicts_with_invalid_arg()524 fn conflicts_with_invalid_arg() {
525     let _ = Command::new("prog")
526         .arg(Arg::new("config").long("config").conflicts_with("extra"))
527         .try_get_matches_from(vec!["", "--config"]);
528 }
529 
530 #[test]
conflict_with_unused_default()531 fn conflict_with_unused_default() {
532     let result = Command::new("conflict")
533         .arg(arg!(-o --opt <opt> "some opt").default_value("default"))
534         .arg(
535             arg!(-f --flag "some flag")
536                 .conflicts_with("opt")
537                 .action(ArgAction::SetTrue),
538         )
539         .try_get_matches_from(vec!["myprog", "-f"]);
540 
541     assert!(result.is_ok(), "{}", result.unwrap_err());
542     let m = result.unwrap();
543 
544     assert_eq!(
545         m.get_one::<String>("opt").map(|v| v.as_str()),
546         Some("default")
547     );
548     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
549 }
550 
551 #[test]
conflicts_with_alongside_default()552 fn conflicts_with_alongside_default() {
553     let result = Command::new("conflict")
554         .arg(
555             arg!(-o --opt <opt> "some opt")
556                 .default_value("default")
557                 .conflicts_with("flag"),
558         )
559         .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
560         .try_get_matches_from(vec!["myprog", "-f"]);
561 
562     assert!(
563         result.is_ok(),
564         "conflicts_with should ignore default_value: {:?}",
565         result.unwrap_err()
566     );
567     let m = result.unwrap();
568 
569     assert_eq!(
570         m.get_one::<String>("opt").map(|v| v.as_str()),
571         Some("default")
572     );
573     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
574 }
575 
576 #[test]
group_in_conflicts_with()577 fn group_in_conflicts_with() {
578     let result = Command::new("conflict")
579         .arg(
580             Arg::new("opt")
581                 .long("opt")
582                 .default_value("default")
583                 .group("one"),
584         )
585         .arg(
586             Arg::new("flag")
587                 .long("flag")
588                 .conflicts_with("one")
589                 .action(ArgAction::SetTrue),
590         )
591         .try_get_matches_from(vec!["myprog", "--flag"]);
592 
593     assert!(
594         result.is_ok(),
595         "conflicts_with on an arg group should ignore default_value: {:?}",
596         result.unwrap_err()
597     );
598     let m = result.unwrap();
599 
600     assert_eq!(
601         m.get_one::<String>("opt").map(|v| v.as_str()),
602         Some("default")
603     );
604     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
605 }
606 
607 #[test]
group_conflicts_with_default_value()608 fn group_conflicts_with_default_value() {
609     let result = Command::new("conflict")
610         .arg(
611             Arg::new("opt")
612                 .long("opt")
613                 .default_value("default")
614                 .group("one"),
615         )
616         .arg(
617             Arg::new("flag")
618                 .long("flag")
619                 .group("one")
620                 .action(ArgAction::SetTrue),
621         )
622         .try_get_matches_from(vec!["myprog", "--flag"]);
623 
624     assert!(
625         result.is_ok(),
626         "arg group count should ignore default_value: {:?}",
627         result.unwrap_err()
628     );
629     let m = result.unwrap();
630 
631     assert_eq!(
632         m.get_one::<String>("opt").map(|v| v.as_str()),
633         Some("default")
634     );
635     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
636 }
637 
638 #[test]
group_conflicts_with_default_arg()639 fn group_conflicts_with_default_arg() {
640     let result = Command::new("conflict")
641         .arg(Arg::new("opt").long("opt").default_value("default"))
642         .arg(
643             Arg::new("flag")
644                 .long("flag")
645                 .group("one")
646                 .action(ArgAction::SetTrue),
647         )
648         .group(ArgGroup::new("one").conflicts_with("opt"))
649         .try_get_matches_from(vec!["myprog", "--flag"]);
650 
651     assert!(
652         result.is_ok(),
653         "arg group conflicts_with should ignore default_value: {:?}",
654         result.unwrap_err()
655     );
656     let m = result.unwrap();
657 
658     assert_eq!(
659         m.get_one::<String>("opt").map(|v| v.as_str()),
660         Some("default")
661     );
662     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
663 }
664 
665 #[test]
exclusive_with_required()666 fn exclusive_with_required() {
667     let cmd = Command::new("bug")
668         .arg(
669             Arg::new("test")
670                 .long("test")
671                 .action(ArgAction::SetTrue)
672                 .exclusive(true),
673         )
674         .arg(Arg::new("input").action(ArgAction::Set).required(true));
675 
676     cmd.clone()
677         .try_get_matches_from(["bug", "--test", "required"])
678         .unwrap_err();
679 
680     cmd.clone()
681         .try_get_matches_from(["bug", "required"])
682         .unwrap();
683 
684     cmd.clone().try_get_matches_from(["bug", "--test"]).unwrap();
685 }
686 
687 #[test]
args_negate_subcommands_one_level()688 fn args_negate_subcommands_one_level() {
689     let res = Command::new("disablehelp")
690         .args_conflicts_with_subcommands(true)
691         .subcommand_negates_reqs(true)
692         .arg(arg!(<arg1> "some arg"))
693         .arg(arg!(<arg2> "some arg"))
694         .subcommand(
695             Command::new("sub1").subcommand(Command::new("sub2").subcommand(Command::new("sub3"))),
696         )
697         .try_get_matches_from(vec!["", "pickles", "sub1"]);
698     assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind());
699     let m = res.unwrap();
700     assert_eq!(
701         m.get_one::<String>("arg2").map(|v| v.as_str()),
702         Some("sub1")
703     );
704 }
705 
706 #[test]
args_negate_subcommands_two_levels()707 fn args_negate_subcommands_two_levels() {
708     let res = Command::new("disablehelp")
709         .args_conflicts_with_subcommands(true)
710         .subcommand_negates_reqs(true)
711         .arg(arg!(<arg1> "some arg"))
712         .arg(arg!(<arg2> "some arg"))
713         .subcommand(
714             Command::new("sub1")
715                 .args_conflicts_with_subcommands(true)
716                 .subcommand_negates_reqs(true)
717                 .arg(arg!(<arg> "some"))
718                 .arg(arg!(<arg2> "some"))
719                 .subcommand(Command::new("sub2").subcommand(Command::new("sub3"))),
720         )
721         .try_get_matches_from(vec!["", "sub1", "arg", "sub2"]);
722     assert!(res.is_ok(), "error: {:?}", res.unwrap_err().kind());
723     let m = res.unwrap();
724     assert_eq!(
725         m.subcommand_matches("sub1")
726             .unwrap()
727             .get_one::<String>("arg2")
728             .map(|v| v.as_str()),
729         Some("sub2")
730     );
731 }
732 
733 #[test]
734 #[cfg(feature = "error-context")]
subcommand_conflict_error_message()735 fn subcommand_conflict_error_message() {
736     static CONFLICT_ERR: &str = "\
737 error: unexpected argument 'sub1' found
738 
739 Usage: test [OPTIONS]
740        test <COMMAND>
741 
742 For more information, try '--help'.
743 ";
744 
745     let cmd = Command::new("test")
746         .args_conflicts_with_subcommands(true)
747         .arg(arg!(-p --place <"place id"> "Place ID to open"))
748         .subcommand(
749             Command::new("sub1").subcommand(Command::new("sub2").subcommand(Command::new("sub3"))),
750         );
751 
752     utils::assert_output(cmd, "test --place id sub1", CONFLICT_ERR, true);
753 }
754 
755 #[test]
subcommand_conflict_negates_required()756 fn subcommand_conflict_negates_required() {
757     let cmd = Command::new("test")
758         .args_conflicts_with_subcommands(true)
759         .subcommand(Command::new("config"))
760         .arg(arg!(-p --place <"place id"> "Place ID to open").required(true));
761 
762     let result = cmd.try_get_matches_from(["test", "config"]);
763     assert!(
764         result.is_ok(),
765         "args_conflicts_with_subcommands should ignore required: {}",
766         result.unwrap_err()
767     );
768     let m = result.unwrap();
769     assert_eq!(m.subcommand_name().unwrap(), "config");
770 }
771