use hyperdb_api::{HyperProcess, Parameters};
use hyperdb_api_core::client::{Client, Config};
use std::path::PathBuf;
pub(crate) fn test_result_path(name: &str, extension: &str) -> hyperdb_api::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) -> hyperdb_api::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 TestServer {
pub hyper: HyperProcess,
pub host: String,
pub port: u16,
pub database_path: PathBuf,
}
impl TestServer {
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn new() -> hyperdb_api::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_name(&test_name)
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn with_name(test_name: &str) -> hyperdb_api::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 endpoint = hyper.endpoint().expect("No endpoint available");
let endpoint_str = endpoint.to_string();
let (host, port) = parse_endpoint(&endpoint_str);
let config = Config::new()
.with_host(&host)
.with_port(port)
.with_user("tableau_internal_user");
let client = Client::connect(&config)
.map_err(|e| hyperdb_api::Error::new(format!("Failed to connect: {e}")))?;
let db_path_escaped = database_path.to_string_lossy().replace('"', "\"\"");
let _ = client.exec(&format!("DROP DATABASE IF EXISTS \"{db_path_escaped}\""));
client
.exec(&format!("CREATE DATABASE \"{db_path_escaped}\""))
.map_err(|e| hyperdb_api::Error::new(format!("Failed to create database: {e}")))?;
client
.close()
.map_err(|e| hyperdb_api::Error::new(format!("Failed to close: {e}")))?;
Ok(TestServer {
hyper,
host,
port,
database_path,
})
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn without_database() -> hyperdb_api::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::without_database_with_name(&test_name)
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn without_database_with_name(test_name: &str) -> hyperdb_api::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 endpoint = hyper.endpoint().expect("No endpoint available");
let endpoint_str = endpoint.to_string();
let (host, port) = parse_endpoint(&endpoint_str);
Ok(TestServer {
hyper,
host,
port,
database_path,
})
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn config(&self) -> Config {
Config::new()
.with_host(&self.host)
.with_port(self.port)
.with_user("tableau_internal_user")
.with_database(self.database_path.to_string_lossy().to_string())
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn config_without_database(&self) -> Config {
Config::new()
.with_host(&self.host)
.with_port(self.port)
.with_user("tableau_internal_user")
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn connect(&self) -> hyperdb_api_core::client::Result<Client> {
let config = self.config();
Client::connect(&config)
}
#[allow(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn connect_without_database(&self) -> hyperdb_api_core::client::Result<Client> {
let config = self.config_without_database();
Client::connect(&config)
}
#[expect(
dead_code,
reason = "test helper; referenced by subset of test binaries in this crate"
)]
pub(crate) fn database_path_str(&self) -> String {
self.database_path.to_string_lossy().to_string()
}
}
fn parse_endpoint(endpoint: &str) -> (String, u16) {
let addr = endpoint.strip_prefix("tab.tcp://").unwrap_or(endpoint);
if let Some((host, port_str)) = addr.rsplit_once(':') {
let port = port_str.parse().unwrap_or(7483);
(host.to_string(), port)
} else {
(addr.to_string(), 7483)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_endpoint() {
assert_eq!(
parse_endpoint("tab.tcp://localhost:12345"),
("localhost".to_string(), 12345)
);
assert_eq!(
parse_endpoint("127.0.0.1:7483"),
("127.0.0.1".to_string(), 7483)
);
}
}