use csaf_core::update_cli::{UpdateFlags, extract_update_flags};
use proptest::prelude::*;
const KNOWN: [&str; 3] = ["--check-update", "--self-update", "--no-self-update"];
proptest! {
#[test]
fn prop_never_panics_on_arbitrary_arguments(args in prop::collection::vec(".*", 0..12)) {
let _ = extract_update_flags(args);
}
#[test]
fn prop_partition_is_exact(args in prop::collection::vec("[-a-zA-Z0-9=._/]{0,24}", 0..12)) {
let (_, rest) = extract_update_flags(args.clone());
for r in &rest {
prop_assert!(
!KNOWN.contains(&r.as_str()),
"recognised flag {r:?} leaked into the leftover arguments",
);
}
let expected_rest: Vec<&String> =
args.iter().filter(|a| !KNOWN.contains(&a.as_str())).collect();
prop_assert_eq!(rest.len(), expected_rest.len(), "an argument was lost or duplicated");
for (got, want) in rest.iter().zip(expected_rest) {
prop_assert_eq!(got, want, "leftover order was not preserved");
}
}
#[test]
fn prop_flag_set_iff_present(args in prop::collection::vec("[-a-zA-Z0-9=._/]{0,24}", 0..12)) {
let (flags, _) = extract_update_flags(args.clone());
let has = |f: &str| args.iter().any(|a| a == f);
prop_assert_eq!(flags.check_update, has("--check-update"));
prop_assert_eq!(flags.self_update, has("--self-update"));
prop_assert_eq!(flags.no_self_update, has("--no-self-update"));
}
#[test]
fn prop_flags_are_order_independent(
args in prop::collection::vec("[-a-zA-Z0-9=._/]{0,24}", 0..10),
) {
let (forward, _) = extract_update_flags(args.clone());
let reversed: Vec<String> = args.into_iter().rev().collect();
let (backward, _) = extract_update_flags(reversed);
prop_assert_eq!(forward, backward);
}
#[test]
fn prop_reparsing_leftovers_is_a_no_op(
args in prop::collection::vec("[-a-zA-Z0-9=._/]{0,24}", 0..12),
) {
let (_, rest) = extract_update_flags(args);
let (second_flags, second_rest) = extract_update_flags(rest.clone());
prop_assert_eq!(second_flags, UpdateFlags::default());
prop_assert_eq!(second_rest, rest);
}
#[test]
fn prop_is_terminal_ignores_the_policy_flag(
check in any::<bool>(),
update in any::<bool>(),
no_update in any::<bool>(),
) {
let flags = UpdateFlags {
check_update: check,
self_update: update,
no_self_update: no_update,
};
prop_assert_eq!(flags.is_terminal(), check || update);
}
#[test]
fn prop_opt_out_is_monotone(flag in any::<bool>(), env in any::<bool>()) {
let base = UpdateFlags::default().is_opted_out_with(false);
prop_assert!(!base, "with nothing set, self-update must be allowed");
let flags = UpdateFlags { no_self_update: flag, ..UpdateFlags::default() };
prop_assert_eq!(flags.is_opted_out_with(env), flag || env);
}
}