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 | 234 +++++++++--------- clap_derive/tests/privacy.rs | 2 +- clap_derive/tests/raw_idents.rs | 15 +- clap_derive/tests/special_types.rs | 73 ------ 13 files changed, 260 insertions(+), 325 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 4ca646c617e..809734ed814 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 e08b624ccd0..2a1b0d11331 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 69f7ee298b9..917fa6dd18a 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 1d6b0c2478e..d502a2b699f 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 8ea9955a7fb..477fea2a4ae 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 9c57683a75c..176c6369182 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 b14a37221e2..48de630164f 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 1e4730c466f..4201cd4209c 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 9d62ff8e4f9..3ee40d2c82c 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)] @@ -88,66 +73,105 @@ fn option_with_raw_default() { } #[test] -fn options() { - #[derive(Parser, PartialEq, Debug)] +fn option_from_str() { + #[derive(Debug, PartialEq)] + struct A; + + impl<'a> From<&'a str> for A { + fn from(_: &str) -> A { + A + } + } + + #[derive(Debug, Parser, PartialEq)] struct Opt { - #[clap(short, long, multiple_occurrences(true))] - arg: Vec, + #[clap(parse(from_str))] + a: Option, } + + assert_eq!(Opt { a: None }, Opt::try_parse_from(&["test"]).unwrap()); assert_eq!( - Opt { arg: vec![24] }, - Opt::try_parse_from(&["test", "-a24"]).unwrap() + Opt { a: Some(A) }, + Opt::try_parse_from(&["test", "foo"]).unwrap() ); - assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap()); +} + +#[test] +fn option_type_is_optional() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(short)] + arg: Option, + } assert_eq!( - Opt { arg: vec![24, 42] }, - Opt::try_parse_from(&["test", "-a24", "--arg", "42"]).unwrap() + 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 default_value() { - #[derive(Parser, PartialEq, Debug)] +fn required_with_option_type() { + #[derive(Debug, PartialEq, Eq, Parser)] + #[clap(setting(clap::AppSettings::SubcommandsNegateReqs))] struct Opt { - #[clap(short, default_value = "test")] - arg: String, + #[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 { arg: "test".into() }, - Opt::try_parse_from(&["test"]).unwrap() + Opt { + req_str: Some(("arg").into()), + cmd: None, + }, + Opt::try_parse_from(&["test", "arg"]).unwrap() ); + assert_eq!( - Opt { arg: "foo".into() }, - Opt::try_parse_from(&["test", "-afoo"]).unwrap() + 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 option_from_str() { - #[derive(Debug, PartialEq)] - struct A; - - impl<'a> From<&'a str> for A { - fn from(_: &str) -> A { - A - } +fn ignore_qualified_option_type() { + fn parser(s: &str) -> Option { + Some(s.to_string()) } - #[derive(Debug, Parser, PartialEq)] + #[derive(Parser, PartialEq, Debug)] struct Opt { - #[clap(parse(from_str))] - a: Option, + #[clap(parse(from_str = parser))] + arg: ::std::option::Option, } - assert_eq!(Opt { a: None }, Opt::try_parse_from(&["test"]).unwrap()); assert_eq!( - Opt { a: Some(A) }, - Opt::try_parse_from(&["test", "foo"]).unwrap() + Opt { + arg: Some("success".into()) + }, + Opt::try_parse_from(&["test", "success"]).unwrap() ); } #[test] -fn optional_argument_for_optional_option() { +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,36 +259,53 @@ 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))] - arg: Option>, + #[clap(short, long)] + arg: Vec, } assert_eq!( - Opt { arg: Some(vec![1]) }, - Opt::try_parse_from(&["test", "-a", "1"]).unwrap() + 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: Some(vec![1, 2]) - }, - Opt::try_parse_from(&["test", "-a1", "-a2"]).unwrap() + 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: Some(vec![1, 2]) + arg: vec!["success".into()] }, - Opt::try_parse_from(&["test", "-a1", "-a2", "-a"]).unwrap() + Opt::try_parse_from(&["test", "success"]).unwrap() ); +} +#[test] +fn option_vec_type() { + #[derive(Parser, PartialEq, Debug)] + struct Opt { + #[clap(short)] + arg: Option>, + } assert_eq!( - Opt { - arg: Some(vec![1, 2]) - }, - Opt::try_parse_from(&["test", "-a1", "-a", "-a2"]).unwrap() + Opt { arg: Some(vec![1]) }, + Opt::try_parse_from(&["test", "-a", "1"]).unwrap() ); assert_eq!( @@ -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 b4609b8312d..12b53b1f2b4 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 1091379c3b6..12c5d1658f0 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 e1f9d26eb79..00000000000 --- 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() - ); -}