Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 42 additions & 29 deletions packages/cipherstash-proxy-integration/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! ```rust
//! #[tokio::test]
//! async fn my_test() {
//! let client = connect_with_tls(PROXY).await;
//! let client = connect_with_tls(*PROXY).await;
//! clear_with_client(&client).await;
//! insert_with_client(sql, params, &client).await;
//! query_by_with_client(sql, param, &client).await;
Expand All @@ -41,26 +41,39 @@ use rustls::{
pki_types::CertificateDer, ClientConfig,
};
use serde_json::Value;
use std::sync::{Arc, Once};
use std::sync::{Arc, LazyLock, Once};
use tokio_postgres::{types::ToSql, Client, NoTls, Row, SimpleQueryMessage};
use tracing::info;
use tracing_subscriber::{filter::Directive, EnvFilter, FmtSubscriber};

pub const PROXY: u16 = 6432;

/// Proxy port for tests: `CS_PROXY__PORT` if set, otherwise [`PROXY`].
/// The ports the suite connects to, defaulting to the standard dev ports.
///
/// Lets a local run target a proxy on a non-default port without patching the
/// test source (mirrors [`get_database_port`] for `CS_DATABASE__PORT`).
pub fn proxy_port() -> u16 {
std::env::var("CS_PROXY__PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(PROXY)
/// Each is overridable by environment variable so that several copies of this
/// suite can run at once, each against its own Proxy and PostgreSQL. Set these
/// to match the `CS_SERVER__PORT` and `CS_DATABASE__PORT` the Proxy under test
/// was started with — nothing here starts anything, it only decides where to
/// connect.
pub static PROXY: LazyLock<u16> = LazyLock::new(|| port_from_env("CS_TEST_PROXY_PORT", 6432));
pub static PROXY_METRICS_PORT: LazyLock<u16> =
LazyLock::new(|| port_from_env("CS_TEST_PROXY_METRICS_PORT", 9930));
pub static PG_PORT: LazyLock<u16> = LazyLock::new(|| port_from_env("CS_TEST_PG_PORT", 5532));
pub static PG_TLS_PORT: LazyLock<u16> =
LazyLock::new(|| port_from_env("CS_TEST_PG_TLS_PORT", 5617));

/// Panics rather than falling back to the default: a typo'd port would
/// otherwise send the whole suite at whatever is already listening on 6432,
/// which is the one outcome that looks like a pass and isn't.
fn port_from_env(var: &str, default: u16) -> u16 {
match std::env::var(var) {
Ok(value) => value
.parse()
.unwrap_or_else(|_| panic!("{var} must be a port number, got: {value:?}")),
Err(std::env::VarError::NotPresent) => default,
Err(std::env::VarError::NotUnicode(value)) => {
panic!("{var} must be a port number, got non-unicode value: {value:?}")
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
pub const PROXY_METRICS_PORT: u16 = 9930;
pub const PG_PORT: u16 = 5532;
pub const PG_TLS_PORT: u16 = 5617;

pub const TEST_SCHEMA_SQL: &str = include_str!(concat!("../../../tests/sql/schema.sql"));

Expand Down Expand Up @@ -88,7 +101,7 @@ pub fn random_string() -> String {
}

pub async fn clear() {
clear_with_client(&connect_with_tls(PROXY).await).await;
clear_with_client(&connect_with_tls(*PROXY).await).await;
}

pub async fn clear_with_client(client: &Client) {
Expand All @@ -108,13 +121,13 @@ pub async fn clear_table_with_client(client: &Client, table: &str) {
}

pub async fn clear_table(table: &str) {
clear_table_with_client(&connect_with_tls(PROXY).await, table).await;
clear_table_with_client(&connect_with_tls(*PROXY).await, table).await;
}

pub async fn reset_schema() {
let port = std::env::var("CS_DATABASE__PORT")
.map(|s| s.parse().unwrap())
.unwrap_or(PG_PORT);
.unwrap_or(*PG_PORT);

let client = connect_with_tls(port).await;
client.simple_query(TEST_SCHEMA_SQL).await.unwrap();
Expand All @@ -123,7 +136,7 @@ pub async fn reset_schema() {
pub async fn reset_schema_to(schema: &'static str) {
let port = std::env::var("CS_DATABASE__PORT")
.map(|s| s.parse().unwrap())
.unwrap_or(PG_PORT);
.unwrap_or(*PG_PORT);

let client = connect_with_tls(port).await;
client.simple_query(schema).await.unwrap();
Expand All @@ -143,7 +156,7 @@ pub async fn table_exists(table: &str) -> bool {

let port = std::env::var("CS_DATABASE__PORT")
.map(|s| s.parse().unwrap())
.unwrap_or(PG_PORT);
.unwrap_or(*PG_PORT);

let client = connect_with_tls(port).await;
let messages = client.simple_query(&query).await.unwrap();
Expand Down Expand Up @@ -226,19 +239,19 @@ pub async fn connect(port: u16) -> Client {
}

pub async fn execute_query(sql: &str, params: &[&(dyn ToSql + Sync)]) {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
client.query(sql, params).await.unwrap();
}

pub async fn execute_simple_query(sql: &str) {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
client.simple_query(sql).await.unwrap();
}

pub async fn query<T: for<'a> tokio_postgres::types::FromSql<'a> + Send + Sync>(
sql: &str,
) -> Vec<T> {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
query_with_client(sql, &client).await
}

Expand Down Expand Up @@ -278,7 +291,7 @@ pub async fn query_by_params<T>(sql: &str, params: &[&(dyn ToSql + Sync)]) -> Ve
where
T: for<'a> tokio_postgres::types::FromSql<'a> + Send + Sync,
{
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
query_by_params_with_client(sql, params, &client).await
}

Expand All @@ -299,7 +312,7 @@ pub fn get_database_port() -> u16 {
std::env::var("CS_DATABASE__PORT")
.ok()
.and_then(|s| s.parse().ok())
.unwrap_or(PG_PORT)
.unwrap_or(*PG_PORT)
}

pub async fn query_direct_by<T>(sql: &str, param: &(dyn ToSql + Sync)) -> Vec<T>
Expand All @@ -318,7 +331,7 @@ pub async fn simple_query<T: std::str::FromStr>(sql: &str) -> Vec<T>
where
<T as std::str::FromStr>::Err: std::fmt::Debug,
{
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
simple_query_with_client(sql, &client).await
}

Expand Down Expand Up @@ -352,7 +365,7 @@ where
// Returns a vector of `Option<String>` for each row in the result set.
// Nulls are represented as `None`, and non-null values are converted to `Some(String)`.
pub async fn simple_query_with_null(sql: &str) -> Vec<Option<String>> {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
let rows = client.simple_query(sql).await.unwrap();
rows.iter()
.filter_map(|row| {
Expand All @@ -366,7 +379,7 @@ pub async fn simple_query_with_null(sql: &str) -> Vec<Option<String>> {
}

pub async fn insert(sql: &str, params: &[&(dyn ToSql + Sync)]) {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
insert_with_client(sql, params, &client).await;
}

Expand All @@ -375,7 +388,7 @@ pub async fn insert_with_client(sql: &str, params: &[&(dyn ToSql + Sync)], clien
}

pub async fn insert_jsonb() -> Value {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
insert_jsonb_with_client(&client).await
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ mod tests {
#[tokio::test]
async fn slow_query_does_not_block_other_connections() {
let result = timeout(Duration::from_secs(30), async {
let client_a = connect_with_tls(PROXY).await;
let client_b = connect_with_tls(PROXY).await;
let client_a = connect_with_tls(*PROXY).await;
let client_b = connect_with_tls(*PROXY).await;

// Connection A: run a slow query
let a_handle = tokio::spawn(async move {
Expand Down Expand Up @@ -56,7 +56,7 @@ mod tests {
let result = timeout(Duration::from_secs(10), async {
// First connection: query, then drop
{
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
let rows = client.simple_query("SELECT 1").await.unwrap();
assert!(!rows.is_empty());
}
Expand All @@ -66,7 +66,7 @@ mod tests {
tokio::time::sleep(Duration::from_millis(100)).await;

// Second connection: should work fine
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
let rows = client.simple_query("SELECT 1").await.unwrap();
assert!(!rows.is_empty());
})
Expand All @@ -84,7 +84,7 @@ mod tests {
// 5 slow connections
for _ in 0..5 {
join_set.spawn(async {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
client.simple_query("SELECT pg_sleep(3)").await.unwrap();
});
}
Expand All @@ -96,7 +96,7 @@ mod tests {
for _ in 0..5 {
join_set.spawn(async {
let start = Instant::now();
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
let rows = client.simple_query("SELECT 1").await.unwrap();
let elapsed = start.elapsed();

Expand Down Expand Up @@ -140,7 +140,7 @@ mod tests {

// Connection B: through proxy, attempt to acquire the same lock (will block)
let b_handle = tokio::spawn(async move {
let client_b = connect_with_tls(PROXY).await;
let client_b = connect_with_tls(*PROXY).await;
// This will block until A releases the lock
client_b
.simple_query(&b_lock_query)
Expand Down Expand Up @@ -173,7 +173,7 @@ mod tests {

// Connection C: through proxy, should complete immediately despite B being blocked
let start = Instant::now();
let client_c = connect_with_tls(PROXY).await;
let client_c = connect_with_tls(*PROXY).await;
let rows = client_c.simple_query("SELECT 1").await.unwrap();
let elapsed = start.elapsed();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod tests {

clear().await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let id = random_id();
let plaintext = "plaintext";
Expand Down Expand Up @@ -59,7 +59,7 @@ mod tests {

clear().await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let id = random_id();
let plaintext = "plaintext";
Expand Down Expand Up @@ -101,7 +101,7 @@ mod tests {

clear().await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let id = random_id();
let plaintext = "plaintext";
Expand Down
6 changes: 3 additions & 3 deletions packages/cipherstash-proxy-integration/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod tests {

/// Fetch metrics with retry logic to handle CI timing variability.
async fn fetch_metrics_with_retry(max_retries: u32, delay_ms: u64) -> String {
let url = format!("http://localhost:{}/metrics", PROXY_METRICS_PORT);
let url = format!("http://localhost:{}/metrics", *PROXY_METRICS_PORT);
let mut last_error = None;

for attempt in 0..max_retries {
Expand All @@ -40,7 +40,7 @@ mod tests {

#[tokio::test]
async fn metrics_include_statement_labels() {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

clear().await;

Expand Down Expand Up @@ -80,7 +80,7 @@ mod tests {

#[tokio::test]
async fn slow_statement_metrics_and_logs() {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

clear().await;

Expand Down
8 changes: 4 additions & 4 deletions packages/cipherstash-proxy-integration/src/disable_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ mod tests {

clear().await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let id = random_id();
let encrypted_text = "hello".to_string();
Expand Down Expand Up @@ -74,7 +74,7 @@ mod tests {

clear().await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let id = random_id();

Expand Down Expand Up @@ -143,15 +143,15 @@ mod tests {
let sql = "INSERT INTO encrypted (id, encrypted_text) VALUES ($1, $2)";
execute_query(sql, &[&id, &encrypted_text]).await;

let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;
let sql = "SET CIPHERSTASH.UNSAFE_DISABLE_MAPPING = true";
client.query(sql, &[]).await.unwrap();

let select_sql = "SELECT encrypted_text FROM encrypted";

// Mapping is NOT disabled for these queries
for _ in 1..5 {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let actual = query_with_client::<String>(select_sql, &client).await;

Expand Down
2 changes: 1 addition & 1 deletion packages/cipherstash-proxy-integration/src/empty_result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod tests {

#[tokio::test]
async fn empty_result_regression() {
let client = connect_with_tls(PROXY).await;
let client = connect_with_tls(*PROXY).await;

let sql = "SELECT ''";

Expand Down
Loading
Loading