#![allow(clippy::expect_used)]
use proptest::prelude::*;
use prikk_object::{ObjectEnvelope, ObjectType, Signature, SignatureAlgorithm, SignerRole};
use super::super::{WalRecord, decode_records, encode_record_for_test};
fn key_id_strategy() -> impl Strategy<Value = String> {
"[a-zA-Z0-9_-]{1,8}"
}
fn signature_strategy() -> impl Strategy<Value = Signature> {
(
key_id_strategy(),
proptest::collection::vec(any::<u8>(), 1..64),
any::<u64>(),
)
.prop_map(|(key_id, signature_bytes, created_at)| Signature {
algorithm: SignatureAlgorithm::Ed25519,
key_id,
signature_bytes,
created_at,
signer_role: SignerRole::Author,
})
}
fn envelope_strategy() -> impl Strategy<Value = ObjectEnvelope> {
(
proptest::collection::vec(any::<u8>(), 0..128),
proptest::collection::vec(signature_strategy(), 0..2),
)
.prop_map(|(canonical_payload, signatures)| ObjectEnvelope {
object_type: ObjectType::Patch,
schema_version: 1,
canonical_payload,
signatures,
})
}
fn records_strategy() -> impl Strategy<Value = Vec<WalRecord>> {
proptest::collection::vec(envelope_strategy(), 1..4).prop_map(|envelopes| {
envelopes
.into_iter()
.enumerate()
.map(|(index, envelope)| WalRecord {
seq: (index as u64) + 1,
envelope,
})
.collect()
})
}
proptest! {
#[test]
fn wal_records_round_trip_with_optional_trailing_partial(
records in records_strategy(),
trailing_partial_len in 0_usize..58
) {
let mut bytes = Vec::new();
for record in &records {
let encoded = encode_record_for_test(record)
.expect("generation invariants keep the envelope structurally valid");
bytes.extend_from_slice(&encoded);
}
bytes.extend(vec![0xAB_u8; trailing_partial_len]);
let replay = decode_records(&bytes).expect("valid records plus a short suffix must decode");
prop_assert_eq!(&replay.records, &records);
prop_assert_eq!(replay.trailing_partial_bytes, trailing_partial_len);
}
#[test]
fn decode_records_never_panics_on_arbitrary_bytes(
bytes in proptest::collection::vec(any::<u8>(), 0..512)
) {
let _ = decode_records(&bytes);
}
}