• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use clap::builder::ArgPredicate;
2 use clap::{arg, error::ErrorKind, Arg, ArgAction, ArgGroup, Command};
3 
4 #[cfg(feature = "error-context")]
5 use super::utils;
6 
7 #[test]
flag_required()8 fn flag_required() {
9     let result = Command::new("flag_required")
10         .arg(arg!(-f --flag "some flag").requires("color"))
11         .arg(arg!(-c --color "third flag"))
12         .try_get_matches_from(vec!["", "-f"]);
13     assert!(result.is_err());
14     let err = result.err().unwrap();
15     assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
16 }
17 
18 #[test]
flag_required_2()19 fn flag_required_2() {
20     let m = Command::new("flag_required")
21         .arg(
22             arg!(-f --flag "some flag")
23                 .requires("color")
24                 .action(ArgAction::SetTrue),
25         )
26         .arg(arg!(-c --color "third flag").action(ArgAction::SetTrue))
27         .try_get_matches_from(vec!["", "-f", "-c"])
28         .unwrap();
29     assert!(*m.get_one::<bool>("color").expect("defaulted by clap"));
30     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
31 }
32 
33 #[test]
option_required()34 fn option_required() {
35     let result = Command::new("option_required")
36         .arg(arg!(f: -f <flag> "some flag").requires("c"))
37         .arg(arg!(c: -c <color> "third flag"))
38         .try_get_matches_from(vec!["", "-f", "val"]);
39     assert!(result.is_err());
40     let err = result.err().unwrap();
41     assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
42 }
43 
44 #[test]
option_required_2()45 fn option_required_2() {
46     let m = Command::new("option_required")
47         .arg(arg!(f: -f <flag> "some flag").requires("c"))
48         .arg(arg!(c: -c <color> "third flag"))
49         .try_get_matches_from(vec!["", "-f", "val", "-c", "other_val"])
50         .unwrap();
51     assert!(m.contains_id("c"));
52     assert_eq!(
53         m.get_one::<String>("c").map(|v| v.as_str()).unwrap(),
54         "other_val"
55     );
56     assert!(m.contains_id("f"));
57     assert_eq!(m.get_one::<String>("f").map(|v| v.as_str()).unwrap(), "val");
58 }
59 
60 #[test]
positional_required()61 fn positional_required() {
62     let result = Command::new("positional_required")
63         .arg(Arg::new("flag").index(1).required(true))
64         .try_get_matches_from(vec![""]);
65     assert!(result.is_err());
66     let err = result.err().unwrap();
67     assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
68 }
69 
70 #[test]
positional_required_2()71 fn positional_required_2() {
72     let m = Command::new("positional_required")
73         .arg(Arg::new("flag").index(1).required(true))
74         .try_get_matches_from(vec!["", "someval"])
75         .unwrap();
76     assert!(m.contains_id("flag"));
77     assert_eq!(
78         m.get_one::<String>("flag").map(|v| v.as_str()).unwrap(),
79         "someval"
80     );
81 }
82 
83 #[test]
84 #[cfg(feature = "error-context")]
positional_required_with_requires()85 fn positional_required_with_requires() {
86     static POSITIONAL_REQ: &str = "\
87 error: the following required arguments were not provided:
88   <flag>
89   <opt>
90 
91 Usage: clap-test <flag> <opt> [bar]
92 
93 For more information, try '--help'.
94 ";
95 
96     let cmd = Command::new("positional_required")
97         .arg(Arg::new("flag").required(true).requires("opt"))
98         .arg(Arg::new("opt"))
99         .arg(Arg::new("bar"));
100 
101     utils::assert_output(cmd, "clap-test", POSITIONAL_REQ, true);
102 }
103 
104 #[test]
105 #[cfg(feature = "error-context")]
positional_required_with_requires_if_no_value()106 fn positional_required_with_requires_if_no_value() {
107     static POSITIONAL_REQ_IF_NO_VAL: &str = "\
108 error: the following required arguments were not provided:
109   <flag>
110 
111 Usage: clap-test <flag> [opt] [bar]
112 
113 For more information, try '--help'.
114 ";
115 
116     let cmd = Command::new("positional_required")
117         .arg(Arg::new("flag").required(true).requires_if("val", "opt"))
118         .arg(Arg::new("opt"))
119         .arg(Arg::new("bar"));
120 
121     utils::assert_output(cmd, "clap-test", POSITIONAL_REQ_IF_NO_VAL, true);
122 }
123 
124 #[test]
125 #[cfg(feature = "error-context")]
positional_required_with_requires_if_value()126 fn positional_required_with_requires_if_value() {
127     static POSITIONAL_REQ_IF_VAL: &str = "\
128 error: the following required arguments were not provided:
129   <foo>
130   <opt>
131 
132 Usage: clap-test <flag> <foo> <opt> [bar]
133 
134 For more information, try '--help'.
135 ";
136 
137     let cmd = Command::new("positional_required")
138         .arg(Arg::new("flag").required(true).requires_if("val", "opt"))
139         .arg(Arg::new("foo").required(true))
140         .arg(Arg::new("opt"))
141         .arg(Arg::new("bar"));
142 
143     utils::assert_output(cmd, "clap-test val", POSITIONAL_REQ_IF_VAL, true);
144 }
145 
146 #[test]
group_required()147 fn group_required() {
148     let result = Command::new("group_required")
149         .arg(arg!(-f --flag "some flag"))
150         .group(ArgGroup::new("gr").required(true).arg("some").arg("other"))
151         .arg(arg!(--some "some arg"))
152         .arg(arg!(--other "other arg"))
153         .try_get_matches_from(vec!["", "-f"]);
154     assert!(result.is_err());
155     let err = result.err().unwrap();
156     assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
157 }
158 
159 #[test]
group_required_2()160 fn group_required_2() {
161     let m = Command::new("group_required")
162         .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
163         .group(ArgGroup::new("gr").required(true).arg("some").arg("other"))
164         .arg(arg!(--some "some arg").action(ArgAction::SetTrue))
165         .arg(arg!(--other "other arg").action(ArgAction::SetTrue))
166         .try_get_matches_from(vec!["", "-f", "--some"])
167         .unwrap();
168     assert!(*m.get_one::<bool>("some").expect("defaulted by clap"));
169     assert!(!*m.get_one::<bool>("other").expect("defaulted by clap"));
170     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
171 }
172 
173 #[test]
group_required_3()174 fn group_required_3() {
175     let m = Command::new("group_required")
176         .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
177         .group(ArgGroup::new("gr").required(true).arg("some").arg("other"))
178         .arg(arg!(--some "some arg").action(ArgAction::SetTrue))
179         .arg(arg!(--other "other arg").action(ArgAction::SetTrue))
180         .try_get_matches_from(vec!["", "-f", "--other"])
181         .unwrap();
182     assert!(!*m.get_one::<bool>("some").expect("defaulted by clap"));
183     assert!(*m.get_one::<bool>("other").expect("defaulted by clap"));
184     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
185 }
186 
187 #[test]
arg_require_group()188 fn arg_require_group() {
189     let result = Command::new("arg_require_group")
190         .arg(arg!(-f --flag "some flag").requires("gr"))
191         .group(ArgGroup::new("gr").arg("some").arg("other"))
192         .arg(arg!(--some "some arg"))
193         .arg(arg!(--other "other arg"))
194         .try_get_matches_from(vec!["", "-f"]);
195     assert!(result.is_err());
196     let err = result.err().unwrap();
197     assert_eq!(err.kind(), ErrorKind::MissingRequiredArgument);
198 }
199 
200 #[test]
arg_require_group_2()201 fn arg_require_group_2() {
202     let res = Command::new("arg_require_group")
203         .arg(
204             arg!(-f --flag "some flag")
205                 .requires("gr")
206                 .action(ArgAction::SetTrue),
207         )
208         .group(ArgGroup::new("gr").arg("some").arg("other"))
209         .arg(arg!(--some "some arg").action(ArgAction::SetTrue))
210         .arg(arg!(--other "other arg").action(ArgAction::SetTrue))
211         .try_get_matches_from(vec!["", "-f", "--some"]);
212     assert!(res.is_ok(), "{}", res.unwrap_err());
213     let m = res.unwrap();
214     assert!(*m.get_one::<bool>("some").expect("defaulted by clap"));
215     assert!(!*m.get_one::<bool>("other").expect("defaulted by clap"));
216     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
217 }
218 
219 #[test]
arg_require_group_3()220 fn arg_require_group_3() {
221     let res = Command::new("arg_require_group")
222         .arg(
223             arg!(-f --flag "some flag")
224                 .requires("gr")
225                 .action(ArgAction::SetTrue),
226         )
227         .group(ArgGroup::new("gr").arg("some").arg("other"))
228         .arg(arg!(--some "some arg").action(ArgAction::SetTrue))
229         .arg(arg!(--other "other arg").action(ArgAction::SetTrue))
230         .try_get_matches_from(vec!["", "-f", "--other"]);
231     assert!(res.is_ok(), "{}", res.unwrap_err());
232     let m = res.unwrap();
233     assert!(!*m.get_one::<bool>("some").expect("defaulted by clap"));
234     assert!(*m.get_one::<bool>("other").expect("defaulted by clap"));
235     assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
236 }
237 
238 // REQUIRED_UNLESS
239 
240 #[test]
issue_753()241 fn issue_753() {
242     let m = Command::new("test")
243         .arg(arg!(
244             -l --list "List available interfaces (and stop there)"
245         ))
246         .arg(
247             arg!(
248                 -i --iface <INTERFACE> "Ethernet interface for fetching NTP packets"
249             )
250             .required(false)
251             .required_unless_present("list"),
252         )
253         .arg(
254             arg!(-f --file <TESTFILE> "Fetch NTP packets from pcap file")
255                 .conflicts_with("iface")
256                 .required_unless_present("list"),
257         )
258         .arg(arg!(-s --server <SERVER_IP> "NTP server IP address").required_unless_present("list"))
259         .try_get_matches_from(vec!["test", "--list"]);
260     assert!(m.is_ok(), "{}", m.unwrap_err());
261 }
262 
263 #[test]
required_unless_present()264 fn required_unless_present() {
265     let res = Command::new("unlesstest")
266         .arg(
267             Arg::new("cfg")
268                 .required_unless_present("dbg")
269                 .action(ArgAction::Set)
270                 .long("config"),
271         )
272         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
273         .try_get_matches_from(vec!["unlesstest", "--debug"]);
274 
275     assert!(res.is_ok(), "{}", res.unwrap_err());
276     let m = res.unwrap();
277     assert!(*m.get_one::<bool>("dbg").expect("defaulted by clap"));
278     assert!(!m.contains_id("cfg"));
279 }
280 
281 #[test]
required_unless_present_err()282 fn required_unless_present_err() {
283     let res = Command::new("unlesstest")
284         .arg(
285             Arg::new("cfg")
286                 .required_unless_present("dbg")
287                 .action(ArgAction::Set)
288                 .long("config"),
289         )
290         .arg(Arg::new("dbg").long("debug"))
291         .try_get_matches_from(vec!["unlesstest"]);
292 
293     assert!(res.is_err());
294     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
295 }
296 
297 #[test]
required_unless_present_with_optional_value()298 fn required_unless_present_with_optional_value() {
299     let res = Command::new("unlesstest")
300         .arg(Arg::new("opt").long("opt").num_args(0..=1))
301         .arg(
302             Arg::new("cfg")
303                 .required_unless_present("dbg")
304                 .action(ArgAction::Set)
305                 .long("config"),
306         )
307         .arg(Arg::new("dbg").long("debug"))
308         .try_get_matches_from(vec!["unlesstest", "--opt"]);
309 
310     assert!(res.is_err());
311     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
312 }
313 
314 // REQUIRED_UNLESS_ALL
315 
316 #[test]
required_unless_present_all()317 fn required_unless_present_all() {
318     let res = Command::new("unlessall")
319         .arg(
320             Arg::new("cfg")
321                 .required_unless_present_all(["dbg", "infile"])
322                 .action(ArgAction::Set)
323                 .long("config"),
324         )
325         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
326         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
327         .try_get_matches_from(vec!["unlessall", "--debug", "-i", "file"]);
328 
329     assert!(res.is_ok(), "{}", res.unwrap_err());
330     let m = res.unwrap();
331     assert!(*m.get_one::<bool>("dbg").expect("defaulted by clap"));
332     assert!(m.contains_id("infile"));
333     assert!(!m.contains_id("cfg"));
334 }
335 
336 #[test]
required_unless_all_err()337 fn required_unless_all_err() {
338     let res = Command::new("unlessall")
339         .arg(
340             Arg::new("cfg")
341                 .required_unless_present_all(["dbg", "infile"])
342                 .action(ArgAction::Set)
343                 .long("config"),
344         )
345         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
346         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
347         .try_get_matches_from(vec!["unlessall", "--debug"]);
348 
349     assert!(res.is_err());
350     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
351 }
352 
353 // REQUIRED_UNLESS_ONE
354 
355 #[test]
required_unless_present_any()356 fn required_unless_present_any() {
357     let res = Command::new("unlessone")
358         .arg(
359             Arg::new("cfg")
360                 .required_unless_present_any(["dbg", "infile"])
361                 .action(ArgAction::Set)
362                 .long("config"),
363         )
364         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
365         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
366         .try_get_matches_from(vec!["unlessone", "--debug"]);
367 
368     assert!(res.is_ok(), "{}", res.unwrap_err());
369     let m = res.unwrap();
370     assert!(*m.get_one::<bool>("dbg").expect("defaulted by clap"));
371     assert!(!m.contains_id("cfg"));
372 }
373 
374 #[test]
required_unless_any_2()375 fn required_unless_any_2() {
376     // This tests that the required_unless_present_any works when the second arg in the array is used
377     // instead of the first.
378     let res = Command::new("unlessone")
379         .arg(
380             Arg::new("cfg")
381                 .required_unless_present_any(["dbg", "infile"])
382                 .action(ArgAction::Set)
383                 .long("config"),
384         )
385         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
386         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
387         .try_get_matches_from(vec!["unlessone", "-i", "file"]);
388 
389     assert!(res.is_ok(), "{}", res.unwrap_err());
390     let m = res.unwrap();
391     assert!(m.contains_id("infile"));
392     assert!(!m.contains_id("cfg"));
393 }
394 
395 #[test]
required_unless_any_works_with_short()396 fn required_unless_any_works_with_short() {
397     // GitHub issue: https://github.com/clap-rs/clap/issues/1135
398     let res = Command::new("unlessone")
399         .arg(
400             Arg::new("a")
401                 .conflicts_with("b")
402                 .short('a')
403                 .action(ArgAction::SetTrue),
404         )
405         .arg(Arg::new("b").short('b').action(ArgAction::SetTrue))
406         .arg(
407             Arg::new("x")
408                 .short('x')
409                 .action(ArgAction::SetTrue)
410                 .required_unless_present_any(["a", "b"]),
411         )
412         .try_get_matches_from(vec!["unlessone", "-a"]);
413 
414     assert!(res.is_ok(), "{}", res.unwrap_err());
415 }
416 
417 #[test]
required_unless_any_works_with_short_err()418 fn required_unless_any_works_with_short_err() {
419     let res = Command::new("unlessone")
420         .arg(
421             Arg::new("a")
422                 .conflicts_with("b")
423                 .short('a')
424                 .action(ArgAction::SetTrue),
425         )
426         .arg(Arg::new("b").short('b').action(ArgAction::SetTrue))
427         .arg(
428             Arg::new("x")
429                 .short('x')
430                 .action(ArgAction::SetTrue)
431                 .required_unless_present_any(["a", "b"]),
432         )
433         .try_get_matches_from(vec!["unlessone"]);
434 
435     assert!(res.is_err());
436 }
437 
438 #[test]
required_unless_any_works_without()439 fn required_unless_any_works_without() {
440     let res = Command::new("unlessone")
441         .arg(
442             Arg::new("a")
443                 .conflicts_with("b")
444                 .short('a')
445                 .action(ArgAction::SetTrue),
446         )
447         .arg(Arg::new("b").short('b').action(ArgAction::SetTrue))
448         .arg(Arg::new("x").required_unless_present_any(["a", "b"]))
449         .try_get_matches_from(vec!["unlessone", "-a"]);
450 
451     assert!(res.is_ok(), "{}", res.unwrap_err());
452 }
453 
454 #[test]
required_unless_any_works_with_long()455 fn required_unless_any_works_with_long() {
456     let res = Command::new("unlessone")
457         .arg(
458             Arg::new("a")
459                 .conflicts_with("b")
460                 .short('a')
461                 .action(ArgAction::SetTrue),
462         )
463         .arg(Arg::new("b").short('b').action(ArgAction::SetTrue))
464         .arg(
465             Arg::new("x")
466                 .long("x_is_the_option")
467                 .action(ArgAction::SetTrue)
468                 .required_unless_present_any(["a", "b"]),
469         )
470         .try_get_matches_from(vec!["unlessone", "-a"]);
471 
472     assert!(res.is_ok(), "{}", res.unwrap_err());
473 }
474 
475 #[test]
required_unless_any_1()476 fn required_unless_any_1() {
477     let res = Command::new("unlessone")
478         .arg(
479             Arg::new("cfg")
480                 .required_unless_present_any(["dbg", "infile"])
481                 .action(ArgAction::Set)
482                 .long("config"),
483         )
484         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
485         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
486         .try_get_matches_from(vec!["unlessone", "--debug"]);
487 
488     assert!(res.is_ok(), "{}", res.unwrap_err());
489     let m = res.unwrap();
490     assert!(!m.contains_id("infile"));
491     assert!(!m.contains_id("cfg"));
492     assert!(*m.get_one::<bool>("dbg").expect("defaulted by clap"));
493 }
494 
495 #[test]
required_unless_any_err()496 fn required_unless_any_err() {
497     let res = Command::new("unlessone")
498         .arg(
499             Arg::new("cfg")
500                 .required_unless_present_any(["dbg", "infile"])
501                 .action(ArgAction::Set)
502                 .long("config"),
503         )
504         .arg(Arg::new("dbg").long("debug").action(ArgAction::SetTrue))
505         .arg(Arg::new("infile").short('i').action(ArgAction::Set))
506         .try_get_matches_from(vec!["unlessone"]);
507 
508     assert!(res.is_err());
509     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
510 }
511 
512 #[test]
513 #[cfg(feature = "error-context")]
missing_required_output()514 fn missing_required_output() {
515     static MISSING_REQ: &str = "\
516 error: the following required arguments were not provided:
517   --long-option-2 <option2>
518   <positional>
519   <positional2>
520 
521 Usage: clap-test --long-option-2 <option2> -F <positional> <positional2> [positional3]...
522 
523 For more information, try '--help'.
524 ";
525 
526     utils::assert_output(utils::complex_app(), "clap-test -F", MISSING_REQ, true);
527 }
528 
529 // Conditional external requirements
530 
531 #[test]
requires_if_present_val()532 fn requires_if_present_val() {
533     let res = Command::new("unlessone")
534         .arg(
535             Arg::new("cfg")
536                 .requires_if("my.cfg", "extra")
537                 .action(ArgAction::Set)
538                 .long("config"),
539         )
540         .arg(Arg::new("extra").long("extra").action(ArgAction::SetTrue))
541         .try_get_matches_from(vec!["unlessone", "--config=my.cfg"]);
542 
543     assert!(res.is_err());
544     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
545 }
546 
547 #[test]
requires_if_present_mult()548 fn requires_if_present_mult() {
549     let res = Command::new("unlessone")
550         .arg(
551             Arg::new("cfg")
552                 .requires_ifs([("my.cfg", "extra"), ("other.cfg", "other")])
553                 .action(ArgAction::Set)
554                 .long("config"),
555         )
556         .arg(Arg::new("extra").long("extra").action(ArgAction::SetTrue))
557         .arg(Arg::new("other").long("other").action(ArgAction::SetTrue))
558         .try_get_matches_from(vec!["unlessone", "--config=other.cfg"]);
559 
560     assert!(res.is_err());
561     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
562 }
563 
564 #[test]
requires_if_present_mult_pass()565 fn requires_if_present_mult_pass() {
566     let res = Command::new("unlessone")
567         .arg(
568             Arg::new("cfg")
569                 .requires_ifs([("my.cfg", "extra"), ("other.cfg", "other")])
570                 .action(ArgAction::Set)
571                 .long("config"),
572         )
573         .arg(Arg::new("extra").long("extra").action(ArgAction::SetTrue))
574         .arg(Arg::new("other").long("other").action(ArgAction::SetTrue))
575         .try_get_matches_from(vec!["unlessone", "--config=some.cfg"]);
576 
577     assert!(res.is_ok(), "{}", res.unwrap_err());
578 }
579 
580 #[test]
requires_if_present_val_no_present_pass()581 fn requires_if_present_val_no_present_pass() {
582     let res = Command::new("unlessone")
583         .arg(
584             Arg::new("cfg")
585                 .requires_if("my.cfg", "extra")
586                 .action(ArgAction::Set)
587                 .long("config"),
588         )
589         .arg(Arg::new("extra").long("extra").action(ArgAction::SetTrue))
590         .try_get_matches_from(vec!["unlessone"]);
591 
592     assert!(res.is_ok(), "{}", res.unwrap_err());
593 }
594 
595 // Conditionally required
596 
597 #[test]
required_if_val_present_pass()598 fn required_if_val_present_pass() {
599     let res = Command::new("ri")
600         .arg(
601             Arg::new("cfg")
602                 .required_if_eq("extra", "val")
603                 .action(ArgAction::Set)
604                 .long("config"),
605         )
606         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
607         .try_get_matches_from(vec!["ri", "--extra", "val", "--config", "my.cfg"]);
608 
609     assert!(res.is_ok(), "{}", res.unwrap_err());
610 }
611 
612 #[test]
required_if_val_present_fail()613 fn required_if_val_present_fail() {
614     let res = Command::new("ri")
615         .arg(
616             Arg::new("cfg")
617                 .required_if_eq("extra", "val")
618                 .action(ArgAction::Set)
619                 .long("config"),
620         )
621         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
622         .try_get_matches_from(vec!["ri", "--extra", "val"]);
623 
624     assert!(res.is_err());
625     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
626 }
627 
628 #[test]
required_if_val_present_ignore_case_pass()629 fn required_if_val_present_ignore_case_pass() {
630     let res = Command::new("ri")
631         .arg(
632             Arg::new("cfg")
633                 .required_if_eq("extra", "Val")
634                 .action(ArgAction::Set)
635                 .long("config"),
636         )
637         .arg(
638             Arg::new("extra")
639                 .action(ArgAction::Set)
640                 .long("extra")
641                 .ignore_case(true),
642         )
643         .try_get_matches_from(vec!["ri", "--extra", "vaL", "--config", "my.cfg"]);
644 
645     assert!(res.is_ok(), "{}", res.unwrap_err());
646 }
647 
648 #[test]
required_if_val_present_ignore_case_fail()649 fn required_if_val_present_ignore_case_fail() {
650     let res = Command::new("ri")
651         .arg(
652             Arg::new("cfg")
653                 .required_if_eq("extra", "Val")
654                 .action(ArgAction::Set)
655                 .long("config"),
656         )
657         .arg(
658             Arg::new("extra")
659                 .action(ArgAction::Set)
660                 .long("extra")
661                 .ignore_case(true),
662         )
663         .try_get_matches_from(vec!["ri", "--extra", "vaL"]);
664 
665     assert!(res.is_err());
666     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
667 }
668 
669 #[test]
required_if_all_values_present_pass()670 fn required_if_all_values_present_pass() {
671     let res = Command::new("ri")
672         .arg(
673             Arg::new("cfg")
674                 .required_if_eq_all([("extra", "val"), ("option", "spec")])
675                 .action(ArgAction::Set)
676                 .long("config"),
677         )
678         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
679         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
680         .try_get_matches_from(vec![
681             "ri", "--extra", "val", "--option", "spec", "--config", "my.cfg",
682         ]);
683 
684     assert!(res.is_ok(), "{}", res.unwrap_err());
685 }
686 
687 #[test]
required_if_some_values_present_pass()688 fn required_if_some_values_present_pass() {
689     let res = Command::new("ri")
690         .arg(
691             Arg::new("cfg")
692                 .required_if_eq_all([("extra", "val"), ("option", "spec")])
693                 .action(ArgAction::Set)
694                 .long("config"),
695         )
696         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
697         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
698         .try_get_matches_from(vec!["ri", "--extra", "val"]);
699 
700     assert!(res.is_ok(), "{}", res.unwrap_err());
701 }
702 
703 #[test]
required_if_all_values_present_fail()704 fn required_if_all_values_present_fail() {
705     let res = Command::new("ri")
706         .arg(
707             Arg::new("cfg")
708                 .required_if_eq_all([("extra", "val"), ("option", "spec")])
709                 .action(ArgAction::Set)
710                 .long("config"),
711         )
712         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
713         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
714         .try_get_matches_from(vec!["ri", "--extra", "val", "--option", "spec"]);
715 
716     assert!(res.is_err());
717     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
718 }
719 
720 #[test]
required_if_any_all_values_present_pass()721 fn required_if_any_all_values_present_pass() {
722     let res = Command::new("ri")
723         .arg(
724             Arg::new("cfg")
725                 .required_if_eq_all([("extra", "val"), ("option", "spec")])
726                 .required_if_eq_any([("extra", "val2"), ("option", "spec2")])
727                 .action(ArgAction::Set)
728                 .long("config"),
729         )
730         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
731         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
732         .try_get_matches_from(vec![
733             "ri", "--extra", "val", "--option", "spec", "--config", "my.cfg",
734         ]);
735 
736     assert!(res.is_ok(), "{}", res.unwrap_err());
737 }
738 
739 #[test]
required_if_any_all_values_present_fail()740 fn required_if_any_all_values_present_fail() {
741     let res = Command::new("ri")
742         .arg(
743             Arg::new("cfg")
744                 .required_if_eq_all([("extra", "val"), ("option", "spec")])
745                 .required_if_eq_any([("extra", "val2"), ("option", "spec2")])
746                 .action(ArgAction::Set)
747                 .long("config"),
748         )
749         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
750         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
751         .try_get_matches_from(vec!["ri", "--extra", "val", "--option", "spec"]);
752 
753     assert!(res.is_err());
754     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
755 }
756 
757 #[test]
758 #[cfg(feature = "error-context")]
list_correct_required_args()759 fn list_correct_required_args() {
760     static COND_REQ_IN_USAGE: &str = "\
761 error: the following required arguments were not provided:
762   --output <output>
763 
764 Usage: test --target <target> --input <input> --output <output>
765 
766 For more information, try '--help'.
767 ";
768 
769     let cmd = Command::new("Test cmd")
770         .version("1.0")
771         .author("F0x06")
772         .about("Arg test")
773         .arg(
774             Arg::new("target")
775                 .action(ArgAction::Set)
776                 .required(true)
777                 .value_parser(["file", "stdout"])
778                 .long("target"),
779         )
780         .arg(
781             Arg::new("input")
782                 .action(ArgAction::Set)
783                 .required(true)
784                 .long("input"),
785         )
786         .arg(
787             Arg::new("output")
788                 .action(ArgAction::Set)
789                 .required(true)
790                 .long("output"),
791         );
792 
793     utils::assert_output(
794         cmd,
795         "test --input somepath --target file",
796         COND_REQ_IN_USAGE,
797         true,
798     );
799 }
800 
801 #[test]
802 #[cfg(feature = "error-context")]
required_if_val_present_fail_error_output()803 fn required_if_val_present_fail_error_output() {
804     static COND_REQ_IN_USAGE: &str = "\
805 error: the following required arguments were not provided:
806   --output <output>
807 
808 Usage: test --target <target> --input <input> --output <output>
809 
810 For more information, try '--help'.
811 ";
812 
813     let cmd = Command::new("Test cmd")
814         .version("1.0")
815         .author("F0x06")
816         .about("Arg test")
817         .arg(
818             Arg::new("target")
819                 .action(ArgAction::Set)
820                 .required(true)
821                 .value_parser(["file", "stdout"])
822                 .long("target"),
823         )
824         .arg(
825             Arg::new("input")
826                 .action(ArgAction::Set)
827                 .required(true)
828                 .long("input"),
829         )
830         .arg(
831             Arg::new("output")
832                 .action(ArgAction::Set)
833                 .required_if_eq("target", "file")
834                 .long("output"),
835         );
836 
837     utils::assert_output(
838         cmd,
839         "test --input somepath --target file",
840         COND_REQ_IN_USAGE,
841         true,
842     );
843 }
844 
845 #[test]
required_if_wrong_val()846 fn required_if_wrong_val() {
847     let res = Command::new("ri")
848         .arg(
849             Arg::new("cfg")
850                 .required_if_eq("extra", "val")
851                 .action(ArgAction::Set)
852                 .long("config"),
853         )
854         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
855         .try_get_matches_from(vec!["ri", "--extra", "other"]);
856 
857     assert!(res.is_ok(), "{}", res.unwrap_err());
858 }
859 
860 #[test]
required_ifs_val_present_pass()861 fn required_ifs_val_present_pass() {
862     let res = Command::new("ri")
863         .arg(
864             Arg::new("cfg")
865                 .required_if_eq_any([("extra", "val"), ("option", "spec")])
866                 .action(ArgAction::Set)
867                 .long("config"),
868         )
869         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
870         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
871         .try_get_matches_from(vec!["ri", "--option", "spec", "--config", "my.cfg"]);
872 
873     assert!(res.is_ok(), "{}", res.unwrap_err());
874 }
875 
876 #[test]
required_ifs_val_present_fail()877 fn required_ifs_val_present_fail() {
878     let res = Command::new("ri")
879         .arg(
880             Arg::new("cfg")
881                 .required_if_eq_any([("extra", "val"), ("option", "spec")])
882                 .action(ArgAction::Set)
883                 .long("config"),
884         )
885         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
886         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
887         .try_get_matches_from(vec!["ri", "--option", "spec"]);
888 
889     assert!(res.is_err());
890     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
891 }
892 
893 #[test]
required_ifs_wrong_val()894 fn required_ifs_wrong_val() {
895     let res = Command::new("ri")
896         .arg(
897             Arg::new("cfg")
898                 .required_if_eq_any([("extra", "val"), ("option", "spec")])
899                 .action(ArgAction::Set)
900                 .long("config"),
901         )
902         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
903         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
904         .try_get_matches_from(vec!["ri", "--option", "other"]);
905 
906     assert!(res.is_ok(), "{}", res.unwrap_err());
907 }
908 
909 #[test]
required_ifs_wrong_val_mult_fail()910 fn required_ifs_wrong_val_mult_fail() {
911     let res = Command::new("ri")
912         .arg(
913             Arg::new("cfg")
914                 .required_if_eq_any([("extra", "val"), ("option", "spec")])
915                 .action(ArgAction::Set)
916                 .long("config"),
917         )
918         .arg(Arg::new("extra").action(ArgAction::Set).long("extra"))
919         .arg(Arg::new("option").action(ArgAction::Set).long("option"))
920         .try_get_matches_from(vec!["ri", "--extra", "other", "--option", "spec"]);
921 
922     assert!(res.is_err());
923     assert_eq!(res.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
924 }
925 
926 #[test]
927 #[cfg(feature = "error-context")]
require_eq()928 fn require_eq() {
929     static REQUIRE_EQUALS: &str = "\
930 error: the following required arguments were not provided:
931   --opt=<FILE>
932 
933 Usage: clap-test --opt=<FILE>
934 
935 For more information, try '--help'.
936 ";
937 
938     let cmd = Command::new("clap-test").version("v1.4.8").arg(
939         Arg::new("opt")
940             .long("opt")
941             .short('o')
942             .required(true)
943             .require_equals(true)
944             .value_name("FILE")
945             .help("some"),
946     );
947     utils::assert_output(cmd, "clap-test", REQUIRE_EQUALS, true);
948 }
949 
950 #[test]
951 #[cfg(feature = "error-context")]
require_eq_filtered()952 fn require_eq_filtered() {
953     static REQUIRE_EQUALS_FILTERED: &str = "\
954 error: the following required arguments were not provided:
955   --opt=<FILE>
956 
957 Usage: clap-test --opt=<FILE> --foo=<FILE>
958 
959 For more information, try '--help'.
960 ";
961 
962     let cmd = Command::new("clap-test")
963         .version("v1.4.8")
964         .arg(
965             Arg::new("opt")
966                 .long("opt")
967                 .short('o')
968                 .required(true)
969                 .require_equals(true)
970                 .value_name("FILE")
971                 .help("some"),
972         )
973         .arg(
974             Arg::new("foo")
975                 .long("foo")
976                 .short('f')
977                 .required(true)
978                 .require_equals(true)
979                 .value_name("FILE")
980                 .help("some other arg"),
981         );
982     utils::assert_output(cmd, "clap-test -f=blah", REQUIRE_EQUALS_FILTERED, true);
983 }
984 
985 #[test]
986 #[cfg(feature = "error-context")]
require_eq_filtered_group()987 fn require_eq_filtered_group() {
988     static REQUIRE_EQUALS_FILTERED_GROUP: &str = "\
989 error: the following required arguments were not provided:
990   --opt=<FILE>
991 
992 Usage: clap-test --opt=<FILE> --foo=<FILE> <--g1=<FILE>|--g2=<FILE>>
993 
994 For more information, try '--help'.
995 ";
996 
997     let cmd = Command::new("clap-test")
998         .version("v1.4.8")
999         .arg(
1000             Arg::new("opt")
1001                 .long("opt")
1002                 .short('o')
1003                 .required(true)
1004                 .require_equals(true)
1005                 .value_name("FILE")
1006                 .help("some"),
1007         )
1008         .arg(
1009             Arg::new("foo")
1010                 .long("foo")
1011                 .short('f')
1012                 .required(true)
1013                 .require_equals(true)
1014                 .value_name("FILE")
1015                 .help("some other arg"),
1016         )
1017         .arg(
1018             Arg::new("g1")
1019                 .long("g1")
1020                 .require_equals(true)
1021                 .value_name("FILE"),
1022         )
1023         .arg(
1024             Arg::new("g2")
1025                 .long("g2")
1026                 .require_equals(true)
1027                 .value_name("FILE"),
1028         )
1029         .group(
1030             ArgGroup::new("test_group")
1031                 .args(["g1", "g2"])
1032                 .required(true),
1033         );
1034     utils::assert_output(
1035         cmd,
1036         "clap-test -f=blah --g1=blah",
1037         REQUIRE_EQUALS_FILTERED_GROUP,
1038         true,
1039     );
1040 }
1041 
issue_1158_app() -> Command1042 fn issue_1158_app() -> Command {
1043     Command::new("example")
1044         .arg(
1045             arg!(-c --config <FILE> "Custom config file.")
1046                 .required_unless_present("ID")
1047                 .conflicts_with("ID"),
1048         )
1049         .arg(
1050             arg!([ID] "ID")
1051                 .required_unless_present("config")
1052                 .conflicts_with("config")
1053                 .requires_ifs([
1054                     (ArgPredicate::IsPresent, "x"),
1055                     (ArgPredicate::IsPresent, "y"),
1056                     (ArgPredicate::IsPresent, "z"),
1057                 ]),
1058         )
1059         .arg(arg!(x: -x <X> "X"))
1060         .arg(arg!(y: -y <Y> "Y"))
1061         .arg(arg!(z: -z <Z> "Z"))
1062 }
1063 
1064 #[test]
1065 #[cfg(feature = "error-context")]
multiple_required_unless_usage_printing()1066 fn multiple_required_unless_usage_printing() {
1067     static MULTIPLE_REQUIRED_UNLESS_USAGE: &str = "\
1068 error: the following required arguments were not provided:
1069   --a <a>
1070   --b <b>
1071 
1072 Usage: test --c <c> --a <a> --b <b>
1073 
1074 For more information, try '--help'.
1075 ";
1076     let cmd = Command::new("test")
1077         .arg(
1078             Arg::new("a")
1079                 .long("a")
1080                 .action(ArgAction::Set)
1081                 .required_unless_present("b")
1082                 .conflicts_with("b"),
1083         )
1084         .arg(
1085             Arg::new("b")
1086                 .long("b")
1087                 .action(ArgAction::Set)
1088                 .required_unless_present("a")
1089                 .conflicts_with("a"),
1090         )
1091         .arg(
1092             Arg::new("c")
1093                 .long("c")
1094                 .action(ArgAction::Set)
1095                 .required_unless_present("d")
1096                 .conflicts_with("d"),
1097         )
1098         .arg(
1099             Arg::new("d")
1100                 .long("d")
1101                 .action(ArgAction::Set)
1102                 .required_unless_present("c")
1103                 .conflicts_with("c"),
1104         );
1105     utils::assert_output(cmd, "test --c asd", MULTIPLE_REQUIRED_UNLESS_USAGE, true);
1106 }
1107 
1108 #[test]
1109 #[cfg(feature = "error-context")]
issue_1158_conflicting_requirements()1110 fn issue_1158_conflicting_requirements() {
1111     static ISSUE_1158: &str = "\
1112 error: the following required arguments were not provided:
1113   -x <X>
1114   -y <Y>
1115   -z <Z>
1116 
1117 Usage: example -x <X> -y <Y> -z <Z> <ID>
1118 
1119 For more information, try '--help'.
1120 ";
1121 
1122     let cmd = issue_1158_app();
1123 
1124     utils::assert_output(cmd, "example id", ISSUE_1158, true);
1125 }
1126 
1127 #[test]
issue_1158_conflicting_requirements_rev()1128 fn issue_1158_conflicting_requirements_rev() {
1129     let res = issue_1158_app().try_get_matches_from(["", "--config", "some.conf"]);
1130 
1131     assert!(res.is_ok(), "{}", res.unwrap_err());
1132 }
1133 
1134 #[test]
issue_1643_args_mutually_require_each_other()1135 fn issue_1643_args_mutually_require_each_other() {
1136     use clap::*;
1137 
1138     let cmd = Command::new("test")
1139         .arg(
1140             Arg::new("relation_id")
1141                 .help("The relation id to get the data from")
1142                 .long("relation-id")
1143                 .short('r')
1144                 .action(ArgAction::Set)
1145                 .requires("remote_unit_name"),
1146         )
1147         .arg(
1148             Arg::new("remote_unit_name")
1149                 .help("The name of the remote unit to get data from")
1150                 .long("remote-unit")
1151                 .short('u')
1152                 .action(ArgAction::Set)
1153                 .requires("relation_id"),
1154         );
1155 
1156     cmd.try_get_matches_from(["test", "-u", "hello", "-r", "farewell"])
1157         .unwrap();
1158 }
1159 
1160 #[test]
short_flag_require_equals_with_minvals_zero()1161 fn short_flag_require_equals_with_minvals_zero() {
1162     let m = Command::new("foo")
1163         .arg(
1164             Arg::new("check")
1165                 .short('c')
1166                 .num_args(0..)
1167                 .require_equals(true),
1168         )
1169         .arg(Arg::new("unique").short('u').action(ArgAction::SetTrue))
1170         .try_get_matches_from(["foo", "-cu"])
1171         .unwrap();
1172     assert!(m.contains_id("check"));
1173     assert!(*m.get_one::<bool>("unique").expect("defaulted by clap"));
1174 }
1175 
1176 #[test]
issue_2624()1177 fn issue_2624() {
1178     let matches = Command::new("foo")
1179         .arg(
1180             Arg::new("check")
1181                 .short('c')
1182                 .long("check")
1183                 .require_equals(true)
1184                 .num_args(0..)
1185                 .value_parser(["silent", "quiet", "diagnose-first"]),
1186         )
1187         .arg(
1188             Arg::new("unique")
1189                 .short('u')
1190                 .long("unique")
1191                 .action(ArgAction::SetTrue),
1192         )
1193         .try_get_matches_from(["foo", "-cu"])
1194         .unwrap();
1195     assert!(matches.contains_id("check"));
1196     assert!(*matches
1197         .get_one::<bool>("unique")
1198         .expect("defaulted by clap"));
1199 }
1200 
1201 #[test]
required_unless_all_with_any()1202 fn required_unless_all_with_any() {
1203     let cmd = Command::new("prog")
1204         .arg(Arg::new("foo").long("foo").action(ArgAction::SetTrue))
1205         .arg(Arg::new("bar").long("bar").action(ArgAction::SetTrue))
1206         .arg(Arg::new("baz").long("baz").action(ArgAction::SetTrue))
1207         .arg(
1208             Arg::new("flag")
1209                 .long("flag")
1210                 .action(ArgAction::SetTrue)
1211                 .required_unless_present_any(["foo"])
1212                 .required_unless_present_all(["bar", "baz"]),
1213         );
1214 
1215     let result = cmd.clone().try_get_matches_from(vec!["myprog"]);
1216     assert!(result.is_err(), "{:?}", result.unwrap());
1217 
1218     let result = cmd.clone().try_get_matches_from(vec!["myprog", "--foo"]);
1219     assert!(result.is_ok(), "{:?}", result.unwrap_err());
1220     let matches = result.unwrap();
1221     assert!(!*matches.get_one::<bool>("flag").expect("defaulted by clap"));
1222 
1223     let result = cmd
1224         .clone()
1225         .try_get_matches_from(vec!["myprog", "--bar", "--baz"]);
1226     assert!(result.is_ok(), "{:?}", result.unwrap_err());
1227     let matches = result.unwrap();
1228     assert!(!*matches.get_one::<bool>("flag").expect("defaulted by clap"));
1229 
1230     let result = cmd.try_get_matches_from(vec!["myprog", "--bar"]);
1231     assert!(result.is_err(), "{:?}", result.unwrap());
1232 }
1233 
1234 #[cfg(debug_assertions)]
1235 #[test]
1236 #[should_panic = "Command prog: Argument or group 'extra' specified in 'requires*' for 'config' does not exist"]
requires_invalid_arg()1237 fn requires_invalid_arg() {
1238     let _ = Command::new("prog")
1239         .arg(Arg::new("config").requires("extra").long("config"))
1240         .try_get_matches_from(vec!["", "--config"]);
1241 }
1242 
1243 #[cfg(debug_assertions)]
1244 #[test]
1245 #[should_panic = "Command prog: Argument or group 'extra' specified in 'requires*' for 'config' does not exist"]
requires_if_invalid_arg()1246 fn requires_if_invalid_arg() {
1247     let _ = Command::new("prog")
1248         .arg(
1249             Arg::new("config")
1250                 .requires_if("val", "extra")
1251                 .long("config"),
1252         )
1253         .try_get_matches_from(vec!["", "--config"]);
1254 }
1255 
1256 #[cfg(debug_assertions)]
1257 #[test]
1258 #[should_panic = "Command prog: Argument or group 'extra' specified in 'required_if_eq*' for 'config' does not exist"]
required_if_invalid_arg()1259 fn required_if_invalid_arg() {
1260     let _ = Command::new("prog")
1261         .arg(
1262             Arg::new("config")
1263                 .required_if_eq("extra", "val")
1264                 .long("config"),
1265         )
1266         .try_get_matches_from(vec!["", "--config"]);
1267 }
1268 
1269 #[cfg(debug_assertions)]
1270 #[test]
1271 #[should_panic = "Command prog: Argument or group 'extra' specified in 'required_unless*' for 'config' does not exist"]
required_unless_invalid_arg()1272 fn required_unless_invalid_arg() {
1273     let _ = Command::new("prog")
1274         .arg(
1275             Arg::new("config")
1276                 .required_unless_present("extra")
1277                 .long("config"),
1278         )
1279         .try_get_matches_from(vec![""]);
1280 }
1281 
1282 #[test]
requires_with_default_value()1283 fn requires_with_default_value() {
1284     let result = Command::new("prog")
1285         .arg(
1286             Arg::new("opt")
1287                 .long("opt")
1288                 .default_value("default")
1289                 .requires("flag"),
1290         )
1291         .arg(Arg::new("flag").long("flag").action(ArgAction::SetTrue))
1292         .try_get_matches_from(vec!["myprog"]);
1293 
1294     assert!(
1295         result.is_ok(),
1296         "requires should ignore default_value: {:?}",
1297         result.unwrap_err()
1298     );
1299     let m = result.unwrap();
1300 
1301     assert_eq!(
1302         m.get_one::<String>("opt").map(|v| v.as_str()),
1303         Some("default")
1304     );
1305     assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
1306 }
1307 
1308 #[test]
requires_if_with_default_value()1309 fn requires_if_with_default_value() {
1310     let result = Command::new("prog")
1311         .arg(
1312             Arg::new("opt")
1313                 .long("opt")
1314                 .default_value("default")
1315                 .requires_if("default", "flag"),
1316         )
1317         .arg(Arg::new("flag").long("flag").action(ArgAction::SetTrue))
1318         .try_get_matches_from(vec!["myprog"]);
1319 
1320     assert!(
1321         result.is_ok(),
1322         "requires_if should ignore default_value: {:?}",
1323         result.unwrap_err()
1324     );
1325     let m = result.unwrap();
1326 
1327     assert_eq!(
1328         m.get_one::<String>("opt").map(|v| v.as_str()),
1329         Some("default")
1330     );
1331     assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
1332 }
1333 
1334 #[test]
group_requires_with_default_value()1335 fn group_requires_with_default_value() {
1336     let result = Command::new("prog")
1337         .arg(Arg::new("opt").long("opt").default_value("default"))
1338         .arg(Arg::new("flag").long("flag").action(ArgAction::SetTrue))
1339         .group(ArgGroup::new("one").arg("opt").requires("flag"))
1340         .try_get_matches_from(vec!["myprog"]);
1341 
1342     assert!(
1343         result.is_ok(),
1344         "arg group requires should ignore default_value: {:?}",
1345         result.unwrap_err()
1346     );
1347     let m = result.unwrap();
1348 
1349     assert_eq!(
1350         m.get_one::<String>("opt").map(|v| v.as_str()),
1351         Some("default")
1352     );
1353     assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
1354 }
1355 
1356 #[test]
required_if_eq_on_default_value()1357 fn required_if_eq_on_default_value() {
1358     let result = Command::new("prog")
1359         .arg(Arg::new("opt").long("opt").default_value("default"))
1360         .arg(
1361             Arg::new("flag")
1362                 .long("flag")
1363                 .action(ArgAction::SetTrue)
1364                 .required_if_eq("opt", "default"),
1365         )
1366         .try_get_matches_from(vec!["myprog"]);
1367 
1368     assert!(
1369         result.is_ok(),
1370         "required_if_eq should ignore default_value: {:?}",
1371         result.unwrap_err()
1372     );
1373     let m = result.unwrap();
1374 
1375     assert_eq!(
1376         m.get_one::<String>("opt").map(|v| v.as_str()),
1377         Some("default")
1378     );
1379     assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
1380 }
1381 
1382 #[test]
required_if_eq_all_on_default_value()1383 fn required_if_eq_all_on_default_value() {
1384     let result = Command::new("prog")
1385         .arg(Arg::new("opt").long("opt").default_value("default"))
1386         .arg(
1387             Arg::new("flag")
1388                 .long("flag")
1389                 .action(ArgAction::SetTrue)
1390                 .required_if_eq_all([("opt", "default")]),
1391         )
1392         .try_get_matches_from(vec!["myprog"]);
1393 
1394     assert!(
1395         result.is_ok(),
1396         "required_if_eq_all should ignore default_value: {:?}",
1397         result.unwrap_err()
1398     );
1399     let m = result.unwrap();
1400 
1401     assert_eq!(
1402         m.get_one::<String>("opt").map(|v| v.as_str()),
1403         Some("default")
1404     );
1405     assert!(!*m.get_one::<bool>("flag").expect("defaulted by clap"));
1406 }
1407 
1408 #[test]
required_unless_on_default_value()1409 fn required_unless_on_default_value() {
1410     let result = Command::new("prog")
1411         .arg(Arg::new("opt").long("opt").default_value("default"))
1412         .arg(Arg::new("flag").long("flag").required_unless_present("opt"))
1413         .try_get_matches_from(vec!["myprog"]);
1414 
1415     assert!(result.is_err(), "{:?}", result.unwrap());
1416 }
1417 
1418 #[test]
required_unless_all_on_default_value()1419 fn required_unless_all_on_default_value() {
1420     let result = Command::new("prog")
1421         .arg(Arg::new("opt").long("opt").default_value("default"))
1422         .arg(
1423             Arg::new("flag")
1424                 .long("flag")
1425                 .required_unless_present_all(["opt"]),
1426         )
1427         .try_get_matches_from(vec!["myprog"]);
1428 
1429     assert!(result.is_err(), "{:?}", result.unwrap());
1430 }
1431 
1432 #[test]
1433 #[cfg(feature = "error-context")]
required_error_doesnt_duplicate()1434 fn required_error_doesnt_duplicate() {
1435     let cmd = Command::new("Clap-created-USAGE-string-bug")
1436         .arg(Arg::new("a").required(true))
1437         .arg(
1438             Arg::new("b")
1439                 .short('b')
1440                 .action(ArgAction::Set)
1441                 .conflicts_with("c"),
1442         )
1443         .arg(
1444             Arg::new("c")
1445                 .short('c')
1446                 .action(ArgAction::Set)
1447                 .conflicts_with("b"),
1448         );
1449     const EXPECTED: &str = "\
1450 error: the argument '-b <b>' cannot be used with '-c <c>'
1451 
1452 Usage: clap-test -b <b> <a>
1453 
1454 For more information, try '--help'.
1455 ";
1456     utils::assert_output(cmd, "clap-test aaa -b bbb -c ccc", EXPECTED, true);
1457 }
1458 
1459 #[test]
1460 #[cfg(feature = "error-context")]
required_require_with_group_shows_flag()1461 fn required_require_with_group_shows_flag() {
1462     let cmd = Command::new("test")
1463         .arg(arg!(--"require-first").requires("first"))
1464         .arg(arg!(--first).group("either_or_both"))
1465         .arg(arg!(--second).group("either_or_both"))
1466         .group(
1467             ArgGroup::new("either_or_both")
1468                 .multiple(true)
1469                 .required(true),
1470         );
1471     const EXPECTED: &str = "\
1472 error: the following required arguments were not provided:
1473   --first
1474 
1475 Usage: test --require-first <--first|--second>
1476 
1477 For more information, try '--help'.
1478 ";
1479     utils::assert_output(cmd, "test --require-first --second", EXPECTED, true);
1480 }
1481