Skip to content

Commit cc76d28

Browse files
committed
test(derive): Allow specializing tests for unstable-v4
1 parent 3686244 commit cc76d28

33 files changed

+5509
-1
lines changed

tests/derive/main.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#![cfg(feature = "derive")]
22

3+
mod legacy;
4+
mod next;
5+
36
mod app_name;
47
mod arguments;
58
mod author_version_about;
@@ -15,7 +18,6 @@ mod flatten;
1518
mod generic;
1619
mod help;
1720
mod issues;
18-
mod legacy;
1921
mod macros;
2022
mod naming;
2123
mod nested_subcommands;

tests/derive/next/app_name.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use clap::CommandFactory;
2+
use clap::Parser;
3+
#[test]
4+
fn app_name_in_short_help_from_struct() {
5+
#[derive(Parser)]
6+
#[clap(name = "my-cmd")]
7+
struct MyApp {}
8+
9+
let mut help = Vec::new();
10+
MyApp::command().write_help(&mut help).unwrap();
11+
let help = String::from_utf8(help).unwrap();
12+
13+
assert!(help.contains("my-cmd"));
14+
}
15+
16+
#[test]
17+
fn app_name_in_long_help_from_struct() {
18+
#[derive(Parser)]
19+
#[clap(name = "my-cmd")]
20+
struct MyApp {}
21+
22+
let mut help = Vec::new();
23+
MyApp::command().write_long_help(&mut help).unwrap();
24+
let help = String::from_utf8(help).unwrap();
25+
26+
assert!(help.contains("my-cmd"));
27+
}
28+
29+
#[test]
30+
fn app_name_in_short_help_from_enum() {
31+
#[derive(Parser)]
32+
#[clap(name = "my-cmd")]
33+
enum MyApp {}
34+
35+
let mut help = Vec::new();
36+
MyApp::command().write_help(&mut help).unwrap();
37+
let help = String::from_utf8(help).unwrap();
38+
39+
assert!(help.contains("my-cmd"));
40+
}
41+
42+
#[test]
43+
fn app_name_in_long_help_from_enum() {
44+
#[derive(Parser)]
45+
#[clap(name = "my-cmd")]
46+
enum MyApp {}
47+
48+
let mut help = Vec::new();
49+
MyApp::command().write_long_help(&mut help).unwrap();
50+
let help = String::from_utf8(help).unwrap();
51+
52+
assert!(help.contains("my-cmd"));
53+
}
54+
55+
#[test]
56+
fn app_name_in_short_version_from_struct() {
57+
#[derive(Parser)]
58+
#[clap(name = "my-cmd")]
59+
struct MyApp {}
60+
61+
let version = MyApp::command().render_version();
62+
63+
assert!(version.contains("my-cmd"));
64+
}
65+
66+
#[test]
67+
fn app_name_in_long_version_from_struct() {
68+
#[derive(Parser)]
69+
#[clap(name = "my-cmd")]
70+
struct MyApp {}
71+
72+
let version = MyApp::command().render_long_version();
73+
74+
assert!(version.contains("my-cmd"));
75+
}
76+
77+
#[test]
78+
fn app_name_in_short_version_from_enum() {
79+
#[derive(Parser)]
80+
#[clap(name = "my-cmd")]
81+
enum MyApp {}
82+
83+
let version = MyApp::command().render_version();
84+
85+
assert!(version.contains("my-cmd"));
86+
}
87+
88+
#[test]
89+
fn app_name_in_long_version_from_enum() {
90+
#[derive(Parser)]
91+
#[clap(name = "my-cmd")]
92+
enum MyApp {}
93+
94+
let version = MyApp::command().render_long_version();
95+
96+
assert!(version.contains("my-cmd"));
97+
}

tests/derive/next/arguments.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright 2018 Guillaume Pinot (@TeXitoi) <[email protected]>,
2+
// Kevin Knapp (@kbknapp) <[email protected]>, and
3+
// Ana Hobden (@hoverbear) <[email protected]>
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
12+
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
13+
// MIT/Apache 2.0 license.
14+
15+
use clap::CommandFactory;
16+
use clap::Parser;
17+
18+
#[test]
19+
fn required_argument() {
20+
#[derive(Parser, PartialEq, Debug)]
21+
struct Opt {
22+
#[clap(value_parser)]
23+
arg: i32,
24+
}
25+
assert_eq!(
26+
Opt { arg: 42 },
27+
Opt::try_parse_from(&["test", "42"]).unwrap()
28+
);
29+
assert!(Opt::try_parse_from(&["test"]).is_err());
30+
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
31+
}
32+
33+
#[test]
34+
fn argument_with_default() {
35+
#[derive(Parser, PartialEq, Debug)]
36+
struct Opt {
37+
#[clap(value_parser, default_value = "42")]
38+
arg: i32,
39+
}
40+
assert_eq!(
41+
Opt { arg: 24 },
42+
Opt::try_parse_from(&["test", "24"]).unwrap()
43+
);
44+
assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(&["test"]).unwrap());
45+
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
46+
}
47+
48+
#[test]
49+
fn auto_value_name() {
50+
#[derive(Parser, PartialEq, Debug)]
51+
struct Opt {
52+
#[clap(value_parser)]
53+
my_special_arg: i32,
54+
}
55+
56+
let mut help = Vec::new();
57+
Opt::command().write_help(&mut help).unwrap();
58+
let help = String::from_utf8(help).unwrap();
59+
60+
assert!(help.contains("MY_SPECIAL_ARG"));
61+
// Ensure the implicit `num_vals` is just 1
62+
assert_eq!(
63+
Opt { my_special_arg: 10 },
64+
Opt::try_parse_from(&["test", "10"]).unwrap()
65+
);
66+
}
67+
68+
#[test]
69+
fn explicit_value_name() {
70+
#[derive(Parser, PartialEq, Debug)]
71+
struct Opt {
72+
#[clap(value_parser, value_name = "BROWNIE_POINTS")]
73+
my_special_arg: i32,
74+
}
75+
76+
let mut help = Vec::new();
77+
Opt::command().write_help(&mut help).unwrap();
78+
let help = String::from_utf8(help).unwrap();
79+
80+
assert!(help.contains("BROWNIE_POINTS"));
81+
assert!(!help.contains("MY_SPECIAL_ARG"));
82+
// Ensure the implicit `num_vals` is just 1
83+
assert_eq!(
84+
Opt { my_special_arg: 10 },
85+
Opt::try_parse_from(&["test", "10"]).unwrap()
86+
);
87+
}
88+
89+
#[test]
90+
fn option_type_is_optional() {
91+
#[derive(Parser, PartialEq, Debug)]
92+
struct Opt {
93+
#[clap(value_parser)]
94+
arg: Option<i32>,
95+
}
96+
assert_eq!(
97+
Opt { arg: Some(42) },
98+
Opt::try_parse_from(&["test", "42"]).unwrap()
99+
);
100+
assert_eq!(Opt { arg: None }, Opt::try_parse_from(&["test"]).unwrap());
101+
assert!(Opt::try_parse_from(&["test", "42", "24"]).is_err());
102+
}
103+
104+
#[test]
105+
fn vec_type_is_multiple_values() {
106+
#[derive(Parser, PartialEq, Debug)]
107+
struct Opt {
108+
#[clap(value_parser)]
109+
arg: Vec<i32>,
110+
}
111+
assert_eq!(
112+
Opt { arg: vec![24] },
113+
Opt::try_parse_from(&["test", "24"]).unwrap()
114+
);
115+
assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(&["test"]).unwrap());
116+
assert_eq!(
117+
Opt { arg: vec![24, 42] },
118+
Opt::try_parse_from(&["test", "24", "42"]).unwrap()
119+
);
120+
assert_eq!(
121+
clap::ErrorKind::ValueValidation,
122+
Opt::try_parse_from(&["test", "NOPE"]).err().unwrap().kind()
123+
);
124+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2018 Guillaume Pinot (@TeXitoi) <[email protected]>,
2+
// Kevin Knapp (@kbknapp) <[email protected]>, and
3+
// Ana Hobden (@hoverbear) <[email protected]>
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
12+
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
13+
// MIT/Apache 2.0 license.
14+
15+
use crate::utils;
16+
17+
use clap::Parser;
18+
19+
#[test]
20+
fn no_author_version_about() {
21+
#[derive(Parser, PartialEq, Debug)]
22+
#[clap(name = "foo")]
23+
struct Opt {}
24+
25+
let output = utils::get_long_help::<Opt>();
26+
assert!(output.starts_with("foo \n\nUSAGE:"));
27+
}
28+
29+
#[test]
30+
fn use_env() {
31+
#[derive(Parser, PartialEq, Debug)]
32+
#[clap(author, about, version)]
33+
struct Opt {}
34+
35+
let output = utils::get_long_help::<Opt>();
36+
assert!(output.starts_with("clap"));
37+
assert!(output
38+
.contains("A simple to use, efficient, and full-featured Command Line Argument Parser"));
39+
}
40+
41+
#[test]
42+
fn explicit_version_not_str_lit() {
43+
const VERSION: &str = "custom version";
44+
45+
#[derive(Parser)]
46+
#[clap(version = VERSION)]
47+
pub struct Opt {}
48+
49+
let output = utils::get_long_help::<Opt>();
50+
assert!(output.contains("custom version"));
51+
}

tests/derive/next/basic.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright 2018 Guillaume Pinot (@TeXitoi) <[email protected]>,
2+
// Kevin Knapp (@kbknapp) <[email protected]>, and
3+
// Ana Hobden (@hoverbear) <[email protected]>
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// This work was derived from Structopt (https://github.com/TeXitoi/structopt)
12+
// commit#ea76fa1b1b273e65e3b0b1046643715b49bec51f which is licensed under the
13+
// MIT/Apache 2.0 license.
14+
15+
use clap::Parser;
16+
17+
#[test]
18+
fn basic() {
19+
#[derive(Parser, PartialEq, Debug)]
20+
struct Opt {
21+
#[clap(short = 'a', long = "arg", value_parser)]
22+
arg: i32,
23+
}
24+
assert_eq!(
25+
Opt { arg: 24 },
26+
Opt::try_parse_from(&["test", "-a24"]).unwrap()
27+
);
28+
}
29+
30+
#[test]
31+
fn update_basic() {
32+
#[derive(Parser, PartialEq, Debug)]
33+
struct Opt {
34+
#[clap(short = 'a', long = "arg", value_parser)]
35+
single_value: i32,
36+
}
37+
38+
let mut opt = Opt::try_parse_from(&["test", "-a0"]).unwrap();
39+
40+
opt.update_from(&["test", "-a42"]);
41+
42+
assert_eq!(Opt { single_value: 42 }, opt);
43+
}
44+
45+
#[test]
46+
fn unit_struct() {
47+
#[derive(Parser, PartialEq, Debug)]
48+
struct Opt;
49+
50+
assert_eq!(Opt {}, Opt::try_parse_from(&["test"]).unwrap());
51+
}

tests/derive/next/boxed.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use clap::{Args, Parser, Subcommand};
2+
3+
#[derive(Parser, PartialEq, Debug)]
4+
struct Opt {
5+
#[clap(subcommand)]
6+
sub: Box<Sub>,
7+
}
8+
9+
#[derive(Subcommand, PartialEq, Debug)]
10+
enum Sub {
11+
Flame {
12+
#[clap(flatten)]
13+
arg: Box<Ext>,
14+
},
15+
}
16+
17+
#[derive(Args, PartialEq, Debug)]
18+
struct Ext {
19+
#[clap(value_parser)]
20+
arg: u32,
21+
}
22+
23+
#[test]
24+
fn boxed_flatten_subcommand() {
25+
assert_eq!(
26+
Opt {
27+
sub: Box::new(Sub::Flame {
28+
arg: Box::new(Ext { arg: 1 })
29+
})
30+
},
31+
Opt::try_parse_from(&["test", "flame", "1"]).unwrap()
32+
);
33+
}
34+
35+
#[test]
36+
fn update_boxed_flatten_subcommand() {
37+
let mut opt = Opt::try_parse_from(&["test", "flame", "1"]).unwrap();
38+
39+
opt.update_from(&["test", "flame", "42"]);
40+
41+
assert_eq!(
42+
Opt {
43+
sub: Box::new(Sub::Flame {
44+
arg: Box::new(Ext { arg: 42 })
45+
})
46+
},
47+
opt
48+
);
49+
}

0 commit comments

Comments
 (0)