mod common;
use common::{csid_strategy, keycard_strategy};
use mk_codec::{decode, encode_with_chunk_set_id};
use proptest::prelude::*;
proptest! {
#[test]
fn keycard_roundtrip(card in keycard_strategy(), csid in csid_strategy()) {
let strings = encode_with_chunk_set_id(&card, csid)
.expect("strategy produces only encodable cards");
let parts: Vec<&str> = strings.iter().map(String::as_str).collect();
let recovered = decode(&parts).expect("a freshly-encoded card must decode");
prop_assert_eq!(recovered, card);
}
#[test]
fn decode_never_panics_on_arbitrary_string(s in "\\PC*") {
let _ = decode(&[s.as_str()]); }
#[test]
fn decode_never_panics_on_arbitrary_string_list(
v in prop::collection::vec("\\PC*", 0..6usize)
) {
let parts: Vec<&str> = v.iter().map(String::as_str).collect();
let _ = decode(&parts); }
#[test]
fn decode_never_panics_on_corrupted_encoding(
card in keycard_strategy(),
csid in csid_strategy(),
n_flips in 0usize..30usize,
seed in any::<u64>(),
) {
let strings = encode_with_chunk_set_id(&card, csid).unwrap();
let mut s: Vec<char> = strings[0].chars().collect();
let mut x = seed | 1;
for _ in 0..n_flips.min(s.len().saturating_sub(3)) {
x ^= x << 13; x ^= x >> 7; x ^= x << 17; let idx = 3 + (x as usize % s.len().saturating_sub(3).max(1));
s[idx] = if s[idx] == 'q' { 'p' } else { 'q' };
}
let corrupted: String = s.into_iter().collect();
let mut parts_owned = strings.clone();
parts_owned[0] = corrupted;
let parts: Vec<&str> = parts_owned.iter().map(String::as_str).collect();
let _ = decode(&parts); }
}