use super::each_split_within; use super::Fail::*; use super::{HasArg, Name, Occur, Opt, Options, ParsingStyle}; #[test] fn test_split_within() { fn t(s: &str, i: usize, u: &[String]) { let v = each_split_within(&(s.to_string()), i); assert!(v.iter().zip(u.iter()).all(|(a, b)| a == b)); } t("", 0, &[]); t("", 15, &[]); t("hello", 15, &["hello".to_string()]); t( "\nMary had a little lamb\nLittle lamb\n", 15, &[ "Mary had a".to_string(), "little lamb".to_string(), "Little lamb".to_string(), ], ); t( "\nMary had a little lamb\nLittle lamb\n", ::std::usize::MAX, &[ "Mary had a little lamb".to_string(), "Little lamb".to_string(), ], ); } // Tests for reqopt #[test] fn test_reqopt() { let long_args = vec!["--test=20".to_string()]; let mut opts = Options::new(); opts.reqopt("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!(m.opt_present("t")); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => { panic!("test_reqopt failed (long arg)"); } } let short_args = vec!["-t".to_string(), "20".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert!((m.opt_present("test"))); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => { panic!("test_reqopt failed (short arg)"); } } } #[test] fn test_reqopt_missing() { let args = vec!["blah".to_string()]; match Options::new() .reqopt("t", "test", "testing", "TEST") .parse(&args) { Err(OptionMissing(_)) => {} _ => panic!(), } } #[test] fn test_reqopt_no_arg() { let long_args = vec!["--test".to_string()]; let mut opts = Options::new(); opts.reqopt("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } let short_args = vec!["-t".to_string()]; match opts.parse(&short_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } } #[test] fn test_reqopt_multi() { let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; match Options::new() .reqopt("t", "test", "testing", "TEST") .parse(&args) { Err(OptionDuplicated(_)) => {} _ => panic!(), } } // Tests for optopt #[test] fn test_optopt() { let long_args = vec!["--test=20".to_string()]; let mut opts = Options::new(); opts.optopt("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => panic!(), } let short_args = vec!["-t".to_string(), "20".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert!((m.opt_present("test"))); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => panic!(), } } #[test] fn test_optopt_missing() { let args = vec!["blah".to_string()]; match Options::new() .optopt("t", "test", "testing", "TEST") .parse(&args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); } _ => panic!(), } } #[test] fn test_optopt_no_arg() { let long_args = vec!["--test".to_string()]; let mut opts = Options::new(); opts.optopt("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } let short_args = vec!["-t".to_string()]; match opts.parse(&short_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } } #[test] fn test_optopt_multi() { let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; match Options::new() .optopt("t", "test", "testing", "TEST") .parse(&args) { Err(OptionDuplicated(_)) => {} _ => panic!(), } } // Tests for optflag #[test] fn test_optflag() { let long_args = vec!["--test".to_string()]; let mut opts = Options::new(); opts.optflag("t", "test", "testing"); match opts.parse(&long_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert!(m.opt_present("t")); } _ => panic!(), } let short_args = vec!["-t".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert!(m.opt_present("t")); } _ => panic!(), } } #[test] fn test_optflag_missing() { let args = vec!["blah".to_string()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); } _ => panic!(), } } #[test] fn test_opt_end() { let args = vec!["--".to_owned(), "-t".to_owned()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); assert_eq!(m.free.len(), 1); assert_eq!(m.free[0], "-t"); } _ => panic!(), } } #[test] fn test_opt_only_end() { let args = vec!["--".to_owned()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); assert_eq!(m.free.len(), 0); } _ => panic!(), } } #[test] fn test_optflag_long_arg() { let args = vec!["--test=20".to_string()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Err(UnexpectedArgument(_)) => {} _ => panic!(), } } #[test] fn test_optflag_multi() { let args = vec!["--test".to_string(), "-t".to_string()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Err(OptionDuplicated(_)) => {} _ => panic!(), } } #[test] fn test_optflag_short_arg() { let args = vec!["-t".to_string(), "20".to_string()]; match Options::new().optflag("t", "test", "testing").parse(&args) { Ok(ref m) => { // The next variable after the flag is just a free argument assert!(m.free[0] == "20"); } _ => panic!(), } } // Tests for optflagmulti #[test] fn test_optflagmulti_short1() { let args = vec!["-v".to_string()]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("v"), 1); } _ => panic!(), } } #[test] fn test_optflagmulti_short2a() { let args = vec!["-v".to_string(), "-v".to_string()]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("v"), 2); } _ => panic!(), } } #[test] fn test_optflagmulti_short2b() { let args = vec!["-vv".to_string()]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("v"), 2); } _ => panic!(), } } #[test] fn test_optflagmulti_long1() { let args = vec!["--verbose".to_string()]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("verbose"), 1); } _ => panic!(), } } #[test] fn test_optflagmulti_long2() { let args = vec!["--verbose".to_string(), "--verbose".to_string()]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("verbose"), 2); } _ => panic!(), } } #[test] fn test_optflagmulti_mix() { let args = vec![ "--verbose".to_string(), "-v".to_string(), "-vv".to_string(), "verbose".to_string(), ]; match Options::new() .optflagmulti("v", "verbose", "verbosity") .parse(&args) { Ok(ref m) => { assert_eq!(m.opt_count("verbose"), 4); assert_eq!(m.opt_count("v"), 4); } _ => panic!(), } } // Tests for optflagopt #[test] fn test_optflagopt() { let long_args = vec!["--test".to_string()]; let mut opts = Options::new(); opts.optflagopt("t", "test", "testing", "ARG"); match opts.parse(&long_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert!(m.opt_present("t")); } _ => panic!(), } let short_args = vec!["-t".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert!(m.opt_present("test")); assert!(m.opt_present("t")); } _ => panic!(), } let short_args = vec!["-t".to_string(), "x".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert_eq!(m.opt_str("t").unwrap(), "x"); assert_eq!(m.opt_str("test").unwrap(), "x"); } _ => panic!(), } let long_args = vec!["--test=x".to_string()]; match opts.parse(&long_args) { Ok(ref m) => { assert_eq!(m.opt_str("t").unwrap(), "x"); assert_eq!(m.opt_str("test").unwrap(), "x"); } _ => panic!(), } let long_args = vec!["--test".to_string(), "x".to_string()]; match opts.parse(&long_args) { Ok(ref m) => { assert_eq!(m.opt_str("t"), None); assert_eq!(m.opt_str("test"), None); } _ => panic!(), } let no_args: Vec = vec![]; match opts.parse(&no_args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); } _ => panic!(), } } // Tests for optmulti #[test] fn test_optmulti() { let long_args = vec!["--test=20".to_string()]; let mut opts = Options::new(); opts.optmulti("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Ok(ref m) => { assert!((m.opt_present("test"))); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => panic!(), } let short_args = vec!["-t".to_string(), "20".to_string()]; match opts.parse(&short_args) { Ok(ref m) => { assert!((m.opt_present("test"))); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!((m.opt_present("t"))); assert_eq!(m.opt_str("t").unwrap(), "20"); } _ => panic!(), } } #[test] fn test_optmulti_missing() { let args = vec!["blah".to_string()]; match Options::new() .optmulti("t", "test", "testing", "TEST") .parse(&args) { Ok(ref m) => { assert!(!m.opt_present("test")); assert!(!m.opt_present("t")); } _ => panic!(), } } #[test] fn test_optmulti_no_arg() { let long_args = vec!["--test".to_string()]; let mut opts = Options::new(); opts.optmulti("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } let short_args = vec!["-t".to_string()]; match opts.parse(&short_args) { Err(ArgumentMissing(_)) => {} _ => panic!(), } } #[test] fn test_optmulti_multi() { let args = vec!["--test=20".to_string(), "-t".to_string(), "30".to_string()]; match Options::new() .optmulti("t", "test", "testing", "TEST") .parse(&args) { Ok(ref m) => { assert!(m.opt_present("test")); assert_eq!(m.opt_str("test").unwrap(), "20"); assert!(m.opt_present("t")); assert_eq!(m.opt_str("t").unwrap(), "20"); let pair = m.opt_strs("test"); assert!(pair[0] == "20"); assert!(pair[1] == "30"); } _ => panic!(), } } #[test] fn test_free_argument_is_hyphen() { let args = vec!["-".to_string()]; match Options::new().parse(&args) { Ok(ref m) => { assert_eq!(m.free.len(), 1); assert_eq!(m.free[0], "-"); } _ => panic!(), } } #[test] fn test_unrecognized_option() { let long_args = vec!["--untest".to_string()]; let mut opts = Options::new(); opts.optmulti("t", "test", "testing", "TEST"); match opts.parse(&long_args) { Err(UnrecognizedOption(_)) => {} _ => panic!(), } let short_args = vec!["-u".to_string()]; match opts.parse(&short_args) { Err(UnrecognizedOption(_)) => {} _ => panic!(), } } #[test] fn test_combined() { let args = vec![ "prog".to_string(), "free1".to_string(), "-s".to_string(), "20".to_string(), "free2".to_string(), "--flag".to_string(), "--long=30".to_string(), "-f".to_string(), "-m".to_string(), "40".to_string(), "-m".to_string(), "50".to_string(), "-n".to_string(), "-A B".to_string(), "-n".to_string(), "-60 70".to_string(), ]; match Options::new() .optopt("s", "something", "something", "SOMETHING") .optflag("", "flag", "a flag") .reqopt("", "long", "hi", "LONG") .optflag("f", "", "another flag") .optmulti("m", "", "mmmmmm", "YUM") .optmulti("n", "", "nothing", "NOTHING") .optopt("", "notpresent", "nothing to see here", "NOPE") .parse(&args) { Ok(ref m) => { assert!(m.free[0] == "prog"); assert!(m.free[1] == "free1"); assert_eq!(m.opt_str("s").unwrap(), "20"); assert!(m.free[2] == "free2"); assert!((m.opt_present("flag"))); assert_eq!(m.opt_str("long").unwrap(), "30"); assert!((m.opt_present("f"))); let pair = m.opt_strs("m"); assert!(pair[0] == "40"); assert!(pair[1] == "50"); let pair = m.opt_strs("n"); assert!(pair[0] == "-A B"); assert!(pair[1] == "-60 70"); assert!((!m.opt_present("notpresent"))); } _ => panic!(), } } #[test] fn test_mixed_stop() { let args = vec![ "-a".to_string(), "b".to_string(), "-c".to_string(), "d".to_string(), ]; match Options::new() .parsing_style(ParsingStyle::StopAtFirstFree) .optflag("a", "", "") .optopt("c", "", "", "") .parse(&args) { Ok(ref m) => { println!("{}", m.opt_present("c")); assert!(m.opt_present("a")); assert!(!m.opt_present("c")); assert_eq!(m.free.len(), 3); assert_eq!(m.free[0], "b"); assert_eq!(m.free[1], "-c"); assert_eq!(m.free[2], "d"); } _ => panic!(), } } #[test] fn test_mixed_stop_hyphen() { let args = vec![ "-a".to_string(), "-".to_string(), "-c".to_string(), "d".to_string(), ]; match Options::new() .parsing_style(ParsingStyle::StopAtFirstFree) .optflag("a", "", "") .optopt("c", "", "", "") .parse(&args) { Ok(ref m) => { println!("{}", m.opt_present("c")); assert!(m.opt_present("a")); assert!(!m.opt_present("c")); assert_eq!(m.free.len(), 3); assert_eq!(m.free[0], "-"); assert_eq!(m.free[1], "-c"); assert_eq!(m.free[2], "d"); } _ => panic!(), } } #[test] fn test_multi() { let mut opts = Options::new(); opts.optopt("e", "", "encrypt", "ENCRYPT"); opts.optopt("", "encrypt", "encrypt", "ENCRYPT"); opts.optopt("f", "", "flag", "FLAG"); let args_single = vec!["-e".to_string(), "foo".to_string()]; let matches_single = &match opts.parse(&args_single) { Ok(m) => m, _ => panic!(), }; assert!(matches_single.opts_present(&["e".to_string()])); assert!(matches_single.opts_present(&["encrypt".to_string(), "e".to_string()])); assert!(matches_single.opts_present(&["e".to_string(), "encrypt".to_string()])); assert!(!matches_single.opts_present(&["encrypt".to_string()])); assert!(!matches_single.opts_present(&["thing".to_string()])); assert!(!matches_single.opts_present(&[])); assert_eq!(matches_single.opts_str(&["e".to_string()]).unwrap(), "foo"); assert_eq!( matches_single .opts_str(&["e".to_string(), "encrypt".to_string()]) .unwrap(), "foo" ); assert_eq!( matches_single .opts_str(&["encrypt".to_string(), "e".to_string()]) .unwrap(), "foo" ); let args_both = vec![ "-e".to_string(), "foo".to_string(), "--encrypt".to_string(), "foo".to_string(), ]; let matches_both = &match opts.parse(&args_both) { Ok(m) => m, _ => panic!(), }; assert!(matches_both.opts_present(&["e".to_string()])); assert!(matches_both.opts_present(&["encrypt".to_string()])); assert!(matches_both.opts_present(&["encrypt".to_string(), "e".to_string()])); assert!(matches_both.opts_present(&["e".to_string(), "encrypt".to_string()])); assert!(!matches_both.opts_present(&["f".to_string()])); assert!(!matches_both.opts_present(&["thing".to_string()])); assert!(!matches_both.opts_present(&[])); assert_eq!(matches_both.opts_str(&["e".to_string()]).unwrap(), "foo"); assert_eq!( matches_both.opts_str(&["encrypt".to_string()]).unwrap(), "foo" ); assert_eq!( matches_both .opts_str(&["e".to_string(), "encrypt".to_string()]) .unwrap(), "foo" ); assert_eq!( matches_both .opts_str(&["encrypt".to_string(), "e".to_string()]) .unwrap(), "foo" ); } #[test] fn test_nospace() { let args = vec!["-Lfoo".to_string(), "-M.".to_string()]; let matches = &match Options::new() .optmulti("L", "", "library directory", "LIB") .optmulti("M", "", "something", "MMMM") .parse(&args) { Ok(m) => m, _ => panic!(), }; assert!(matches.opts_present(&["L".to_string()])); assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "foo"); assert!(matches.opts_present(&["M".to_string()])); assert_eq!(matches.opts_str(&["M".to_string()]).unwrap(), "."); } #[test] fn test_nospace_conflict() { let args = vec!["-vvLverbose".to_string(), "-v".to_string()]; let matches = &match Options::new() .optmulti("L", "", "library directory", "LIB") .optflagmulti("v", "verbose", "Verbose") .parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert!(matches.opts_present(&["L".to_string()])); assert_eq!(matches.opts_str(&["L".to_string()]).unwrap(), "verbose"); assert!(matches.opts_present(&["v".to_string()])); assert_eq!(3, matches.opt_count("v")); } #[test] fn test_long_to_short() { let mut short = Opt { name: Name::Long("banana".to_string()), hasarg: HasArg::Yes, occur: Occur::Req, aliases: Vec::new(), }; short.aliases = vec![Opt { name: Name::Short('b'), hasarg: HasArg::Yes, occur: Occur::Req, aliases: Vec::new(), }]; let mut opts = Options::new(); opts.reqopt("b", "banana", "some bananas", "VAL"); let verbose = &opts.grps[0]; assert!(verbose.long_to_short() == short); } #[test] fn test_aliases_long_and_short() { let args = vec!["-a".to_string(), "--apple".to_string(), "-a".to_string()]; let matches = Options::new() .optflagmulti("a", "apple", "Desc") .parse(&args) .unwrap(); assert_eq!(3, matches.opt_count("a")); assert_eq!(3, matches.opt_count("apple")); } #[test] fn test_usage() { let mut opts = Options::new(); opts.reqopt("b", "banana", "Desc", "VAL"); opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL"); opts.optflag("k", "kiwi", "Desc"); opts.optflagopt("p", "", "Desc", "VAL"); opts.optmulti("l", "", "Desc", "VAL"); opts.optflag("", "starfruit", "Starfruit"); let expected = "Usage: fruits Options: -b, --banana VAL Desc -a, --012345678901234567890123456789 VAL Desc -k, --kiwi Desc -p [VAL] Desc -l VAL Desc --starfruit Starfruit "; let generated_usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", generated_usage); assert_eq!(generated_usage, expected); } #[test] fn test_usage_description_wrapping() { // indentation should be 24 spaces // lines wrap after 78: or rather descriptions wrap after 54 let mut opts = Options::new(); opts.optflag( "k", "kiwi", "This is a long description which won't be wrapped..+..", ); // 54 opts.optflag( "a", "apple", "This is a long description which _will_ be wrapped..+..", ); opts.optflag( "b", "banana", "HereWeNeedOneSingleWordThatIsLongerThanTheWrappingLengthAndThisIsIt", ); let expected = "Usage: fruits Options: -k, --kiwi This is a long description which won't be wrapped..+.. -a, --apple This is a long description which _will_ be wrapped..+.. -b, --banana HereWeNeedOneSingleWordThatIsLongerThanTheWrappingLengthAndThisIsIt "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_usage_description_multibyte_handling() { let mut opts = Options::new(); opts.optflag( "k", "k\u{2013}w\u{2013}", "The word kiwi is normally spelled with two i's", ); opts.optflag( "a", "apple", "This \u{201C}description\u{201D} has some characters that could \ confuse the line wrapping; an apple costs 0.51€ in some parts of Europe.", ); let expected = "Usage: fruits Options: -k, --k–w– The word kiwi is normally spelled with two i's -a, --apple This “description” has some characters that could confuse the line wrapping; an apple costs 0.51€ in some parts of Europe. "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_usage_description_newline_handling() { let mut opts = Options::new(); opts.optflag( "k", "k\u{2013}w\u{2013}", "The word kiwi is normally spelled with two i's", ); opts.optflag( "a", "apple", "This description forces a new line.\n Here is a premature\n\ newline", ); let expected = "Usage: fruits Options: -k, --k–w– The word kiwi is normally spelled with two i's -a, --apple This description forces a new line. Here is a premature newline "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_usage_multiwidth() { let mut opts = Options::new(); opts.optflag("a", "apple", "apple description"); opts.optflag("b", "banana\u{00AB}", "banana description"); opts.optflag("c", "brûlée", "brûlée quite long description"); opts.optflag("k", "kiwi\u{20AC}", "kiwi description"); opts.optflag("o", "orange\u{2039}", "orange description"); opts.optflag( "r", "raspberry-but-making-this-option-way-too-long", "raspberry description is also quite long indeed longer than \ every other piece of text we might encounter here and thus will \ be automatically broken up", ); let expected = "Usage: fruits Options: -a, --apple apple description -b, --banana« banana description -c, --brûlée brûlée quite long description -k, --kiwi€ kiwi description -o, --orange‹ orange description -r, --raspberry-but-making-this-option-way-too-long\u{0020} raspberry description is also quite long indeed longer than every other piece of text we might encounter here and thus will be automatically broken up "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_usage_short_only() { let mut opts = Options::new(); opts.optopt("k", "", "Kiwi", "VAL"); opts.optflag("s", "", "Starfruit"); opts.optflagopt("a", "", "Apple", "TYPE"); let expected = "Usage: fruits Options: -k VAL Kiwi -s Starfruit -a [TYPE] Apple "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_usage_long_only() { let mut opts = Options::new(); opts.optopt("", "kiwi", "Kiwi", "VAL"); opts.optflag("", "starfruit", "Starfruit"); opts.optflagopt("", "apple", "Apple", "TYPE"); let expected = "Usage: fruits Options: --kiwi VAL Kiwi --starfruit Starfruit --apple [TYPE] Apple "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_short_usage() { let mut opts = Options::new(); opts.reqopt("b", "banana", "Desc", "VAL"); opts.optopt("a", "012345678901234567890123456789", "Desc", "VAL"); opts.optflag("k", "kiwi", "Desc"); opts.optflagopt("p", "", "Desc", "VAL"); opts.optmulti("l", "", "Desc", "VAL"); let expected = "Usage: fruits -b VAL [-a VAL] [-k] [-p [VAL]] [-l VAL]..".to_string(); let generated_usage = opts.short_usage("fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", generated_usage); assert_eq!(generated_usage, expected); } #[test] fn test_nonexistant_opt() { let mut opts = Options::new(); opts.optflag("b", "bar", "Desc"); let args: Vec = Vec::new(); let matches = opts.parse(&args).unwrap(); assert_eq!(matches.opt_defined("foo"), false); assert_eq!(matches.opt_defined("bar"), true); } #[test] fn test_args_with_equals() { let mut opts = Options::new(); opts.optopt("o", "one", "One", "INFO"); opts.optopt("t", "two", "Two", "INFO"); let args = vec![ "--one".to_string(), "A=B".to_string(), "--two=C=D".to_string(), ]; let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert_eq!(matches.opts_str(&["o".to_string()]).unwrap(), "A=B"); assert_eq!(matches.opts_str(&["t".to_string()]).unwrap(), "C=D"); } #[test] fn test_long_only_usage() { let mut opts = Options::new(); opts.long_only(true); opts.optflag("k", "kiwi", "Description"); opts.optflag("a", "apple", "Description"); let expected = "Usage: fruits Options: -k, -kiwi Description -a, -apple Description "; let usage = opts.usage("Usage: fruits"); debug!("expected: <<{}>>", expected); debug!("generated: <<{}>>", usage); assert!(usage == expected) } #[test] fn test_long_only_mode() { let mut opts = Options::new(); opts.long_only(true); opts.optopt("a", "apple", "Description", "X"); opts.optopt("b", "banana", "Description", "X"); opts.optopt("c", "currant", "Description", "X"); opts.optopt("", "durian", "Description", "X"); opts.optopt("e", "", "Description", "X"); opts.optopt("", "fruit", "Description", "X"); let args = vec![ "-a", "A", "-b=B", "--c=C", "-durian", "D", "--e", "E", "-fruit=any", ]; let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert_eq!(matches.opts_str(&["a".to_string()]).unwrap(), "A"); assert_eq!(matches.opts_str(&["b".to_string()]).unwrap(), "B"); assert_eq!(matches.opts_str(&["c".to_string()]).unwrap(), "C"); assert_eq!(matches.opts_str(&["durian".to_string()]).unwrap(), "D"); assert_eq!(matches.opts_str(&["e".to_string()]).unwrap(), "E"); assert_eq!(matches.opts_str(&["fruit".to_string()]).unwrap(), "any"); } #[test] fn test_long_only_mode_no_short_parse() { let mut opts = Options::new(); opts.long_only(true); opts.optflag("h", "help", "Description"); opts.optflag("i", "ignore", "Description"); opts.optflag("", "hi", "Description"); let args = vec!["-hi"]; let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert!(matches.opt_present("hi")); assert!(!matches.opt_present("h")); assert!(!matches.opt_present("i")); } #[test] fn test_normal_mode_no_long_parse() { // Like test_long_only_mode_no_short_parse, but we make sure // that long_only can be disabled, and the right thing // happens. let mut opts = Options::new(); opts.long_only(true); opts.optflag("h", "help", "Description"); opts.optflag("i", "ignore", "Description"); opts.optflag("", "hi", "Description"); opts.long_only(false); let args = vec!["-hi"]; let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert!(!matches.opt_present("hi")); assert!(matches.opt_present("h")); assert!(matches.opt_present("i")); } #[test] #[should_panic] fn test_long_name_too_short() { let mut opts = Options::new(); opts.optflag("", "a", "Oops, long option too short"); } #[test] #[should_panic] fn test_undefined_opt_present() { let mut opts = Options::new(); opts.optflag("h", "help", "Description"); let args = vec!["-h"]; match opts.parse(args) { Ok(matches) => assert!(!matches.opt_present("undefined")), Err(e) => panic!("{}", e), } } #[test] fn test_opt_default() { let mut opts = Options::new(); opts.optflag("h", "help", "Description"); opts.optflag("i", "ignore", "Description"); opts.optflag("r", "run", "Description"); opts.long_only(false); let args: Vec = ["-i", "-r", "10"].iter().map(|x| x.to_string()).collect(); let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; assert_eq!(matches.opt_default("help", ""), None); assert_eq!(matches.opt_default("i", "def"), Some("def".to_string())); } #[test] fn test_opt_get() { let mut opts = Options::new(); opts.optflag("h", "help", "Description"); opts.optflagopt("i", "ignore", "Description", "true | false"); opts.optflagopt("r", "run", "Description", "0 .. 10"); opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0"); opts.long_only(false); let args: Vec = ["-i", "true", "-p", "1.1"] .iter() .map(|x| x.to_string()) .collect(); let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; let h_arg = matches.opt_get::("help"); assert_eq!(h_arg, Ok(None)); let i_arg = matches.opt_get("i"); assert_eq!(i_arg, Ok(Some(true))); let p_arg = matches.opt_get("p"); assert_eq!(p_arg, Ok(Some(1.1))); } #[test] fn test_opt_get_default() { let mut opts = Options::new(); opts.optflag("h", "help", "Description"); opts.optflagopt("i", "ignore", "Description", "true | false"); opts.optflagopt("r", "run", "Description", "0 .. 10"); opts.optflagopt("p", "percent", "Description", "0.0 .. 10.0"); opts.long_only(false); let args: Vec = ["-i", "true", "-p", "1.1"] .iter() .map(|x| x.to_string()) .collect(); let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; let h_arg = matches.opt_get_default("help", 10); assert_eq!(h_arg, Ok(10)); let i_arg = matches.opt_get_default("i", false); assert_eq!(i_arg, Ok(true)); let p_arg = matches.opt_get_default("p", 10.2); assert_eq!(p_arg, Ok(1.1)); } #[test] fn test_opt_positions() { let mut opts = Options::new(); opts.optflagmulti("a", "act", "Description"); opts.optflagmulti("e", "enact", "Description"); opts.optflagmulti("r", "react", "Description"); let args: Vec = ["-a", "-a", "-r", "-a", "-r", "-r"] .iter() .map(|x| x.to_string()) .collect(); let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; let a_pos = matches.opt_positions("a"); assert_eq!(a_pos, vec![0, 1, 3]); let e_pos = matches.opt_positions("e"); assert_eq!(e_pos, vec![]); let r_pos = matches.opt_positions("r"); assert_eq!(r_pos, vec![2, 4, 5]); } #[test] fn test_opt_strs_pos() { let mut opts = Options::new(); opts.optmulti("a", "act", "Description", "NUM"); opts.optmulti("e", "enact", "Description", "NUM"); opts.optmulti("r", "react", "Description", "NUM"); let args: Vec = ["-a1", "-a2", "-r3", "-a4", "-r5", "-r6"] .iter() .map(|x| x.to_string()) .collect(); let matches = &match opts.parse(&args) { Ok(m) => m, Err(e) => panic!("{}", e), }; let a_pos = matches.opt_strs_pos("a"); assert_eq!( a_pos, vec![ (0, "1".to_string()), (1, "2".to_string()), (3, "4".to_string()) ] ); let e_pos = matches.opt_strs_pos("e"); assert_eq!(e_pos, vec![]); let r_pos = matches.opt_strs_pos("r"); assert_eq!( r_pos, vec![ (2, "3".to_string()), (4, "5".to_string()), (5, "6".to_string()) ] ); }