From 185d0294ebd45c7d868378be4f6153a631f04571 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 23 Oct 2026 08:55:50 +0200 Subject: [PATCH] Keep the store address's query in every test database's address, so store tests reach a socket-addressed store (issue 1889) The checker's integration store answers on a unix socket named in the query of MESH_TEST_POSTGRES (?host=&sslmode=disable). The identity, inventory and licences fixtures cut the address at its last slash and appended ?sslmode=disable, dropping host=, so pgx dialled its default socket where no server is: every store test waited out its 20 s readiness bound, each package ran into go test's 10-minute timeout, and the verdict named only the first failure, identity.TestACertificateChainsToTheMeshsOwnAuthority. store.DatabaseForTest now builds that address for every fixture, keeping the query as the template raise already did; identity's fresh is ForTest rather than a second copy. The readiness bound and its error, which wraps the driver's cause, are unchanged. --- internal/identity/fortest.go | 3 +- internal/identity/identity_test.go | 50 +++--------------------------- internal/inventory/fortest.go | 6 ++-- internal/licences/fortest.go | 3 +- internal/store/fortest.go | 23 ++++++++++---- internal/store/fortest_test.go | 25 +++++++++++++++ internal/store/live_test.go | 11 +------ 7 files changed, 51 insertions(+), 70 deletions(-) create mode 100644 internal/store/fortest_test.go diff --git a/internal/identity/fortest.go b/internal/identity/fortest.go index 0dbeab61..efbeb6ec 100644 --- a/internal/identity/fortest.go +++ b/internal/identity/fortest.go @@ -37,8 +37,7 @@ func ForTest(t *testing.T) *Identity { } store.CreateMigratedForTest(t, admin, name, migrations) - cut := strings.LastIndex(admin, "/") - t.Setenv(store.Variable(Name), admin[:cut]+"/"+name+"?sslmode=disable") + t.Setenv(store.Variable(Name), store.DatabaseForTest(admin, name)) ident, err := Open(t.Context()) if err != nil { diff --git a/internal/identity/identity_test.go b/internal/identity/identity_test.go index bacf1d62..9322b4c1 100644 --- a/internal/identity/identity_test.go +++ b/internal/identity/identity_test.go @@ -7,61 +7,19 @@ import ( "context" "crypto/ed25519" "errors" - "fmt" "os" - "strings" "sync" "testing" - "time" "github.com/jackc/pgx/v5" - "github.com/novox/mesh-controller/internal/store" ) +// fresh is the package's own name for ForTest: one fixture for every store test of identity, so the way +// a test's database is made and addressed is kept true in one place (novox/hq issue 1889: this copy +// dropped the store address's query and reached no server on the checker's socket-addressed store). func fresh(t *testing.T) *Identity { t.Helper() - admin := os.Getenv("MESH_TEST_POSTGRES") - if admin == "" { - t.Skip("no MESH_TEST_POSTGRES; run `make check` to raise one") - } - name := fmt.Sprintf("ident_%d", time.Now().UnixNano()%10_000_000) - - conn, err := pgx.Connect(t.Context(), admin) - if err != nil { - t.Fatalf("cannot reach the test PostgreSQL: %v", err) - } - if _, err := conn.Exec(t.Context(), "create database "+name); err != nil { - t.Fatalf("cannot create %s: %v", name, err) - } - conn.Close(t.Context()) - - cut := strings.LastIndex(admin, "/") - t.Setenv(store.Variable(Name), admin[:cut]+"/"+name+"?sslmode=disable") - - ident, err := Open(t.Context()) - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { - ident.Close() - c, err := pgx.Connect(context.Background(), admin) - if err != nil { - return - } - defer c.Close(context.Background()) - _, _ = c.Exec(context.Background(), "drop database if exists "+name+" with (force)") - }) - if err := ident.Ready(t.Context(), 20*time.Second); err != nil { - t.Fatal(err) - } - migrations, err := Migrations() - if err != nil { - t.Fatal(err) - } - if _, err := ident.store.Migrate(t.Context(), migrations); err != nil { - t.Fatal(err) - } - return ident + return ForTest(t) } func TestNoKeyIsAnErrorRatherThanAnEmptyKey(t *testing.T) { diff --git a/internal/inventory/fortest.go b/internal/inventory/fortest.go index 4cecc83c..1de57540 100644 --- a/internal/inventory/fortest.go +++ b/internal/inventory/fortest.go @@ -42,8 +42,7 @@ func ForTest(t *testing.T) *Inventory { store.CreateMigratedForTest(t, admin, name, migrations) busPasswordCostForTest.Store(int32(bcrypt.MinCost)) - cut := strings.LastIndex(admin, "/") - t.Setenv(store.Variable(Name), admin[:cut]+"/"+name+"?sslmode=disable") + t.Setenv(store.Variable(Name), store.DatabaseForTest(admin, name)) inv, err := Open(t.Context()) if err != nil { @@ -113,8 +112,7 @@ func ForTestBefore(t *testing.T, number int) (*Inventory, func()) { } store.CreateMigratedForTest(t, admin, name, before) busPasswordCostForTest.Store(int32(bcrypt.MinCost)) - cut := strings.LastIndex(admin, "/") - t.Setenv(store.Variable(Name), admin[:cut]+"/"+name+"?sslmode=disable") + t.Setenv(store.Variable(Name), store.DatabaseForTest(admin, name)) inv, err := Open(t.Context()) if err != nil { t.Fatal(err) diff --git a/internal/licences/fortest.go b/internal/licences/fortest.go index 2bbf72c8..9e9a0830 100644 --- a/internal/licences/fortest.go +++ b/internal/licences/fortest.go @@ -40,8 +40,7 @@ func ForTest(t *testing.T) *Licences { } store.CreateMigratedForTest(t, admin, name, migrations) - cut := strings.LastIndex(admin, "/") - t.Setenv(store.Variable(Name), admin[:cut]+"/"+name+"?sslmode=disable") + t.Setenv(store.Variable(Name), store.DatabaseForTest(admin, name)) held, err := Open(t.Context()) if err != nil { diff --git a/internal/store/fortest.go b/internal/store/fortest.go index 9727c82b..840cde3e 100644 --- a/internal/store/fortest.go +++ b/internal/store/fortest.go @@ -110,12 +110,7 @@ func raiseTemplate(ctx context.Context, admin, name string, key int64, migration if _, err := conn.Exec(ctx, "create database "+name); err != nil { return err } - cut := strings.LastIndex(admin, "/") - rest := "" - if q := strings.Index(admin[cut:], "?"); q >= 0 { - rest = admin[cut+q:] - } - pool, err := pgxpool.New(ctx, admin[:cut]+"/"+name+rest) + pool, err := pgxpool.New(ctx, DatabaseForTest(admin, name)) if err != nil { return err } @@ -136,3 +131,19 @@ func raiseTemplate(ctx context.Context, admin, name string, key int64, migration } return nil } + +// DatabaseForTest is the address of the database name on the same test PostgreSQL that admin reaches: admin +// with its database replaced and its query kept. +// +// **The query is kept, never replaced** (novox/hq issue 1889): the checker's integration store answers on a +// unix socket named in the query (`?host=&sslmode=disable`), and an address that drops it +// reaches pgx's default socket, where no server is, so every store test waited out its readiness bound and +// failed. Every store fixture builds its database's address here, so none can drop it again. +func DatabaseForTest(admin, name string) string { + cut := strings.LastIndex(admin, "/") + query := "" + if q := strings.Index(admin[cut:], "?"); q >= 0 { + query = admin[cut+q:] + } + return admin[:cut] + "/" + name + query +} diff --git a/internal/store/fortest_test.go b/internal/store/fortest_test.go new file mode 100644 index 00000000..be74618e --- /dev/null +++ b/internal/store/fortest_test.go @@ -0,0 +1,25 @@ +package store + +import "testing" + +// 1889/AC1: the checker's integration store answers on a unix socket named in the address's query +// (mesh-build-go's store). A test database's address that drops the query reaches pgx's default socket, +// where no server is, and every store test waits out its 20 s and fails. +func TestATestDatabaseIsOnTheSocketItsAdminAddressNames(t *testing.T) { + admin := "postgres://postgres@/postgres?host=%2Fwork%2Frun-1%2Fpg%2Fsocket&sslmode=disable" + got := DatabaseForTest(admin, "ident_1_x") + want := "postgres://postgres@/ident_1_x?host=%2Fwork%2Frun-1%2Fpg%2Fsocket&sslmode=disable" + if got != want { + t.Fatalf("the test database's address is %q, want %q", got, want) + } +} + +// 1889/AC2: the address `make check` gives (TCP, with sslmode) builds what the fixtures always built. +func TestATestDatabaseOnTCPIsAddressedAsBefore(t *testing.T) { + admin := "postgres://postgres:check@127.0.0.1:55566/postgres?sslmode=disable" + got := DatabaseForTest(admin, "inv_2_y") + want := "postgres://postgres:check@127.0.0.1:55566/inv_2_y?sslmode=disable" + if got != want { + t.Fatalf("the test database's address is %q, want %q", got, want) + } +} diff --git a/internal/store/live_test.go b/internal/store/live_test.go index 9fc67ba4..1ff0bc1f 100644 --- a/internal/store/live_test.go +++ b/internal/store/live_test.go @@ -55,7 +55,7 @@ func freshStore(t *testing.T) *Store { } conn.Close(t.Context()) - t.Setenv(Variable("testing"), replaceDatabase(dsn, name)) + t.Setenv(Variable("testing"), DatabaseForTest(dsn, name)) s, err := Open(t.Context(), "testing") if err != nil { t.Fatal(err) @@ -75,15 +75,6 @@ func freshStore(t *testing.T) *Store { return s } -func replaceDatabase(dsn, name string) string { - cut := strings.LastIndex(dsn, "/") - rest := "" - if q := strings.Index(dsn[cut:], "?"); q >= 0 { - rest = dsn[cut+q:] - } - return dsn[:cut] + "/" + name + rest -} - func TestTheSchemaIsAppliedAndRecorded(t *testing.T) { s := freshStore(t) migrations := []Migration{{Number: 1, Name: "people", SQL: "create table person (id int)", Checksum: "a"}}