Skip to main content

browser_forensic_core/
test_utils.rs

1/// SQLite helpers for use in tests across the workspace.
2///
3/// This is test-support scaffolding (a `pub mod` so other crates' `#[cfg(test)]`
4/// modules can build fixture databases). It is not part of the production parsing
5/// surface, so it opts out of the panic lints: setup failures here must fail loudly.
6#[allow(clippy::unwrap_used, clippy::expect_used)]
7pub mod sqlite {
8    use rusqlite::Connection;
9    use std::path::Path;
10    use tempfile::NamedTempFile;
11
12    /// A temporary SQLite database for use in tests.
13    pub struct TestDb {
14        file: NamedTempFile,
15    }
16
17    impl TestDb {
18        /// Create a new temporary database and run `schema_sql` to set it up.
19        pub fn new(schema_sql: &str) -> Self {
20            let file = NamedTempFile::new().unwrap();
21            let conn = Connection::open(file.path()).unwrap();
22            conn.execute_batch(schema_sql).unwrap();
23            Self { file }
24        }
25
26        /// Return the path to the temporary database file.
27        pub fn path(&self) -> &Path {
28            self.file.path()
29        }
30
31        /// Execute an INSERT (or any single statement) with positional params.
32        pub fn insert<P: rusqlite::Params>(&self, sql: &str, params: P) {
33            let conn = Connection::open(self.file.path()).unwrap();
34            conn.execute(sql, params).unwrap();
35        }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::sqlite::TestDb;
42    use rusqlite::{params, Connection};
43
44    #[test]
45    fn test_db_creates_with_schema() {
46        let db = TestDb::new("CREATE TABLE foo (id INTEGER PRIMARY KEY, name TEXT);");
47        // If the path is valid, we can open the DB
48        let conn = Connection::open(db.path()).unwrap();
49        let count: i64 = conn
50            .query_row("SELECT COUNT(*) FROM foo", [], |r| r.get(0))
51            .unwrap();
52        assert_eq!(count, 0);
53    }
54
55    #[test]
56    fn test_db_insert_stores_row() {
57        let db = TestDb::new("CREATE TABLE bar (val TEXT);");
58        db.insert("INSERT INTO bar VALUES (?1)", params!["hello"]);
59        let conn = Connection::open(db.path()).unwrap();
60        let val: String = conn
61            .query_row("SELECT val FROM bar", [], |r| r.get(0))
62            .unwrap();
63        assert_eq!(val, "hello");
64    }
65}