#![cfg(feature = "postgres")]
#[macro_use]
mod storage_harness;
use sqlx::PgPool;
use sqlx::postgres::PgPoolOptions;
use std::sync::OnceLock;
use storage_harness::*;
use testcontainers::runners::AsyncRunner;
use testcontainers_modules::postgres::Postgres;
use this::storage::{PostgresDataService, PostgresLinkService};
struct PgTestEnv {
_container: testcontainers::ContainerAsync<Postgres>,
connection_url: String,
}
static TEST_ENV: OnceLock<PgTestEnv> = OnceLock::new();
async fn init_pg_env() -> &'static PgTestEnv {
if let Some(env) = TEST_ENV.get() {
return env;
}
let container = Postgres::default()
.start()
.await
.expect("Failed to start PostgreSQL container — is Docker running?");
let host = container.get_host().await.unwrap();
let port = container.get_host_port_ipv4(5432).await.unwrap();
let url = format!("postgres://postgres:postgres@{}:{}/postgres", host, port);
let pool = PgPool::connect(&url)
.await
.expect("Failed to connect to PostgreSQL");
sqlx::migrate!("./migrations")
.run(&pool)
.await
.expect("Failed to run migrations");
pool.close().await;
let env = PgTestEnv {
_container: container,
connection_url: url,
};
let _ = TEST_ENV.set(env);
TEST_ENV.get().unwrap()
}
async fn pg_pool() -> PgPool {
let env = init_pg_env().await;
PgPoolOptions::new()
.max_connections(2)
.acquire_timeout(std::time::Duration::from_secs(30))
.connect(&env.connection_url)
.await
.expect("Failed to connect to PostgreSQL")
}
async fn clean_pg_data_service() -> PostgresDataService<TestDataEntity> {
let pool = pg_pool().await;
sqlx::query("TRUNCATE entities CASCADE")
.execute(&pool)
.await
.expect("Failed to truncate entities table");
PostgresDataService::new(pool)
}
async fn clean_pg_link_service() -> PostgresLinkService {
let pool = pg_pool().await;
sqlx::query("TRUNCATE links CASCADE")
.execute(&pool)
.await
.expect("Failed to truncate links table");
PostgresLinkService::new(pool)
}
data_service_tests!(clean_pg_data_service().await);
link_service_tests!(clean_pg_link_service().await);
rest_integration_tests!(clean_pg_data_service().await);