use postgresql_commands::CommandBuilder;
use postgresql_commands::psql::PsqlBuilder;
use postgresql_embedded::{PostgreSQL, Result, Settings, Status};
use std::fs::{remove_dir_all, remove_file};
use test_log::test;
async fn lifecycle() -> Result<()> {
let mut postgresql = PostgreSQL::default();
let settings = postgresql.settings();
assert_eq!(0, settings.port);
assert!(settings.temporary);
let initial_statuses = [Status::NotInstalled, Status::Installed, Status::Stopped];
assert!(initial_statuses.contains(&postgresql.status()));
postgresql.setup().await?;
assert_eq!(Status::Stopped, postgresql.status());
postgresql.start().await?;
assert_eq!(Status::Started, postgresql.status());
let database_name = "test";
assert!(!postgresql.database_exists(database_name).await?);
postgresql.create_database(database_name).await?;
assert!(postgresql.database_exists(database_name).await?);
postgresql.drop_database(database_name).await?;
postgresql.stop().await?;
assert_eq!(Status::Stopped, postgresql.status());
Ok(())
}
#[test(tokio::test)]
async fn test_embedded_async_lifecycle() -> Result<()> {
lifecycle().await
}
#[test(tokio::test)]
async fn test_temporary_database() -> Result<()> {
let settings = Settings::default();
let data_dir = settings.data_dir.clone();
let password_file = settings.password_file.clone();
assert!(settings.temporary);
{
let mut postgresql = PostgreSQL::new(settings);
postgresql.setup().await?;
postgresql.start().await?;
assert!(data_dir.exists());
assert!(password_file.exists());
}
assert!(!data_dir.exists());
assert!(!password_file.exists());
Ok(())
}
#[test(tokio::test)]
async fn test_persistent_database() -> Result<()> {
let mut settings = Settings::default();
let data_dir = settings.data_dir.clone();
let password_file = settings.password_file.clone();
settings.temporary = false;
{
let mut postgresql = PostgreSQL::new(settings);
postgresql.setup().await?;
postgresql.start().await?;
assert!(data_dir.exists());
assert!(password_file.exists());
}
assert!(data_dir.exists());
assert!(password_file.exists());
let _ = remove_dir_all(&data_dir);
let _ = remove_file(&password_file);
Ok(())
}
#[test(tokio::test)]
async fn test_persistent_database_reuse() -> Result<()> {
let database_name = "test";
let mut settings = Settings::default();
let data_dir = settings.data_dir.clone();
let password = settings.password.clone();
let password_file = settings.password_file.clone();
settings.temporary = false;
{
let mut postgresql = PostgreSQL::new(settings);
postgresql.setup().await?;
postgresql.start().await?;
postgresql.create_database(database_name).await?;
assert!(postgresql.database_exists(database_name).await?);
postgresql.stop().await?;
}
assert!(data_dir.exists());
assert!(password_file.exists());
let settings = Settings {
data_dir: data_dir.clone(),
password: password.clone(),
password_file: password_file.clone(),
temporary: false,
..Default::default()
};
{
let mut postgresql = PostgreSQL::new(settings);
postgresql.setup().await?;
postgresql.start().await?;
assert!(postgresql.database_exists(database_name).await?);
postgresql.stop().await?;
}
let _ = remove_dir_all(&data_dir);
let _ = remove_file(&password_file);
Ok(())
}
#[test(tokio::test)]
async fn postgres_concurrency() -> Result<()> {
let handle1 = tokio::spawn(lifecycle());
let handle2 = tokio::spawn(lifecycle());
let handle3 = tokio::spawn(lifecycle());
match tokio::try_join!(handle1, handle2, handle3) {
Ok(_) => {}
Err(error) => {
assert_eq!("", error.to_string());
}
}
Ok(())
}
#[test(tokio::test)]
async fn test_authentication_success() -> Result<()> {
let mut postgresql = PostgreSQL::default();
postgresql.setup().await?;
postgresql.start().await?;
let mut psql = PsqlBuilder::from(postgresql.settings())
.command("SELECT 1")
.no_psqlrc()
.tuples_only()
.build();
let output = psql.output()?;
assert!(output.status.success());
Ok(())
}
#[test(tokio::test)]
async fn test_authentication_invalid_username() -> Result<()> {
let mut postgresql = PostgreSQL::default();
postgresql.setup().await?;
postgresql.start().await?;
let mut psql = PsqlBuilder::from(postgresql.settings())
.command("SELECT 1")
.username("invalid")
.no_psqlrc()
.tuples_only()
.build();
let output = psql.output()?;
assert!(!output.status.success());
Ok(())
}
#[test(tokio::test)]
async fn test_authentication_invalid_password() -> Result<()> {
let mut postgresql = PostgreSQL::default();
postgresql.setup().await?;
postgresql.start().await?;
let mut psql = PsqlBuilder::from(postgresql.settings())
.command("SELECT 1")
.pg_password("invalid")
.no_psqlrc()
.tuples_only()
.build();
let output = psql.output()?;
assert!(!output.status.success());
Ok(())
}
#[test(tokio::test)]
async fn test_username_setting() -> Result<()> {
let settings = Settings {
username: "admin".to_string(),
..Default::default()
};
let mut postgresql = PostgreSQL::new(settings);
postgresql.setup().await?;
postgresql.start().await?;
let database_name = "test";
postgresql.create_database(database_name).await?;
let database_exists = postgresql.database_exists(database_name).await?;
assert!(database_exists);
postgresql.drop_database(database_name).await?;
let database_exists = postgresql.database_exists(database_name).await?;
assert!(!database_exists);
Ok(())
}