Move the test-only helpers out of the shipped db package (closes #248)
check / check (push) Canceled after 0s
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:
@@ -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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user