Files
post3/crates/post3-server/tests/common/mod.rs
2026-02-27 11:52:29 +01:00

103 lines
3.2 KiB
Rust

use std::net::SocketAddr;
use aws_credential_types::Credentials;
use aws_sdk_s3::Client;
use post3::PostgresBackend;
use sqlx::PgPool;
use tokio::net::TcpListener;
use tokio_util::sync::CancellationToken;
static TRACING: std::sync::Once = std::sync::Once::new();
fn init_tracing() {
TRACING.call_once(|| {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::from_default_env()
.add_directive("post3_server=debug".parse().unwrap())
.add_directive("tower_http=debug".parse().unwrap()),
)
.with_test_writer()
.init();
});
}
pub struct TestServer {
pub addr: SocketAddr,
pub client: Client,
cancel: CancellationToken,
pool: PgPool,
}
impl TestServer {
pub async fn start() -> Self {
init_tracing();
let db_url = std::env::var("DATABASE_URL").unwrap_or_else(|_| {
"postgresql://devuser:devpassword@localhost:5435/post3_dev".into()
});
let pool = sqlx::pool::PoolOptions::new()
.max_connections(5)
.connect(&db_url)
.await
.unwrap();
// Run migrations
post3::MIGRATOR.run(&pool).await.unwrap();
// Clean slate
sqlx::query("DELETE FROM upload_parts").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM multipart_upload_metadata").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM multipart_uploads").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM blocks").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM object_metadata").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM objects").execute(&pool).await.unwrap();
sqlx::query("DELETE FROM buckets").execute(&pool).await.unwrap();
let backend = PostgresBackend::new(pool.clone());
let state = post3_server::state::State { store: backend };
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let cancel = CancellationToken::new();
let cancel_clone = cancel.clone();
let router = post3_server::s3::router::build_router(state);
tokio::spawn(async move {
axum::serve(listener, router.into_make_service())
.with_graceful_shutdown(async move {
cancel_clone.cancelled().await;
})
.await
.unwrap();
});
let creds = Credentials::new("test", "test", None, None, "test");
let config = aws_sdk_s3::Config::builder()
.behavior_version_latest()
.region(aws_types::region::Region::new("us-east-1"))
.endpoint_url(format!("http://{}", addr))
.credentials_provider(creds)
.force_path_style(true)
.build();
let client = Client::from_conf(config);
Self {
addr,
client,
cancel,
pool,
}
}
pub async fn shutdown(self) {
self.cancel.cancel();
// Give the server task a moment to wind down
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
self.pool.close().await;
}
}