diff --git a/core/src/local/mod.rs b/core/src/local/mod.rs index 44d308f..4b68ed5 100644 --- a/core/src/local/mod.rs +++ b/core/src/local/mod.rs @@ -28,6 +28,18 @@ pub fn open(path: &Path) -> rusqlite::Result { Ok(Db(Mutex::new(conn))) } +/// Open a migrated, in-memory store. +/// +/// Exists so a CONSUMER can test against a real schema without taking a rusqlite +/// dependency of its own just to build a `Db` — which is exactly what the desktop +/// crate was doing before the core was extracted. The Android bindings will want the +/// same thing. +pub fn open_in_memory() -> rusqlite::Result { + let conn = Connection::open_in_memory()?; + schema::migrate(&conn)?; + Ok(Db(Mutex::new(conn))) +} + /// A one-line count summary of the store, for the startup log. pub fn summary(db: &Db) -> String { let conn = match db.0.lock() { diff --git a/desktop/src-tauri/src/update.rs b/desktop/src-tauri/src/update.rs index 86d589b..c343d4a 100644 --- a/desktop/src-tauri/src/update.rs +++ b/desktop/src-tauri/src/update.rs @@ -308,14 +308,20 @@ fn describe_check_error(detail: &str) -> String { #[cfg(test)] mod tests { use super::*; - use rusqlite::Connection; - use std::sync::Mutex; - use thoughtsync_core::local::schema; + use std::sync::atomic::{AtomicU32, Ordering}; fn db() -> Db { - let conn = Connection::open_in_memory().expect("in-memory db"); - schema::migrate(&conn).expect("migrate"); - Db(Mutex::new(conn)) + thoughtsync_core::local::open_in_memory().expect("in-memory db") + } + + /// A scratch path nothing else will collide with. Process id keeps concurrent + /// `cargo test` runs apart, the counter keeps tests within one run apart — which + /// is all uuid was doing here, without the dependency (the core owns uuid now, + /// and pulling it into the desktop crate for two test filenames would be silly). + fn scratch_path(tag: &str) -> std::path::PathBuf { + static SEQ: AtomicU32 = AtomicU32::new(0); + let n = SEQ.fetch_add(1, Ordering::Relaxed); + std::env::temp_dir().join(format!("ts-{tag}-{}-{n}", std::process::id())) } /// The channel `update_check` would actually use. @@ -336,7 +342,7 @@ mod tests { /// A scratch directory holding a marker file, named uniquely so tests can run in /// parallel. Dropped by the OS' temp cleanup; nothing here is worth a new dependency. fn data_dir_with_marker(contents: &str) -> std::path::PathBuf { - let dir = std::env::temp_dir().join(format!("ts-marker-{}", uuid::Uuid::new_v4())); + let dir = scratch_path("marker"); std::fs::create_dir_all(&dir).expect("scratch dir"); std::fs::write(dir.join(INSTALL_MARKER), contents).expect("write marker"); dir @@ -397,7 +403,7 @@ mod tests { // Built from source, or installed by anything that isn't install.sh. let db = db(); set_channel(&db, Channel::Dev); - let empty = std::env::temp_dir().join(format!("ts-nomarker-{}", uuid::Uuid::new_v4())); + let empty = scratch_path("nomarker"); std::fs::create_dir_all(&empty).expect("scratch dir"); adopt_installer_channel(&db, &empty); assert_eq!(effective(&db), Channel::Dev);