use crate::common::fixtures::*;
use crate::common::setup_postgres_cdc;
use testcontainers::clients::Cli;
use testcontainers_modules::postgres::Postgres;
#[cfg(test)]
mod connection_tests {
use super::*;
use crate::common::containers::wait_for_postgres;
#[tokio::test]
async fn test_connection_establishment() {
let (_container, client, connection_string) = setup_postgres_cdc().await.unwrap();
let _config = create_test_postgres_config(&connection_string);
let row = client.query_one("SELECT 1 as num", &[]).await.unwrap();
let num: i32 = row.get("num");
assert_eq!(num, 1);
}
#[tokio::test]
async fn test_connection_pool_behavior() {
let (_container, _client, connection_string) = setup_postgres_cdc().await.unwrap();
let mut handles = vec![];
for i in 0..5 {
let conn_str = connection_string.clone();
let handle = tokio::spawn(async move {
let (client, connection) =
tokio_postgres::connect(&conn_str, tokio_postgres::NoTls)
.await
.unwrap();
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
let row = client
.query_one(&format!("SELECT {} as num", i), &[])
.await
.unwrap();
let num: i32 = row.get("num");
assert_eq!(num, i);
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
}
#[tokio::test]
async fn test_connection_with_invalid_credentials() {
use crate::common::containers::{start_postgres_with_cdc, wait_for_postgres};
use crate::common::DOCKER;
let postgres = start_postgres_with_cdc(&DOCKER);
let port = postgres.get_host_port_ipv4(5432);
let valid_connection = format!("postgresql://postgres:postgres@localhost:{}/testdb", port);
wait_for_postgres(&valid_connection).await.unwrap();
let invalid_connection =
format!("postgresql://postgres:wrongpass@localhost:{}/testdb", port);
let result = tokio_postgres::connect(&invalid_connection, tokio_postgres::NoTls).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_connection_timeout() {
let invalid_connection = "postgresql://postgres:postgres@localhost:59999/testdb";
let start = tokio::time::Instant::now();
let result = tokio::time::timeout(
std::time::Duration::from_secs(5),
tokio_postgres::connect(invalid_connection, tokio_postgres::NoTls),
)
.await;
assert!(result.is_err() || result.unwrap().is_err());
assert!(start.elapsed() < std::time::Duration::from_secs(6));
}
#[tokio::test]
async fn test_ssl_connection_modes() {
let docker = Cli::default();
let postgres = docker.run(Postgres::default().with_db_name("testdb"));
let port = postgres.get_host_port_ipv4(5432);
let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port);
wait_for_postgres(&connection_string).await.unwrap();
let result = tokio_postgres::connect(&connection_string, tokio_postgres::NoTls).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_connection_parameter_validation() {
let docker = Cli::default();
let postgres = docker.run(Postgres::default().with_db_name("testdb"));
let port = postgres.get_host_port_ipv4(5432);
let connection_strings = vec![
format!("postgresql://postgres:postgres@localhost:{}/testdb", port),
format!("postgres://postgres:postgres@localhost:{}/testdb", port),
format!(
"postgresql://postgres:postgres@localhost:{}/testdb?application_name=meilibridge",
port
),
];
for conn_str in connection_strings {
wait_for_postgres(&conn_str).await.unwrap();
let result = tokio_postgres::connect(&conn_str, tokio_postgres::NoTls).await;
assert!(result.is_ok(), "Failed to connect with: {}", conn_str);
}
}
#[tokio::test]
async fn test_reconnection_after_disconnect() {
let docker = Cli::default();
let postgres = docker.run(Postgres::default().with_db_name("testdb"));
let port = postgres.get_host_port_ipv4(5432);
let connection_string = format!("postgresql://postgres:postgres@localhost:{}/testdb", port);
wait_for_postgres(&connection_string).await.unwrap();
let (client, connection) =
tokio_postgres::connect(&connection_string, tokio_postgres::NoTls)
.await
.unwrap();
let conn_handle = tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
assert!(client.query_one("SELECT 1", &[]).await.is_ok());
drop(client);
conn_handle.await.ok();
let (new_client, new_connection) =
tokio_postgres::connect(&connection_string, tokio_postgres::NoTls)
.await
.unwrap();
tokio::spawn(async move {
if let Err(e) = new_connection.await {
eprintln!("connection error: {}", e);
}
});
let row = new_client.query_one("SELECT 2 as num", &[]).await.unwrap();
let num: i32 = row.get("num");
assert_eq!(num, 2);
}
#[tokio::test]
async fn test_connection_with_different_databases() {
let docker = Cli::default();
let postgres = docker.run(Postgres::default().with_db_name("testdb"));
let port = postgres.get_host_port_ipv4(5432);
let postgres_db = format!("postgresql://postgres:postgres@localhost:{}/postgres", port);
wait_for_postgres(&postgres_db).await.unwrap();
let (client, connection) = tokio_postgres::connect(&postgres_db, tokio_postgres::NoTls)
.await
.unwrap();
tokio::spawn(async move {
if let Err(e) = connection.await {
eprintln!("connection error: {}", e);
}
});
client
.execute("CREATE DATABASE meilibridge_test", &[])
.await
.ok();
let new_db = format!(
"postgresql://postgres:postgres@localhost:{}/meilibridge_test",
port
);
let (new_client, new_connection) = tokio_postgres::connect(&new_db, tokio_postgres::NoTls)
.await
.unwrap();
tokio::spawn(async move {
if let Err(e) = new_connection.await {
eprintln!("connection error: {}", e);
}
});
let row = new_client
.query_one("SELECT current_database()", &[])
.await
.unwrap();
let db_name: String = row.get(0);
assert_eq!(db_name, "meilibridge_test");
}
}