1 use super::each_split_within;
2 use super::Fail::*;
3 use super::{HasArg, Name, Occur, Opt, Options, ParsingStyle};
4 
5 #[test]
test_split_within()6 fn test_split_within() {
7     fn t(s: &str, i: usize, u: &[String]) {
8         let v = each_split_within(&(s.to_string()), i);
9         assert!(v.iter().zip(u.iter()).all(|(a, b)| a == b));
10     }
11     t("", 0, &[]);
12     t("", 15, &[]);
13     t("hello", 15, &["hello".to_string()]);
14     t(
15         "\nMary had a little lamb\nLittle lamb\n",
16         15,
17         &[
18             "Mary had a".to_string(),
19             "little lamb".to_string(),
20             "Little lamb".to_string(),
21         ],
22     );
23     t(
24         "\nMary had a little lamb\nLittle lamb\n",
25         ::std::usize::MAX,
26         &[
27             "Mary had a little lamb".to_string(),
28             "Little lamb".to_string(),
29         ],
30     );
31 }
32 
33 // Tests for reqopt
34 #[test]
test_reqopt()35 fn test_reqopt() {
36     let long_args = vec!["--test=20".to_string()];
37     let mut opts = Options::new();
38     opts.reqopt("t", "test", "testing", "TEST");
39     match opts.parse(&long_args) {
40         Ok(ref m) => {
41             assert!(m.opt_present("test"));
42             assert_eq!(m.opt_str("test").unwrap(), "20");
43             assert!(m.opt_present("t"));
44             assert_eq!(m.opt_str("t").unwrap(), "20");
45         }
46         _ => {
47             panic!("test_reqopt failed (long arg)");
48         }
49     }
50     let short_args = vec!["-t".to_string(), "20".to_string()];
51     match opts.parse(&short_args) {
52         Ok(ref m) => {
53             assert!((m.opt_present("test")));
54             assert_eq!(m.opt_str("test").unwrap(), "20");
55             assert!((m.opt_present("t")));
56             assert_eq!(m.opt_str("t").unwrap(), "20");
57         }
58         _ => {
59             panic!("test_reqopt failed (short arg)");
60         }
61     }
62 }
63 
64 #[test]
test_reqopt_missing()65 fn test_reqopt_missing() {
66     let args = vec!["blah".to_string()];
67     match Options::new()
68         .reqopt("t", "test", "testing", "TEST")
69         .parse(&args)
70     {
71         Err(OptionMissing(_)) => {}
72         _ => panic!(),
73     }
74 }
75 
76 #[test]
test_reqopt_no_arg()77 fn test_reqopt_no_arg() {
78     let long_args = vec!["--test".to_string()];
79     let mut opts = Options::new();
80     opts.reqopt("t", "test", "testing", "TEST");
81     match opts.parse(&long_args) {
82         Err(ArgumentMissing(_)) => {}
83         _ => panic!(),
84     }
85     let short_args = vec!["-t".to_string()];
86     match opts.parse(&short_args) {
87         Err(ArgumentMissing(_)) => {}
88         _ => panic!(),
89     }
90 }
91 
92 #[test]
test_reqopt_multi()93 fn test_reqopt_multi() {
94     let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()];
95     match Options::new()
96         .reqopt("t", "test", "testing", "TEST")
97         .parse(&args)
98     {
99         Err(OptionDuplicated(_)) => {}
100         _ => panic!(),
101     }
102 }
103 
104 // Tests for optopt
105 #[test]
test_optopt()106 fn test_optopt() {
107     let long_args = vec!["--test=20".to_string()];
108     let mut opts = Options::new();
109     opts.optopt("t", "test", "testing", "TEST");
110     match opts.parse(&long_args) {
111         Ok(ref m) => {
112             assert!(m.opt_present("test"));
113             assert_eq!(m.opt_str("test").unwrap(), "20");
114             assert!((m.opt_present("t")));
115             assert_eq!(m.opt_str("t").unwrap(), "20");
116         }
117         _ => panic!(),
118     }
119     let short_args = vec!["-t".to_string(), "20".to_string()];
120     match opts.parse(&short_args) {
121         Ok(ref m) => {
122             assert!((m.opt_present("test")));
123             assert_eq!(m.opt_str("test").unwrap(), "20");
124             assert!((m.opt_present("t")));
125             assert_eq!(m.opt_str("t").unwrap(), "20");
126         }
127         _ => panic!(),
128     }
129 }
130 
131 #[test]
test_optopt_missing()132 fn test_optopt_missing() {
133     let args = vec!["blah".to_string()];
134     match Options::new()
135         .optopt("t", "test", "testing", "TEST")
136         .parse(&args)
137     {
138         Ok(ref m) => {
139             assert!(!m.opt_present("test"));
140             assert!(!m.opt_present("t"));
141         }
142         _ => panic!(),
143     }
144 }
145 
146 #[test]
test_optopt_no_arg()147 fn test_optopt_no_arg() {
148     let long_args = vec!["--test".to_string()];
149     let mut opts = Options::new();
150     opts.optopt("t", "test", "testing", "TEST");
151     match opts.parse(&long_args) {
152         Err(ArgumentMissing(_)) => {}
153         _ => panic!(),
154     }
155     let short_args = vec!["-t".to_string()];
156     match opts.parse(&short_args) {
157         Err(ArgumentMissing(_)) => {}
158         _ => panic!(),
159     }
160 }
161 
162 #[test]
test_optopt_multi()163 fn test_optopt_multi() {
164     let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()];
165     match Options::new()
166         .optopt("t", "test", "testing", "TEST")
167         .parse(&args)
168     {
169         Err(OptionDuplicated(_)) => {}
170         _ => panic!(),
171     }
172 }
173 
174 // Tests for optflag
175 #[test]
test_optflag()176 fn test_optflag() {
177     let long_args = vec!["--test".to_string()];
178     let mut opts = Options::new();
179     opts.optflag("t", "test", "testing");
180     match opts.parse(&long_args) {
181         Ok(ref m) => {
182             assert!(m.opt_present("test"));
183             assert!(m.opt_present("t"));
184         }
185         _ => panic!(),
186     }
187     let short_args = vec!["-t".to_string()];
188     match opts.parse(&short_args) {
189         Ok(ref m) => {
190             assert!(m.opt_present("test"));
191             assert!(m.opt_present("t"));
192         }
193         _ => panic!(),
194     }
195 }
196 
197 #[test]
test_optflag_missing()198 fn test_optflag_missing() {
199     let args = vec!["blah".to_string()];
200     match Options::new().optflag("t", "test", "testing").parse(&args) {
201         Ok(ref m) => {
202             assert!(!m.opt_present("test"));
203             assert!(!m.opt_present("t"));
204         }
205         _ => panic!(),
206     }
207 }
208 
209 #[test]
test_opt_end()210 fn test_opt_end() {
211     let args = vec!["--".to_owned(), "-t".to_owned()];
212     match Options::new().optflag("t", "test", "testing").parse(&args) {
213         Ok(ref m) => {
214             assert!(!m.opt_present("test"));
215             assert!(!m.opt_present("t"));
216             assert_eq!(m.free.len(), 1);
217             assert_eq!(m.free[0], "-t");
218         }
219         _ => panic!(),
220     }
221 }
222 
223 #[test]
test_opt_only_end()224 fn test_opt_only_end() {
225     let args = vec!["--".to_owned()];
226     match Options::new().optflag("t", "test", "testing").parse(&args) {
227         Ok(ref m) => {
228             assert!(!m.opt_present("test"));
229             assert!(!m.opt_present("t"));
230             assert_eq!(m.free.len(), 0);
231         }
232         _ => panic!(),
233     }
234 }
235 
236 #[test]
test_optflag_long_arg()237 fn test_optflag_long_arg() {
238     let args = vec!["--test=20".to_string()];
239     match Options::new().optflag("t", "test", "testing").parse(&args) {
240         Err(UnexpectedArgument(_)) => {}
241         _ => panic!(),
242     }
243 }
244 
245 #[test]
test_optflag_multi()246 fn test_optflag_multi() {
247     let args = vec!["--test".to_string(), "-t".to_string()];
248     match Options::new().optflag("t", "test", "testing").parse(&args) {
249         Err(OptionDuplicated(_)) => {}
250         _ => panic!(),
251     }
252 }
253 
254 #[test]
test_optflag_short_arg()255 fn test_optflag_short_arg() {
256     let args = vec!["-t".to_string(), "20".to_string()];
257     match Options::new().optflag("t", "test", "testing").parse(&args) {
258         Ok(ref m) => {
259             // The next variable after the flag is just a free argument
260 
261             assert!(m.free[0] == "20");
262         }
263         _ => panic!(),
264     }
265 }
266 
267 // Tests for optflagmulti
268 #[test]
test_optflagmulti_short1()269 fn test_optflagmulti_short1() {
270     let args = vec!["-v".to_string()];
271     match Options::new()
272         .optflagmulti("v", "verbose", "verbosity")
273         .parse(&args)
274     {
275         Ok(ref m) => {
276             assert_eq!(m.opt_count("v"), 1);
277         }
278         _ => panic!(),
279     }
280 }
281 
282 #[test]
test_optflagmulti_short2a()283 fn test_optflagmulti_short2a() {
284     let args = vec!["-v".to_string(), "-v".to_string()];
285     match Options::new()
286         .optflagmulti("v", "verbose", "verbosity")
287         .parse(&args)
288     {
289         Ok(ref m) => {
290             assert_eq!(m.opt_count("v"), 2);
291         }
292         _ => panic!(),
293     }
294 }
295 
296 #[test]
test_optflagmulti_short2b()297 fn test_optflagmulti_short2b() {
298     let args = vec!["-vv".to_string()];
299     match Options::new()
300         .optflagmulti("v", "verbose", "verbosity")
301         .parse(&args)
302     {
303         Ok(ref m) => {
304             assert_eq!(m.opt_count("v"), 2);
305         }
306         _ => panic!(),
307     }
308 }
309 
310 #[test]
test_optflagmulti_long1()311 fn test_optflagmulti_long1() {
312     let args = vec!["--verbose".to_string()];
313     match Options::new()
314         .optflagmulti("v", "verbose", "verbosity")
315         .parse(&args)
316     {
317         Ok(ref m) => {
318             assert_eq!(m.opt_count("verbose"), 1);
319         }
320         _ => panic!(),
321     }
322 }
323 
324 #[test]
test_optflagmulti_long2()325 fn test_optflagmulti_long2() {
326     let args = vec!["--verbose".to_string(), "--verbose".to_string()];
327     match Options::new()
328         .optflagmulti("v", "verbose", "verbosity")
329         .parse(&args)
330     {
331         Ok(ref m) => {
332             assert_eq!(m.opt_count("verbose"), 2);
333         }
334         _ => panic!(),
335     }
336 }
337 
338 #[test]
test_optflagmulti_mix()339 fn test_optflagmulti_mix() {
340     let args = vec![
341         "--verbose".to_string(),
342         "-v".to_string(),
343         "-vv".to_string(),
344         "verbose".to_string(),
345     ];
346     match Options::new()
347         .optflagmulti("v", "verbose", "verbosity")
348         .parse(&args)
349     {
350         Ok(ref m) => {
351             assert_eq!(m.opt_count("verbose"), 4);
352             assert_eq!(m.opt_count("v"), 4);
353         }
354         _ => panic!(),
355     }
356 }
357 
358 // Tests for optflagopt
359 #[test]
test_optflagopt()360 fn test_optflagopt() {
361     let long_args = vec!["--test".to_string()];
362     let mut opts = Options::new();
363     opts.optflagopt("t", "test", "testing", "ARG");
364     match opts.parse(&long_args) {
365         Ok(ref m) => {
366             assert!(m.opt_present("test"));
367             assert!(m.opt_present("t"));
368         }
369         _ => panic!(),
370     }
371     let short_args = vec!["-t".to_string()];
372     match opts.parse(&short_args) {
373         Ok(ref m) => {
374             assert!(m.opt_present("test"));
375             assert!(m.opt_present("t"));
376         }
377         _ => panic!(),
378     }
379     let short_args = vec!["-t".to_string(), "x".to_string()];
380     match opts.parse(&short_args) {
381         Ok(ref m) => {
382             assert_eq!(m.opt_str("t").unwrap(), "x");
383             assert_eq!(m.opt_str("test").unwrap(), "x");
384         }
385         _ => panic!(),
386     }
387     let long_args = vec!["--test=x".to_string()];
388     match opts.parse(&long_args) {
389         Ok(ref m) => {
390             assert_eq!(m.opt_str("t").unwrap(), "x");
391             assert_eq!(m.opt_str("test").unwrap(), "x");
392         }
393         _ => panic!(),
394     }
395     let long_args = vec!["--test".to_string(), "x".to_string()];
396     match opts.parse(&long_args) {
397         Ok(ref m) => {
398             assert_eq!(m.opt_str("t"), None);
399             assert_eq!(m.opt_str("test"), None);
400         }
401         _ => panic!(),
402     }
403     let no_args: Vec<String> = vec![];
404     match opts.parse(&no_args) {
405         Ok(ref m) => {
406             assert!(!m.opt_present("test"));
407             assert!(!m.opt_present("t"));
408         }
409         _ => panic!(),
410     }
411 }
412 
413 // Tests for optmulti
414 #[test]
test_optmulti()415 fn test_optmulti() {
416     let long_args = vec!["--test=20".to_string()];
417     let mut opts = Options::new();
418     opts.optmulti("t", "test", "testing", "TEST");
419     match opts.parse(&long_args) {
420         Ok(ref m) => {
421             assert!((m.opt_present("test")));
422             assert_eq!(m.opt_str("test").unwrap(), "20");
423             assert!((m.opt_present("t")));
424             assert_eq!(m.opt_str("t").unwrap(), "20");
425         }
426         _ => panic!(),
427     }
428     let short_args = vec!["-t".to_string(), "20".to_string()];
429     match opts.parse(&short_args) {
430         Ok(ref m) => {
431             assert!((m.opt_present("test")));
432             assert_eq!(m.opt_str("test").unwrap(), "20");
433             assert!((m.opt_present("t")));
434             assert_eq!(m.opt_str("t").unwrap(), "20");
435         }
436         _ => panic!(),
437     }
438 }
439 
440 #[test]
test_optmulti_missing()441 fn test_optmulti_missing() {
442     let args = vec!["blah".to_string()];
443     match Options::new()
444         .optmulti("t", "test", "testing", "TEST")
445         .parse(&args)
446     {
447         Ok(ref m) => {
448             assert!(!m.opt_present("test"));
449             assert!(!m.opt_present("t"));
450         }
451         _ => panic!(),
452     }
453 }
454 
455 #[test]
test_optmulti_no_arg()456 fn test_optmulti_no_arg() {
457     let long_args = vec!["--test".to_string()];
458     let mut opts = Options::new();
459     opts.optmulti("t", "test", "testing", "TEST");
460     match opts.parse(&long_args) {
461         Err(ArgumentMissing(_)) => {}
462         _ => panic!(),
463     }
464     let short_args = vec!["-t".to_string()];
465     match opts.parse(&short_args) {
466         Err(ArgumentMissing(_)) => {}
467         _ => panic!(),
468     }
469 }
470 
471 #[test]
test_optmulti_multi()472 fn test_optmulti_multi() {
473     let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()];
474     match Options::new()
475         .optmulti("t", "test", "testing", "TEST")
476         .parse(&args)
477     {
478         Ok(ref m) => {
479             assert!(m.opt_present("test"));
480             assert_eq!(m.opt_str("test").unwrap(), "20");
481             assert!(m.opt_present("t"));
482             assert_eq!(m.opt_str("t").unwrap(), "20");
483             let pair = m.opt_strs("test");
484             assert!(pair[0] == "20");
485             assert!(pair[1] == "30");
486         }
487         _ => panic!(),
488     }
489 }
490 
491 #[test]
test_free_argument_is_hyphen()492 fn test_free_argument_is_hyphen() {
493     let args = vec!["-".to_string()];
494     match Options::new().parse(&args) {
495         Ok(ref m) => {
496             assert_eq!(m.free.len(), 1);
497             assert_eq!(m.free[0], "-");
498         }
499         _ => panic!(),
500     }
501 }
502 
503 #[test]
test_unrecognized_option()504 fn test_unrecognized_option() {
505     let long_args = vec!["--untest".to_string()];
506     let mut opts = Options::new();
507     opts.optmulti("t", "test", "testing", "TEST");
508     match opts.parse(&long_args) {
509         Err(UnrecognizedOption(_)) => {}
510         _ => panic!(),
511     }
512     let short_args = vec!["-u".to_string()];
513     match opts.parse(&short_args) {
514         Err(UnrecognizedOption(_)) => {}
515         _ => panic!(),
516     }
517 }
518 
519 #[test]
test_combined()520 fn test_combined() {
521     let args = vec![
522         "prog".to_string(),
523         "free1".to_string(),
524         "-s".to_string(),
525         "20".to_string(),
526         "free2".to_string(),
527         "--flag".to_string(),
528         "--long=30".to_string(),
529         "-f".to_string(),
530         "-m".to_string(),
531         "40".to_string(),
532         "-m".to_string(),
533         "50".to_string(),
534         "-n".to_string(),
535         "-A B".to_string(),
536         "-n".to_string(),
537         "-60 70".to_string(),
538     ];
539     match Options::new()
540         .optopt("s", "something", "something", "SOMETHING")
541         .optflag("", "flag", "a flag")
542         .reqopt("", "long", "hi", "LONG")
543         .optflag("f", "", "another flag")
544         .optmulti("m", "", "mmmmmm", "YUM")
545         .optmulti("n", "", "nothing", "NOTHING")
546         .optopt("", "notpresent", "nothing to see here", "NOPE")
547         .parse(&args)
548     {
549         Ok(ref m) => {
550             assert!(m.free[0] == "prog");
551             assert!(m.free[1] == "free1");
552             assert_eq!(m.opt_str("s").unwrap(), "20");
553             assert!(m.free[2] == "free2");
554             assert!((m.opt_present("flag")));
555             assert_eq!(m.opt_str("long").unwrap(), "30");
556             assert!((m.opt_present("f")));
557             let pair = m.opt_strs("m");
558             assert!(pair[0] == "40");
559             assert!(pair[1] == "50");
560             let pair = m.opt_strs("n");
561             assert!(pair[0] == "-A B");
562             assert!(pair[1] == "-60 70");
563             assert!((!m.opt_present("notpresent")));
564         }
565         _ => panic!(),
566     }
567 }
568 
569 #[test]
test_mixed_stop()570 fn test_mixed_stop() {
571     let args = vec![
572         "-a".to_string(),
573         "b".to_string(),
574         "-c".to_string(),
575         "d".to_string(),
576     ];
577     match Options::new()
578         .parsing_style(ParsingStyle::StopAtFirstFree)
579         .optflag("a", "", "")
580         .optopt("c", "", "", "")
581         .parse(&args)
582     {
583         Ok(ref m) => {
584             println!("{}", m.opt_present("c"));
585             assert!(m.opt_present("a"));
586             assert!(!m.opt_present("c"));
587             assert_eq!(m.free.len(), 3);
588             assert_eq!(m.free[0], "b");
589             assert_eq!(m.free[1], "-c");
590             assert_eq!(m.free[2], "d");
591         }
592         _ => panic!(),
593     }
594 }
595 
596 #[test]
test_mixed_stop_hyphen()597 fn test_mixed_stop_hyphen() {
598     let args = vec![
599         "-a".to_string(),
600         "-".to_string(),
601         "-c".to_string(),
602         "d".to_string(),
603     ];
604     match Options::new()
605         .parsing_style(ParsingStyle::StopAtFirstFree)
606         .optflag("a", "", "")
607         .optopt("c", "", "", "")
608         .parse(&args)
609     {
610         Ok(ref m) => {
611             println!("{}", m.opt_present("c"));
612             assert!(m.opt_present("a"));
613             assert!(!m.opt_present("c"));
614             assert_eq!(m.free.len(), 3);
615             assert_eq!(m.free[0], "-");
616             assert_eq!(m.free[1], "-c");
617             assert_eq!(m.free[2], "d");
618         }
619         _ => panic!(),
620     }
621 }
622 
623 #[test]
test_multi()624 fn test_multi() {
625     let mut opts = Options::new();
626     opts.optopt("e", "", "encrypt", "ENCRYPT");
627     opts.optopt("", "encrypt", "encrypt", "ENCRYPT");
628     opts.optopt("f", "", "flag", "FLAG");
629 
630     let args_single = vec!["-e".to_string(), "foo".to_string()];
631     let matches_single = &match opts.parse(&args_single) {
632         Ok(m) => m,
633         _ => panic!(),
634     };
635     assert!(matches_single.opts_present(&["e".to_string()]));
636     assert!(matches_single.opts_present(&["encrypt".to_string(), "e".to_string()]));
637     assert!(matches_single.opts_present(&["e".to_string(), "encrypt".to_string()]));
638     assert!(!matches_single.opts_present(&["encrypt".to_string()]));
639     assert!(!matches_single.opts_present(&["thing".to_string()]));
640     assert!(!matches_single.opts_present(&[]));
641 
642     assert_eq!(matches_single.opts_str(&["e".to_string()]).unwrap(), "foo");
643     assert_eq!(
644         matches_single
645             .opts_str(&["e".to_string(), "encrypt".to_string()])
646             .unwrap(),
647         "foo"
648     );
649     assert_eq!(
650         matches_single
651             .opts_str(&["encrypt".to_string(), "e".to_string()])
652             .unwrap(),
653         "foo"
654     );
655 
656     let args_both = vec![
657         "-e".to_string(),
658         "foo".to_string(),
659         "--encrypt".to_string(),
660         "foo".to_string(),
661     ];
662     let matches_both = &match opts.parse(&args_both) {
663         Ok(m) => m,
664         _ => panic!(),
665     };
666     assert!(matches_both.opts_present(&["e".to_string()]));
667     assert!(matches_both.opts_present(&["encrypt".to_string()]));
668     assert!(matches_both.opts_present(&["encrypt".to_string(), "e".to_string()]));
669     assert!(matches_both.opts_present(&["e".to_string(), "encrypt".to_string()]));
670     assert!(!matches_both.opts_present(&["f".to_string()]));
671     assert!(!matches_both.opts_present(&["thing".to_string()]));
672     assert!(!matches_both.opts_present(&[]));
673 
674     assert_eq!(matches_both.opts_str(&["e".to_string()]).unwrap(), "foo");
675     assert_eq!(
676         matches_both.opts_str(&["encrypt".to_string()]).unwrap(),
677         "foo"
678     );
679     assert_eq!(
680         matches_both
681             .opts_str(&["e".to_string(), "encrypt".to_string()])
682             .unwrap(),
683         "foo"
684     );
685     assert_eq!(
686         matches_both
687             .opts_str(&["encrypt".to_string(), "e".to_string()])
688             .unwrap(),
689         "foo"
690     );
691 }
692 
693 #[test]
test_nospace()694 fn test_nospace() {
695     let args = vec!["-Lfoo".to_string(), "-M.".to_string()];
696     let matches = &match Options::new()
697         .optmulti("L", "", "library directory", "LIB")
698         .optmulti("M", "", "something", "MMMM")
699         .parse(&args)
700     {
701         Ok(m) => m,
702         _ => panic!(),
703     };
704     assert!(matches.opts_present(&["L".to_string()]));
705     assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "foo");
706     assert!(matches.opts_present(&["M".to_string()]));
707     assert_eq!(matches.opts_str(&["M".to_string()]).unwrap(), ".");
708 }
709 
710 #[test]
test_nospace_conflict()711 fn test_nospace_conflict() {
712     let args = vec!["-vvLverbose".to_string(), "-v".to_string()];
713     let matches = &match Options::new()
714         .optmulti("L", "", "library directory", "LIB")
715         .optflagmulti("v", "verbose", "Verbose")
716         .parse(&args)
717     {
718         Ok(m) => m,
719         Err(e) => panic!("{}", e),
720     };
721     assert!(matches.opts_present(&["L".to_string()]));
722     assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "verbose");
723     assert!(matches.opts_present(&["v".to_string()]));
724     assert_eq!(3, matches.opt_count("v"));
725 }
726 
727 #[test]
test_long_to_short()728 fn test_long_to_short() {
729     let mut short = Opt {
730         name: Name::Long("banana".to_string()),
731         hasarg: HasArg::Yes,
732         occur: Occur::Req,
733         aliases: Vec::new(),
734     };
735     short.aliases = vec![Opt {
736         name: Name::Short('b'),
737         hasarg: HasArg::Yes,
738         occur: Occur::Req,
739         aliases: Vec::new(),
740     }];
741     let mut opts = Options::new();
742     opts.reqopt("b", "banana", "some bananas", "VAL");
743     let verbose = &opts.grps[0];
744     assert!(verbose.long_to_short() == short);
745 }
746 
747 #[test]
test_aliases_long_and_short()748 fn test_aliases_long_and_short() {
749     let args = vec!["-a".to_string(), "--apple".to_string(), "-a".to_string()];
750 
751     let matches = Options::new()
752         .optflagmulti("a", "apple", "Desc")
753         .parse(&args)
754         .unwrap();
755     assert_eq!(3, matches.opt_count("a"));
756     assert_eq!(3, matches.opt_count("apple"));
757 }
758 
759 #[test]
test_usage()760 fn test_usage() {
761     let mut opts = Options::new();
762     opts.reqopt("b", "banana", "Desc", "VAL");
763     opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL");
764     opts.optflag("k", "kiwi", "Desc");
765     opts.optflagopt("p", "", "Desc", "VAL");
766     opts.optmulti("l", "", "Desc", "VAL");
767     opts.optflag("", "starfruit", "Starfruit");
768 
769     let expected = "Usage: fruits
770 
771 Options:
772     -b, --banana VAL    Desc
773     -a, --012345678901234567890123456789 VAL
774                         Desc
775     -k, --kiwi          Desc
776     -p [VAL]            Desc
777     -l VAL              Desc
778         --starfruit     Starfruit
779 ";
780 
781     let generated_usage = opts.usage("Usage: fruits");
782 
783     debug!("expected: <<{}>>", expected);
784     debug!("generated: <<{}>>", generated_usage);
785     assert_eq!(generated_usage, expected);
786 }
787 
788 #[test]
test_usage_description_wrapping()789 fn test_usage_description_wrapping() {
790     // indentation should be 24 spaces
791     // lines wrap after 78: or rather descriptions wrap after 54
792 
793     let mut opts = Options::new();
794     opts.optflag(
795         "k",
796         "kiwi",
797         "This is a long description which won't be wrapped..+..",
798     ); // 54
799     opts.optflag(
800         "a",
801         "apple",
802         "This is a long description which _will_ be wrapped..+..",
803     );
804     opts.optflag(
805         "b",
806         "banana",
807         "HereWeNeedOneSingleWordThatIsLongerThanTheWrappingLengthAndThisIsIt",
808     );
809 
810     let expected = "Usage: fruits
811 
812 Options:
813     -k, --kiwi          This is a long description which won't be wrapped..+..
814     -a, --apple         This is a long description which _will_ be
815                         wrapped..+..
816     -b, --banana        HereWeNeedOneSingleWordThatIsLongerThanTheWrappingLengthAndThisIsIt
817 ";
818 
819     let usage = opts.usage("Usage: fruits");
820 
821     debug!("expected: <<{}>>", expected);
822     debug!("generated: <<{}>>", usage);
823     assert!(usage == expected)
824 }
825 
826 #[test]
test_usage_description_multibyte_handling()827 fn test_usage_description_multibyte_handling() {
828     let mut opts = Options::new();
829     opts.optflag(
830         "k",
831         "k\u{2013}w\u{2013}",
832         "The word kiwi is normally spelled with two i's",
833     );
834     opts.optflag(
835         "a",
836         "apple",
837         "This \u{201C}description\u{201D} has some characters that could \
838          confuse the line wrapping; an apple costs 0.51€ in some parts of Europe.",
839     );
840 
841     let expected = "Usage: fruits
842 
843 Options:
844     -k, --k–w–          The word kiwi is normally spelled with two i's
845     -a, --apple         This “description” has some characters that could
846                         confuse the line wrapping; an apple costs 0.51€ in
847                         some parts of Europe.
848 ";
849 
850     let usage = opts.usage("Usage: fruits");
851 
852     debug!("expected: <<{}>>", expected);
853     debug!("generated: <<{}>>", usage);
854     assert!(usage == expected)
855 }
856 
857 #[test]
test_usage_description_newline_handling()858 fn test_usage_description_newline_handling() {
859     let mut opts = Options::new();
860     opts.optflag(
861         "k",
862         "k\u{2013}w\u{2013}",
863         "The word kiwi is normally spelled with two i's",
864     );
865     opts.optflag(
866         "a",
867         "apple",
868         "This description forces a new line.\n Here is a premature\n\
869          newline",
870     );
871 
872     let expected = "Usage: fruits
873 
874 Options:
875     -k, --k–w–          The word kiwi is normally spelled with two i's
876     -a, --apple         This description forces a new line.
877                         Here is a premature
878                         newline
879 ";
880 
881     let usage = opts.usage("Usage: fruits");
882 
883     debug!("expected: <<{}>>", expected);
884     debug!("generated: <<{}>>", usage);
885     assert!(usage == expected)
886 }
887 
888 #[test]
test_usage_multiwidth()889 fn test_usage_multiwidth() {
890     let mut opts = Options::new();
891     opts.optflag("a", "apple", "apple description");
892     opts.optflag("b", "banana\u{00AB}", "banana description");
893     opts.optflag("c", "brûlée", "brûlée quite long description");
894     opts.optflag("k", "kiwi\u{20AC}", "kiwi description");
895     opts.optflag("o", "orange\u{2039}", "orange description");
896     opts.optflag(
897         "r",
898         "raspberry-but-making-this-option-way-too-long",
899         "raspberry description is also quite long indeed longer than \
900          every other piece of text we might encounter here and thus will \
901          be automatically broken up",
902     );
903 
904     let expected = "Usage: fruits
905 
906 Options:
907     -a, --apple         apple description
908     -b, --banana«       banana description
909     -c, --brûlée        brûlée quite long description
910     -k, --kiwi€         kiwi description
911     -o, --orange‹       orange description
912     -r, --raspberry-but-making-this-option-way-too-long\u{0020}
913                         raspberry description is also quite long indeed longer
914                         than every other piece of text we might encounter here
915                         and thus will be automatically broken up
916 ";
917 
918     let usage = opts.usage("Usage: fruits");
919 
920     debug!("expected: <<{}>>", expected);
921     debug!("generated: <<{}>>", usage);
922     assert!(usage == expected)
923 }
924 
925 #[test]
test_usage_short_only()926 fn test_usage_short_only() {
927     let mut opts = Options::new();
928     opts.optopt("k", "", "Kiwi", "VAL");
929     opts.optflag("s", "", "Starfruit");
930     opts.optflagopt("a", "", "Apple", "TYPE");
931 
932     let expected = "Usage: fruits
933 
934 Options:
935     -k VAL              Kiwi
936     -s                  Starfruit
937     -a [TYPE]           Apple
938 ";
939 
940     let usage = opts.usage("Usage: fruits");
941     debug!("expected: <<{}>>", expected);
942     debug!("generated: <<{}>>", usage);
943     assert!(usage == expected)
944 }
945 
946 #[test]
test_usage_long_only()947 fn test_usage_long_only() {
948     let mut opts = Options::new();
949     opts.optopt("", "kiwi", "Kiwi", "VAL");
950     opts.optflag("", "starfruit", "Starfruit");
951     opts.optflagopt("", "apple", "Apple", "TYPE");
952 
953     let expected = "Usage: fruits
954 
955 Options:
956     --kiwi VAL          Kiwi
957     --starfruit         Starfruit
958     --apple [TYPE]      Apple
959 ";
960 
961     let usage = opts.usage("Usage: fruits");
962     debug!("expected: <<{}>>", expected);
963     debug!("generated: <<{}>>", usage);
964     assert!(usage == expected)
965 }
966 
967 #[test]
test_short_usage()968 fn test_short_usage() {
969     let mut opts = Options::new();
970     opts.reqopt("b", "banana", "Desc", "VAL");
971     opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL");
972     opts.optflag("k", "kiwi", "Desc");
973     opts.optflagopt("p", "", "Desc", "VAL");
974     opts.optmulti("l", "", "Desc", "VAL");
975 
976     let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL]..".to_string();
977     let generated_usage = opts.short_usage("fruits");
978 
979     debug!("expected: <<{}>>", expected);
980     debug!("generated: <<{}>>", generated_usage);
981     assert_eq!(generated_usage, expected);
982 }
983 #[test]
test_nonexistant_opt()984 fn test_nonexistant_opt() {
985     let mut opts = Options::new();
986     opts.optflag("b", "bar", "Desc");
987     let args: Vec<String> = Vec::new();
988     let matches = opts.parse(&args).unwrap();
989     assert_eq!(matches.opt_defined("foo"), false);
990     assert_eq!(matches.opt_defined("bar"), true);
991 }
992 #[test]
test_args_with_equals()993 fn test_args_with_equals() {
994     let mut opts = Options::new();
995     opts.optopt("o", "one", "One", "INFO");
996     opts.optopt("t", "two", "Two", "INFO");
997 
998     let args = vec![
999         "--one".to_string(),
1000         "A=B".to_string(),
1001         "--two=C=D".to_string(),
1002     ];
1003     let matches = &match opts.parse(&args) {
1004         Ok(m) => m,
1005         Err(e) => panic!("{}", e),
1006     };
1007     assert_eq!(matches.opts_str(&["o".to_string()]).unwrap(), "A=B");
1008     assert_eq!(matches.opts_str(&["t".to_string()]).unwrap(), "C=D");
1009 }
1010 
1011 #[test]
test_long_only_usage()1012 fn test_long_only_usage() {
1013     let mut opts = Options::new();
1014     opts.long_only(true);
1015     opts.optflag("k", "kiwi", "Description");
1016     opts.optflag("a", "apple", "Description");
1017 
1018     let expected = "Usage: fruits
1019 
1020 Options:
1021     -k, -kiwi           Description
1022     -a, -apple          Description
1023 ";
1024 
1025     let usage = opts.usage("Usage: fruits");
1026 
1027     debug!("expected: <<{}>>", expected);
1028     debug!("generated: <<{}>>", usage);
1029     assert!(usage == expected)
1030 }
1031 
1032 #[test]
test_long_only_mode()1033 fn test_long_only_mode() {
1034     let mut opts = Options::new();
1035     opts.long_only(true);
1036     opts.optopt("a", "apple", "Description", "X");
1037     opts.optopt("b", "banana", "Description", "X");
1038     opts.optopt("c", "currant", "Description", "X");
1039     opts.optopt("", "durian", "Description", "X");
1040     opts.optopt("e", "", "Description", "X");
1041     opts.optopt("", "fruit", "Description", "X");
1042 
1043     let args = vec![
1044         "-a",
1045         "A",
1046         "-b=B",
1047         "--c=C",
1048         "-durian",
1049         "D",
1050         "--e",
1051         "E",
1052         "-fruit=any",
1053     ];
1054     let matches = &match opts.parse(&args) {
1055         Ok(m) => m,
1056         Err(e) => panic!("{}", e),
1057     };
1058     assert_eq!(matches.opts_str(&["a".to_string()]).unwrap(), "A");
1059     assert_eq!(matches.opts_str(&["b".to_string()]).unwrap(), "B");
1060     assert_eq!(matches.opts_str(&["c".to_string()]).unwrap(), "C");
1061     assert_eq!(matches.opts_str(&["durian".to_string()]).unwrap(), "D");
1062     assert_eq!(matches.opts_str(&["e".to_string()]).unwrap(), "E");
1063     assert_eq!(matches.opts_str(&["fruit".to_string()]).unwrap(), "any");
1064 }
1065 
1066 #[test]
test_long_only_mode_no_short_parse()1067 fn test_long_only_mode_no_short_parse() {
1068     let mut opts = Options::new();
1069     opts.long_only(true);
1070     opts.optflag("h", "help", "Description");
1071     opts.optflag("i", "ignore", "Description");
1072     opts.optflag("", "hi", "Description");
1073 
1074     let args = vec!["-hi"];
1075     let matches = &match opts.parse(&args) {
1076         Ok(m) => m,
1077         Err(e) => panic!("{}", e),
1078     };
1079     assert!(matches.opt_present("hi"));
1080     assert!(!matches.opt_present("h"));
1081     assert!(!matches.opt_present("i"));
1082 }
1083 
1084 #[test]
test_normal_mode_no_long_parse()1085 fn test_normal_mode_no_long_parse() {
1086     // Like test_long_only_mode_no_short_parse, but we make sure
1087     // that long_only can be disabled, and the right thing
1088     // happens.
1089     let mut opts = Options::new();
1090     opts.long_only(true);
1091     opts.optflag("h", "help", "Description");
1092     opts.optflag("i", "ignore", "Description");
1093     opts.optflag("", "hi", "Description");
1094     opts.long_only(false);
1095 
1096     let args = vec!["-hi"];
1097     let matches = &match opts.parse(&args) {
1098         Ok(m) => m,
1099         Err(e) => panic!("{}", e),
1100     };
1101     assert!(!matches.opt_present("hi"));
1102     assert!(matches.opt_present("h"));
1103     assert!(matches.opt_present("i"));
1104 }
1105 
1106 #[test]
1107 #[should_panic]
test_long_name_too_short()1108 fn test_long_name_too_short() {
1109     let mut opts = Options::new();
1110     opts.optflag("", "a", "Oops, long option too short");
1111 }
1112 
1113 #[test]
1114 #[should_panic]
test_undefined_opt_present()1115 fn test_undefined_opt_present() {
1116     let mut opts = Options::new();
1117     opts.optflag("h", "help", "Description");
1118     let args = vec!["-h"];
1119     match opts.parse(args) {
1120         Ok(matches) => assert!(!matches.opt_present("undefined")),
1121         Err(e) => panic!("{}", e),
1122     }
1123 }
1124 
1125 #[test]
test_opt_default()1126 fn test_opt_default() {
1127     let mut opts = Options::new();
1128     opts.optflag("h", "help", "Description");
1129     opts.optflag("i", "ignore", "Description");
1130     opts.optflag("r", "run", "Description");
1131     opts.long_only(false);
1132 
1133     let args: Vec<String> = ["-i", "-r", "10"].iter().map(|x| x.to_string()).collect();
1134     let matches = &match opts.parse(&args) {
1135         Ok(m) => m,
1136         Err(e) => panic!("{}", e),
1137     };
1138     assert_eq!(matches.opt_default("help", ""), None);
1139     assert_eq!(matches.opt_default("i", "def"), Some("def".to_string()));
1140 }
1141 
1142 #[test]
test_opt_get()1143 fn test_opt_get() {
1144     let mut opts = Options::new();
1145     opts.optflag("h", "help", "Description");
1146     opts.optflagopt("i", "ignore", "Description", "true | false");
1147     opts.optflagopt("r", "run", "Description", "0 .. 10");
1148     opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0");
1149     opts.long_only(false);
1150 
1151     let args: Vec<String> = ["-i", "true", "-p", "1.1"]
1152         .iter()
1153         .map(|x| x.to_string())
1154         .collect();
1155     let matches = &match opts.parse(&args) {
1156         Ok(m) => m,
1157         Err(e) => panic!("{}", e),
1158     };
1159     let h_arg = matches.opt_get::<i32>("help");
1160     assert_eq!(h_arg, Ok(None));
1161     let i_arg = matches.opt_get("i");
1162     assert_eq!(i_arg, Ok(Some(true)));
1163     let p_arg = matches.opt_get("p");
1164     assert_eq!(p_arg, Ok(Some(1.1)));
1165 }
1166 
1167 #[test]
test_opt_get_default()1168 fn test_opt_get_default() {
1169     let mut opts = Options::new();
1170     opts.optflag("h", "help", "Description");
1171     opts.optflagopt("i", "ignore", "Description", "true | false");
1172     opts.optflagopt("r", "run", "Description", "0 .. 10");
1173     opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0");
1174     opts.long_only(false);
1175 
1176     let args: Vec<String> = ["-i", "true", "-p", "1.1"]
1177         .iter()
1178         .map(|x| x.to_string())
1179         .collect();
1180     let matches = &match opts.parse(&args) {
1181         Ok(m) => m,
1182         Err(e) => panic!("{}", e),
1183     };
1184     let h_arg = matches.opt_get_default("help", 10);
1185     assert_eq!(h_arg, Ok(10));
1186     let i_arg = matches.opt_get_default("i", false);
1187     assert_eq!(i_arg, Ok(true));
1188     let p_arg = matches.opt_get_default("p", 10.2);
1189     assert_eq!(p_arg, Ok(1.1));
1190 }
1191 
1192 #[test]
test_opt_positions()1193 fn test_opt_positions() {
1194     let mut opts = Options::new();
1195     opts.optflagmulti("a", "act", "Description");
1196     opts.optflagmulti("e", "enact", "Description");
1197     opts.optflagmulti("r", "react", "Description");
1198 
1199     let args: Vec<String> = ["-a", "-a", "-r", "-a", "-r", "-r"]
1200         .iter()
1201         .map(|x| x.to_string())
1202         .collect();
1203 
1204     let matches = &match opts.parse(&args) {
1205         Ok(m) => m,
1206         Err(e) => panic!("{}", e),
1207     };
1208 
1209     let a_pos = matches.opt_positions("a");
1210     assert_eq!(a_pos, vec![0, 1, 3]);
1211     let e_pos = matches.opt_positions("e");
1212     assert_eq!(e_pos, vec![]);
1213     let r_pos = matches.opt_positions("r");
1214     assert_eq!(r_pos, vec![2, 4, 5]);
1215 }
1216 
1217 #[test]
test_opt_strs_pos()1218 fn test_opt_strs_pos() {
1219     let mut opts = Options::new();
1220     opts.optmulti("a", "act", "Description", "NUM");
1221     opts.optmulti("e", "enact", "Description", "NUM");
1222     opts.optmulti("r", "react", "Description", "NUM");
1223 
1224     let args: Vec<String> = ["-a1", "-a2", "-r3", "-a4", "-r5", "-r6"]
1225         .iter()
1226         .map(|x| x.to_string())
1227         .collect();
1228 
1229     let matches = &match opts.parse(&args) {
1230         Ok(m) => m,
1231         Err(e) => panic!("{}", e),
1232     };
1233 
1234     let a_pos = matches.opt_strs_pos("a");
1235     assert_eq!(
1236         a_pos,
1237         vec![
1238             (0, "1".to_string()),
1239             (1, "2".to_string()),
1240             (3, "4".to_string())
1241         ]
1242     );
1243     let e_pos = matches.opt_strs_pos("e");
1244     assert_eq!(e_pos, vec![]);
1245     let r_pos = matches.opt_strs_pos("r");
1246     assert_eq!(
1247         r_pos,
1248         vec![
1249             (2, "3".to_string()),
1250             (4, "5".to_string()),
1251             (5, "6".to_string())
1252         ]
1253     );
1254 }
1255