#![allow(clippy::unwrap_used, clippy::expect_used)]
use sqlite_core::{Database, Value};
const MAIN: &[u8] = include_bytes!("../../tests/data/wal_places.db");
const WAL: &[u8] = include_bytes!("../../tests/data/wal_places.db-wal");
const MOZ_PLACES_ROOT: u32 = 2;
const MOZ_PLACES_COLS: usize = 6;
#[test]
fn main_only_view_shows_pre_wal_state() {
let db = Database::open(MAIN.to_vec()).expect("open main");
let rows = db
.read_table(MOZ_PLACES_ROOT, MOZ_PLACES_COLS)
.expect("walk");
assert_eq!(rows.len(), 2, "main file has 2 committed rows");
assert_eq!(rows[0].values[2], Value::Text("Rust".into()));
assert_eq!(rows[0].values[3], Value::Integer(5));
}
#[test]
fn wal_applied_view_overlays_committed_frame() {
let db = Database::open_with_wal(MAIN.to_vec(), WAL).expect("open with wal");
assert!(db.wal_applied(), "WAL frames were overlaid");
let rows = db
.read_table(MOZ_PLACES_ROOT, MOZ_PLACES_COLS)
.expect("walk wal-applied");
assert_eq!(rows.len(), 3, "WAL adds a third row");
assert_eq!(
rows[0].values[2],
Value::Text("Rust (EDITED IN WAL)".into()),
"WAL overlay changed the title"
);
assert_eq!(rows[0].values[3], Value::Integer(777));
assert_eq!(rows[2].values[2], Value::Text("WAL-ONLY ROW".into()));
}
#[test]
fn open_without_wal_does_not_claim_wal_applied() {
let db = Database::open(MAIN.to_vec()).expect("open");
assert!(!db.wal_applied());
}
#[test]
fn empty_wal_overlays_nothing() {
let mut empty_wal = vec![0u8; 32];
empty_wal[0..4].copy_from_slice(&0x377f_0682u32.to_be_bytes());
let db = Database::open_with_wal(MAIN.to_vec(), &empty_wal).expect("open empty wal");
let rows = db
.read_table(MOZ_PLACES_ROOT, MOZ_PLACES_COLS)
.expect("walk");
assert_eq!(rows.len(), 2, "no frames → main-only state");
assert_eq!(rows[0].values[2], Value::Text("Rust".into()));
}
const CARVE_MAIN: &[u8] = include_bytes!("../../tests/data/wal_carve.db");
const CARVE_WAL: &[u8] = include_bytes!("../../tests/data/wal_carve.db-wal");
#[test]
fn wal_frame_pages_exposes_each_frames_image_and_provenance() {
let db = Database::open_with_wal(CARVE_MAIN.to_vec(), CARVE_WAL).expect("open with wal");
let frames = db.wal_frame_pages();
assert_eq!(frames.len(), 2, "two committed WAL frames");
let page_size = db.header().page_size as usize;
for (i, f) in frames.iter().enumerate() {
assert_eq!(f.frame_index, i, "frame_index is the 0-based file order");
assert_eq!(f.page_no, 2, "both frames rewrite page 2");
assert_eq!(f.page.len(), page_size, "each frame carries one full page");
assert!(f.salt1 != 0 && f.salt2 != 0, "frame carries WAL salts");
}
assert_eq!(
frames[0].salt1, frames[1].salt1,
"same checkpoint generation"
);
assert_eq!(
frames[0].salt2, frames[1].salt2,
"same checkpoint generation"
);
assert!(frames[1].is_commit, "the DELETE frame is a COMMIT frame");
let needle = b"secret WAL body 130";
let in_wal_frame = frames
.iter()
.any(|f| f.page.windows(needle.len()).any(|w| w == needle));
assert!(
in_wal_frame,
"deleted-row residue must live in a WAL frame image"
);
let on_disk_page2 = db.raw_page(2).expect("page 2 present");
let on_disk = on_disk_page2.windows(needle.len()).any(|w| w == needle);
assert!(
!on_disk,
"deleted-row residue must NOT be on the on-disk page (WAL-only)"
);
}
#[test]
fn wal_frame_pages_empty_without_wal() {
let db = Database::open(CARVE_MAIN.to_vec()).expect("open");
assert!(
db.wal_frame_pages().is_empty(),
"no WAL → no frame images to carve"
);
}