use proptest::prelude::*;
use rstest::rstest;
use super::{
super::date_strategies::{
month_name_strategy,
numeric_day_strategy,
numeric_day_with_range,
ordinal_day_strategy,
ordinal_day_with_range,
year_strategy,
},
MONTH_NAMES,
is_month_name,
is_numeric_day,
is_opening_punct,
is_ordinal_day,
is_year,
};
fn arbitrary_short_string_strategy() -> BoxedStrategy<String> {
prop::collection::vec(any::<char>(), 0..24)
.prop_map(|chars| chars.into_iter().collect::<String>())
.boxed()
}
fn strip_leading_openers(token: &str) -> &str { token.trim_start_matches(is_opening_punct) }
fn ordinal_day_out_of_range_strategy() -> BoxedStrategy<String> {
ordinal_day_with_range(prop_oneof![Just(0u8), (32u8..=u8::MAX)])
}
fn numeric_day_out_of_range_strategy() -> BoxedStrategy<String> {
numeric_day_with_range(prop_oneof![Just(0u8), (32u8..=u8::MAX)])
}
fn year_out_of_range_strategy() -> BoxedStrategy<String> {
prop_oneof![(0u16..=999u16), (3000u16..=u16::MAX)]
.prop_map(|year| year.to_string())
.boxed()
}
#[rstest]
#[case("(July", true)]
#[case("\"December", true)]
#[case("(foo", false)]
fn is_month_name_strips_leading_openers(#[case] token: &str, #[case] expected: bool) {
assert_eq!(is_month_name(token), expected);
}
#[rstest]
#[case("\"25th", true)]
#[case("(1st", true)]
#[case("(0th", false)]
fn is_ordinal_day_strips_leading_openers(#[case] token: &str, #[case] expected: bool) {
assert_eq!(is_ordinal_day(token), expected);
}
#[rstest]
#[case("(4,", true)]
#[case("(19", true)]
#[case("(foo", false)]
fn is_numeric_day_strips_leading_openers(#[case] token: &str, #[case] expected: bool) {
assert_eq!(is_numeric_day(token), expected);
}
proptest! {
#[test]
fn prop_is_month_name_accepts_canonical_names_case_insensitively(
token in month_name_strategy(),
) {
prop_assert!(is_month_name(&token));
}
#[test]
fn prop_is_month_name_rejects_arbitrary_strings(
token in arbitrary_short_string_strategy(),
) {
let normalized = strip_leading_openers(&token);
prop_assume!(!MONTH_NAMES
.iter()
.any(|month| normalized.eq_ignore_ascii_case(month)));
prop_assert!(!is_month_name(&token));
}
#[test]
fn prop_is_ordinal_day_accepts_valid_range(token in ordinal_day_strategy()) {
prop_assert!(is_ordinal_day(&token));
}
#[test]
fn prop_is_ordinal_day_rejects_out_of_range(
token in ordinal_day_out_of_range_strategy(),
) {
prop_assert!(!is_ordinal_day(&token));
}
#[test]
fn prop_is_numeric_day_accepts_valid_range(token in numeric_day_strategy()) {
prop_assert!(is_numeric_day(&token));
}
#[test]
fn prop_is_numeric_day_rejects_out_of_range(
token in numeric_day_out_of_range_strategy(),
) {
prop_assert!(!is_numeric_day(&token));
}
#[test]
fn prop_is_year_accepts_four_digit_range(token in year_strategy()) {
prop_assert!(is_year(&token));
}
#[test]
fn prop_is_year_rejects_out_of_range(token in year_out_of_range_strategy()) {
prop_assert!(!is_year(&token));
}
}