From 78e4c90326c8a7d9235c3d1435f5ba0bff18c1df Mon Sep 17 00:00:00 2001 From: Ed Page Date: Thu, 4 Nov 2021 10:15:04 -0500 Subject: [PATCH] refactor(tests): Prepare for Special Type experiments In experimenting on #1772, I want to write test cases for various combinations of required or not, values vs occurrences, etc. There wasn't really a clear place to put these. On top of that, I wanted there to be a clear place in the tests for describing the behavior of special types, to make it easier to audit and easier to see how a PR for #1772 changes things. As part of this effort in organizing these tests, I reduced the number of tests that use special types. This better focuses these tests on the cases they are intending to cover, rather than pulling in unrelated features. This makes it easier to audit special types and makes it so failures give more focused results, making it easier to see what broke. --- clap_derive/tests/arg_enum.rs | 76 +++--- clap_derive/tests/arguments.rs | 88 +++--- clap_derive/tests/basic.rs | 9 +- clap_derive/tests/doc-comments-help.rs | 2 +- .../tests/explicit_name_no_renaming.rs | 17 +- clap_derive/tests/flags.rs | 45 ++- clap_derive/tests/help.rs | 22 +- clap_derive/tests/issues.rs | 2 +- clap_derive/tests/{nested.rs => macros.rs} | 0 clap_derive/tests/options.rs | 256 +++++++++--------- clap_derive/tests/privacy.rs | 2 +- clap_derive/tests/raw_idents.rs | 15 +- clap_derive/tests/special_types.rs | 73 ----- 13 files changed, 271 insertions(+), 336 deletions(-) rename clap_derive/tests/{nested.rs => macros.rs} (100%) delete mode 100644 clap_derive/tests/special_types.rs diff --git a/clap_derive/tests/arg_enum.rs b/clap_derive/tests/arg_enum.rs index 4ca646c6..809734ed 100644 --- a/clap_derive/tests/arg_enum.rs +++ b/clap_derive/tests/arg_enum.rs @@ -297,7 +297,41 @@ fn multiple_alias() { } #[test] -fn option() { +fn skip_variant() { + #[derive(ArgEnum, PartialEq, Debug, Clone)] + #[allow(dead_code)] // silence warning about `Baz` being unused + enum ArgChoice { + Foo, + Bar, + #[clap(skip)] + Baz, + } + + assert_eq!( + ArgChoice::value_variants() + .iter() + .map(ArgEnum::to_possible_value) + .map(Option::unwrap) + .collect::>(), + vec![PossibleValue::new("foo"), PossibleValue::new("bar")] + ); + assert!(ArgChoice::from_str("foo", true).is_ok()); + assert!(ArgChoice::from_str("bar", true).is_ok()); + assert!(ArgChoice::from_str("baz", true).is_err()); +} + +#[test] +fn from_str_invalid() { + #[derive(ArgEnum, PartialEq, Debug, Clone)] + enum ArgChoice { + Foo, + } + + assert!(ArgChoice::from_str("bar", true).is_err()); +} + +#[test] +fn option_type() { #[derive(ArgEnum, PartialEq, Debug, Clone)] enum ArgChoice { Foo, @@ -327,7 +361,7 @@ fn option() { } #[test] -fn option_option() { +fn option_option_type() { #[derive(ArgEnum, PartialEq, Debug, Clone)] enum ArgChoice { Foo, @@ -361,7 +395,7 @@ fn option_option() { } #[test] -fn vector() { +fn vec_type() { #[derive(ArgEnum, PartialEq, Debug, Clone)] enum ArgChoice { Foo, @@ -391,7 +425,7 @@ fn vector() { } #[test] -fn option_vector() { +fn option_vec_type() { #[derive(ArgEnum, PartialEq, Debug, Clone)] enum ArgChoice { Foo, @@ -423,37 +457,3 @@ fn option_vector() { ); assert!(Opt::try_parse_from(&["", "-a", "fOo"]).is_err()); } - -#[test] -fn skip_variant() { - #[derive(ArgEnum, PartialEq, Debug, Clone)] - #[allow(dead_code)] // silence warning about `Baz` being unused - enum ArgChoice { - Foo, - Bar, - #[clap(skip)] - Baz, - } - - assert_eq!( - ArgChoice::value_variants() - .iter() - .map(ArgEnum::to_possible_value) - .map(Option::unwrap) - .collect::>(), - vec![PossibleValue::new("foo"), PossibleValue::new("bar")] - ); - assert!(ArgChoice::from_str("foo", true).is_ok()); - assert!(ArgChoice::from_str("bar", true).is_ok()); - assert!(ArgChoice::from_str("baz", true).is_err()); -} - -#[test] -fn from_str_invalid() { - #[derive(ArgEnum, PartialEq, Debug, Clone)] - enum ArgChoice { - Foo, - } - - assert!(ArgChoice::from_str("bar", true).is_err()); -} diff --git a/clap_derive/tests/arguments.rs b/clap_derive/tests/arguments.rs index e08b624c..2a1b0d11 100644 --- a/clap_derive/tests/arguments.rs +++ b/clap_derive/tests/arguments.rs @@ -29,20 +29,6 @@ fn required_argument() { assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err()); } -#[test] -fn optional_argument() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - arg: Option, - } - assert_eq!( - Opt { arg: Some(42) }, - Opt::try_parse_from(&["test", "42"]).unwrap() - ); - assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap()); - assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err()); -} - #[test] fn argument_with_default() { #[derive(Parser, PartialEq, Debug)] @@ -58,45 +44,6 @@ fn argument_with_default() { assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err()); } -#[test] -fn arguments() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - arg: Vec, - } - assert_eq!( - Opt { arg: vec![24] }, - Opt::try_parse_from(&["test", "24"]).unwrap() - ); - assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::try_parse_from(&["test", "24", "42"]).unwrap() - ); -} - -#[test] -fn arguments_safe() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - arg: Vec, - } - assert_eq!( - Opt { arg: vec![24] }, - Opt::try_parse_from(&["test", "24"]).unwrap() - ); - assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::try_parse_from(&["test", "24", "42"]).unwrap() - ); - - assert_eq!( - clap::ErrorKind::ValueValidation, - Opt::try_parse_from(&["test", "NOPE"]).err().unwrap().kind - ); -} - #[test] fn auto_value_name() { #[derive(Parser, PartialEq, Debug)] @@ -136,3 +83,38 @@ fn explicit_value_name() { Opt::try_parse_from(&["test", "10"]).unwrap() ); } + +#[test] +fn option_type_is_optional() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + arg: Option, + } + assert_eq!( + Opt { arg: Some(42) }, + Opt::try_parse_from(&["test", "42"]).unwrap() + ); + assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap()); + assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err()); +} + +#[test] +fn vec_type_is_multiple_values() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + arg: Vec, + } + assert_eq!( + Opt { arg: vec![24] }, + Opt::try_parse_from(&["test", "24"]).unwrap() + ); + assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); + assert_eq!( + Opt { arg: vec![24, 42] }, + Opt::try_parse_from(&["test", "24", "42"]).unwrap() + ); + assert_eq!( + clap::ErrorKind::ValueValidation, + Opt::try_parse_from(&["test", "NOPE"]).err().unwrap().kind + ); +} diff --git a/clap_derive/tests/basic.rs b/clap_derive/tests/basic.rs index 69f7ee29..917fa6dd 100644 --- a/clap_derive/tests/basic.rs +++ b/clap_derive/tests/basic.rs @@ -19,17 +19,12 @@ fn basic() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short = 'a', long = "arg")] - arg: Vec, + arg: i32, } assert_eq!( - Opt { arg: vec![24] }, + Opt { arg: 24 }, Opt::try_parse_from(&["test", "-a24"]).unwrap() ); - assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::try_parse_from(&["test", "--arg", "24", "42"]).unwrap() - ); } #[test] diff --git a/clap_derive/tests/doc-comments-help.rs b/clap_derive/tests/doc-comments-help.rs index 1d6b0c24..d502a2b6 100644 --- a/clap_derive/tests/doc-comments-help.rs +++ b/clap_derive/tests/doc-comments-help.rs @@ -108,7 +108,7 @@ fn top_long_doc_comment_both_help_long_help() { /// Or something else Foo { #[clap(about = "foo")] - bars: Vec, + bars: String, }, } diff --git a/clap_derive/tests/explicit_name_no_renaming.rs b/clap_derive/tests/explicit_name_no_renaming.rs index 8ea9955a..477fea2a 100644 --- a/clap_derive/tests/explicit_name_no_renaming.rs +++ b/clap_derive/tests/explicit_name_no_renaming.rs @@ -7,15 +7,20 @@ use utils::*; fn explicit_short_long_no_rename() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short = '.', long = ".foo", multiple_occurrences(true))] - foo: Vec, + #[clap(short = '.', long = ".foo")] + foo: String, } + assert_eq!( + Opt { foo: "long".into() }, + Opt::try_parse_from(&["test", "--.foo", "long"]).unwrap() + ); + assert_eq!( Opt { - foo: vec!["short".into(), "long".into()] + foo: "short".into(), }, - Opt::try_parse_from(&["test", "-.", "short", "--.foo", "long"]).unwrap() + Opt::try_parse_from(&["test", "-.", "short"]).unwrap() ); } @@ -24,9 +29,9 @@ fn explicit_name_no_rename() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(name = ".options")] - foo: Vec, + foo: String, } let help = get_long_help::(); - assert!(help.contains("[.options]...")) + assert!(help.contains("<.options>")) } diff --git a/clap_derive/tests/flags.rs b/clap_derive/tests/flags.rs index 9c57683a..176c6369 100644 --- a/clap_derive/tests/flags.rs +++ b/clap_derive/tests/flags.rs @@ -15,7 +15,7 @@ use clap::Parser; #[test] -fn unique_flag() { +fn bool_type_is_flag() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short, long)] @@ -41,7 +41,7 @@ fn unique_flag() { } #[test] -fn multiple_flag() { +fn from_occurrences() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short, long, parse(from_occurrences))] @@ -74,12 +74,12 @@ fn multiple_flag() { assert!(Opt::try_parse_from(&["test", "-a", "foo"]).is_err()); } -fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool { - std::sync::atomic::AtomicBool::new(b) -} - #[test] -fn non_bool_flags() { +fn non_bool_type_flag() { + fn parse_from_flag(b: bool) -> std::sync::atomic::AtomicBool { + std::sync::atomic::AtomicBool::new(b) + } + #[derive(Parser, Debug)] struct Opt { #[clap(short, long, parse(from_flag = parse_from_flag))] @@ -106,7 +106,7 @@ fn non_bool_flags() { } #[test] -fn combined_flags() { +fn mixed_type_flags() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short, long)] @@ -158,3 +158,32 @@ fn combined_flags() { Opt::try_parse_from(&["test", "-bb", "-a", "-bb"]).unwrap() ); } + +#[test] +fn ignore_qualified_bool_type() { + mod inner { + #[allow(non_camel_case_types)] + #[derive(PartialEq, Debug)] + pub struct bool(pub String); + + impl std::str::FromStr for self::bool { + type Err = String; + + fn from_str(s: &str) -> Result { + Ok(self::bool(s.into())) + } + } + } + + #[derive(Parser, PartialEq, Debug)] + struct Opt { + arg: inner::bool, + } + + assert_eq!( + Opt { + arg: inner::bool("success".into()) + }, + Opt::try_parse_from(&["test", "success"]).unwrap() + ); +} diff --git a/clap_derive/tests/help.rs b/clap_derive/tests/help.rs index b14a3722..48de6301 100644 --- a/clap_derive/tests/help.rs +++ b/clap_derive/tests/help.rs @@ -6,10 +6,10 @@ fn arg_help_heading_applied() { struct CliOptions { #[clap(long)] #[clap(help_heading = Some("HEADING A"))] - should_be_in_section_a: Option, + should_be_in_section_a: u32, #[clap(long)] - no_section: Option, + no_section: u32, } let app = CliOptions::into_app(); @@ -34,10 +34,10 @@ fn app_help_heading_applied() { struct CliOptions { #[clap(long)] #[clap(help_heading = Some("HEADING A"))] - should_be_in_section_a: Option, + should_be_in_section_a: u32, #[clap(long)] - should_be_in_default_section: Option, + should_be_in_default_section: u32, } let app = CliOptions::into_app(); @@ -72,21 +72,21 @@ fn app_help_heading_flattened() { sub_a: SubA, #[clap(long)] - should_be_in_default_section: Option, + should_be_in_default_section: u32, } #[derive(Debug, Clone, Args)] #[clap(help_heading = "HEADING A")] struct OptionsA { #[clap(long)] - should_be_in_section_a: Option, + should_be_in_section_a: u32, } #[derive(Debug, Clone, Args)] #[clap(help_heading = "HEADING B")] struct OptionsB { #[clap(long)] - should_be_in_section_b: Option, + should_be_in_section_b: u32, } #[derive(Debug, Clone, Subcommand)] @@ -98,20 +98,20 @@ fn app_help_heading_flattened() { SubAOne, #[clap(help_heading = "SUB A")] SubATwo { - should_be_in_sub_a: Option, + should_be_in_sub_a: u32, }, } #[derive(Debug, Clone, Subcommand)] enum SubB { #[clap(help_heading = "SUB B")] - SubBOne { should_be_in_sub_b: Option }, + SubBOne { should_be_in_sub_b: u32 }, } #[derive(Debug, Clone, Subcommand)] enum SubC { #[clap(help_heading = "SUB C")] - SubCOne { should_be_in_sub_c: Option }, + SubCOne { should_be_in_sub_c: u32 }, } let app = CliOptions::into_app(); @@ -172,7 +172,7 @@ fn flatten_field_with_help_heading() { #[derive(Debug, Clone, Args)] struct OptionsA { #[clap(long)] - should_be_in_section_a: Option, + should_be_in_section_a: u32, } let app = CliOptions::into_app(); diff --git a/clap_derive/tests/issues.rs b/clap_derive/tests/issues.rs index 1e4730c4..4201cd42 100644 --- a/clap_derive/tests/issues.rs +++ b/clap_derive/tests/issues.rs @@ -63,7 +63,7 @@ fn issue_324() { #[clap(version = my_version())] struct Opt { #[clap(subcommand)] - _cmd: Option, + _cmd: SubCommand, } #[derive(Subcommand)] diff --git a/clap_derive/tests/nested.rs b/clap_derive/tests/macros.rs similarity index 100% rename from clap_derive/tests/nested.rs rename to clap_derive/tests/macros.rs diff --git a/clap_derive/tests/options.rs b/clap_derive/tests/options.rs index 9d62ff8e..3ee40d2c 100644 --- a/clap_derive/tests/options.rs +++ b/clap_derive/tests/options.rs @@ -42,21 +42,6 @@ fn required_option() { assert!(Opt::try_parse_from(&["test", "-a42", "-a24"]).is_err()); } -#[test] -fn optional_option() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - #[clap(short)] - arg: Option, - } - assert_eq!( - Opt { arg: Some(42) }, - Opt::try_parse_from(&["test", "-a42"]).unwrap() - ); - assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap()); - assert!(Opt::try_parse_from(&["test", "-a42", "-a24"]).is_err()); -} - #[test] fn option_with_default() { #[derive(Parser, PartialEq, Debug)] @@ -87,41 +72,6 @@ fn option_with_raw_default() { assert!(Opt::try_parse_from(&["test", "-a42", "-a24"]).is_err()); } -#[test] -fn options() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - #[clap(short, long, multiple_occurrences(true))] - arg: Vec, - } - assert_eq!( - Opt { arg: vec![24] }, - Opt::try_parse_from(&["test", "-a24"]).unwrap() - ); - assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); - assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::try_parse_from(&["test", "-a24", "--arg", "42"]).unwrap() - ); -} - -#[test] -fn default_value() { - #[derive(Parser, PartialEq, Debug)] - struct Opt { - #[clap(short, default_value = "test")] - arg: String, - } - assert_eq!( - Opt { arg: "test".into() }, - Opt::try_parse_from(&["test"]).unwrap() - ); - assert_eq!( - Opt { arg: "foo".into() }, - Opt::try_parse_from(&["test", "-afoo"]).unwrap() - ); -} - #[test] fn option_from_str() { #[derive(Debug, PartialEq)] @@ -147,7 +97,81 @@ fn option_from_str() { } #[test] -fn optional_argument_for_optional_option() { +fn option_type_is_optional() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(short)] + arg: Option, + } + assert_eq!( + Opt { arg: Some(42) }, + Opt::try_parse_from(&["test", "-a42"]).unwrap() + ); + assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap()); + assert!(Opt::try_parse_from(&["test", "-a42", "-a24"]).is_err()); +} + +#[test] +fn required_with_option_type() { + #[derive(Debug, PartialEq, Eq, Parser)] + #[clap(setting(clap::AppSettings::SubcommandsNegateReqs))] + struct Opt { + #[clap(required = true)] + req_str: Option, + + #[clap(subcommand)] + cmd: Option, + } + + #[derive(Debug, PartialEq, Eq, Subcommand)] + enum SubCommands { + ExSub { + #[clap(short, long, parse(from_occurrences))] + verbose: u8, + }, + } + + assert_eq!( + Opt { + req_str: Some(("arg").into()), + cmd: None, + }, + Opt::try_parse_from(&["test", "arg"]).unwrap() + ); + + assert_eq!( + Opt { + req_str: None, + cmd: Some(SubCommands::ExSub { verbose: 1 }), + }, + Opt::try_parse_from(&["test", "ex-sub", "-v"]).unwrap() + ); + + assert!(Opt::try_parse_from(&["test"]).is_err()); +} + +#[test] +fn ignore_qualified_option_type() { + fn parser(s: &str) -> Option { + Some(s.to_string()) + } + + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(parse(from_str = parser))] + arg: ::std::option::Option, + } + + assert_eq!( + Opt { + arg: Some("success".into()) + }, + Opt::try_parse_from(&["test", "success"]).unwrap() + ); +} + +#[test] +fn option_option_type_is_optional_value() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short, multiple_occurrences(true))] @@ -169,7 +193,7 @@ fn optional_argument_for_optional_option() { } #[test] -fn option_option_help() { +fn option_option_type_help() { #[derive(Parser, Debug)] struct Opt { #[clap(long, value_name = "val")] @@ -181,7 +205,7 @@ fn option_option_help() { } #[test] -fn two_option_options() { +fn two_option_option_types() { #[derive(Parser, PartialEq, Debug)] struct Opt { #[clap(short)] @@ -235,10 +259,48 @@ fn two_option_options() { } #[test] -fn optional_vec() { +fn vec_type_is_multiple_values() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, multiple_occurrences(true))] + #[clap(short, long)] + arg: Vec, + } + assert_eq!( + Opt { arg: vec![24] }, + Opt::try_parse_from(&["test", "-a24"]).unwrap() + ); + assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); + assert_eq!( + Opt { arg: vec![24, 42] }, + Opt::try_parse_from(&["test", "-a", "24", "42"]).unwrap() + ); +} + +#[test] +fn ignore_qualified_vec_type() { + fn parser(s: &str) -> Vec { + vec![s.to_string()] + } + + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(parse(from_str = parser))] + arg: ::std::vec::Vec, + } + + assert_eq!( + Opt { + arg: vec!["success".into()] + }, + Opt::try_parse_from(&["test", "success"]).unwrap() + ); +} + +#[test] +fn option_vec_type() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(short)] arg: Option>, } assert_eq!( @@ -246,27 +308,6 @@ fn optional_vec() { Opt::try_parse_from(&["test", "-a", "1"]).unwrap() ); - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::try_parse_from(&["test", "-a1", "-a2"]).unwrap() - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::try_parse_from(&["test", "-a1", "-a2", "-a"]).unwrap() - ); - - assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::try_parse_from(&["test", "-a1", "-a", "-a2"]).unwrap() - ); - assert_eq!( Opt { arg: Some(vec![1, 2]) @@ -274,34 +315,22 @@ fn optional_vec() { Opt::try_parse_from(&["test", "-a", "1", "2"]).unwrap() ); - assert_eq!( - Opt { - arg: Some(vec![1, 2, 3]) - }, - Opt::try_parse_from(&["test", "-a", "1", "2", "-a", "3"]).unwrap() - ); - assert_eq!( Opt { arg: Some(vec![]) }, Opt::try_parse_from(&["test", "-a"]).unwrap() ); - assert_eq!( - Opt { arg: Some(vec![]) }, - Opt::try_parse_from(&["test", "-a", "-a"]).unwrap() - ); - assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap()); } #[test] -fn two_optional_vecs() { +fn two_option_vec_types() { #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(short, multiple_occurrences(true))] + #[clap(short)] arg: Option>, - #[clap(short, multiple_occurrences(true))] + #[clap(short)] b: Option>, } @@ -316,9 +345,9 @@ fn two_optional_vecs() { assert_eq!( Opt { arg: Some(vec![1]), - b: Some(vec![]) + b: Some(vec![1]) }, - Opt::try_parse_from(&["test", "-a", "-b", "-a1"]).unwrap() + Opt::try_parse_from(&["test", "-a", "1", "-b", "1"]).unwrap() ); assert_eq!( @@ -326,7 +355,7 @@ fn two_optional_vecs() { arg: Some(vec![1, 2]), b: Some(vec![1, 2]) }, - Opt::try_parse_from(&["test", "-a1", "-a2", "-b1", "-b2"]).unwrap() + Opt::try_parse_from(&["test", "-a", "1", "2", "-b", "1", "2"]).unwrap() ); assert_eq!( @@ -334,42 +363,3 @@ fn two_optional_vecs() { Opt::try_parse_from(&["test"]).unwrap() ); } - -#[test] -fn required_option_type() { - #[derive(Debug, PartialEq, Eq, Parser)] - #[clap(setting(clap::AppSettings::SubcommandsNegateReqs))] - struct Opt { - #[clap(required = true)] - req_str: Option, - - #[clap(subcommand)] - cmd: Option, - } - - #[derive(Debug, PartialEq, Eq, Subcommand)] - enum SubCommands { - ExSub { - #[clap(short, long, parse(from_occurrences))] - verbose: u8, - }, - } - - assert_eq!( - Opt { - req_str: Some(("arg").into()), - cmd: None, - }, - Opt::try_parse_from(&["test", "arg"]).unwrap() - ); - - assert_eq!( - Opt { - req_str: None, - cmd: Some(SubCommands::ExSub { verbose: 1 }), - }, - Opt::try_parse_from(&["test", "ex-sub", "-v"]).unwrap() - ); - - assert!(Opt::try_parse_from(&["test"]).is_err()); -} diff --git a/clap_derive/tests/privacy.rs b/clap_derive/tests/privacy.rs index b4609b83..12b53b1f 100644 --- a/clap_derive/tests/privacy.rs +++ b/clap_derive/tests/privacy.rs @@ -30,7 +30,7 @@ mod subcommands { /// foo Foo { /// foo - bars: Vec, + bars: String, }, } } diff --git a/clap_derive/tests/raw_idents.rs b/clap_derive/tests/raw_idents.rs index 1091379c..12c5d165 100644 --- a/clap_derive/tests/raw_idents.rs +++ b/clap_derive/tests/raw_idents.rs @@ -4,14 +4,21 @@ use clap::Parser; fn raw_idents() { #[derive(Parser, Debug, PartialEq)] struct Opt { - #[clap(short, long, multiple_occurrences(true))] - r#type: Vec, + #[clap(short, long)] + r#type: String, } assert_eq!( Opt { - r#type: vec!["long".into(), "short".into()] + r#type: "long".into() }, - Opt::try_parse_from(&["test", "--type", "long", "-t", "short"]).unwrap() + Opt::try_parse_from(&["test", "--type", "long"]).unwrap() + ); + + assert_eq!( + Opt { + r#type: "short".into() + }, + Opt::try_parse_from(&["test", "-t", "short"]).unwrap() ); } diff --git a/clap_derive/tests/special_types.rs b/clap_derive/tests/special_types.rs deleted file mode 100644 index e1f9d26e..00000000 --- a/clap_derive/tests/special_types.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Checks that types like `::std::option::Option` are not special - -use clap::Parser; - -#[rustversion::all(since(1.37), stable)] -#[test] -fn special_types_bool() { - mod inner { - #[allow(non_camel_case_types)] - #[derive(PartialEq, Debug)] - pub struct bool(pub String); - - impl std::str::FromStr for self::bool { - type Err = String; - - fn from_str(s: &str) -> Result { - Ok(self::bool(s.into())) - } - } - } - - #[derive(Parser, PartialEq, Debug)] - struct Opt { - arg: inner::bool, - } - - assert_eq!( - Opt { - arg: inner::bool("success".into()) - }, - Opt::try_parse_from(&["test", "success"]).unwrap() - ); -} - -#[test] -fn special_types_option() { - fn parser(s: &str) -> Option { - Some(s.to_string()) - } - - #[derive(Parser, PartialEq, Debug)] - struct Opt { - #[clap(parse(from_str = parser))] - arg: ::std::option::Option, - } - - assert_eq!( - Opt { - arg: Some("success".into()) - }, - Opt::try_parse_from(&["test", "success"]).unwrap() - ); -} - -#[test] -fn special_types_vec() { - fn parser(s: &str) -> Vec { - vec![s.to_string()] - } - - #[derive(Parser, PartialEq, Debug)] - struct Opt { - #[clap(parse(from_str = parser))] - arg: ::std::vec::Vec, - } - - assert_eq!( - Opt { - arg: vec!["success".into()] - }, - Opt::try_parse_from(&["test", "success"]).unwrap() - ); -}