mirror of
https://github.com/clap-rs/clap
synced 2024-12-14 23:02:31 +00:00
66341b3c11
When supporting multiple occurrences for positional arguments in #2804, I added some tests to cover this but apparently simpler cases fail despite those more complicated cases being tested. This adds more multiple-occurrences tests for positional arguments, fixes them, and in general equates multiple values with occurrences for positional arguments as part of #2692. There are a couple more points for consideration for #2692 for us to decide on once this unblocks them (usage special case in #2977 and how subcommand help should be handled). I fully admit I have not fully quantified the impact of all of these changes and am heavily relying on the quality of our tests to carry this forward.
252 lines
8.2 KiB
Rust
252 lines
8.2 KiB
Rust
use clap::{App, Arg, ArgSettings, ErrorKind};
|
|
|
|
#[test]
|
|
fn multiple_occurrences_of_flags_long() {
|
|
let m = App::new("mo_flags_long")
|
|
.arg(
|
|
Arg::from("--multflag 'allowed multiple flag'")
|
|
.setting(ArgSettings::MultipleOccurrences),
|
|
)
|
|
.arg(Arg::from("--flag 'disallowed multiple flag'"))
|
|
.get_matches_from(vec!["", "--multflag", "--flag", "--multflag"]);
|
|
assert!(m.is_present("multflag"));
|
|
assert_eq!(m.occurrences_of("multflag"), 2);
|
|
assert!(m.is_present("flag"));
|
|
assert_eq!(m.occurrences_of("flag"), 1)
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_occurrences_of_flags_short() {
|
|
let m = App::new("mo_flags_short")
|
|
.arg(
|
|
Arg::from("-m --multflag 'allowed multiple flag'")
|
|
.setting(ArgSettings::MultipleOccurrences),
|
|
)
|
|
.arg(Arg::from("-f --flag 'disallowed multiple flag'"))
|
|
.get_matches_from(vec!["", "-m", "-f", "-m"]);
|
|
assert!(m.is_present("multflag"));
|
|
assert_eq!(m.occurrences_of("multflag"), 2);
|
|
assert!(m.is_present("flag"));
|
|
assert_eq!(m.occurrences_of("flag"), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_occurrences_of_flags_mixed() {
|
|
let m = App::new("mo_flags_mixed")
|
|
.arg(
|
|
Arg::from("-m, --multflag1 'allowed multiple flag'")
|
|
.setting(ArgSettings::MultipleOccurrences),
|
|
)
|
|
.arg(
|
|
Arg::from("-n, --multflag2 'another allowed multiple flag'")
|
|
.setting(ArgSettings::MultipleOccurrences),
|
|
)
|
|
.arg(Arg::from("-f, --flag 'disallowed multiple flag'"))
|
|
.get_matches_from(vec![
|
|
"",
|
|
"-m",
|
|
"-f",
|
|
"-n",
|
|
"--multflag1",
|
|
"-m",
|
|
"--multflag2",
|
|
]);
|
|
assert!(m.is_present("multflag1"));
|
|
assert_eq!(m.occurrences_of("multflag1"), 3);
|
|
assert!(m.is_present("multflag2"));
|
|
assert_eq!(m.occurrences_of("multflag2"), 2);
|
|
assert!(m.is_present("flag"));
|
|
assert_eq!(m.occurrences_of("flag"), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_occurrences_of_positional() {
|
|
let app = App::new("test").arg(Arg::new("multi").setting(ArgSettings::MultipleOccurrences));
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(&["test"])
|
|
.expect("zero occurrences work");
|
|
assert!(!m.is_present("multi"));
|
|
assert_eq!(m.occurrences_of("multi"), 0);
|
|
assert!(m.values_of("multi").is_none());
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(&["test", "one"])
|
|
.expect("single occurrence work");
|
|
assert!(m.is_present("multi"));
|
|
assert_eq!(m.occurrences_of("multi"), 1);
|
|
assert_eq!(m.values_of("multi").unwrap().collect::<Vec<_>>(), ["one"]);
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(&["test", "one", "two", "three", "four"])
|
|
.expect("many occurrences work");
|
|
assert!(m.is_present("multi"));
|
|
assert_eq!(m.occurrences_of("multi"), 4);
|
|
assert_eq!(
|
|
m.values_of("multi").unwrap().collect::<Vec<_>>(),
|
|
["one", "two", "three", "four"]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_occurrences_of_flags_large_quantity() {
|
|
let args: Vec<&str> = vec![""]
|
|
.into_iter()
|
|
.chain(vec!["-m"; 1024].into_iter())
|
|
.collect();
|
|
let m = App::new("mo_flags_large_qty")
|
|
.arg(
|
|
Arg::from("-m --multflag 'allowed multiple flag'")
|
|
.setting(ArgSettings::MultipleOccurrences),
|
|
)
|
|
.get_matches_from(args);
|
|
assert!(m.is_present("multflag"));
|
|
assert_eq!(m.occurrences_of("multflag"), 1024);
|
|
}
|
|
|
|
#[cfg(feature = "env")]
|
|
#[test]
|
|
fn multiple_occurrences_of_before_env() {
|
|
let app = App::new("mo_before_env").arg(
|
|
Arg::new("verbose")
|
|
.env("VERBOSE")
|
|
.short('v')
|
|
.long("verbose")
|
|
.takes_value(false)
|
|
.multiple_occurrences(true),
|
|
);
|
|
|
|
let m = app.clone().try_get_matches_from(vec![""]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 0);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["", "-v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["", "-vv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
|
|
let m = app.clone().try_get_matches_from(vec!["", "-vvv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
}
|
|
|
|
#[cfg(feature = "env")]
|
|
#[test]
|
|
fn multiple_occurrences_of_after_env() {
|
|
let app = App::new("mo_after_env").arg(
|
|
Arg::new("verbose")
|
|
.short('v')
|
|
.long("verbose")
|
|
.takes_value(false)
|
|
.multiple_occurrences(true)
|
|
.env("VERBOSE"),
|
|
);
|
|
|
|
let m = app.clone().try_get_matches_from(vec![""]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 0);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["", "-v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["", "-vv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
|
|
let m = app.clone().try_get_matches_from(vec!["", "-vvv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
}
|
|
|
|
#[test]
|
|
fn max_occurrences_implies_multiple_occurrences() {
|
|
let app = App::new("prog").arg(
|
|
Arg::new("verbose")
|
|
.short('v')
|
|
.long("verbose")
|
|
.max_occurrences(3),
|
|
);
|
|
let m = app.try_get_matches_from(vec!["prog", "-vvv"]);
|
|
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
|
|
// One max should not imply multiple occurrences
|
|
let app = App::new("prog").arg(
|
|
Arg::new("verbose")
|
|
.short('v')
|
|
.long("verbose")
|
|
.max_occurrences(1),
|
|
);
|
|
|
|
let m = app.try_get_matches_from(vec!["prog", "-vvv"]);
|
|
|
|
assert!(m.is_err());
|
|
assert_eq!(m.unwrap_err().kind, ErrorKind::UnexpectedMultipleUsage);
|
|
}
|
|
|
|
#[test]
|
|
fn max_occurrences_try_inputs() {
|
|
let app = App::new("prog").arg(
|
|
Arg::new("verbose")
|
|
.short('v')
|
|
.long("verbose")
|
|
.max_occurrences(3),
|
|
);
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "-v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "-vv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "-vvv"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "-vvvv"]);
|
|
assert!(m.is_err());
|
|
assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyOccurrences);
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(vec!["prog", "-v", "-v", "-v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(vec!["prog", "-v", "-vv", "-v"]);
|
|
assert!(m.is_err());
|
|
assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyOccurrences);
|
|
}
|
|
|
|
#[test]
|
|
fn max_occurrences_positional() {
|
|
let app = App::new("prog").arg(Arg::new("verbose").max_occurrences(3));
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 1);
|
|
|
|
let m = app.clone().try_get_matches_from(vec!["prog", "v", "v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 2);
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(vec!["prog", "v", "v", "v"]);
|
|
assert!(m.is_ok(), "{}", m.unwrap_err());
|
|
assert_eq!(m.unwrap().occurrences_of("verbose"), 3);
|
|
|
|
let m = app
|
|
.clone()
|
|
.try_get_matches_from(vec!["prog", "v", "v", "v", "v"]);
|
|
assert!(m.is_err());
|
|
assert_eq!(m.unwrap_err().kind, ErrorKind::TooManyOccurrences);
|
|
}
|