• 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 #![allow(clippy::option_option)]
16 
17 use crate::utils;
18 
19 use clap::{Parser, Subcommand};
20 
21 #[test]
required_option()22 fn required_option() {
23     #[derive(Parser, PartialEq, Debug)]
24     #[command(args_override_self = true)]
25     struct Opt {
26         #[arg(short, long)]
27         arg: i32,
28     }
29     assert_eq!(
30         Opt { arg: 42 },
31         Opt::try_parse_from(["test", "-a42"]).unwrap()
32     );
33     assert_eq!(
34         Opt { arg: 42 },
35         Opt::try_parse_from(["test", "-a", "42"]).unwrap()
36     );
37     assert_eq!(
38         Opt { arg: 42 },
39         Opt::try_parse_from(["test", "--arg", "42"]).unwrap()
40     );
41     assert_eq!(
42         Opt { arg: 42 },
43         Opt::try_parse_from(["test", "--arg", "24", "--arg", "42"]).unwrap()
44     );
45     assert!(Opt::try_parse_from(["test"]).is_err());
46 }
47 
48 #[test]
option_with_default()49 fn option_with_default() {
50     #[derive(Parser, PartialEq, Debug)]
51     #[command(args_override_self = true)]
52     struct Opt {
53         #[arg(short, default_value = "42")]
54         arg: i32,
55     }
56     assert_eq!(
57         Opt { arg: 24 },
58         Opt::try_parse_from(["test", "-a24"]).unwrap()
59     );
60     assert_eq!(
61         Opt { arg: 42 },
62         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
63     );
64     assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(["test"]).unwrap());
65 }
66 
67 #[test]
option_with_raw_default()68 fn option_with_raw_default() {
69     #[derive(Parser, PartialEq, Debug)]
70     #[command(args_override_self = true)]
71     struct Opt {
72         #[arg(short, default_value = "42")]
73         arg: i32,
74     }
75     assert_eq!(
76         Opt { arg: 24 },
77         Opt::try_parse_from(["test", "-a24"]).unwrap()
78     );
79     assert_eq!(
80         Opt { arg: 42 },
81         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
82     );
83     assert_eq!(Opt { arg: 42 }, Opt::try_parse_from(["test"]).unwrap());
84 }
85 
86 #[test]
option_from_str()87 fn option_from_str() {
88     #[derive(Clone, Debug, PartialEq)]
89     struct A;
90 
91     impl std::str::FromStr for A {
92         type Err = std::convert::Infallible;
93 
94         fn from_str(_: &str) -> Result<A, Self::Err> {
95             Ok(A)
96         }
97     }
98 
99     #[derive(Debug, Parser, PartialEq)]
100     #[command(args_override_self = true)]
101     struct Opt {
102         a: Option<A>,
103     }
104 
105     assert_eq!(Opt { a: None }, Opt::try_parse_from(["test"]).unwrap());
106     assert_eq!(
107         Opt { a: Some(A) },
108         Opt::try_parse_from(["test", "foo"]).unwrap()
109     );
110 }
111 
112 #[test]
vec_from_str()113 fn vec_from_str() {
114     #[derive(Clone, Debug, PartialEq)]
115     struct A;
116 
117     impl std::str::FromStr for A {
118         type Err = std::convert::Infallible;
119 
120         fn from_str(_: &str) -> Result<A, Self::Err> {
121             Ok(A)
122         }
123     }
124 
125     #[derive(Debug, Parser, PartialEq)]
126     #[command(args_override_self = true)]
127     struct Opt {
128         a: Vec<A>,
129     }
130 
131     assert_eq!(
132         Opt { a: Vec::new() },
133         Opt::try_parse_from(["test"]).unwrap()
134     );
135     assert_eq!(
136         Opt { a: vec![A] },
137         Opt::try_parse_from(["test", "foo"]).unwrap()
138     );
139 }
140 
141 #[test]
option_vec_from_str()142 fn option_vec_from_str() {
143     #[derive(Clone, Debug, PartialEq)]
144     struct A;
145 
146     impl std::str::FromStr for A {
147         type Err = std::convert::Infallible;
148 
149         fn from_str(_: &str) -> Result<A, Self::Err> {
150             Ok(A)
151         }
152     }
153 
154     #[derive(Debug, Parser, PartialEq)]
155     #[command(args_override_self = true)]
156     struct Opt {
157         #[arg(short)]
158         a: Option<Vec<A>>,
159     }
160 
161     assert_eq!(Opt { a: None }, Opt::try_parse_from(["test"]).unwrap());
162     assert_eq!(
163         Opt { a: Some(vec![A]) },
164         Opt::try_parse_from(["test", "-a", "foo"]).unwrap()
165     );
166 }
167 
168 #[test]
option_type_is_optional()169 fn option_type_is_optional() {
170     #[derive(Parser, PartialEq, Debug)]
171     #[command(args_override_self = true)]
172     struct Opt {
173         #[arg(short)]
174         arg: Option<i32>,
175     }
176     assert_eq!(
177         Opt { arg: Some(42) },
178         Opt::try_parse_from(["test", "-a42"]).unwrap()
179     );
180     assert_eq!(
181         Opt { arg: Some(42) },
182         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
183     );
184     assert_eq!(Opt { arg: None }, Opt::try_parse_from(["test"]).unwrap());
185 }
186 
187 #[test]
required_with_option_type()188 fn required_with_option_type() {
189     #[derive(Debug, PartialEq, Eq, Parser)]
190     #[command(subcommand_negates_reqs = true)]
191     #[command(args_override_self = true)]
192     struct Opt {
193         #[arg(required = true)]
194         req_str: Option<String>,
195 
196         #[command(subcommand)]
197         cmd: Option<SubCommands>,
198     }
199 
200     #[derive(Debug, PartialEq, Eq, Subcommand)]
201     enum SubCommands {
202         ExSub {
203             #[arg(short, long, action = clap::ArgAction::Count)]
204             verbose: u8,
205         },
206     }
207 
208     assert_eq!(
209         Opt {
210             req_str: Some(("arg").into()),
211             cmd: None,
212         },
213         Opt::try_parse_from(["test", "arg"]).unwrap()
214     );
215 
216     assert_eq!(
217         Opt {
218             req_str: None,
219             cmd: Some(SubCommands::ExSub { verbose: 1 }),
220         },
221         Opt::try_parse_from(["test", "ex-sub", "-v"]).unwrap()
222     );
223 
224     assert!(Opt::try_parse_from(["test"]).is_err());
225 }
226 
227 #[test]
ignore_qualified_option_type()228 fn ignore_qualified_option_type() {
229     fn parser(s: &str) -> Result<Option<String>, std::convert::Infallible> {
230         Ok(Some(s.to_string()))
231     }
232 
233     #[derive(Parser, PartialEq, Debug)]
234     #[command(args_override_self = true)]
235     struct Opt {
236         #[arg(value_parser = parser)]
237         arg: ::std::option::Option<String>,
238     }
239 
240     assert_eq!(
241         Opt {
242             arg: Some("success".into())
243         },
244         Opt::try_parse_from(["test", "success"]).unwrap()
245     );
246 }
247 
248 #[test]
option_option_type_is_optional_value()249 fn option_option_type_is_optional_value() {
250     #[derive(Parser, PartialEq, Debug)]
251     #[command(args_override_self = true)]
252     struct Opt {
253         #[arg(short)]
254         #[allow(clippy::option_option)]
255         arg: Option<Option<i32>>,
256     }
257     assert_eq!(
258         Opt {
259             arg: Some(Some(42))
260         },
261         Opt::try_parse_from(["test", "-a42"]).unwrap()
262     );
263     assert_eq!(
264         Opt { arg: Some(None) },
265         Opt::try_parse_from(["test", "-a"]).unwrap()
266     );
267     assert_eq!(
268         Opt {
269             arg: Some(Some(42))
270         },
271         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
272     );
273     assert_eq!(Opt { arg: None }, Opt::try_parse_from(["test"]).unwrap());
274 }
275 
276 #[test]
option_option_type_help()277 fn option_option_type_help() {
278     #[derive(Parser, Debug)]
279     #[command(args_override_self = true)]
280     struct Opt {
281         #[arg(long, value_name = "val")]
282         arg: Option<Option<i32>>,
283     }
284     let help = utils::get_help::<Opt>();
285     assert!(help.contains("--arg [<val>]"));
286     assert!(!help.contains("--arg [<val>...]"));
287 }
288 
289 #[test]
two_option_option_types()290 fn two_option_option_types() {
291     #[derive(Parser, PartialEq, Debug)]
292     #[command(args_override_self = true)]
293     struct Opt {
294         #[arg(short)]
295         arg: Option<Option<i32>>,
296 
297         #[arg(long)]
298         field: Option<Option<String>>,
299     }
300     assert_eq!(
301         Opt {
302             arg: Some(Some(42)),
303             field: Some(Some("f".into()))
304         },
305         Opt::try_parse_from(["test", "-a42", "--field", "f"]).unwrap()
306     );
307     assert_eq!(
308         Opt {
309             arg: Some(Some(42)),
310             field: Some(None)
311         },
312         Opt::try_parse_from(["test", "-a42", "--field"]).unwrap()
313     );
314     assert_eq!(
315         Opt {
316             arg: Some(None),
317             field: Some(None)
318         },
319         Opt::try_parse_from(["test", "-a", "--field"]).unwrap()
320     );
321     assert_eq!(
322         Opt {
323             arg: Some(None),
324             field: Some(Some("f".into()))
325         },
326         Opt::try_parse_from(["test", "-a", "--field", "f"]).unwrap()
327     );
328     assert_eq!(
329         Opt {
330             arg: None,
331             field: Some(None)
332         },
333         Opt::try_parse_from(["test", "--field"]).unwrap()
334     );
335     assert_eq!(
336         Opt {
337             arg: None,
338             field: None
339         },
340         Opt::try_parse_from(["test"]).unwrap()
341     );
342 }
343 
344 #[test]
vec_type_is_multiple_occurrences()345 fn vec_type_is_multiple_occurrences() {
346     #[derive(Parser, PartialEq, Debug)]
347     #[command(args_override_self = true)]
348     struct Opt {
349         #[arg(short, long)]
350         arg: Vec<i32>,
351     }
352     assert_eq!(
353         Opt { arg: vec![24] },
354         Opt::try_parse_from(["test", "-a24"]).unwrap()
355     );
356     assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(["test"]).unwrap());
357     assert_eq!(
358         Opt { arg: vec![24, 42] },
359         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
360     );
361 }
362 
363 #[test]
vec_type_with_required()364 fn vec_type_with_required() {
365     #[derive(Parser, PartialEq, Debug)]
366     #[command(args_override_self = true)]
367     struct Opt {
368         #[arg(short, long, required = true)]
369         arg: Vec<i32>,
370     }
371     assert_eq!(
372         Opt { arg: vec![24] },
373         Opt::try_parse_from(["test", "-a24"]).unwrap()
374     );
375     assert!(Opt::try_parse_from(["test"]).is_err());
376     assert_eq!(
377         Opt { arg: vec![24, 42] },
378         Opt::try_parse_from(["test", "-a", "24", "-a", "42"]).unwrap()
379     );
380 }
381 
382 #[test]
vec_type_with_multiple_values_only()383 fn vec_type_with_multiple_values_only() {
384     #[derive(Parser, PartialEq, Debug)]
385     #[command(args_override_self = true)]
386     struct Opt {
387         #[arg(short, long, num_args(1..))]
388         arg: Vec<i32>,
389     }
390     assert_eq!(
391         Opt { arg: vec![24] },
392         Opt::try_parse_from(["test", "-a24"]).unwrap()
393     );
394     assert_eq!(Opt { arg: vec![] }, Opt::try_parse_from(["test"]).unwrap());
395     assert_eq!(
396         Opt { arg: vec![24, 42] },
397         Opt::try_parse_from(["test", "-a", "24", "42"]).unwrap()
398     );
399 }
400 
401 #[test]
ignore_qualified_vec_type()402 fn ignore_qualified_vec_type() {
403     fn parser(s: &str) -> Result<Vec<String>, std::convert::Infallible> {
404         Ok(vec![s.to_string()])
405     }
406 
407     #[derive(Parser, PartialEq, Debug)]
408     #[command(args_override_self = true)]
409     struct Opt {
410         #[arg(value_parser = parser)]
411         arg: ::std::vec::Vec<String>,
412     }
413 
414     assert_eq!(
415         Opt {
416             arg: vec!["success".into()]
417         },
418         Opt::try_parse_from(["test", "success"]).unwrap()
419     );
420 }
421 
422 #[test]
option_vec_type()423 fn option_vec_type() {
424     #[derive(Parser, PartialEq, Debug)]
425     #[command(args_override_self = true)]
426     struct Opt {
427         #[arg(short)]
428         arg: Option<Vec<i32>>,
429     }
430     assert_eq!(
431         Opt { arg: Some(vec![1]) },
432         Opt::try_parse_from(["test", "-a", "1"]).unwrap()
433     );
434 
435     assert_eq!(
436         Opt {
437             arg: Some(vec![1, 2])
438         },
439         Opt::try_parse_from(["test", "-a", "1", "-a", "2"]).unwrap()
440     );
441 
442     assert_eq!(Opt { arg: None }, Opt::try_parse_from(["test"]).unwrap());
443 }
444 
445 #[test]
option_vec_type_structopt_behavior()446 fn option_vec_type_structopt_behavior() {
447     #[derive(Parser, PartialEq, Debug)]
448     #[command(args_override_self = true)]
449     struct Opt {
450         #[arg(short, long, num_args(0..))]
451         arg: Option<Vec<i32>>,
452     }
453     assert_eq!(
454         Opt { arg: Some(vec![1]) },
455         Opt::try_parse_from(["test", "-a", "1"]).unwrap()
456     );
457 
458     assert_eq!(
459         Opt {
460             arg: Some(vec![1, 2])
461         },
462         Opt::try_parse_from(["test", "-a", "1", "2"]).unwrap()
463     );
464 
465     assert_eq!(
466         Opt { arg: Some(vec![]) },
467         Opt::try_parse_from(["test", "-a"]).unwrap()
468     );
469 
470     assert_eq!(Opt { arg: None }, Opt::try_parse_from(["test"]).unwrap());
471 }
472 
473 #[test]
two_option_vec_types()474 fn two_option_vec_types() {
475     #[derive(Parser, PartialEq, Debug)]
476     #[command(args_override_self = true)]
477     struct Opt {
478         #[arg(short)]
479         arg: Option<Vec<i32>>,
480 
481         #[arg(short)]
482         b: Option<Vec<i32>>,
483     }
484 
485     assert_eq!(
486         Opt {
487             arg: Some(vec![1]),
488             b: None,
489         },
490         Opt::try_parse_from(["test", "-a", "1"]).unwrap()
491     );
492 
493     assert_eq!(
494         Opt {
495             arg: Some(vec![1]),
496             b: Some(vec![1])
497         },
498         Opt::try_parse_from(["test", "-a", "1", "-b", "1"]).unwrap()
499     );
500 
501     assert_eq!(
502         Opt {
503             arg: Some(vec![1, 2]),
504             b: Some(vec![1, 2])
505         },
506         Opt::try_parse_from(["test", "-a", "1", "-a", "2", "-b", "1", "-b", "2"]).unwrap()
507     );
508 
509     assert_eq!(
510         Opt { arg: None, b: None },
511         Opt::try_parse_from(["test"]).unwrap()
512     );
513 }
514 
515 #[test]
explicit_value_parser()516 fn explicit_value_parser() {
517     #[derive(Parser, PartialEq, Debug)]
518     #[command(args_override_self = true)]
519     struct Opt {
520         #[arg(long, value_parser = clap::value_parser!(i32))]
521         arg: i32,
522     }
523     assert_eq!(
524         Opt { arg: 42 },
525         Opt::try_parse_from(["test", "--arg", "42"]).unwrap()
526     );
527 }
528 
529 #[test]
implicit_value_parser()530 fn implicit_value_parser() {
531     #[derive(Parser, PartialEq, Debug)]
532     #[command(args_override_self = true)]
533     struct Opt {
534         #[arg(long)]
535         arg: i32,
536     }
537     assert_eq!(
538         Opt { arg: 42 },
539         Opt::try_parse_from(["test", "--arg", "42"]).unwrap()
540     );
541 }
542