use std::path::Path;
use miden_node_db::sqlite::{DbReader, DbWriter, ReadTx, WriteTx};
use miden_node_db::{DatabaseError, default_connection_pool_size};
use tokio::runtime::Runtime;
use crate::db::migrations::bootstrap_database;
pub(crate) struct TestDb {
writer: Option<DbWriter>,
reader: Option<DbReader>,
runtime: Runtime,
}
impl TestDb {
pub(crate) fn new() -> Self {
let temp_dir = tempfile::tempdir().expect("failed to create temp directory");
let path = temp_dir.path().join("test.sqlite3");
bootstrap_database(&path).expect("database should bootstrap");
let _kept_dir = temp_dir.keep();
Self::open(&path)
}
pub(crate) fn open(path: &Path) -> Self {
let (writer, reader) =
miden_node_db::sqlite::open_with_pool_size(path, default_connection_pool_size())
.expect("temp file sqlite should always work");
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("test runtime should build");
Self {
writer: Some(writer),
reader: Some(reader),
runtime,
}
}
pub(crate) fn read<R, E, F>(&self, query: F) -> Result<R, E>
where
F: FnOnce(&ReadTx<'_>) -> Result<R, E> + Send + 'static,
R: Send + 'static,
E: From<DatabaseError> + Send + 'static,
{
let reader = self.reader.as_ref().expect("handles live until drop");
self.runtime.block_on(reader.read("test read", query))
}
pub(crate) fn write<R, E, F>(&self, query: F) -> Result<R, E>
where
F: FnOnce(&WriteTx<'_>) -> Result<R, E> + Send + 'static,
R: Send + 'static,
E: From<DatabaseError> + Send + 'static,
{
let writer = self.writer.as_ref().expect("handles live until drop");
self.runtime.block_on(writer.write("test write", query))
}
}
impl Drop for TestDb {
fn drop(&mut self) {
let _guard = self.runtime.enter();
self.writer.take();
self.reader.take();
}
}