Stop the slow test packages waiting (closes #263)
check / check (push) Failing after 1m9s

The slowest test packages spent their time waiting rather than testing.

db.Params gains an optional PasswordCost (zero means bcrypt.DefaultCost), and the db, ircserver and handlers tests hash at bcrypt.MinCost. A test IRC server's relay checks its queue on broker notification instead of polling. The service and handlers tests build config.Config directly and run in parallel; config exports DefaultTrustedProxies and ParseTrustedProxies for them. Fixed sleeps give way to waits for the event. Production defaults are unchanged.

What still takes time is CPU work under -race or a timeout a test is about.

Model: opus-5-5
This commit was merged in pull request #267.
This commit is contained in:
clawbot committed 2026-11-11 01:15:43 +01:00
1 parent 847f5c6fec
commit ed5125606a
15 files changed
+558 -261

No files matched your search

+26 -13
View File
@@ -18,6 +18,7 @@ import (
"time"
"go.uber.org/fx/fxtest"
"golang.org/x/crypto/bcrypt"
"sneak.berlin/go/neoirc/internal/broker"
"sneak.berlin/go/neoirc/internal/config"
"sneak.berlin/go/neoirc/internal/db"
@@ -35,6 +36,12 @@ import (
// enough for a heavily loaded host.
const testTimeout = 30 * time.Second
// testPollInterval is how often the relay of a test server
// checks the client output queue without a broker
// notification. It is so long that the relay delivers only on
// notification, and a test fails when one is missing.
const testPollInterval = time.Hour
// testEnv holds the shared test infrastructure.
type testEnv struct {
dbURL string
@@ -94,16 +101,19 @@ func newTestEnvWithPingTimes(
t.Helper()
return newTestEnvWithResolver(
t, cfg, interval, deadline, ircserver.ResolveHost,
t, cfg, interval, deadline, testPollInterval,
ircserver.ResolveHost,
)
}
// newTestEnvWithResolver is newTestEnvWithPingTimes, except
// that the server looks up a client's hostname with resolve.
// that the relay checks the client output queue every poll
// without a broker notification, and the server looks up a
// client's hostname with resolve.
func newTestEnvWithResolver(
t *testing.T,
cfg *config.Config,
interval, deadline time.Duration,
interval, deadline, poll time.Duration,
resolve func(ctx context.Context, addr string) string,
) *testEnv {
t.Helper()
@@ -119,8 +129,9 @@ func newTestEnvWithResolver(
}
database, err := db.New(lifecycle, db.Params{
Logger: dbLog,
Config: &config.Config{DBURL: dbURL},
Logger: dbLog,
Config: &config.Config{DBURL: dbURL},
PasswordCost: bcrypt.MinCost,
})
if err != nil {
t.Fatalf("new database: %v", err)
@@ -137,7 +148,7 @@ func newTestEnvWithResolver(
))
srv := ircserver.NewTestServer(
log, cfg, database, brk, interval, deadline, resolve,
log, cfg, database, brk, interval, deadline, poll, resolve,
)
// Port 0 makes the system pick a free port. dial reads it
@@ -433,7 +444,8 @@ func TestRegistrationWhileAnotherLookupIsPending(t *testing.T) {
env := newTestEnvWithResolver(
t, &config.Config{ServerName: testServerName},
ircserver.PingInterval, ircserver.PongDeadline, resolve,
ircserver.PingInterval, ircserver.PongDeadline,
testPollInterval, resolve,
)
env.dial(t)
@@ -1064,12 +1076,16 @@ func TestStopEndsSessions(t *testing.T) {
}
// TestStopReturnsWhileCleanupIsStuck checks that Stop stops
// waiting for a connection's cleanup after StopTimeout, so a
// cleanup that cannot finish does not hold up stopping.
// waiting for a connection's cleanup after its stop timeout,
// so a cleanup that cannot finish does not hold up stopping.
func TestStopReturnsWhileCleanupIsStuck(t *testing.T) {
t.Parallel()
const stopTimeout = 100 * time.Millisecond
env := newTestEnv(t)
env.srv.SetStopTimeout(stopTimeout)
client := env.dial(t)
client.register("stuck")
@@ -1095,7 +1111,7 @@ func TestStopReturnsWhileCleanupIsStuck(t *testing.T) {
select {
case <-stopped:
case <-time.After(ircserver.StopTimeout + testTimeout):
case <-time.After(stopTimeout + testTimeout):
t.Error("Stop did not return while a cleanup was stuck")
}
@@ -1147,9 +1163,6 @@ func TestDirectMessage(t *testing.T) {
receiver := env.dial(t)
receiver.register("dmreceiver")
// Give relay goroutines time to start.
time.Sleep(100 * time.Millisecond)
sender.send("PRIVMSG dmreceiver :hello privately")
lines := receiver.readUntil(func(line string) bool {