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