mod common;
use common::*;
use nanoargs::{ArgBuilder, Flag, FlagDef, Opt, OptionDef, Pos, PositionalDef};
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop1_flag_new_constructor_produces_correct_flag_def(
long in arb_identifier(),
desc in prop::option::of(arb_description()),
) {
let flag = if let Some(ref d) = desc {
Flag::new(&long).desc(d)
} else {
Flag::new(&long)
};
let parser = ArgBuilder::new().flag(flag).build().unwrap();
let flags = parser.flags();
prop_assert_eq!(flags.len(), 1);
let expected = FlagDef {
long: long.clone(),
short: None,
description: desc.unwrap_or_default(),
hidden: false,
};
prop_assert_eq!(&flags[0], &expected);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop2_opt_new_constructor_produces_correct_option_def(
long in arb_identifier(),
placeholder in prop::option::of(arb_identifier()),
desc in prop::option::of(arb_description()),
) {
let mut opt = Opt::new(&long);
if let Some(ref ph) = placeholder {
opt = opt.placeholder(ph);
}
if let Some(ref d) = desc {
opt = opt.desc(d);
}
let parser = ArgBuilder::new().option(opt).build().unwrap();
let opts = parser.options();
prop_assert_eq!(opts.len(), 1);
let expected = OptionDef {
long: long.clone(),
short: None,
placeholder: placeholder.unwrap_or_else(|| long.to_uppercase()),
description: desc.unwrap_or_default(),
required: false,
default: None,
env_var: None,
multi: false,
hidden: false,
validator: None,
};
prop_assert_eq!(&opts[0], &expected);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop3_pos_new_constructor_produces_correct_positional_def(
name in arb_identifier(),
desc in prop::option::of(arb_description()),
) {
let pos = if let Some(ref d) = desc {
Pos::new(&name).desc(d)
} else {
Pos::new(&name)
};
let parser = ArgBuilder::new().positional(pos).build().unwrap();
let positionals = parser.positionals();
prop_assert_eq!(positionals.len(), 1);
let expected = PositionalDef {
name: name.clone(),
description: desc.unwrap_or_default(),
required: false,
default: None,
multi: false,
validator: None,
};
prop_assert_eq!(&positionals[0], &expected);
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop4_flag_modifier_order_independence(
long in arb_identifier(),
short in arb_short(),
desc in arb_description(),
hidden in any::<bool>(),
) {
let apply = |order: [usize; 3]| -> FlagDef {
let mut f = Flag::new(&long);
for &i in &order {
match i {
0 => { if let Some(ch) = short { f = f.short(ch); } }
1 => { if hidden { f = f.hidden(); } }
2 => { f = f.desc(&desc); }
_ => unreachable!(),
}
}
FlagDef::from(f)
};
let permutations: [[usize; 3]; 6] = [
[0, 1, 2], [0, 2, 1], [1, 0, 2],
[1, 2, 0], [2, 0, 1], [2, 1, 0],
];
let baseline = apply(permutations[0]);
for perm in &permutations[1..] {
prop_assert_eq!(&baseline, &apply(*perm));
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop5_opt_modifier_order_independence(
long in arb_identifier(),
short in arb_short(),
desc in arb_description(),
placeholder in arb_identifier(),
required in any::<bool>(),
default in prop::option::of(arb_identifier()),
env_var in prop::option::of(arb_env_var_name()),
multi in any::<bool>(),
hidden in any::<bool>(),
) {
let apply = |order: &[usize]| -> OptionDef {
let mut o = Opt::new(&long);
for &i in order {
match i {
0 => { if let Some(ch) = short { o = o.short(ch); } }
1 => { o = o.desc(&desc); }
2 => { o = o.placeholder(&placeholder); }
3 => { if required { o = o.required(); } }
4 => { if let Some(ref d) = default { o = o.default(d); } }
5 => { if let Some(ref e) = env_var { o = o.env(e); } }
6 => { if multi { o = o.multi(); } }
7 => { if hidden { o = o.hidden(); } }
_ => unreachable!(),
}
}
OptionDef::from(o)
};
let orderings: &[&[usize]] = &[
&[0, 1, 2, 3, 4, 5, 6, 7],
&[7, 6, 5, 4, 3, 2, 1, 0],
&[3, 7, 1, 5, 0, 2, 6, 4],
&[6, 4, 2, 0, 7, 5, 3, 1],
&[1, 0, 3, 2, 5, 4, 7, 6],
&[5, 3, 7, 1, 4, 6, 0, 2],
];
let baseline = apply(orderings[0]);
for ordering in &orderings[1..] {
prop_assert_eq!(&baseline, &apply(ordering));
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop6_pos_modifier_order_independence(
name in arb_identifier(),
desc in arb_description(),
required in any::<bool>(),
) {
let apply = |order: [usize; 2]| -> PositionalDef {
let mut p = Pos::new(&name);
for &i in &order {
match i {
0 => { p = p.desc(&desc); }
1 => { if required { p = p.required(); } }
_ => unreachable!(),
}
}
PositionalDef::from(p)
};
let perm_a = apply([0, 1]);
let perm_b = apply([1, 0]);
prop_assert_eq!(&perm_a, &perm_b);
}
}