#![allow(dead_code)]
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
pub const SECRET_PW: &str = "s3cr3t_pw_do_not_leak";
pub const fn autumn_bin() -> &'static str {
env!("CARGO_BIN_EXE_autumn")
}
fn psql_free_path() -> TempDir {
tempfile::tempdir().unwrap()
}
pub fn run_autumn(
dir: &Path,
args: &[&str],
envs: &[(&str, &str)],
) -> (String, String, Option<i32>) {
let empty_path = psql_free_path();
let output = Command::new(autumn_bin())
.args(args)
.current_dir(dir)
.env("PATH", empty_path.path())
.envs(envs.iter().copied())
.output()
.expect("failed to run autumn");
(
String::from_utf8_lossy(&output.stdout).into_owned(),
String::from_utf8_lossy(&output.stderr).into_owned(),
output.status.code(),
)
}
pub fn run_autumn_ok(dir: &Path, args: &[&str], envs: &[(&str, &str)]) -> (String, String) {
let (stdout, stderr, code) = run_autumn(dir, args, envs);
assert_eq!(
code,
Some(0),
"autumn {args:?} failed (exit={code:?})\nstdout: {stdout}\nstderr: {stderr}",
);
(stdout, stderr)
}
pub fn run_autumn_fail(dir: &Path, args: &[&str], envs: &[(&str, &str)]) -> (String, String) {
let (stdout, stderr, code) = run_autumn(dir, args, envs);
assert_ne!(
code,
Some(0),
"autumn {args:?} should have failed but exited 0\nstdout: {stdout}\nstderr: {stderr}",
);
(stdout, stderr)
}
pub async fn start_postgres() -> (
testcontainers::ContainerAsync<testcontainers_modules::postgres::Postgres>,
String,
u16,
) {
use testcontainers::runners::AsyncRunner as _;
use testcontainers_modules::postgres::Postgres;
let container = Postgres::default()
.with_password(SECRET_PW)
.start()
.await
.expect("failed to start Postgres testcontainer — is Docker running?");
let host = container.get_host().await.unwrap().to_string();
let port = container.get_host_port_ipv4(5432).await.unwrap();
(container, host, port)
}
pub async fn apply_sql(url: &str, statements: &[&str]) {
let (client, connection) = tokio_postgres::connect(url, tokio_postgres::NoTls)
.await
.expect("failed to connect to test Postgres database");
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("test fixture connection error: {e}");
}
});
for sql in statements {
client
.batch_execute(sql)
.await
.unwrap_or_else(|e| panic!("failed to apply fixture SQL: {e}\nSQL: {sql}"));
}
}
pub async fn query_one_text(
url: &str,
sql: &str,
params: &[&(dyn tokio_postgres::types::ToSql + Sync)],
) -> Option<String> {
let (client, connection) = tokio_postgres::connect(url, tokio_postgres::NoTls)
.await
.expect("failed to connect to test Postgres database");
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("test fixture connection error: {e}");
}
});
let rows = client.query(sql, params).await.expect("query failed");
rows.first().map(|r| r.get::<_, String>(0))
}
pub async fn execute_params(
url: &str,
sql: &str,
params: &[&(dyn tokio_postgres::types::ToSql + Sync)],
) {
let (client, connection) = tokio_postgres::connect(url, tokio_postgres::NoTls)
.await
.expect("failed to connect to test Postgres database");
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("test fixture connection error: {e}");
}
});
client
.execute(sql, params)
.await
.unwrap_or_else(|e| panic!("failed to execute fixture SQL: {e}\nSQL: {sql}"));
}