use hyperdb_api::{Catalog, Connection, CreateMode, HyperProcess, Parameters, Result};
use std::path::PathBuf;
pub(crate) fn test_result_path(name: &str, extension: &str) -> Result<PathBuf> {
let test_results_dir = std::env::current_dir()?.join("test_results");
std::fs::create_dir_all(&test_results_dir)?;
let canonical_dir = test_results_dir.canonicalize().unwrap_or(test_results_dir);
Ok(canonical_dir.join(format!("{name}.{extension}")))
}
pub(crate) fn test_hyper_params(_test_name: &str) -> Result<Parameters> {
let test_results_dir = std::env::current_dir()?.join("test_results");
std::fs::create_dir_all(&test_results_dir)?;
let mut params = Parameters::new();
let log_dir = test_results_dir.canonicalize().unwrap_or(test_results_dir);
params.set("log_dir", log_dir.to_string_lossy().to_string());
Ok(params)
}
#[expect(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) struct TestConnection {
pub hyper: HyperProcess,
pub connection: Connection,
pub database_path: PathBuf,
}
impl TestConnection {
pub(crate) fn new() -> Result<Self> {
Self::with_create_mode(CreateMode::CreateAndReplace)
}
pub(crate) fn with_create_mode(create_mode: CreateMode) -> Result<Self> {
let thread = std::thread::current();
let test_name = thread
.name()
.and_then(|n| n.split("::").last())
.map_or_else(|| "test".to_string(), std::string::ToString::to_string);
Self::with_create_mode_and_name(create_mode, &test_name)
}
pub(crate) fn with_create_mode_and_name(
create_mode: CreateMode,
test_name: &str,
) -> Result<Self> {
let database_path = test_result_path(test_name, "hyper")?;
let params = test_hyper_params(test_name)?;
let hyper = HyperProcess::new(None, Some(¶ms))?;
let connection = Connection::new(&hyper, &database_path, create_mode)?;
Ok(TestConnection {
hyper,
connection,
database_path,
})
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_command(&self, sql: &str) -> Result<u64> {
self.connection.execute_command(sql)
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_query(&self, sql: &str) -> Result<hyperdb_api::Rowset<'_>> {
self.connection.execute_query(sql)
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_scalar_i32(&self, sql: &str) -> Result<i32> {
self.connection
.execute_scalar_query::<i32>(sql)?
.ok_or_else(|| hyperdb_api::Error::new(format!("NULL value for query: {sql}")))
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_scalar_i64(&self, sql: &str) -> Result<i64> {
self.connection
.execute_scalar_query::<i64>(sql)?
.ok_or_else(|| hyperdb_api::Error::new(format!("NULL value for query: {sql}")))
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_scalar_string(&self, sql: &str) -> Result<String> {
self.connection
.execute_scalar_query::<String>(sql)?
.ok_or_else(|| hyperdb_api::Error::new(format!("NULL value for query: {sql}")))
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn execute_scalar_bool(&self, sql: &str) -> Result<bool> {
self.connection
.execute_scalar_query::<bool>(sql)?
.ok_or_else(|| hyperdb_api::Error::new(format!("NULL value for query: {sql}")))
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn count_tuples(&self, table_name: &str) -> Result<i64> {
self.execute_scalar_i64(&format!("SELECT COUNT(*) FROM {table_name}"))
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn catalog(&self) -> Catalog<'_> {
Catalog::new(&self.connection)
}
}
impl Default for TestConnection {
fn default() -> Self {
Self::new().expect("Failed to create test connection")
}
}