1 use clap::{arg, error::ErrorKind, Arg, ArgAction, Command};
2
3 #[test]
only_pos_follow()4 fn only_pos_follow() {
5 let r = Command::new("onlypos")
6 .args([arg!(f: -f [flag] "some opt"), arg!([arg] "some arg")])
7 .try_get_matches_from(vec!["", "--", "-f"]);
8 assert!(r.is_ok(), "{}", r.unwrap_err());
9 let m = r.unwrap();
10 assert!(m.contains_id("arg"));
11 assert!(!m.contains_id("f"));
12 assert_eq!(
13 m.get_one::<String>("arg").map(|v| v.as_str()).unwrap(),
14 "-f"
15 );
16 }
17
18 #[test]
issue_946()19 fn issue_946() {
20 let r = Command::new("compiletest")
21 .arg(arg!(--exact "filters match exactly").action(ArgAction::SetTrue))
22 .arg(
23 clap::Arg::new("filter")
24 .index(1)
25 .action(ArgAction::Set)
26 .allow_hyphen_values(true)
27 .help("filters to apply to output"),
28 )
29 .try_get_matches_from(vec!["compiletest", "--exact"]);
30 assert!(r.is_ok(), "{:#?}", r);
31 let matches = r.unwrap();
32
33 assert!(*matches.get_one::<bool>("exact").expect("defaulted by clap"));
34 assert!(matches
35 .get_one::<String>("filter")
36 .map(|v| v.as_str())
37 .is_none());
38 }
39
40 #[test]
positional()41 fn positional() {
42 let r = Command::new("positional")
43 .args([
44 arg!(-f --flag "some flag").action(ArgAction::SetTrue),
45 Arg::new("positional").index(1),
46 ])
47 .try_get_matches_from(vec!["", "-f", "test"]);
48 assert!(r.is_ok(), "{:#?}", r);
49 let m = r.unwrap();
50 assert!(m.contains_id("positional"));
51 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
52 assert_eq!(
53 m.get_one::<String>("positional")
54 .map(|v| v.as_str())
55 .unwrap(),
56 "test"
57 );
58
59 let m = Command::new("positional")
60 .args([
61 arg!(-f --flag "some flag").action(ArgAction::SetTrue),
62 Arg::new("positional").index(1),
63 ])
64 .try_get_matches_from(vec!["", "test", "--flag"])
65 .unwrap();
66 assert!(m.contains_id("positional"));
67 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
68 assert_eq!(
69 m.get_one::<String>("positional")
70 .map(|v| v.as_str())
71 .unwrap(),
72 "test"
73 );
74 }
75
76 #[test]
lots_o_vals()77 fn lots_o_vals() {
78 let r = Command::new("opts")
79 .arg(arg!(<opt>... "some pos"))
80 .try_get_matches_from(vec![
81 "", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
82 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
83 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
84 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
85 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
86 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
87 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
88 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
89 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
90 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
91 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
92 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
93 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
94 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
95 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
96 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
97 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
98 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
99 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
100 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
101 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
102 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
103 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
104 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
105 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
106 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
107 "some", "some", "some", "some", "some", "some", "some", "some", "some", "some", "some",
108 "some",
109 ]);
110 assert!(r.is_ok(), "{}", r.unwrap_err());
111 let m = r.unwrap();
112 assert!(m.contains_id("opt"));
113 assert_eq!(m.get_many::<String>("opt").unwrap().count(), 297); // i.e. more than u8
114 }
115
116 #[test]
positional_multiple()117 fn positional_multiple() {
118 let r = Command::new("positional_multiple")
119 .args([
120 arg!(-f --flag "some flag").action(ArgAction::SetTrue),
121 Arg::new("positional")
122 .index(1)
123 .action(ArgAction::Set)
124 .num_args(1..),
125 ])
126 .try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
127 assert!(r.is_ok(), "{:#?}", r);
128 let m = r.unwrap();
129 assert!(m.contains_id("positional"));
130 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
131 assert_eq!(
132 &*m.get_many::<String>("positional")
133 .unwrap()
134 .map(|v| v.as_str())
135 .collect::<Vec<_>>(),
136 ["test1", "test2", "test3"]
137 );
138 }
139
140 #[test]
positional_multiple_3()141 fn positional_multiple_3() {
142 let r = Command::new("positional_multiple")
143 .args([
144 arg!(-f --flag "some flag").action(ArgAction::SetTrue),
145 Arg::new("positional")
146 .index(1)
147 .action(ArgAction::Set)
148 .num_args(1..),
149 ])
150 .try_get_matches_from(vec!["", "test1", "test2", "test3", "--flag"]);
151 assert!(r.is_ok(), "{:#?}", r);
152 let m = r.unwrap();
153 assert!(m.contains_id("positional"));
154 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
155 assert_eq!(
156 &*m.get_many::<String>("positional")
157 .unwrap()
158 .map(|v| v.as_str())
159 .collect::<Vec<_>>(),
160 ["test1", "test2", "test3"]
161 );
162 }
163
164 #[test]
positional_multiple_2()165 fn positional_multiple_2() {
166 let result = Command::new("positional_multiple")
167 .args([arg!(-f --flag "some flag"), Arg::new("positional").index(1)])
168 .try_get_matches_from(vec!["", "-f", "test1", "test2", "test3"]);
169 assert!(result.is_err());
170 let err = result.err().unwrap();
171 assert_eq!(err.kind(), ErrorKind::UnknownArgument);
172 }
173
174 #[test]
positional_possible_values()175 fn positional_possible_values() {
176 let r = Command::new("positional_possible_values")
177 .args([
178 arg!(-f --flag "some flag").action(ArgAction::SetTrue),
179 Arg::new("positional").index(1).value_parser(["test123"]),
180 ])
181 .try_get_matches_from(vec!["", "-f", "test123"]);
182 assert!(r.is_ok(), "{r:#?}");
183 let m = r.unwrap();
184 assert!(m.contains_id("positional"));
185 assert!(*m.get_one::<bool>("flag").expect("defaulted by clap"));
186 assert_eq!(
187 &*m.get_many::<String>("positional")
188 .unwrap()
189 .map(|v| v.as_str())
190 .collect::<Vec<_>>(),
191 ["test123"]
192 );
193 }
194
195 #[test]
create_positional()196 fn create_positional() {
197 let _ = Command::new("test")
198 .arg(Arg::new("test").index(1).help("testing testing"))
199 .try_get_matches_from(vec![""])
200 .unwrap();
201 }
202
203 #[test]
positional_hyphen_does_not_panic()204 fn positional_hyphen_does_not_panic() {
205 let _ = Command::new("test")
206 .arg(Arg::new("dummy"))
207 .try_get_matches_from(vec!["test", "-"])
208 .unwrap();
209 }
210
211 #[test]
single_positional_usage_string()212 fn single_positional_usage_string() {
213 let mut cmd = Command::new("test").arg(arg!([FILE] "some file"));
214 crate::utils::assert_eq(cmd.render_usage().to_string(), "Usage: test [FILE]");
215 }
216
217 #[test]
single_positional_multiple_usage_string()218 fn single_positional_multiple_usage_string() {
219 let mut cmd = Command::new("test").arg(arg!([FILE]... "some file"));
220 crate::utils::assert_eq(cmd.render_usage().to_string(), "Usage: test [FILE]...");
221 }
222
223 #[test]
multiple_positional_usage_string()224 fn multiple_positional_usage_string() {
225 let mut cmd = Command::new("test")
226 .arg(arg!([FILE] "some file"))
227 .arg(arg!([FILES]... "some file"));
228 crate::utils::assert_eq(
229 cmd.render_usage().to_string(),
230 "\
231 Usage: test [FILE] [FILES]...",
232 );
233 }
234
235 #[test]
multiple_positional_one_required_usage_string()236 fn multiple_positional_one_required_usage_string() {
237 let mut cmd = Command::new("test")
238 .arg(arg!(<FILE> "some file"))
239 .arg(arg!([FILES]... "some file"));
240 crate::utils::assert_eq(
241 cmd.render_usage().to_string(),
242 "Usage: test <FILE> [FILES]...",
243 );
244 }
245
246 #[test]
single_positional_required_usage_string()247 fn single_positional_required_usage_string() {
248 let mut cmd = Command::new("test").arg(arg!(<FILE> "some file"));
249 crate::utils::assert_eq(cmd.render_usage().to_string(), "Usage: test <FILE>");
250 }
251
252 // This tests a programmer error and will only succeed with debug_assertions
253 #[cfg(debug_assertions)]
254 #[test]
255 #[should_panic = "Found non-required positional argument \
256 with a lower index than a required positional argument"]
missing_required()257 fn missing_required() {
258 let _ = Command::new("test")
259 .arg(arg!([FILE1] "some file"))
260 .arg(arg!(<FILE2> "some file"))
261 .try_get_matches_from(vec![""]);
262 }
263
264 #[test]
missing_required_2()265 fn missing_required_2() {
266 let r = Command::new("test")
267 .arg(arg!(<FILE1> "some file"))
268 .arg(arg!(<FILE2> "some file"))
269 .try_get_matches_from(vec!["test", "file"]);
270 assert!(r.is_err());
271 assert_eq!(r.unwrap_err().kind(), ErrorKind::MissingRequiredArgument);
272 }
273
274 #[test]
last_positional()275 fn last_positional() {
276 let r = Command::new("test")
277 .arg(arg!(<TARGET> "some target"))
278 .arg(arg!([CORPUS] "some corpus"))
279 .arg(arg!([ARGS]... "some file").last(true))
280 .try_get_matches_from(vec!["test", "tgt", "--", "arg"]);
281 assert!(r.is_ok(), "{}", r.unwrap_err());
282 let m = r.unwrap();
283 assert_eq!(
284 m.get_many::<String>("ARGS")
285 .unwrap()
286 .map(|v| v.as_str())
287 .collect::<Vec<_>>(),
288 ["arg"]
289 );
290 }
291
292 #[test]
last_positional_no_double_dash()293 fn last_positional_no_double_dash() {
294 let r = Command::new("test")
295 .arg(arg!(<TARGET> "some target"))
296 .arg(arg!([CORPUS] "some corpus"))
297 .arg(arg!([ARGS]... "some file").last(true))
298 .try_get_matches_from(vec!["test", "tgt", "crp", "arg"]);
299 assert!(r.is_err());
300 assert_eq!(r.unwrap_err().kind(), ErrorKind::UnknownArgument);
301 }
302
303 #[test]
last_positional_second_to_last_mult()304 fn last_positional_second_to_last_mult() {
305 let r = Command::new("test")
306 .arg(arg!(<TARGET> "some target"))
307 .arg(arg!([CORPUS]... "some corpus"))
308 .arg(arg!([ARGS]... "some file").last(true))
309 .try_get_matches_from(vec!["test", "tgt", "crp1", "crp2", "--", "arg"]);
310 assert!(r.is_ok(), "{:?}", r.unwrap_err().kind());
311 }
312
313 #[cfg(debug_assertions)]
314 #[test]
315 #[should_panic = "Argument 'arg' is a positional argument and can't have short or long name versions"]
positional_arg_with_long()316 fn positional_arg_with_long() {
317 use clap::{Arg, Command};
318
319 let _ = Command::new("test")
320 .arg(Arg::new("arg").index(1).long("arg"))
321 .try_get_matches();
322 }
323
324 #[cfg(debug_assertions)]
325 #[test]
326 #[should_panic = "Argument 'arg' is a positional argument and can't have short or long name versions"]
positional_arg_with_short()327 fn positional_arg_with_short() {
328 use clap::{Arg, Command};
329
330 let _ = Command::new("test")
331 .arg(Arg::new("arg").index(1).short('a'))
332 .try_get_matches();
333 }
334
335 #[test]
ignore_hyphen_values_on_last()336 fn ignore_hyphen_values_on_last() {
337 let cmd = clap::Command::new("foo")
338 .arg(
339 clap::Arg::new("cmd")
340 .num_args(1..)
341 .last(true)
342 .allow_hyphen_values(true),
343 )
344 .arg(
345 clap::Arg::new("name")
346 .long("name")
347 .short('n')
348 .action(ArgAction::Set)
349 .required(false),
350 );
351
352 let matches = cmd.try_get_matches_from(["test", "-n", "foo"]).unwrap();
353 assert_eq!(
354 matches.get_one::<String>("name").map(|v| v.as_str()),
355 Some("foo")
356 );
357 }
358