1use clap::{arg, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
2
3#[cfg(feature = "error-context")]
4use super::utils;
5
6#[test]
7fn 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]
18fn 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]
29fn 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]
40fn 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]
54fn 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]
65fn 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]
78fn 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]
92fn 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]
105fn 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]
139fn 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]
171fn 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]
210fn 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]
239fn 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]
268fn 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]
303fn 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")]
322fn conflict_output() {
323    static CONFLICT_ERR: &str = "\
324error: the argument '--flag...' cannot be used with '-F'
325
326Usage: clap-test --flag... --long-option-2 <option2> <positional> <positional2> [positional3]...
327
328For 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")]
341fn conflict_output_rev() {
342    static CONFLICT_ERR_REV: &str = "\
343error: the argument '-F' cannot be used with '--flag...'
344
345Usage: clap-test -F --long-option-2 <option2> <positional> <positional2> [positional3]...
346
347For 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")]
360fn conflict_output_repeat() {
361    static ERR: &str = "\
362error: the argument '-F' cannot be used multiple times
363
364Usage: clap-test [OPTIONS] [positional] [positional2] [positional3]... [COMMAND]
365
366For 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")]
374fn conflict_output_with_required() {
375    static CONFLICT_ERR: &str = "\
376error: the argument '--flag...' cannot be used with '-F'
377
378Usage: clap-test --flag... --long-option-2 <option2> <positional> <positional2> [positional3]...
379
380For 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")]
393fn conflict_output_rev_with_required() {
394    static CONFLICT_ERR_REV: &str = "\
395error: the argument '-F' cannot be used with '--flag...'
396
397Usage: clap-test -F --long-option-2 <option2> <positional> <positional2> [positional3]...
398
399For 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")]
412fn conflict_output_three_conflicting() {
413    static CONFLICT_ERR_THREE: &str = "\
414error: the argument '--one' cannot be used with:
415  --two
416  --three
417
418Usage: three_conflicting_arguments --one
419
420For 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")]
452fn 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")]
480fn 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"]
515fn 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"]
524fn 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]
531fn 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]
552fn 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]
577fn 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]
608fn 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]
639fn 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]
666fn 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]
688fn 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]
707fn 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")]
735fn subcommand_conflict_error_message() {
736    static CONFLICT_ERR: &str = "\
737error: unexpected argument 'sub1' found
738
739Usage: test [OPTIONS]
740       test <COMMAND>
741
742For 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]
756fn 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