Move the test-only helpers out of the shipped db package (closes #248)
check / check (push) Canceled after 0s

The server binary carried exported names that only tests call, including
raw SQL access and a way to weaken the password hash.

Delete testing.go, GetDB and SetBcryptCost from the shipped code, so
passwords always hash at bcrypt.DefaultCost. Move GetDB, GetOrCreateChannel,
JoinChannel and HasChannelInvite into export_test.go. Delete
GetClientHostInfo, whose remaining check GetLatestClientForSession covers.

Tests in other packages now build the database with db.New and run raw SQL
through dbtest.Exec. Handler tests and the relay tests' aliceWithHTTPClient
helper need a password only to log in, so they store one hashed at
bcrypt.MinCost. Tests of PASS itself keep the real cost.

Model: opus-5-5
This commit is contained in:
2026-11-03 10:23:41 +00:00
parent c12668226f
commit e44080fcbb
12 changed files with 199 additions and 276 deletions
+33 -49
View File
@@ -32,14 +32,9 @@ import (
const testTimeout = 5 * time.Second
func TestMain(m *testing.M) {
db.SetBcryptCost(4)
os.Exit(m.Run())
}
// testEnv holds the shared test infrastructure.
type testEnv struct {
dbURL string
database *db.Database
brk *broker.Broker
cfg *config.Config
@@ -110,34 +105,27 @@ func newTestEnvWithResolver(
) *testEnv {
t.Helper()
conn, err := sql.Open("sqlite", dbtest.NewURL(t))
if err != nil {
t.Fatalf("open db: %v", err)
}
dbURL := dbtest.NewURL(t)
lifecycle := fxtest.NewLifecycle(t)
t.Cleanup(func() {
err := conn.Close()
if err != nil {
t.Logf("close db: %v", err)
}
dbLog, err := logger.New(lifecycle, logger.Params{
Globals: &globals.Globals{},
})
conn.SetMaxOpenConns(1)
_, err = conn.ExecContext(
t.Context(), "PRAGMA foreign_keys = ON",
)
if err != nil {
t.Fatalf("pragma: %v", err)
t.Fatalf("new logger: %v", err)
}
database := db.NewTestDatabaseFromConn(conn)
err = database.RunMigrations(t.Context())
database, err := db.New(lifecycle, db.Params{
Logger: dbLog,
Config: &config.Config{DBURL: dbURL},
})
if err != nil {
t.Fatalf("migrate: %v", err)
t.Fatalf("new database: %v", err)
}
lifecycle.RequireStart()
t.Cleanup(lifecycle.RequireStop)
brk := broker.New()
log := slog.New(slog.NewTextHandler(
@@ -161,6 +149,7 @@ func newTestEnvWithResolver(
t.Cleanup(srv.Stop)
return &testEnv{
dbURL: dbURL,
database: database,
brk: brk,
cfg: cfg,
@@ -929,12 +918,7 @@ func quitSeenByPeers(t *testing.T, quit string) (string, []string) {
t.Fatalf("create peer session: %v", err)
}
channelID, err := env.database.GetChannelByName(ctx, "#bye")
if err != nil {
t.Fatalf("get channel: %v", err)
}
err = env.database.JoinChannel(ctx, channelID, apiPeerID)
_, _, err = env.database.CreateOrJoinChannel(ctx, "#bye", apiPeerID, "")
if err != nil {
t.Fatalf("join peer: %v", err)
}
@@ -1005,12 +989,9 @@ func TestStopEndsSessions(t *testing.T) {
t.Fatalf("create peer session: %v", err)
}
channelID, err := env.database.GetChannelByName(ctx, "#shut")
if err != nil {
t.Fatalf("get channel: %v", err)
}
err = env.database.JoinChannel(ctx, channelID, peerID)
channelID, _, err := env.database.CreateOrJoinChannel(
ctx, "#shut", peerID, "",
)
if err != nil {
t.Fatalf("join peer: %v", err)
}
@@ -1068,11 +1049,16 @@ func TestStopReturnsWhileCleanupIsStuck(t *testing.T) {
client.register("stuck")
// The test database has one connection. While the test
// holds it, the cleanup's first query waits for it.
held, err := env.database.GetDB().Conn(t.Context())
// While a connection of the test's own holds a write
// transaction, the cleanup's first write waits for it to end.
holder, err := sql.Open("sqlite", env.dbURL)
if err != nil {
t.Fatalf("take the database connection: %v", err)
t.Fatalf("open a second database connection: %v", err)
}
_, err = holder.ExecContext(t.Context(), "BEGIN IMMEDIATE")
if err != nil {
t.Fatalf("begin a write transaction: %v", err)
}
stopped := make(chan struct{})
@@ -1088,10 +1074,11 @@ func TestStopReturnsWhileCleanupIsStuck(t *testing.T) {
t.Error("Stop did not return while a cleanup was stuck")
}
// Lets the cleanup finish before the database is closed.
err = held.Close()
// Closing ends the transaction, which lets the cleanup finish
// before the database is closed.
err = holder.Close()
if err != nil {
t.Errorf("release the database connection: %v", err)
t.Errorf("close the second database connection: %v", err)
}
}
@@ -1370,14 +1357,11 @@ func TestPassPostRegistrationNotStored(t *testing.T) {
client.register("failpass")
_, err := env.database.GetDB().ExecContext(t.Context(),
dbtest.Exec(t, env.dbURL,
`CREATE TRIGGER refuse_password
BEFORE UPDATE OF password_hash ON sessions
BEGIN SELECT RAISE(ABORT, 'refused'); END`,
)
if err != nil {
t.Fatalf("create trigger: %v", err)
}
client.send("PASS :mypassword123")