From dd6285560c82dba3b4d769d883201f326e6742f6 Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou Date: Fri, 13 Sep 2024 11:39:18 +0200 Subject: [PATCH] test adding a page that will overflow --- test/src/lib.rs | 123 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 19 deletions(-) diff --git a/test/src/lib.rs b/test/src/lib.rs index b74d59e97..10d7537a1 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -1,28 +1,50 @@ -#[cfg(test)] -mod tests { - use limbo_core::{Database, RowResult, Value}; - use rusqlite::Connection; - use std::env::current_dir; - use std::sync::Arc; - #[test] - fn test_sequential_write() -> anyhow::Result<()> { - env_logger::init(); - let path = "test.db"; +use limbo_core::Connection; +use limbo_core::Database; +use std::env; +use std::fs; +use std::path::PathBuf; +use std::sync::Arc; - let io: Arc = Arc::new(limbo_core::PlatformIO::new()?); - dbg!(path); - let mut path = current_dir()?; +struct TempDatabase { + pub path: PathBuf, + pub io: Arc, +} + +impl TempDatabase { + pub fn new(table_sql: &str) -> Self { + let mut path = env::current_dir().unwrap(); path.push("test.db"); { if path.exists() { - std::fs::remove_file(&path)?; + fs::remove_file(&path).unwrap(); } - let connection = Connection::open(&path)?; - connection.execute("CREATE TABLE test (x INTEGER PRIMARY KEY);", ())?; + let connection = rusqlite::Connection::open(&path).unwrap(); + connection.execute(table_sql, ()).unwrap(); } + let io: Arc = Arc::new(limbo_core::PlatformIO::new().unwrap()); - let db = Database::open_file(io.clone(), path.to_str().unwrap())?; + Self { path, io } + } + + pub fn connect_limbo(&self) -> limbo_core::Connection { + let db = Database::open_file(self.io.clone(), self.path.to_str().unwrap()).unwrap(); let conn = db.connect(); + conn + } +} + +#[cfg(test)] +mod tests { + use super::*; + use limbo_core::{Database, RowResult, Value}; + use std::sync::Arc; + + #[test] + fn test_sequential_write() -> anyhow::Result<()> { + env_logger::init(); + + let tmp_db = TempDatabase::new("CREATE TABLE test (x INTEGER PRIMARY KEY);"); + let conn = tmp_db.connect_limbo(); let list_query = "SELECT * FROM test"; let max_iterations = 10000; @@ -36,7 +58,7 @@ mod tests { Ok(Some(ref mut rows)) => loop { match rows.next_row()? { RowResult::IO => { - io.run_once()?; + tmp_db.io.run_once()?; } RowResult::Done => break, _ => unreachable!(), @@ -63,7 +85,7 @@ mod tests { current_read_index += 1; } RowResult::IO => { - io.run_once()?; + tmp_db.io.run_once()?; } RowResult::Done => break, } @@ -77,4 +99,67 @@ mod tests { } Ok(()) } + + #[test] + fn test_simple_overflow_page() -> anyhow::Result<()> { + env_logger::init(); + let tmp_db = TempDatabase::new("CREATE TABLE test (x INTEGER PRIMARY KEY, t TEXT);"); + let conn = tmp_db.connect_limbo(); + + let mut huge_text = String::new(); + for i in 0..8192 { + huge_text.push(('A' as u8 + (i % 24) as u8) as char); + } + + let list_query = "SELECT * FROM test LIMIT 1"; + let insert_query = format!("INSERT INTO test VALUES (1, '{}')", huge_text.as_str()); + + match conn.query(insert_query) { + Ok(Some(ref mut rows)) => loop { + match rows.next_row()? { + RowResult::IO => { + tmp_db.io.run_once()?; + } + RowResult::Done => break, + _ => unreachable!(), + } + }, + Ok(None) => {} + Err(err) => { + eprintln!("{}", err); + } + }; + + match conn.query(list_query) { + Ok(Some(ref mut rows)) => loop { + match rows.next_row()? { + RowResult::Row(row) => { + let first_value = &row.values[0]; + let text = &row.values[1]; + let id = match first_value { + Value::Integer(i) => *i as i32, + Value::Float(f) => *f as i32, + _ => unreachable!(), + }; + let text = match text { + Value::Text(t) => *t, + _ => unreachable!(), + }; + assert_eq!(1, id); + assert_eq!(*text, huge_text); + } + RowResult::IO => { + tmp_db.io.run_once()?; + } + RowResult::Done => break, + } + }, + Ok(None) => {} + Err(err) => { + eprintln!("{}", err); + } + } + conn.cacheflush()?; + Ok(()) + } }