mod common;
use common::{load_vectors, run_parser, run_parser_whole, split_at_points, split_by_sizes};
use proptest::prelude::*;
#[test]
fn every_two_split_of_short_vectors_matches_single_chunk() {
for v in load_vectors().iter().filter(|v| !v.is_generator) {
let bytes = v.stream_bytes();
if bytes.len() >= 64 {
continue;
}
let whole = run_parser_whole(&bytes);
assert_eq!(whole.events, v.events, "{}", v.id);
for cut in 0..=bytes.len() {
let got = run_parser(&split_at_points(&bytes, &[cut]));
assert_eq!(got, whole, "{}: split at {cut}", v.id);
}
}
}
#[test]
fn every_three_split_of_short_vectors_matches_single_chunk() {
for v in load_vectors().iter().filter(|v| !v.is_generator) {
let bytes = v.stream_bytes();
if bytes.len() >= 40 {
continue;
}
let whole = run_parser_whole(&bytes);
for a in 0..=bytes.len() {
for b in a..=bytes.len() {
let got = run_parser(&split_at_points(&bytes, &[a, b]));
assert_eq!(got, whole, "{}: split at {a},{b}", v.id);
}
}
}
}
#[test]
fn generator_vectors_match_under_other_chunkings() {
for v in load_vectors().iter().filter(|v| v.is_generator) {
let bytes = v.stream_bytes();
let whole = run_parser_whole(&bytes);
assert_eq!(whole.events, v.events, "{}", v.id);
for sizes in [&[1usize][..], &[7, 3, 1], &[4096], &[13, 1, 1, 1000]] {
let got = run_parser(&split_by_sizes(&bytes, sizes));
assert_eq!(got, whole, "{}: sizes {sizes:?}", v.id);
}
}
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(2000))]
#[test]
fn arbitrary_bytes_are_chunking_invariant(
bytes in prop::collection::vec(any::<u8>(), 0..256),
sizes in prop::collection::vec(1usize..24, 1..32),
) {
let whole = run_parser_whole(&bytes);
let got = run_parser(&split_by_sizes(&bytes, &sizes));
prop_assert_eq!(got, whole);
}
#[test]
fn sse_shaped_bytes_are_chunking_invariant(
bytes in prop::collection::vec(sse_byte(), 0..300),
sizes in prop::collection::vec(1usize..12, 1..40),
) {
let whole = run_parser_whole(&bytes);
let got = run_parser(&split_by_sizes(&bytes, &sizes));
prop_assert_eq!(got, whole);
}
#[test]
fn conformance_streams_are_chunking_invariant(
index in 0usize..36,
sizes in prop::collection::vec(1usize..40, 1..40),
) {
let vectors = load_vectors();
let v = &vectors[index];
let bytes = v.stream_bytes();
let whole = run_parser_whole(&bytes);
prop_assert_eq!(&whole.events, &v.events);
let got = run_parser(&split_by_sizes(&bytes, &sizes));
prop_assert_eq!(got, whole);
}
}
fn sse_byte() -> impl Strategy<Value = u8> {
prop_oneof![
8 => Just(b'\n'),
4 => Just(b'\r'),
4 => Just(b':'),
3 => Just(b' '),
2 => Just(0xEF),
1 => Just(0xBB),
1 => Just(0xBF),
1 => Just(0x00),
1 => Just(0xFF),
1 => Just(0xC3),
6 => prop::sample::select(&b"dataeventidretry0123456789"[..]),
3 => any::<u8>(),
]
}