use logdb::LogDb;
use logdb::config::{Config, DurabilityMode};
use logdb::storage::format::{SEGMENT_HEADER_SIZE, SegmentHeader, deserialize_record};
use proptest::prelude::*;
use std::time::Duration;
proptest! {
#[test]
fn deserialize_record_never_panics(data in any::<Vec<u8>>()) {
let _ = deserialize_record(&data);
}
}
proptest! {
#[test]
fn segment_header_never_panics(data in any::<[u8; SEGMENT_HEADER_SIZE]>()) {
let _ = SegmentHeader::deserialize(&data);
}
}
proptest! {
#[test]
fn append_flush_read_roundtrip(content in any::<Vec<u8>>()) {
let dir = tempfile::tempdir().unwrap();
let mut config = Config::default();
config.data_dir = dir.path().to_path_buf();
config.ring_size = 64;
config.durability_mode = DurabilityMode::Sync;
config.flush_timeout = Duration::from_secs(5);
config.max_content_size = 1024 * 1024;
let db = LogDb::open(config).unwrap();
let content: &[u8] = if content.len() > 1024 { &content[..1024] } else { &content };
let id = match db.append(content) {
Ok(id) => id,
Err(_) => return Ok(()),
};
db.flush().ok();
std::thread::sleep(Duration::from_millis(20));
if let Ok(Some(record)) = db.read(id) {
prop_assert_eq!(&record.content, &content,
"roundtrip mismatch: seq={}", id);
}
}
}
proptest! {
#[test]
fn many_rapid_appends_no_panic(
sizes in proptest::collection::vec(0usize..1024, 0..500)
) {
let dir = tempfile::tempdir().unwrap();
let mut config = Config::default();
config.data_dir = dir.path().to_path_buf();
config.ring_size = 1024;
config.durability_mode = DurabilityMode::Async;
config.flush_timeout = Duration::from_secs(5);
let db = LogDb::open(config).unwrap();
for &size in &sizes {
let content = vec![0x42u8; size];
let _ = db.append(&content);
}
}
}