Keep the store address's query in every test database's address, so store tests reach a socket-addressed store (issue 1889)
mesh/merge-gate head 185d0294ebd4 merged into trunk 89abce5df955 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; the ch…
mesh/repo-check head 185d0294ebd4 merged into trunk 89abce5df955 — pass: its merge-check.sh passed
mesh/delivery covered after its stop: a later merge that contains it was delivered: novox/mesh-controller@0b312218f90f (merged as 791786d5 into main, wal…
mesh/check pass 185d0294ebd4 on 89abce5df955 | unit 1756 run, 0 kept, 4 skipped | integration 3034 run, 0 kept, 16 skipped | over bound: integration (…
mesh/merge-gate head 185d0294ebd4 merged into trunk 89abce5df955 — pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; the ch…
mesh/repo-check head 185d0294ebd4 merged into trunk 89abce5df955 — pass: its merge-check.sh passed
mesh/delivery covered after its stop: a later merge that contains it was delivered: novox/mesh-controller@0b312218f90f (merged as 791786d5 into main, wal…
mesh/check pass 185d0294ebd4 on 89abce5df955 | unit 1756 run, 0 kept, 4 skipped | integration 3034 run, 0 kept, 16 skipped | over bound: integration (…
The checker's integration store answers on a unix socket named in the query of MESH_TEST_POSTGRES (?host=<socket dir>&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.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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=<socket directory>&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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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"}}
|
||||
|
||||
Reference in New Issue
Block a user