wip: implement 1061

This commit is contained in:
Kevin K 2017-10-21 15:55:31 -04:00
parent 569ced1f3d
commit 8a2e1dbdcd
No known key found for this signature in database
GPG key ID: 17218E4B3692F01A
2 changed files with 149 additions and 90 deletions

149
tests/propagate_globals.rs Normal file
View file

@ -0,0 +1,149 @@
extern crate clap;
extern crate regex;
#[cfg(test)]
mod tests {
include!("../clap-test.rs");
use clap::{App, Arg, SubCommand, AppSettings, ArgMatches};
fn get_global_arg() -> Arg<'static, 'static> {
Arg::with_name("GLOBAL_ARG")
.long("global-arg")
.help(
"Specifies something needed by the subcommands",
)
.global(true)
.takes_value(true)
}
fn get_global_flag() -> Arg<'static, 'static> {
Arg::with_name("GLOBAL_FLAG")
.long("global-flag")
.help(
"Specifies something needed by the subcommands",
)
.global(true)
}
fn get_app() -> App<'static, 'static> {
App::new("myprog")
.global_setting(AppSettings::PropagateGlobalValuesDown)
}
fn get_subcommands() -> App<'static, 'static> {
SubCommand::with_name("outer")
.subcommand(SubCommand::with_name("inner"))
}
fn get_matches(app: App<'static, 'static>, argv: &'static str) -> ArgMatches<'static> {
app.get_matches_from(argv.split(" ").collect::<Vec<_>>())
}
fn get_outer_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
m.subcommand_matches("outer").expect("could not access outer subcommand")
}
fn get_inner_matches<'a>(m: &'a ArgMatches<'static>) -> &'a ArgMatches<'static> {
get_outer_matches(m).subcommand_matches("inner").expect("could not access inner subcommand")
}
fn top_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
m.value_of("GLOBAL_ARG") == val.into()
}
fn inner_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
get_inner_matches(m).value_of("GLOBAL_ARG") == val.into()
}
fn outer_can_access_arg<T: Into<Option<&'static str>>>(m: &ArgMatches<'static>, val: T) -> bool {
get_outer_matches(m).value_of("GLOBAL_ARG") == val.into()
}
fn inner_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
let m = get_inner_matches(m);
(m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
}
fn outer_can_access_flag(m: &ArgMatches<'static>, present: bool, occurrences: u64) -> bool {
let m = get_outer_matches(m);
(m.is_present("GLOBAL_FLAG") == present) && (m.occurrences_of("GLOBAL_FLAG") == occurrences)
}
#[test]
fn global_arg_defined_top_level_used_top_level() {
let app = get_app()
.arg(get_global_arg())
.subcommand(get_subcommands());
let m = get_matches(app, "myprog --global-arg=some_value outer inner");
assert!(top_can_access_arg(&m, "some_value"));
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
#[test]
fn global_arg_defined_top_level_used_outer() {
let app = get_app()
.arg(get_global_arg())
.subcommand(get_subcommands());
let m = get_matches(app, "myprog outer --global-arg=some_value inner");
assert!(top_can_access_arg(&m, "some_value"));
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
#[test]
fn global_arg_defined_top_level_used_inner() {
let app = get_app()
.arg(get_global_arg())
.subcommand(get_subcommands());
let m = get_matches(app, "myprog outer inner --global-arg=some_value");
assert!(top_can_access_arg(&m, "some_value"), "{:?}", m);
assert!(inner_can_access_arg(&m, "some_value"));
assert!(outer_can_access_arg(&m, "some_value"));
}
// #[test]
// fn global_arg_defined_nested_used_top_level() {
// let app = get_app()
// .subcommand(get_subcommands()
// .arg(get_global_arg()));
// let m = get_matches(app, "myprog --global-arg=some_value outer inner");
// assert!(top_can_access_arg(&m, "some_value"));
// assert!(inner_can_access_arg(&m, "some_value"));
// assert!(outer_can_access_arg(&m, "some_value"));
// }
// #[test]
// fn global_arg_defined_nested_used_outer() {
// let app = get_app()
// .subcommand(get_subcommands()
// .arg(get_global_arg()));
// let m = get_matches(app, "myprog outer --global-arg=some_value inner");
// assert!(top_can_access_arg(&m, "some_value"));
// assert!(inner_can_access_arg(&m, "some_value"));
// assert!(outer_can_access_arg(&m, "some_value"));
// }
// #[test]
// fn global_arg_defined_nested_used_inner() {
// let app = get_app()
// .subcommand(get_subcommands()
// .arg(get_global_arg()));
// let m = get_matches(app, "myprog outer inner --global-arg=some_value");
// assert!(top_can_access_arg(&m, "some_value"));
// assert!(inner_can_access_arg(&m, "some_value"));
// assert!(outer_can_access_arg(&m, "some_value"));
// }
}

View file

@ -1,90 +0,0 @@
extern crate clap;
extern crate regex;
#[cfg(test)]
mod tests {
include!("../clap-test.rs");
use clap;
use clap::{App, Arg, SubCommand, AppSettings};
fn setup_app_with_globals_and_subcommands<'a, 'b>() -> clap::App<'a, 'b> {
let global_arg = Arg::with_name("GLOBAL_ARG")
.long("global-arg")
.help(
"Specifies something needed by the subcommands",
)
.global(true)
.takes_value(true);
let double_sub_command = SubCommand::with_name("outer")
.setting(AppSettings::PropagateGlobalValuesDown)
.subcommand(SubCommand::with_name("inner"));
App::new("myprog")
.global_setting(AppSettings::PropagateGlobalValuesDown)
.arg(global_arg)
.subcommand(double_sub_command)
}
fn first_subcommand_can_access_global(arg_vector : Vec<&str>) {
let matches = setup_app_with_globals_and_subcommands().get_matches_from(
arg_vector
);
let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");
assert_eq!(sub_match.value_of("GLOBAL_ARG").expect("subcommand could not access global arg"),
"some_value", "subcommand did not have expected value for global arg");
}
fn second_subcommand_can_access_global(arg_vector : Vec<&str>) {
let matches = setup_app_with_globals_and_subcommands().get_matches_from(
arg_vector
);
let sub_match = matches.subcommand_matches("outer").expect("could not access subcommand");
let sub_sub_match = sub_match.subcommand_matches("inner").expect("could not access inner sub");
assert_eq!(sub_sub_match.value_of("GLOBAL_ARG").expect("inner subcommand could not access global arg"),
"some_value", "inner subcommand did not have expected value for global arg");
}
#[test]
fn subcommand_can_access_global_arg_if_global_arg_is_first() {
// currently passes
first_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
}
#[test]
fn subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
// currently passes
first_subcommand_can_access_global(vec!["myprog", "outer", "--global-arg", "some_value" ,"inner"]);
}
#[test]
fn first_subcommand_can_access_global_arg_if_global_arg_is_last() {
// currently fails - hypothesis - nothing propagates global args back up
first_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
}
#[test]
fn second_subcommand_can_access_global_arg_if_global_arg_is_first() {
// currently passes
second_subcommand_can_access_global(vec!["myprog", "--global-arg", "some_value", "outer", "inner"]);
}
#[test]
fn second_subcommand_can_access_global_arg_if_global_arg_is_in_the_middle() {
// currently fails - hypothesis: subcommands do not recursively propagate global args
second_subcommand_can_access_global(vec!["myprog", "outer", "--global-arg", "some_value" ,"inner"]);
}
#[test]
fn second_subcommand_can_access_global_arg_if_global_arg_is_last() {
// currently passes
second_subcommand_can_access_global(vec!["myprog", "outer", "inner", "--global-arg", "some_value"]);
}
}