From 618511805d760a7434ecefd4eda4b5e8a6c78bb3 Mon Sep 17 00:00:00 2001 From: Philippe Vienne Date: Thu, 1 Oct 2026 09:15:34 +0200 Subject: [PATCH] =?UTF-8?q?test:=20noms=20de=20base=20PostgreSQL=20uniques?= =?UTF-8?q?=20entre=20tests=20parall=C3=A8les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Plusieurs suites forment le nom de leur base de test avec la seule horloge (`prefix_{nanos}`) : deux tests lancés dans la même nanoseconde se heurtent sur `pg_database_datname_index` (« duplicate key »). Constaté sur la CI de #91 (action_challenge, déjà corrigé) et en local sur `db_guard::a_role_that_can_write_the_registry_is_refused_with_every_violation`. Les douze fichiers restants ajoutent à l'horloge le pid du processus et un compteur atomique local. Vérifié par trois exécutions complètes de `cargo test -p ra-console -p ca-server` avec PostgreSQL, sans échec. Co-authored-by: Claude --- bin/ca-server/tests/audit_cli.rs | 10 ++++++++-- bin/ca-server/tests/bootstrap_cli.rs | 5 ++++- bin/ca-server/tests/internal_link.rs | 5 ++++- bin/ca-server/tests/reconcile_cli.rs | 10 ++++++++-- bin/ca-server/tests/recover_cli.rs | 5 ++++- bin/ca-server/tests/revocation_action.rs | 5 ++++- bin/ca-server/tests/s3_journal.rs | 5 ++++- bin/ra-console/tests/db_guard.rs | 5 ++++- bin/ra-console/tests/login.rs | 5 ++++- bin/ra-console/tests/purge.rs | 5 ++++- bin/ra-console/tests/register_relay.rs | 5 ++++- bin/ra-console/tests/requests.rs | 5 ++++- 12 files changed, 56 insertions(+), 14 deletions(-) diff --git a/bin/ca-server/tests/audit_cli.rs b/bin/ca-server/tests/audit_cli.rs index 65094c7..25282e3 100644 --- a/bin/ca-server/tests/audit_cli.rs +++ b/bin/ca-server/tests/audit_cli.rs @@ -17,7 +17,10 @@ async fn the_audit_command_reports_what_the_journal_cannot_vouch_for() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("audcli_{nanos}"); + let name = format!("audcli_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) @@ -88,7 +91,10 @@ async fn the_audit_command_does_not_require_hsm_configuration() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("audnohsm_{nanos}"); + let name = format!("audnohsm_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ca-server/tests/bootstrap_cli.rs b/bin/ca-server/tests/bootstrap_cli.rs index 9739516..d75c2fd 100644 --- a/bin/ca-server/tests/bootstrap_cli.rs +++ b/bin/ca-server/tests/bootstrap_cli.rs @@ -25,7 +25,10 @@ async fn standard_output_carries_only_the_token() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("cli_{nanos}"); + let name = format!("cli_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ca-server/tests/internal_link.rs b/bin/ca-server/tests/internal_link.rs index bcf8406..fc9d66d 100644 --- a/bin/ca-server/tests/internal_link.rs +++ b/bin/ca-server/tests/internal_link.rs @@ -35,7 +35,10 @@ fn unique(prefix: &str) -> String { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - format!("{prefix}-{nanos}") + format!("{prefix}-{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }) } async fn call( diff --git a/bin/ca-server/tests/reconcile_cli.rs b/bin/ca-server/tests/reconcile_cli.rs index b491bf0..b2b81b3 100644 --- a/bin/ca-server/tests/reconcile_cli.rs +++ b/bin/ca-server/tests/reconcile_cli.rs @@ -19,7 +19,10 @@ async fn fixture(prefix: &str) -> Option { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("{prefix}_{nanos}"); + let name = format!("{prefix}_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) @@ -262,7 +265,10 @@ async fn the_reconcile_command_does_not_require_hsm_configuration() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("reconohsm_{nanos}"); + let name = format!("reconohsm_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ca-server/tests/recover_cli.rs b/bin/ca-server/tests/recover_cli.rs index d3192c1..6a077fb 100644 --- a/bin/ca-server/tests/recover_cli.rs +++ b/bin/ca-server/tests/recover_cli.rs @@ -35,7 +35,10 @@ async fn the_token_pin_from_stdin_is_the_proof_of_custody() { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("recli_{nanos}"); + let name = format!("recli_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let dir = std::env::temp_dir().join(&name); std::fs::create_dir_all(dir.join("tokens")).unwrap(); std::fs::write( diff --git a/bin/ca-server/tests/revocation_action.rs b/bin/ca-server/tests/revocation_action.rs index 7d9249c..52a83a6 100644 --- a/bin/ca-server/tests/revocation_action.rs +++ b/bin/ca-server/tests/revocation_action.rs @@ -52,7 +52,10 @@ impl Env { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("rev_{nanos}"); + let name = format!("rev_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ca-server/tests/s3_journal.rs b/bin/ca-server/tests/s3_journal.rs index 61d7df8..c2a505b 100644 --- a/bin/ca-server/tests/s3_journal.rs +++ b/bin/ca-server/tests/s3_journal.rs @@ -72,7 +72,10 @@ async fn fixture(prefix: &str) -> Option { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("{prefix}_{nanos}"); + let name = format!("{prefix}_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ra-console/tests/db_guard.rs b/bin/ra-console/tests/db_guard.rs index ca12528..1e7b58a 100644 --- a/bin/ra-console/tests/db_guard.rs +++ b/bin/ra-console/tests/db_guard.rs @@ -17,7 +17,10 @@ async fn fresh() -> Option<(PgPool, String)> { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("dbg_{nanos}"); + let name = format!("dbg_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ra-console/tests/login.rs b/bin/ra-console/tests/login.rs index 5f2712e..6661eb5 100644 --- a/bin/ra-console/tests/login.rs +++ b/bin/ra-console/tests/login.rs @@ -56,7 +56,10 @@ impl Env { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("login_{nanos}"); + let name = format!("login_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ra-console/tests/purge.rs b/bin/ra-console/tests/purge.rs index 01884ba..cda0ee1 100644 --- a/bin/ra-console/tests/purge.rs +++ b/bin/ra-console/tests/purge.rs @@ -14,7 +14,10 @@ async fn fixture(prefix: &str) -> Option<(sqlx::PgPool, oe_webauthn::Uuid, Strin .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("{prefix}_{nanos}"); + let name = format!("{prefix}_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ra-console/tests/register_relay.rs b/bin/ra-console/tests/register_relay.rs index e7bdc28..5632abc 100644 --- a/bin/ra-console/tests/register_relay.rs +++ b/bin/ra-console/tests/register_relay.rs @@ -54,7 +54,10 @@ impl Env { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("rel_{nanos}"); + let name = format!("rel_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin) diff --git a/bin/ra-console/tests/requests.rs b/bin/ra-console/tests/requests.rs index 5dd262f..281c51f 100644 --- a/bin/ra-console/tests/requests.rs +++ b/bin/ra-console/tests/requests.rs @@ -44,7 +44,10 @@ impl Env { .duration_since(std::time::UNIX_EPOCH) .unwrap() .as_nanos(); - let name = format!("requests_{nanos}"); + let name = format!("requests_{nanos}_{}_{}", std::process::id(), { + static SEQ: std::sync::atomic::AtomicU32 = std::sync::atomic::AtomicU32::new(0); + SEQ.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + }); let admin = PgPoolOptions::new().connect(&base).await.unwrap(); sqlx::query(&format!("CREATE DATABASE {name}")) .execute(&admin)