blob: f1fb390987a422ecaf795813a4877c93305a6d80 [file] [log] [blame]
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<String> = 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, --kw 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, --kw 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<String> = 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<String> = ["-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<String> = ["-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::<i32>("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<String> = ["-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<String> = ["-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<String> = ["-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())
]
);
}