1 use std::str::FromStr;
2 use std::ffi::OsString;
3
4 use pico_args::*;
5
to_vec(args: &[&str]) -> Vec<OsString>6 fn to_vec(args: &[&str]) -> Vec<OsString> {
7 args.iter().map(|s| s.to_string().into()).collect()
8 }
9
10 #[test]
no_args()11 fn no_args() {
12 let _ = Arguments::from_vec(to_vec(&[]));
13 }
14
15 #[test]
single_short_contains()16 fn single_short_contains() {
17 let mut args = Arguments::from_vec(to_vec(&["-V"]));
18 assert!(args.contains("-V"));
19 }
20
21 #[test]
single_long_contains()22 fn single_long_contains() {
23 let mut args = Arguments::from_vec(to_vec(&["--version"]));
24 assert!(args.contains("--version"));
25 }
26
27 #[test]
contains_two_01()28 fn contains_two_01() {
29 let mut args = Arguments::from_vec(to_vec(&["--version"]));
30 assert!(args.contains(["-v", "--version"]));
31 }
32
33 #[test]
contains_two_02()34 fn contains_two_02() {
35 let mut args = Arguments::from_vec(to_vec(&["-v"]));
36 assert!(args.contains(["-v", "--version"]));
37 }
38
39 #[test]
contains_two_03()40 fn contains_two_03() {
41 let mut args = Arguments::from_vec(to_vec(&["-v", "--version"]));
42 assert!(args.contains(["-v", "--version"]));
43 }
44
45 #[test]
46 #[should_panic]
invalid_flag_01()47 fn invalid_flag_01() {
48 let mut args = Arguments::from_vec(to_vec(&["-v", "--version"]));
49 assert!(args.contains("v"));
50 }
51
52 #[cfg(debug_assertions)]
53 #[test]
54 #[should_panic]
invalid_flag_02()55 fn invalid_flag_02() {
56 let mut args = Arguments::from_vec(to_vec(&["-v", "--version"]));
57 assert!(args.contains(["v", "--version"]));
58 }
59
60 #[cfg(debug_assertions)]
61 #[test]
62 #[should_panic]
invalid_flag_03()63 fn invalid_flag_03() {
64 let mut args = Arguments::from_vec(to_vec(&["-v", "--version"]));
65 assert!(args.contains(["-v", "-version"]));
66 }
67
68 #[cfg(debug_assertions)]
69 #[test]
70 #[should_panic]
invalid_flag_04()71 fn invalid_flag_04() {
72 let mut args = Arguments::from_vec(to_vec(&["-v", "--version"]));
73 assert!(args.contains(["-v", "version"]));
74 }
75
76
77 #[test]
option_01()78 fn option_01() {
79 let mut args = Arguments::from_vec(to_vec(&["-w", "10"]));
80 let value: Option<u32> = args.opt_value_from_str("-w").unwrap();
81 assert_eq!(value.unwrap(), 10);
82 }
83
84 #[test]
option_02()85 fn option_02() {
86 let mut args = Arguments::from_vec(to_vec(&["--width", "10"]));
87 let value: Option<u32> = args.opt_value_from_str("--width").unwrap();
88 assert_eq!(value.unwrap(), 10);
89 }
90
91 #[test]
option_03()92 fn option_03() {
93 let mut args = Arguments::from_vec(to_vec(&["--name", "test"]));
94 let value: Option<String> = args.opt_value_from_str("--name").unwrap();
95 assert_eq!(value.unwrap(), "test");
96 }
97
98 #[cfg(feature = "eq-separator")]
99 #[test]
eq_option_01()100 fn eq_option_01() {
101 let mut args = Arguments::from_vec(to_vec(&["-w=10"]));
102 let value: Option<u32> = args.opt_value_from_str("-w").unwrap();
103 assert_eq!(value.unwrap(), 10);
104 }
105
106 #[cfg(feature = "eq-separator")]
107 #[test]
eq_option_02()108 fn eq_option_02() {
109 let mut args = Arguments::from_vec(to_vec(&["-w='10'"]));
110 let value: Option<u32> = args.opt_value_from_str("-w").unwrap();
111 assert_eq!(value.unwrap(), 10);
112 }
113
114 #[cfg(feature = "eq-separator")]
115 #[test]
eq_option_03()116 fn eq_option_03() {
117 let mut args = Arguments::from_vec(to_vec(&["-w=\"10\""]));
118 let value: Option<u32> = args.opt_value_from_str("-w").unwrap();
119 assert_eq!(value.unwrap(), 10);
120 }
121
122 #[cfg(feature = "eq-separator")]
123 #[test]
eq_option_04()124 fn eq_option_04() {
125 let mut args = Arguments::from_vec(to_vec(&["--width2=15", "--width=10"]));
126 let value: Option<u32> = args.opt_value_from_str("--width").unwrap();
127 assert_eq!(value.unwrap(), 10);
128 }
129
130 #[cfg(feature = "eq-separator")]
131 #[test]
eq_option_err_01()132 fn eq_option_err_01() {
133 let mut args = Arguments::from_vec(to_vec(&["-w="]));
134 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
135 assert_eq!(value.unwrap_err().to_string(),
136 "the '-w' option doesn't have an associated value");
137 }
138
139 #[cfg(feature = "eq-separator")]
140 #[test]
eq_option_err_02()141 fn eq_option_err_02() {
142 let mut args = Arguments::from_vec(to_vec(&["-w='"]));
143 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
144 assert_eq!(value.unwrap_err().to_string(),
145 "the '-w' option doesn't have an associated value");
146 }
147
148 #[cfg(feature = "eq-separator")]
149 #[test]
eq_option_err_03()150 fn eq_option_err_03() {
151 let mut args = Arguments::from_vec(to_vec(&["-w=''"]));
152 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
153 assert_eq!(value.unwrap_err().to_string(),
154 "the '-w' option doesn't have an associated value");
155 }
156
157 #[cfg(feature = "eq-separator")]
158 #[test]
eq_option_err_04()159 fn eq_option_err_04() {
160 let mut args = Arguments::from_vec(to_vec(&["-w='\""]));
161 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
162 assert_eq!(value.unwrap_err().to_string(),
163 "the '-w' option doesn't have an associated value");
164 }
165
166 #[cfg(feature = "eq-separator")]
167 #[test]
eq_option_err_05()168 fn eq_option_err_05() {
169 let mut args = Arguments::from_vec(to_vec(&["-w='10\""]));
170 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
171 assert_eq!(value.unwrap_err().to_string(),
172 "the '-w' option doesn't have an associated value");
173 }
174
175 #[cfg(feature = "eq-separator")]
176 #[test]
eq_option_err_06()177 fn eq_option_err_06() {
178 let mut args = Arguments::from_vec(to_vec(&["-w-10"]));
179 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
180 assert_eq!(value.unwrap(), None);
181 }
182
183 #[cfg(feature = "eq-separator")]
184 #[test]
eq_option_err_07()185 fn eq_option_err_07() {
186 let mut args = Arguments::from_vec(to_vec(&["-w=a"]));
187 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
188 assert_eq!(value.unwrap_err().to_string(),
189 "failed to parse 'a' cause invalid digit found in string");
190 }
191
192 #[cfg(not(feature = "eq-separator"))]
193 #[test]
no_eq_separator_01()194 fn no_eq_separator_01() {
195 let mut args = Arguments::from_vec(to_vec(&["-w=a"]));
196 let value: Result<Option<u32>, Error> = args.opt_value_from_str("-w");
197 assert_eq!(value.unwrap(), None);
198 }
199
200 #[test]
duplicated_options_01()201 fn duplicated_options_01() {
202 let mut args = Arguments::from_vec(to_vec(&["--name", "test1", "--name", "test2"]));
203 let value1: Option<String> = args.opt_value_from_str("--name").unwrap();
204 let value2: Option<String> = args.opt_value_from_str("--name").unwrap();
205 assert_eq!(value1.unwrap(), "test1");
206 assert_eq!(value2.unwrap(), "test2");
207 }
208
209 #[test]
option_from_os_str_01()210 fn option_from_os_str_01() {
211 use std::path::PathBuf;
212
213 fn parse_path(s: &std::ffi::OsStr) -> Result<PathBuf, &'static str> {
214 Ok(s.into())
215 }
216
217 let mut args = Arguments::from_vec(to_vec(&["--input", "text.txt"]));
218 let value: Result<Option<PathBuf>, Error> = args.opt_value_from_os_str("--input", parse_path);
219 assert_eq!(value.unwrap().unwrap().display().to_string(), "text.txt");
220 }
221
222 #[test]
missing_option_value_01()223 fn missing_option_value_01() {
224 let mut args = Arguments::from_vec(to_vec(&["--value"]));
225 let value: Result<Option<u32>, Error> = args.opt_value_from_str("--value");
226 assert_eq!(value.unwrap_err().to_string(),
227 "the '--value' option doesn't have an associated value");
228 }
229
230 #[test]
missing_option_value_02()231 fn missing_option_value_02() {
232 let mut args = Arguments::from_vec(to_vec(&["--value"]));
233 let value: Result<Option<u32>, Error> = args.opt_value_from_str("--value");
234 assert!(value.is_err()); // ignore error
235 // the `--value` flag should not be removed by the previous command
236 assert!(args.finish().is_err());
237 }
238
239 #[test]
missing_option_value_03()240 fn missing_option_value_03() {
241 let mut args = Arguments::from_vec(to_vec(&["--value", "q"]));
242 let value: Result<Option<u32>, Error> = args.opt_value_from_str("--value");
243 assert!(value.is_err()); // ignore error
244 // the `--value` flag should not be removed by the previous command
245 assert!(args.finish().is_err());
246 }
247
248 #[test]
multiple_options_01()249 fn multiple_options_01() {
250 let mut args = Arguments::from_vec(to_vec(&["-w", "10", "-w", "20"]));
251 let value: Vec<u32> = args.values_from_str("-w").unwrap();
252 assert_eq!(value, &[10, 20]);
253 }
254
255 #[test]
multiple_options_02()256 fn multiple_options_02() {
257 // No values is not an error.
258 let mut args = Arguments::from_vec(to_vec(&[]));
259 let value: Vec<u32> = args.values_from_str("-w").unwrap();
260 assert_eq!(value, &[]);
261 }
262
263 #[test]
multiple_options_03()264 fn multiple_options_03() {
265 // Argument can be split.
266 let mut args = Arguments::from_vec(to_vec(&["-w", "10", "--other", "-w", "20"]));
267 let value: Vec<u32> = args.values_from_str("-w").unwrap();
268 assert_eq!(value, &[10, 20]);
269 }
270
271 #[test]
free_01()272 fn free_01() {
273 let args = Arguments::from_vec(to_vec(&[]));
274 assert_eq!(args.free_os().unwrap(), to_vec(&[]));
275 }
276
277 #[test]
free_02()278 fn free_02() {
279 let args = Arguments::from_vec(to_vec(&["text.txt"]));
280 assert_eq!(args.free_os().unwrap(), to_vec(&["text.txt"]));
281 }
282
283 #[test]
free_03()284 fn free_03() {
285 let args = Arguments::from_vec(to_vec(&["text.txt", "text2.txt"]));
286 assert_eq!(args.free_os().unwrap(), to_vec(&["text.txt", "text2.txt"]));
287 }
288
289 #[test]
free_04()290 fn free_04() {
291 let mut args = Arguments::from_vec(to_vec(&["-h", "text.txt", "text2.txt"]));
292 assert!(args.contains("-h"));
293 assert_eq!(args.free_os().unwrap(), to_vec(&["text.txt", "text2.txt"]));
294 }
295
296 #[test]
free_05()297 fn free_05() {
298 let mut args = Arguments::from_vec(to_vec(&["text.txt", "-h", "text2.txt"]));
299 assert!(args.contains("-h"));
300 assert_eq!(args.free_os().unwrap(), to_vec(&["text.txt", "text2.txt"]));
301 }
302
303 #[test]
free_06()304 fn free_06() {
305 let mut args = Arguments::from_vec(to_vec(&["text.txt", "text2.txt", "-h"]));
306 assert!(args.contains("-h"));
307 assert_eq!(args.free_os().unwrap(), to_vec(&["text.txt", "text2.txt"]));
308 }
309
310 #[test]
free_from_fn_01()311 fn free_from_fn_01() {
312 let mut args = Arguments::from_vec(to_vec(&["5"]));
313 assert_eq!(args.free_from_fn(u32::from_str).unwrap(), Some(5));
314 }
315
316 #[test]
free_from_fn_02()317 fn free_from_fn_02() {
318 let mut args = Arguments::from_vec(to_vec(&[]));
319 assert_eq!(args.free_from_fn(u32::from_str).unwrap(), None);
320 }
321
322 #[test]
free_from_fn_03()323 fn free_from_fn_03() {
324 let mut args = Arguments::from_vec(to_vec(&["-h"]));
325 assert_eq!(args.free_from_fn(u32::from_str).unwrap_err().to_string(),
326 "unused arguments left: -h");
327 }
328
329 #[test]
free_from_fn_04()330 fn free_from_fn_04() {
331 let mut args = Arguments::from_vec(to_vec(&["a"]));
332 assert_eq!(args.free_from_fn(u32::from_str).unwrap_err().to_string(),
333 "failed to parse 'a' cause invalid digit found in string");
334 }
335
336 #[test]
free_from_str_01()337 fn free_from_str_01() {
338 let mut args = Arguments::from_vec(to_vec(&["5"]));
339 let value: Result<Option<u32>, Error> = args.free_from_str();
340 assert_eq!(value.unwrap(), Some(5));
341 }
342
343 #[test]
unused_args_01()344 fn unused_args_01() {
345 let args = Arguments::from_vec(to_vec(&["-h", "text.txt"]));
346 assert_eq!(args.finish().unwrap_err().to_string(),
347 "unused arguments left: -h, text.txt");
348 }
349
350 #[test]
unused_args_02()351 fn unused_args_02() {
352 let args = Arguments::from_vec(to_vec(&["-h", "text.txt"]));
353 assert_eq!(args.free().unwrap_err().to_string(),
354 "unused arguments left: -h");
355 }
356
357 #[test]
stdin()358 fn stdin() {
359 let args = Arguments::from_vec(to_vec(&["-"]));
360 assert_eq!(args.free_os().unwrap(), to_vec(&["-"]));
361 }
362
363 #[test]
required_option_01()364 fn required_option_01() {
365 let mut args = Arguments::from_vec(to_vec(&["--width", "10"]));
366 let value: u32 = args.value_from_str("--width").unwrap();
367 assert_eq!(value, 10);
368 }
369
370 #[test]
missing_required_option_01()371 fn missing_required_option_01() {
372 let mut args = Arguments::from_vec(to_vec(&[]));
373 let value: Result<u32, Error> = args.value_from_str("-w");
374 assert_eq!(value.unwrap_err().to_string(),
375 "the '-w' option must be set");
376 }
377
378 #[test]
missing_required_option_02()379 fn missing_required_option_02() {
380 let mut args = Arguments::from_vec(to_vec(&[]));
381 let value: Result<u32, Error> = args.value_from_str("--width");
382 assert_eq!(value.unwrap_err().to_string(),
383 "the '--width' option must be set");
384 }
385
386 #[test]
missing_required_option_03()387 fn missing_required_option_03() {
388 let mut args = Arguments::from_vec(to_vec(&[]));
389 let value: Result<u32, Error> = args.value_from_str(["-w", "--width"]);
390 assert_eq!(value.unwrap_err().to_string(),
391 "the '-w/--width' option must be set");
392 }
393
394 #[test]
subcommand()395 fn subcommand() {
396 let mut args = Arguments::from_vec(to_vec(&["toolchain", "install", "--help"]));
397
398 let cmd = args.subcommand().unwrap();
399 assert_eq!(cmd, Some("toolchain".to_string()));
400
401 let cmd = args.subcommand().unwrap();
402 assert_eq!(cmd, Some("install".to_string()));
403
404 let cmd = args.subcommand().unwrap();
405 assert_eq!(cmd, None);
406 }
407