mod common;
use std::time::{Duration, Instant};
use common::load_vectors;
use sse_parse::SseParser;
fn bytes_scanned_for(chunks: &[Vec<u8>]) -> (u64, usize) {
let mut parser = SseParser::new();
let mut total = 0usize;
let mut events = 0usize;
for chunk in chunks {
parser.feed(chunk);
total += chunk.len();
while parser.next_event().is_some() {
events += 1;
}
}
parser.finish();
while parser.next_event().is_some() {
events += 1;
}
let _ = events;
(parser.stats().bytes_scanned, total)
}
#[test]
fn d1_g02_huge_line_one_byte_chunks_scans_each_byte_at_most_twice() {
let vectors = load_vectors();
let g02 = vectors
.iter()
.find(|v| v.id.starts_with("g02"))
.expect("g02 present");
assert!(g02.chunks.iter().all(|c| c.len() == 1));
let (scanned, total) = bytes_scanned_for(&g02.chunks);
assert_eq!(total, 6 + 65536 + 2);
assert!(
scanned <= 2 * total as u64 + 64,
"g02: scanned {scanned} bytes for {total} input bytes"
);
}
#[test]
fn d1_g01_many_events_one_byte_chunks_scans_each_byte_at_most_twice() {
let vectors = load_vectors();
let g01 = vectors
.iter()
.find(|v| v.id.starts_with("g01"))
.expect("g01 present");
let (scanned, total) = bytes_scanned_for(&g01.chunks);
assert_eq!(total, 20 * 2000);
assert!(
scanned <= 2 * total as u64 + 64,
"g01: scanned {scanned} bytes for {total} input bytes"
);
}
#[test]
fn d1_scan_counter_is_linear_for_every_vector() {
for v in load_vectors() {
let (scanned, total) = bytes_scanned_for(&v.chunks);
assert!(
scanned <= 2 * total as u64 + 64,
"{}: scanned {scanned} for {total}",
v.id
);
}
}
fn long_line_stream(fill: usize) -> Vec<u8> {
let mut s = Vec::with_capacity(fill + 16);
s.extend_from_slice(b"data: ");
s.resize(s.len() + fill, b'a');
s.extend_from_slice(b"\n\n");
s
}
fn min_time_one_byte_chunks(bytes: &[u8], runs: usize) -> Duration {
let mut best = Duration::MAX;
for _ in 0..runs {
let start = Instant::now();
let mut parser = SseParser::new();
for b in bytes {
parser.feed(std::slice::from_ref(b));
}
parser.finish();
let ev = parser.next_event().expect("one event");
assert_eq!(ev.data.len(), bytes.len() - 8);
best = best.min(start.elapsed());
}
best
}
#[test]
fn d1_wall_clock_growth_is_sub_quadratic() {
let small = long_line_stream(16 * 1024);
let large = long_line_stream(64 * 1024);
let _ = min_time_one_byte_chunks(&small, 1);
let t_small = min_time_one_byte_chunks(&small, 7);
let t_large = min_time_one_byte_chunks(&large, 7);
let ratio = t_large.as_secs_f64() / t_small.as_secs_f64().max(1e-9);
assert!(
ratio < 8.0,
"T(64 KiB) / T(16 KiB) = {ratio:.2} ({t_large:?} / {t_small:?}); quadratic would be about 16"
);
}