use proptest::prelude::*;
use ferray_strings::align::center;
use ferray_strings::array;
use ferray_strings::case::{lower, upper};
use ferray_strings::concat::{add, multiply};
use ferray_strings::search::{count, endswith, find, replace, startswith};
use ferray_strings::split_join::join;
use ferray_strings::strip::strip;
fn config() -> ProptestConfig {
ProptestConfig::with_cases(256)
}
proptest! {
#![proptest_config(config())]
#[test]
fn prop_upper_idempotent(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let once = upper(&a).unwrap();
let twice = upper(&once).unwrap();
prop_assert_eq!(once, twice);
}
#[test]
fn prop_lower_idempotent(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let once = lower(&a).unwrap();
let twice = lower(&once).unwrap();
prop_assert_eq!(once, twice);
}
#[test]
fn prop_upper_lower_roundtrip(
s1 in "[a-zA-Z]{1,10}",
s2 in "[a-zA-Z]{1,10}",
s3 in "[a-zA-Z]{1,10}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let via_upper = lower(&upper(&a).unwrap()).unwrap();
let direct = lower(&a).unwrap();
prop_assert_eq!(via_upper, direct);
}
#[test]
fn prop_strip_idempotent(
s1 in "[a-z ]{1,10}",
s2 in "[a-z ]{1,10}",
s3 in "[a-z ]{1,10}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let once = strip(&a, None).unwrap();
let twice = strip(&once, None).unwrap();
prop_assert_eq!(once, twice);
}
#[test]
fn prop_split_join_roundtrip(
s1 in "[a-z]{1,5}",
s2 in "[a-z]{1,5}",
s3 in "[a-z]{1,5}",
) {
let sep = "|";
let a = array(&[&s1, &s2, &s3]).unwrap();
let parts = ferray_strings::split_ragged(&a, sep).unwrap();
let rejoined = join(sep, &parts).unwrap();
prop_assert_eq!(a.as_slice(), rejoined.as_slice());
}
#[test]
fn prop_multiply_length(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
n in 0usize..10,
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let result = multiply(&a, n).unwrap();
for (original, repeated) in a.as_slice().iter().zip(result.as_slice().iter()) {
prop_assert_eq!(repeated.len(), original.len() * n);
}
}
#[test]
fn prop_find_not_found(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
) {
let needle = "999";
let a = array(&[&s1, &s2, &s3]).unwrap();
let result = find(&a, needle).unwrap();
let data = result.as_slice().unwrap();
for &val in data {
prop_assert_eq!(val, -1_i64);
}
}
#[test]
fn prop_count_nonnegative(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
needle in "[a-z]{1,3}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let result = count(&a, &needle).unwrap();
let data = result.as_slice().unwrap();
for &val in data {
prop_assert!(val <= s1.len() as i64 || val <= s2.len() as i64 || val <= s3.len() as i64
|| val == 0);
}
}
#[test]
fn prop_startswith_after_add(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
prefix in "[A-Z]{1,5}",
) {
let base = array(&[&s1, &s2, &s3]).unwrap();
let pfx = array(&[&*prefix]).unwrap();
let prepended = add(&pfx, &base).unwrap();
let result = startswith(&prepended, &prefix).unwrap();
let data = result.as_slice().unwrap();
for &val in data {
prop_assert!(val, "Expected startswith to be true after prepending prefix");
}
}
#[test]
fn prop_endswith_after_add(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
suffix in "[A-Z]{1,5}",
) {
let base = array(&[&s1, &s2, &s3]).unwrap();
let sfx = array(&[&*suffix]).unwrap();
let appended = add(&base, &sfx).unwrap();
let result = endswith(&appended, &suffix).unwrap();
let data = result.as_slice().unwrap();
for &val in data {
prop_assert!(val, "Expected endswith to be true after appending suffix");
}
}
#[test]
fn prop_center_preserves_content(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
extra_width in 0usize..20,
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let max_len = a.as_slice().iter().map(std::string::String::len).max().unwrap_or(0);
let width = max_len + extra_width;
let centered = center(&a, width, ' ').unwrap();
let stripped = strip(¢ered, None).unwrap();
prop_assert_eq!(a.as_slice(), stripped.as_slice());
}
#[test]
fn prop_replace_removes_all(
s1 in "[a-z]{1,10}",
s2 in "[a-z]{1,10}",
s3 in "[a-z]{1,10}",
sub in "[a-z]{1,3}",
) {
let a = array(&[&s1, &s2, &s3]).unwrap();
let replaced = replace(&a, &sub, "", None).unwrap();
let result = count(&replaced, &sub).unwrap();
let data = result.as_slice().unwrap();
for &val in data {
prop_assert_eq!(val, 0_i64, "Expected count to be 0 after replacing all occurrences");
}
}
}