• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 Guillaume Pinot (@TeXitoi) <texitoi@texitoi.eu>,
2 // Kevin Knapp (@kbknapp) <kbknapp@gmail.com>, and
3 // Ana Hobden (@hoverbear) <operator@hoverbear.org>
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::builder::BoolishValueParser;
16 use clap::builder::TypedValueParser as _;
17 use clap::ArgAction;
18 use clap::CommandFactory;
19 use clap::Parser;
20 
21 #[test]
bool_type_is_flag()22 fn bool_type_is_flag() {
23     #[derive(Parser, PartialEq, Eq, Debug)]
24     #[command(args_override_self = true)]
25     struct Opt {
26         #[arg(short, long)]
27         alice: bool,
28     }
29 
30     assert_eq!(Opt { alice: false }, Opt::try_parse_from(["test"]).unwrap());
31     assert_eq!(
32         Opt { alice: true },
33         Opt::try_parse_from(["test", "-a"]).unwrap()
34     );
35     assert_eq!(
36         Opt { alice: true },
37         Opt::try_parse_from(["test", "-a", "-a"]).unwrap()
38     );
39     assert_eq!(
40         Opt { alice: true },
41         Opt::try_parse_from(["test", "--alice"]).unwrap()
42     );
43     assert!(Opt::try_parse_from(["test", "-i"]).is_err());
44     assert!(Opt::try_parse_from(["test", "-a", "foo"]).is_err());
45 }
46 
47 #[test]
non_bool_type_flag()48 fn non_bool_type_flag() {
49     fn parse_from_flag(b: bool) -> usize {
50         if b {
51             10
52         } else {
53             5
54         }
55     }
56 
57     #[derive(Parser, Debug)]
58     struct Opt {
59         #[arg(short, long, action = ArgAction::SetTrue, value_parser = BoolishValueParser::new().map(parse_from_flag))]
60         alice: usize,
61         #[arg(short, long, action = ArgAction::SetTrue, value_parser = BoolishValueParser::new().map(parse_from_flag))]
62         bob: usize,
63     }
64 
65     let opt = Opt::try_parse_from(["test"]).unwrap();
66     assert_eq!(opt.alice, 5);
67     assert_eq!(opt.bob, 5);
68 
69     let opt = Opt::try_parse_from(["test", "-a"]).unwrap();
70     assert_eq!(opt.alice, 10);
71     assert_eq!(opt.bob, 5);
72 
73     let opt = Opt::try_parse_from(["test", "-b"]).unwrap();
74     assert_eq!(opt.alice, 5);
75     assert_eq!(opt.bob, 10);
76 
77     let opt = Opt::try_parse_from(["test", "-b", "-a"]).unwrap();
78     assert_eq!(opt.alice, 10);
79     assert_eq!(opt.bob, 10);
80 }
81 
82 #[test]
83 #[ignore] // Not a good path for supporting this atm
inferred_help()84 fn inferred_help() {
85     #[derive(Parser, PartialEq, Eq, Debug)]
86     struct Opt {
87         /// Foo
88         #[arg(short, long)]
89         help: bool,
90     }
91 
92     let mut cmd = Opt::command();
93     cmd.build();
94     let arg = cmd.get_arguments().find(|a| a.get_id() == "help").unwrap();
95     assert_eq!(
96         arg.get_help().map(|s| s.to_string()),
97         Some("Foo".to_owned()),
98         "Incorrect help"
99     );
100     assert!(matches!(arg.get_action(), clap::ArgAction::Help));
101 }
102 
103 #[test]
104 #[ignore] // Not a good path for supporting this atm
inferred_version()105 fn inferred_version() {
106     #[derive(Parser, PartialEq, Eq, Debug)]
107     struct Opt {
108         /// Foo
109         #[arg(short, long)]
110         version: bool,
111     }
112 
113     let mut cmd = Opt::command();
114     cmd.build();
115     let arg = cmd
116         .get_arguments()
117         .find(|a| a.get_id() == "version")
118         .unwrap();
119     assert_eq!(
120         arg.get_help().map(|s| s.to_string()),
121         Some("Foo".to_owned()),
122         "Incorrect help"
123     );
124     assert!(matches!(arg.get_action(), clap::ArgAction::Version));
125 }
126 
127 #[test]
count()128 fn count() {
129     #[derive(Parser, PartialEq, Eq, Debug)]
130     struct Opt {
131         #[arg(short, long, action = clap::ArgAction::Count)]
132         alice: u8,
133         #[arg(short, long, action = clap::ArgAction::Count)]
134         bob: u8,
135     }
136 
137     assert_eq!(
138         Opt { alice: 0, bob: 0 },
139         Opt::try_parse_from(["test"]).unwrap()
140     );
141     assert_eq!(
142         Opt { alice: 1, bob: 0 },
143         Opt::try_parse_from(["test", "-a"]).unwrap()
144     );
145     assert_eq!(
146         Opt { alice: 2, bob: 0 },
147         Opt::try_parse_from(["test", "-a", "-a"]).unwrap()
148     );
149     assert_eq!(
150         Opt { alice: 2, bob: 2 },
151         Opt::try_parse_from(["test", "-a", "--alice", "-bb"]).unwrap()
152     );
153     assert_eq!(
154         Opt { alice: 3, bob: 1 },
155         Opt::try_parse_from(["test", "-aaa", "--bob"]).unwrap()
156     );
157     assert!(Opt::try_parse_from(["test", "-i"]).is_err());
158     assert!(Opt::try_parse_from(["test", "-a", "foo"]).is_err());
159 }
160 
161 #[test]
mixed_type_flags()162 fn mixed_type_flags() {
163     #[derive(Parser, PartialEq, Eq, Debug)]
164     struct Opt {
165         #[arg(short, long)]
166         alice: bool,
167         #[arg(short, long, action = clap::ArgAction::Count)]
168         bob: u8,
169     }
170 
171     assert_eq!(
172         Opt {
173             alice: false,
174             bob: 0
175         },
176         Opt::try_parse_from(["test"]).unwrap()
177     );
178     assert_eq!(
179         Opt {
180             alice: true,
181             bob: 0
182         },
183         Opt::try_parse_from(["test", "-a"]).unwrap()
184     );
185     assert_eq!(
186         Opt {
187             alice: true,
188             bob: 0
189         },
190         Opt::try_parse_from(["test", "-a"]).unwrap()
191     );
192     assert_eq!(
193         Opt {
194             alice: false,
195             bob: 1
196         },
197         Opt::try_parse_from(["test", "-b"]).unwrap()
198     );
199     assert_eq!(
200         Opt {
201             alice: true,
202             bob: 1
203         },
204         Opt::try_parse_from(["test", "--alice", "--bob"]).unwrap()
205     );
206     assert_eq!(
207         Opt {
208             alice: true,
209             bob: 4
210         },
211         Opt::try_parse_from(["test", "-bb", "-a", "-bb"]).unwrap()
212     );
213 }
214 
215 #[test]
ignore_qualified_bool_type()216 fn ignore_qualified_bool_type() {
217     mod inner {
218         #[allow(non_camel_case_types)]
219         #[derive(PartialEq, Eq, Debug, Clone)]
220         pub struct bool(pub String);
221 
222         impl std::str::FromStr for self::bool {
223             type Err = String;
224 
225             fn from_str(s: &str) -> Result<Self, Self::Err> {
226                 Ok(self::bool(s.into()))
227             }
228         }
229     }
230 
231     #[derive(Parser, PartialEq, Eq, Debug)]
232     struct Opt {
233         arg: inner::bool,
234     }
235 
236     assert_eq!(
237         Opt {
238             arg: inner::bool("success".into())
239         },
240         Opt::try_parse_from(["test", "success"]).unwrap()
241     );
242 }
243 
244 #[test]
override_implicit_action()245 fn override_implicit_action() {
246     #[derive(Parser, PartialEq, Eq, Debug)]
247     struct Opt {
248         #[arg(long, action = clap::ArgAction::Set)]
249         arg: bool,
250     }
251 
252     assert_eq!(
253         Opt { arg: false },
254         Opt::try_parse_from(["test", "--arg", "false"]).unwrap()
255     );
256 
257     assert_eq!(
258         Opt { arg: true },
259         Opt::try_parse_from(["test", "--arg", "true"]).unwrap()
260     );
261 }
262 
263 #[test]
override_implicit_from_flag_positional()264 fn override_implicit_from_flag_positional() {
265     #[derive(Parser, PartialEq, Eq, Debug)]
266     struct Opt {
267         #[arg(action = clap::ArgAction::Set)]
268         arg: bool,
269     }
270 
271     assert_eq!(
272         Opt { arg: false },
273         Opt::try_parse_from(["test", "false"]).unwrap()
274     );
275 
276     assert_eq!(
277         Opt { arg: true },
278         Opt::try_parse_from(["test", "true"]).unwrap()
279     );
280 }
281 
282 #[test]
unit_for_negation()283 fn unit_for_negation() {
284     #[derive(Parser, PartialEq, Eq, Debug)]
285     struct Opt {
286         #[arg(long)]
287         arg: bool,
288         #[arg(long, action = ArgAction::SetTrue, overrides_with = "arg")]
289         no_arg: (),
290     }
291 
292     assert_eq!(
293         Opt {
294             arg: false,
295             no_arg: ()
296         },
297         Opt::try_parse_from(["test"]).unwrap()
298     );
299 
300     assert_eq!(
301         Opt {
302             arg: true,
303             no_arg: ()
304         },
305         Opt::try_parse_from(["test", "--arg"]).unwrap()
306     );
307 
308     assert_eq!(
309         Opt {
310             arg: false,
311             no_arg: ()
312         },
313         Opt::try_parse_from(["test", "--no-arg"]).unwrap()
314     );
315 
316     assert_eq!(
317         Opt {
318             arg: true,
319             no_arg: ()
320         },
321         Opt::try_parse_from(["test", "--no-arg", "--arg"]).unwrap()
322     );
323 
324     assert_eq!(
325         Opt {
326             arg: false,
327             no_arg: ()
328         },
329         Opt::try_parse_from(["test", "--arg", "--no-arg"]).unwrap()
330     );
331 }
332