1use super::utils; 2 3use clap::{arg, error::ErrorKind, Arg, ArgAction, Command}; 4 5#[test] 6fn 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] 27fn 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] 52fn 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] 73fn 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] 94fn 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] 119fn 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] 128fn 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] 141fn 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] 168fn 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] 193fn 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] 212fn 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] 230fn 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] 247fn 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] 268fn 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] 292fn 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] 316fn 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"] 355fn 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"] 366fn 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"] 377fn 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"] 392fn 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"] 403fn 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"] 414fn 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"] 424fn 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"] 434fn 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] 443fn 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] 454fn 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] 466fn 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] 477fn 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] 488fn 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 499static FLAG_SUBCOMMAND_HELP: &str = "\ 500Query the package database. 501 502Usage: pacman {query|--query|-Q} [OPTIONS] 503 504Options: 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] 511fn 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 547static FLAG_SUBCOMMAND_NO_SHORT_HELP: &str = "\ 548Query the package database. 549 550Usage: pacman {query|--query} [OPTIONS] 551 552Options: 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] 559fn 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 599static FLAG_SUBCOMMAND_NO_LONG_HELP: &str = "\ 600Query the package database. 601 602Usage: pacman {query|-Q} [OPTIONS] 603 604Options: 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] 611fn 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