From 876f9d4ccfccdaa7307f98fab1a7558bfdb4eb31 Mon Sep 17 00:00:00 2001 From: Amir Fathi Date: Tue, 1 Sep 2026 14:22:21 +0000 Subject: [PATCH 1/2] fix(testutil): derive a per-workspace database for non-.test binaries derivedDBSuffix() only derived the per-workspace, per-package database suffix when os.Args[0] ended in ".test", so cmd/e2a-contract-server, the one non-test binary sharing this harness, fell back to the base URL verbatim. Two contract-server instances from different checkouts (two agents, two worktrees) landed on the same e2a_test database and truncated each other's rows on Close. The suffix is now keyed on the running binary's own name regardless of a ".test" suffix, so a compiled binary derives one too. testutil is imported by exactly one other non-test file, cmd/e2a-contract-server; every other consumer is already a `go test` binary and derives the same suffix it did before. Fixes #827 --- internal/testutil/db.go | 7 ++---- internal/testutil/db_test.go | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/internal/testutil/db.go b/internal/testutil/db.go index cee81312e..03037686a 100644 --- a/internal/testutil/db.go +++ b/internal/testutil/db.go @@ -52,7 +52,7 @@ func baseTestDBURL() string { // binary's name (os.Args[0] = .test — unique per package in this // repo), so every URL consumer in one test binary — TestDB, hand-built // pools, the in-process contract server — lands on the same database. -// Non-test binaries (cmd/e2a-contract-server) and E2A_TEST_DB_SHARED=1 get +// E2A_TEST_DB_SHARED=1 gets // the base URL verbatim. Missing databases self-provision on first open // (see OpenPreparedTestDB). Concurrent sessions, agents, and worktrees are // isolated by the per-workspace component below, so handing each runner its @@ -100,7 +100,7 @@ const maxPostgresIdentifier = 63 // derivedDBSuffix derives the database-name suffix beneath the configured base: // a per-WORKSPACE component plus a per-PACKAGE component, or "" when the process -// is not a test binary or sharing is forced. +// shares via E2A_TEST_DB_SHARED=1. // // Two dimensions, because per-package alone was not enough. It stops packages in // ONE run from truncating each other, but every checkout computed the same names, @@ -121,9 +121,6 @@ func derivedDBSuffix() string { return "" } bin := filepath.Base(os.Args[0]) - if !strings.HasSuffix(bin, ".test") { - return "" - } name := strings.ToLower(strings.TrimSuffix(bin, ".test")) sanitized := make([]rune, 0, len(name)) for _, r := range name { diff --git a/internal/testutil/db_test.go b/internal/testutil/db_test.go index 8bb29ac93..c9a42d03b 100644 --- a/internal/testutil/db_test.go +++ b/internal/testutil/db_test.go @@ -7,6 +7,7 @@ import ( "net/url" "os" "os/exec" + "path/filepath" "strings" "testing" "time" @@ -418,6 +419,53 @@ func TestTestDBURLDerivesPerPackageDatabase(t *testing.T) { } } +// TestTestDBURLDerivesForNonTestBinaries proves the derivation also covers +// cmd/e2a-contract-server (see #827): a symlink to this test binary under a +// non-test name reproduces a real non-".test" argv[0]. +func TestTestDBURLDerivesForNonTestBinaries(t *testing.T) { + if os.Getenv(testDBErrorChildEnv) == t.Name() { + u, err := url.Parse(TestDBURL()) + if err != nil { + t.Fatalf("parse TestDBURL: %v", err) + } + fmt.Printf("DBNAME=%s\n", strings.TrimPrefix(u.Path, "/")) + return + } + + self, err := filepath.Abs(os.Args[0]) + if err != nil { + t.Fatalf("resolve this test binary's path: %v", err) + } + renamed := filepath.Join(t.TempDir(), "e2a-contract-server") + if err := os.Symlink(self, renamed); err != nil { + t.Fatalf("symlink the test binary under a non-test name: %v", err) + } + + cmd := exec.Command(renamed, "-test.run=^"+t.Name()+"$") + cmd.Env = testDBChildEnv(t.Name(), "postgres://e2a:e2a@localhost:5433/e2a_test?sslmode=disable") + output, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("child failed: %v\n%s", err, output) + } + + var dbname string + for _, line := range strings.Split(string(output), "\n") { + if rest, ok := strings.CutPrefix(line, "DBNAME="); ok { + dbname = rest + break + } + } + if dbname == "" { + t.Fatalf("child did not report a dbname:\n%s", output) + } + if !strings.Contains(dbname, "_ws") { + t.Errorf("dbname = %q from a non-test binary, want a _ws workspace component", dbname) + } + if !strings.HasSuffix(dbname, "_pkg_e2a_contract_server") { + t.Errorf("dbname = %q, want the _pkg_e2a_contract_server suffix", dbname) + } +} + func TestOpenPreparedTestDBCreatesMissingDatabase(t *testing.T) { // First use of a package database must self-provision: connect failure // with SQLSTATE 3D000 creates the database from the base URL's server From 0c34a324f8727c020370049d1a0ef8ddcbce6474 Mon Sep 17 00:00:00 2001 From: Amir Fathi Date: Wed, 2 Sep 2026 08:55:51 +0000 Subject: [PATCH 2/2] ci: rerun to check Go e2e tests timeout reproducibility Signed-off-by: Amir Fathi