1 use super::utils;
2
3 use clap::{arg, error::ErrorKind, Arg, ArgAction, Command};
4
5 #[test]
flag_subcommand_normal()6 fn flag_subcommand_normal() {
7 let matches = Command::new("test")
8 .subcommand(
9 Command::new("some").short_flag('S').long_flag("some").arg(
10 Arg::new("test")
11 .short('t')
12 .long("test")
13 .help("testing testing")
14 .action(ArgAction::SetTrue),
15 ),
16 )
17 .try_get_matches_from(vec!["myprog", "some", "--test"])
18 .unwrap();
19 assert_eq!(matches.subcommand_name().unwrap(), "some");
20 let sub_matches = matches.subcommand_matches("some").unwrap();
21 assert!(*sub_matches
22 .get_one::<bool>("test")
23 .expect("defaulted by clap"));
24 }
25
26 #[test]
flag_subcommand_normal_with_alias()27 fn flag_subcommand_normal_with_alias() {
28 let matches = Command::new("test")
29 .subcommand(
30 Command::new("some")
31 .short_flag('S')
32 .long_flag("S")
33 .arg(
34 Arg::new("test")
35 .short('t')
36 .long("test")
37 .help("testing testing")
38 .action(ArgAction::SetTrue),
39 )
40 .alias("result"),
41 )
42 .try_get_matches_from(vec!["myprog", "result", "--test"])
43 .unwrap();
44 assert_eq!(matches.subcommand_name().unwrap(), "some");
45 let sub_matches = matches.subcommand_matches("some").unwrap();
46 assert!(*sub_matches
47 .get_one::<bool>("test")
48 .expect("defaulted by clap"));
49 }
50
51 #[test]
flag_subcommand_short()52 fn flag_subcommand_short() {
53 let matches = Command::new("test")
54 .subcommand(
55 Command::new("some").short_flag('S').arg(
56 Arg::new("test")
57 .short('t')
58 .long("test")
59 .help("testing testing")
60 .action(ArgAction::SetTrue),
61 ),
62 )
63 .try_get_matches_from(vec!["myprog", "-S", "--test"])
64 .unwrap();
65 assert_eq!(matches.subcommand_name().unwrap(), "some");
66 let sub_matches = matches.subcommand_matches("some").unwrap();
67 assert!(*sub_matches
68 .get_one::<bool>("test")
69 .expect("defaulted by clap"));
70 }
71
72 #[test]
flag_subcommand_short_with_args()73 fn flag_subcommand_short_with_args() {
74 let matches = Command::new("test")
75 .subcommand(
76 Command::new("some").short_flag('S').arg(
77 Arg::new("test")
78 .short('t')
79 .long("test")
80 .help("testing testing")
81 .action(ArgAction::SetTrue),
82 ),
83 )
84 .try_get_matches_from(vec!["myprog", "-St"])
85 .unwrap();
86 assert_eq!(matches.subcommand_name().unwrap(), "some");
87 let sub_matches = matches.subcommand_matches("some").unwrap();
88 assert!(*sub_matches
89 .get_one::<bool>("test")
90 .expect("defaulted by clap"));
91 }
92
93 #[test]
flag_subcommand_short_with_alias()94 fn flag_subcommand_short_with_alias() {
95 let matches = Command::new("test")
96 .subcommand(
97 Command::new("some")
98 .short_flag('S')
99 .arg(
100 Arg::new("test")
101 .short('t')
102 .long("test")
103 .help("testing testing")
104 .action(ArgAction::SetTrue),
105 )
106 .short_flag_alias('M')
107 .short_flag_alias('B'),
108 )
109 .try_get_matches_from(vec!["myprog", "-Bt"])
110 .unwrap();
111 assert_eq!(matches.subcommand_name().unwrap(), "some");
112 let sub_matches = matches.subcommand_matches("some").unwrap();
113 assert!(*sub_matches
114 .get_one::<bool>("test")
115 .expect("defaulted by clap"));
116 }
117
118 #[test]
flag_subcommand_short_with_alias_same_as_short_flag()119 fn flag_subcommand_short_with_alias_same_as_short_flag() {
120 let matches = Command::new("test")
121 .subcommand(Command::new("some").short_flag('S').short_flag_alias('S'))
122 .try_get_matches_from(vec!["myprog", "-S"])
123 .unwrap();
124 assert_eq!(matches.subcommand_name().unwrap(), "some");
125 }
126
127 #[test]
flag_subcommand_long_with_alias_same_as_long_flag()128 fn flag_subcommand_long_with_alias_same_as_long_flag() {
129 let matches = Command::new("test")
130 .subcommand(
131 Command::new("some")
132 .long_flag("sync")
133 .long_flag_alias("sync"),
134 )
135 .try_get_matches_from(vec!["myprog", "--sync"])
136 .unwrap();
137 assert_eq!(matches.subcommand_name().unwrap(), "some");
138 }
139
140 #[test]
flag_subcommand_short_with_aliases_vis_and_hidden()141 fn flag_subcommand_short_with_aliases_vis_and_hidden() {
142 let cmd = Command::new("test").subcommand(
143 Command::new("some")
144 .short_flag('S')
145 .arg(
146 Arg::new("test")
147 .short('t')
148 .long("test")
149 .help("testing testing"),
150 )
151 .visible_short_flag_aliases(['M', 'B'])
152 .short_flag_alias('C'),
153 );
154 let app1 = cmd.clone();
155 let matches1 = app1.try_get_matches_from(vec!["test", "-M"]).unwrap();
156 assert_eq!(matches1.subcommand_name().unwrap(), "some");
157
158 let app2 = cmd.clone();
159 let matches2 = app2.try_get_matches_from(vec!["test", "-C"]).unwrap();
160 assert_eq!(matches2.subcommand_name().unwrap(), "some");
161
162 let app3 = cmd.clone();
163 let matches3 = app3.try_get_matches_from(vec!["test", "-B"]).unwrap();
164 assert_eq!(matches3.subcommand_name().unwrap(), "some");
165 }
166
167 #[test]
flag_subcommand_short_with_aliases()168 fn flag_subcommand_short_with_aliases() {
169 let matches = Command::new("test")
170 .subcommand(
171 Command::new("some")
172 .short_flag('S')
173 .arg(
174 Arg::new("test")
175 .short('t')
176 .long("test")
177 .help("testing testing")
178 .action(ArgAction::SetTrue),
179 )
180 .short_flag_aliases(['M', 'B']),
181 )
182 .try_get_matches_from(vec!["myprog", "-Bt"])
183 .unwrap();
184 assert_eq!(matches.subcommand_name().unwrap(), "some");
185 let sub_matches = matches.subcommand_matches("some").unwrap();
186 assert!(*sub_matches
187 .get_one::<bool>("test")
188 .expect("defaulted by clap"));
189 }
190
191 #[test]
192 #[should_panic]
flag_subcommand_short_with_alias_hyphen()193 fn flag_subcommand_short_with_alias_hyphen() {
194 let _ = Command::new("test")
195 .subcommand(
196 Command::new("some")
197 .short_flag('S')
198 .arg(
199 Arg::new("test")
200 .short('t')
201 .long("test")
202 .help("testing testing"),
203 )
204 .short_flag_alias('-'),
205 )
206 .try_get_matches_from(vec!["myprog", "-Bt"])
207 .unwrap();
208 }
209
210 #[test]
211 #[should_panic]
flag_subcommand_short_with_aliases_hyphen()212 fn flag_subcommand_short_with_aliases_hyphen() {
213 let _ = Command::new("test")
214 .subcommand(
215 Command::new("some")
216 .short_flag('S')
217 .arg(
218 Arg::new("test")
219 .short('t')
220 .long("test")
221 .help("testing testing"),
222 )
223 .short_flag_aliases(['-', '-', '-']),
224 )
225 .try_get_matches_from(vec!["myprog", "-Bt"])
226 .unwrap();
227 }
228
229 #[test]
flag_subcommand_short_after_long_arg()230 fn flag_subcommand_short_after_long_arg() {
231 let m = Command::new("pacman")
232 .subcommand(
233 Command::new("sync")
234 .short_flag('S')
235 .arg(Arg::new("clean").short('c').action(ArgAction::SetTrue)),
236 )
237 .arg(Arg::new("arg").long("arg").action(ArgAction::Set))
238 .try_get_matches_from(vec!["pacman", "--arg", "foo", "-Sc"])
239 .unwrap();
240 let subm = m.subcommand_matches("sync");
241 assert!(subm.is_some());
242 let subm = subm.unwrap();
243 assert!(*subm.get_one::<bool>("clean").expect("defaulted by clap"));
244 }
245
246 #[test]
flag_subcommand_long()247 fn flag_subcommand_long() {
248 let matches = Command::new("test")
249 .subcommand(
250 Command::new("some").long_flag("some").arg(
251 Arg::new("test")
252 .short('t')
253 .long("test")
254 .help("testing testing")
255 .action(ArgAction::SetTrue),
256 ),
257 )
258 .try_get_matches_from(vec!["myprog", "--some", "--test"])
259 .unwrap();
260 assert_eq!(matches.subcommand_name().unwrap(), "some");
261 let sub_matches = matches.subcommand_matches("some").unwrap();
262 assert!(*sub_matches
263 .get_one::<bool>("test")
264 .expect("defaulted by clap"));
265 }
266
267 #[test]
flag_subcommand_long_with_alias()268 fn flag_subcommand_long_with_alias() {
269 let matches = Command::new("test")
270 .subcommand(
271 Command::new("some")
272 .long_flag("some")
273 .arg(
274 Arg::new("test")
275 .short('t')
276 .long("test")
277 .help("testing testing")
278 .action(ArgAction::SetTrue),
279 )
280 .long_flag_alias("result"),
281 )
282 .try_get_matches_from(vec!["myprog", "--result", "--test"])
283 .unwrap();
284 assert_eq!(matches.subcommand_name().unwrap(), "some");
285 let sub_matches = matches.subcommand_matches("some").unwrap();
286 assert!(*sub_matches
287 .get_one::<bool>("test")
288 .expect("defaulted by clap"));
289 }
290
291 #[test]
flag_subcommand_long_with_aliases()292 fn flag_subcommand_long_with_aliases() {
293 let matches = Command::new("test")
294 .subcommand(
295 Command::new("some")
296 .long_flag("some")
297 .arg(
298 Arg::new("test")
299 .short('t')
300 .long("test")
301 .help("testing testing")
302 .action(ArgAction::SetTrue),
303 )
304 .long_flag_aliases(["result", "someall"]),
305 )
306 .try_get_matches_from(vec!["myprog", "--result", "--test"])
307 .unwrap();
308 assert_eq!(matches.subcommand_name().unwrap(), "some");
309 let sub_matches = matches.subcommand_matches("some").unwrap();
310 assert!(*sub_matches
311 .get_one::<bool>("test")
312 .expect("defaulted by clap"));
313 }
314
315 #[test]
flag_subcommand_multiple()316 fn flag_subcommand_multiple() {
317 let matches = Command::new("test")
318 .subcommand(
319 Command::new("some")
320 .short_flag('S')
321 .long_flag("some")
322 .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
323 .arg(arg!(-p --print "print something").action(ArgAction::SetTrue))
324 .subcommand(
325 Command::new("result")
326 .short_flag('R')
327 .long_flag("result")
328 .arg(arg!(-f --flag "some flag").action(ArgAction::SetTrue))
329 .arg(arg!(-p --print "print something").action(ArgAction::SetTrue)),
330 ),
331 )
332 .try_get_matches_from(vec!["myprog", "-SfpRfp"])
333 .unwrap();
334 assert_eq!(matches.subcommand_name().unwrap(), "some");
335 let sub_matches = matches.subcommand_matches("some").unwrap();
336 assert!(*sub_matches
337 .get_one::<bool>("flag")
338 .expect("defaulted by clap"));
339 assert!(*sub_matches
340 .get_one::<bool>("print")
341 .expect("defaulted by clap"));
342 assert_eq!(sub_matches.subcommand_name().unwrap(), "result");
343 let result_matches = sub_matches.subcommand_matches("result").unwrap();
344 assert!(*result_matches
345 .get_one::<bool>("flag")
346 .expect("defaulted by clap"));
347 assert!(*result_matches
348 .get_one::<bool>("print")
349 .expect("defaulted by clap"));
350 }
351
352 #[cfg(debug_assertions)]
353 #[test]
354 #[should_panic = "the \'-f\' short flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
flag_subcommand_short_conflict_with_arg()355 fn flag_subcommand_short_conflict_with_arg() {
356 let _ = Command::new("test")
357 .subcommand(Command::new("some").short_flag('f').long_flag("some"))
358 .arg(Arg::new("test").short('f'))
359 .try_get_matches_from(vec!["myprog", "-f"])
360 .unwrap();
361 }
362
363 #[cfg(debug_assertions)]
364 #[test]
365 #[should_panic = "the \'-f\' short flag is specified for both \'some\' and \'result\' subcommands"]
flag_subcommand_short_conflict_with_alias()366 fn flag_subcommand_short_conflict_with_alias() {
367 let _ = Command::new("test")
368 .subcommand(Command::new("some").short_flag('f').long_flag("some"))
369 .subcommand(Command::new("result").short_flag('t').short_flag_alias('f'))
370 .try_get_matches_from(vec!["myprog", "-f"])
371 .unwrap();
372 }
373
374 #[cfg(debug_assertions)]
375 #[test]
376 #[should_panic = "the \'--flag\' long flag is specified for both \'some\' and \'result\' subcommands"]
flag_subcommand_long_conflict_with_alias()377 fn flag_subcommand_long_conflict_with_alias() {
378 let _ = Command::new("test")
379 .subcommand(Command::new("some").long_flag("flag"))
380 .subcommand(
381 Command::new("result")
382 .long_flag("test")
383 .long_flag_alias("flag"),
384 )
385 .try_get_matches_from(vec!["myprog", "--flag"])
386 .unwrap();
387 }
388
389 #[cfg(debug_assertions)]
390 #[test]
391 #[should_panic = "the \'-f\' short flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
flag_subcommand_short_conflict_with_arg_alias()392 fn flag_subcommand_short_conflict_with_arg_alias() {
393 let _ = Command::new("test")
394 .subcommand(Command::new("some").short_flag('f').long_flag("some"))
395 .arg(Arg::new("test").short('t').short_alias('f'))
396 .try_get_matches_from(vec!["myprog", "-f"])
397 .unwrap();
398 }
399
400 #[cfg(debug_assertions)]
401 #[test]
402 #[should_panic = "the \'--some\' long flag for the \'test\' argument conflicts with the short flag for \'some\' subcommand"]
flag_subcommand_long_conflict_with_arg_alias()403 fn flag_subcommand_long_conflict_with_arg_alias() {
404 let _ = Command::new("test")
405 .subcommand(Command::new("some").short_flag('f').long_flag("some"))
406 .arg(Arg::new("test").long("test").alias("some"))
407 .try_get_matches_from(vec!["myprog", "--some"])
408 .unwrap();
409 }
410
411 #[cfg(debug_assertions)]
412 #[test]
413 #[should_panic = "the \'--flag\' long flag for the \'flag\' argument conflicts with the short flag for \'some\' subcommand"]
flag_subcommand_long_conflict_with_arg()414 fn flag_subcommand_long_conflict_with_arg() {
415 let _ = Command::new("test")
416 .subcommand(Command::new("some").short_flag('a').long_flag("flag"))
417 .arg(Arg::new("flag").long("flag"))
418 .try_get_matches_from(vec!["myprog", "--flag"])
419 .unwrap();
420 }
421
422 #[test]
423 #[should_panic = "the '--help' long flag for the 'help' argument conflicts with the short flag for 'help' subcommand"]
flag_subcommand_conflict_with_help()424 fn flag_subcommand_conflict_with_help() {
425 let _ = Command::new("test")
426 .subcommand(Command::new("help").short_flag('h').long_flag("help"))
427 .try_get_matches_from(vec!["myprog", "--help"])
428 .unwrap();
429 }
430
431 #[test]
432 #[cfg(debug_assertions)]
433 #[should_panic = "the '--version' long flag for the 'version' argument conflicts with the short flag for 'ver' subcommand"]
flag_subcommand_conflict_with_version()434 fn flag_subcommand_conflict_with_version() {
435 let _ = Command::new("test")
436 .version("1.0.0")
437 .subcommand(Command::new("ver").short_flag('V').long_flag("version"))
438 .try_get_matches_from(vec!["myprog", "--version"])
439 .unwrap();
440 }
441
442 #[test]
flag_subcommand_long_infer_pass()443 fn flag_subcommand_long_infer_pass() {
444 let m = Command::new("prog")
445 .infer_subcommands(true)
446 .subcommand(Command::new("test").long_flag("test"))
447 .try_get_matches_from(vec!["prog", "--te"])
448 .unwrap();
449 assert_eq!(m.subcommand_name(), Some("test"));
450 }
451
452 #[cfg(not(feature = "suggestions"))]
453 #[test]
flag_subcommand_long_infer_fail()454 fn flag_subcommand_long_infer_fail() {
455 let m = Command::new("prog")
456 .infer_subcommands(true)
457 .subcommand(Command::new("test").long_flag("test"))
458 .subcommand(Command::new("temp").long_flag("temp"))
459 .try_get_matches_from(vec!["prog", "--te"]);
460 assert!(m.is_err(), "{:#?}", m.unwrap());
461 assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
462 }
463
464 #[cfg(feature = "suggestions")]
465 #[test]
flag_subcommand_long_infer_fail()466 fn flag_subcommand_long_infer_fail() {
467 let m = Command::new("prog")
468 .infer_subcommands(true)
469 .subcommand(Command::new("test").long_flag("test"))
470 .subcommand(Command::new("temp").long_flag("temp"))
471 .try_get_matches_from(vec!["prog", "--te"]);
472 assert!(m.is_err(), "{:#?}", m.unwrap());
473 assert_eq!(m.unwrap_err().kind(), ErrorKind::UnknownArgument);
474 }
475
476 #[test]
flag_subcommand_long_infer_pass_close()477 fn flag_subcommand_long_infer_pass_close() {
478 let m = Command::new("prog")
479 .infer_subcommands(true)
480 .subcommand(Command::new("test").long_flag("test"))
481 .subcommand(Command::new("temp").long_flag("temp"))
482 .try_get_matches_from(vec!["prog", "--tes"])
483 .unwrap();
484 assert_eq!(m.subcommand_name(), Some("test"));
485 }
486
487 #[test]
flag_subcommand_long_infer_exact_match()488 fn flag_subcommand_long_infer_exact_match() {
489 let m = Command::new("prog")
490 .infer_subcommands(true)
491 .subcommand(Command::new("test").long_flag("test"))
492 .subcommand(Command::new("testa").long_flag("testa"))
493 .subcommand(Command::new("testb").long_flag("testb"))
494 .try_get_matches_from(vec!["prog", "--test"])
495 .unwrap();
496 assert_eq!(m.subcommand_name(), Some("test"));
497 }
498
499 static FLAG_SUBCOMMAND_HELP: &str = "\
500 Query the package database.
501
502 Usage: pacman {query|--query|-Q} [OPTIONS]
503
504 Options:
505 -s, --search <search>... search locally installed packages for matching strings
506 -i, --info <info>... view package information
507 -h, --help Print help
508 ";
509
510 #[test]
flag_subcommand_long_short_normal_usage_string()511 fn flag_subcommand_long_short_normal_usage_string() {
512 let cmd = Command::new("pacman")
513 .about("package manager utility")
514 .version("5.2.1")
515 .subcommand_required(true)
516 .author("Pacman Development Team")
517 // Query subcommand
518 //
519 // Only a few of its arguments are implemented below.
520 .subcommand(
521 Command::new("query")
522 .short_flag('Q')
523 .long_flag("query")
524 .about("Query the package database.")
525 .arg(
526 Arg::new("search")
527 .short('s')
528 .long("search")
529 .help("search locally installed packages for matching strings")
530 .conflicts_with("info")
531 .action(ArgAction::Set)
532 .num_args(1..),
533 )
534 .arg(
535 Arg::new("info")
536 .long("info")
537 .short('i')
538 .conflicts_with("search")
539 .help("view package information")
540 .action(ArgAction::Set)
541 .num_args(1..),
542 ),
543 );
544 utils::assert_output(cmd, "pacman -Qh", FLAG_SUBCOMMAND_HELP, false);
545 }
546
547 static FLAG_SUBCOMMAND_NO_SHORT_HELP: &str = "\
548 Query the package database.
549
550 Usage: pacman {query|--query} [OPTIONS]
551
552 Options:
553 -s, --search <search>... search locally installed packages for matching strings
554 -i, --info <info>... view package information
555 -h, --help Print help
556 ";
557
558 #[test]
flag_subcommand_long_normal_usage_string()559 fn flag_subcommand_long_normal_usage_string() {
560 let cmd = Command::new("pacman")
561 .about("package manager utility")
562 .version("5.2.1")
563 .subcommand_required(true)
564 .author("Pacman Development Team")
565 // Query subcommand
566 //
567 // Only a few of its arguments are implemented below.
568 .subcommand(
569 Command::new("query")
570 .long_flag("query")
571 .about("Query the package database.")
572 .arg(
573 Arg::new("search")
574 .short('s')
575 .long("search")
576 .help("search locally installed packages for matching strings")
577 .conflicts_with("info")
578 .action(ArgAction::Set)
579 .num_args(1..),
580 )
581 .arg(
582 Arg::new("info")
583 .long("info")
584 .short('i')
585 .conflicts_with("search")
586 .help("view package information")
587 .action(ArgAction::Set)
588 .num_args(1..),
589 ),
590 );
591 utils::assert_output(
592 cmd,
593 "pacman query --help",
594 FLAG_SUBCOMMAND_NO_SHORT_HELP,
595 false,
596 );
597 }
598
599 static FLAG_SUBCOMMAND_NO_LONG_HELP: &str = "\
600 Query the package database.
601
602 Usage: pacman {query|-Q} [OPTIONS]
603
604 Options:
605 -s, --search <search>... search locally installed packages for matching strings
606 -i, --info <info>... view package information
607 -h, --help Print help
608 ";
609
610 #[test]
flag_subcommand_short_normal_usage_string()611 fn flag_subcommand_short_normal_usage_string() {
612 let cmd = Command::new("pacman")
613 .about("package manager utility")
614 .version("5.2.1")
615 .subcommand_required(true)
616 .author("Pacman Development Team")
617 // Query subcommand
618 //
619 // Only a few of its arguments are implemented below.
620 .subcommand(
621 Command::new("query")
622 .short_flag('Q')
623 .about("Query the package database.")
624 .arg(
625 Arg::new("search")
626 .short('s')
627 .long("search")
628 .help("search locally installed packages for matching strings")
629 .conflicts_with("info")
630 .action(ArgAction::Set)
631 .num_args(1..),
632 )
633 .arg(
634 Arg::new("info")
635 .long("info")
636 .short('i')
637 .conflicts_with("search")
638 .help("view package information")
639 .action(ArgAction::Set)
640 .num_args(1..),
641 ),
642 );
643 utils::assert_output(
644 cmd,
645 "pacman query --help",
646 FLAG_SUBCOMMAND_NO_LONG_HELP,
647 false,
648 );
649 }
650