From 4ab320ab2d3f8828f577185e93da40360f872c6a Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 20 Oct 2026 13:04:40 +0200 Subject: [PATCH] Give each handler and service test its own database (closes #131) Test databases in internal/handlers and internal/service were named after the address of the running test. A later test could get the address of a finished one, and with it a database that test's server might still hold open. Each test database now gets a random name, as in internal/ircserver. A new test in each package opens two test databases at once and checks that they do not share one; both new tests fail with the old names. Model: opus-5-5 Co-authored-by: clawbot --- internal/handlers/api_test.go | 31 +++++++++++++++++++++++++++++-- internal/service/service_test.go | 21 +++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/internal/handlers/api_test.go b/internal/handlers/api_test.go index e74f9fd..d859b55 100644 --- a/internal/handlers/api_test.go +++ b/internal/handlers/api_test.go @@ -7,6 +7,7 @@ package handlers_test import ( "bytes" "context" + "crypto/rand" "database/sql" "encoding/json" "errors" @@ -152,9 +153,12 @@ func newTestServerWith( ) *testServer { t.Helper() + // A random name, so that no other test can share it, not + // even one that has finished but still holds its database + // open. dbURL := fmt.Sprintf( - "file:test_%p?mode=memory&cache=shared", - t, + "file:%s?mode=memory&cache=shared", + rand.Text(), ) copyTemplateDB(t, dbURL) @@ -667,6 +671,29 @@ func TestCreateSessionDuplicate(t *testing.T) { } } +// TestEachTestServerHasItsOwnDatabase checks that starting a +// second test server leaves the first one's database alone and +// starts on an empty one of its own. +func TestEachTestServerHasItsOwnDatabase(t *testing.T) { + first := newTestServer(t) + first.createSession("samenick") + + second := newTestServer(t) + + resp := postSession(t, first, "samenick") + + defer func() { _ = resp.Body.Close() }() + + if resp.StatusCode != http.StatusConflict { + t.Fatalf( + "first server: expected 409, got %d", + resp.StatusCode, + ) + } + + second.createSession("samenick") +} + func TestCreateSessionEmpty(t *testing.T) { tserver := newTestServer(t) diff --git a/internal/service/service_test.go b/internal/service/service_test.go index 2cc9ef2..e619054 100644 --- a/internal/service/service_test.go +++ b/internal/service/service_test.go @@ -6,6 +6,7 @@ package service_test import ( "context" + "crypto/rand" "encoding/json" "errors" "fmt" @@ -43,9 +44,12 @@ type testEnv struct { func newTestEnv(t *testing.T) *testEnv { t.Helper() + // A random name, so that no other test can share it, not + // even one that has finished but still holds its database + // open. dbURL := fmt.Sprintf( - "file:svc_test_%p?mode=memory&cache=shared", - t, + "file:%s?mode=memory&cache=shared", + rand.Text(), ) var ( @@ -137,6 +141,19 @@ func createSession( return sessionID } +// TestEachTestEnvHasItsOwnDatabase checks that a test +// environment starts on an empty database while another one +// is still open. +func TestEachTestEnvHasItsOwnDatabase(t *testing.T) { + ctx := t.Context() + + first := newTestEnv(t) + createSession(ctx, t, first.db, "samenick") + + second := newTestEnv(t) + createSession(ctx, t, second.db, "samenick") +} + func TestFanOut(t *testing.T) { env := newTestEnv(t) ctx := t.Context()