check / check (push) Successful in 3m21s
The `main` side of #414: the two changes that make `next` green, and nothing else from `next`. Each is its own commit, so it can be compared with its `next` counterpart. - #404, as merged to `next`: a test binary hashes passwords at a 1 MB Argon2id cost instead of 64 MB, `TestHashPassword_ShippedParameters` keeps the shipped cost covered, and `script/test` runs at most four packages and eight parallel tests at once. Every test that starts a database hashed the admin password at 64 MB, which on a busy host made `internal/handlers` overrun its application start and its 90-second timeout. That is what turned `main` red. - #415: `script/test` runs without `-v`, so the build log, which the Docker build cuts off at 2 MiB, carries one result line per package and, for a package that fails, everything its tests wrote, application log lines included, instead of only passing packages. What the diff does not show: `script/test` differs from `next` by one line. `main` has no `script/assets` yet, so it is not called. Several packages failing at once can still reach the 2 MiB limit. - Judgement call: both commits keep their subjects from `next`, including their `closes` references. - Deviation and not fixed here: the same two as on #415 (no `-v` rerun on failure, #315; remaining sensitivity to extreme CPU load, #225). Model: opus-5-5 Co-authored-by: sneak <sneak@sneak.berlin> Reviewed-on: #416 Co-authored-by: clawbot <35+clawbot@noreply.example.org>
94 lines
2.5 KiB
Go
94 lines
2.5 KiB
Go
package database
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"go.uber.org/fx"
|
|
)
|
|
|
|
// NewTestRetentionReaper builds a RetentionReaper backed by the given
|
|
// main database and per-webhook database manager, without the fx
|
|
// lifecycle. Intended for tests.
|
|
func NewTestRetentionReaper(
|
|
db *Database,
|
|
mgr *WebhookDBManager,
|
|
) *RetentionReaper {
|
|
return &RetentionReaper{
|
|
db: db,
|
|
dbManager: mgr,
|
|
log: slog.New(slog.NewTextHandler(
|
|
os.Stderr,
|
|
&slog.HandlerOptions{Level: slog.LevelDebug},
|
|
)),
|
|
interval: time.Hour,
|
|
}
|
|
}
|
|
|
|
// ExportSweep runs a single retention sweep synchronously for tests.
|
|
func (r *RetentionReaper) ExportSweep(ctx context.Context) {
|
|
r.sweep(ctx)
|
|
}
|
|
|
|
// ExportRegisterHooks registers the reaper's real fx lifecycle hooks
|
|
// on a lifecycle supplied by a test, so a test can drive the exact
|
|
// OnStart/OnStop functions the application runs and hand OnStart the
|
|
// kind of context fx actually supplies.
|
|
func (r *RetentionReaper) ExportRegisterHooks(lc fx.Lifecycle) {
|
|
r.registerHooks(lc)
|
|
}
|
|
|
|
// ExportStart starts the reaper's background loop for tests.
|
|
func (r *RetentionReaper) ExportStart() {
|
|
r.start()
|
|
}
|
|
|
|
// ExportStop stops the reaper's background loop for tests.
|
|
func (r *RetentionReaper) ExportStop(ctx context.Context) error {
|
|
return r.stop(ctx)
|
|
}
|
|
|
|
// ExportWedgeLoop adds a goroutine to the reaper's WaitGroup that
|
|
// never observes cancellation and returns only when release is
|
|
// closed. It stands in for a sweep stuck on a locked database.
|
|
func (r *RetentionReaper) ExportWedgeLoop(
|
|
release <-chan struct{},
|
|
) {
|
|
r.wg.Go(func() {
|
|
<-release
|
|
})
|
|
}
|
|
|
|
// ExportSetInterval overrides the sweep interval for tests.
|
|
func (r *RetentionReaper) ExportSetInterval(d time.Duration) {
|
|
r.interval = d
|
|
}
|
|
|
|
// ExportSetBannerOut redirects the first-boot credentials banner, so a
|
|
// test can read what the operator would have seen. It must be called
|
|
// before the fx start hook runs, which is where the account is seeded.
|
|
func (d *Database) ExportSetBannerOut(w io.Writer) {
|
|
d.bannerOut = w
|
|
}
|
|
|
|
// DummyPasswordHashForTest exposes the encoded hash that unknown
|
|
// usernames are verified against.
|
|
func DummyPasswordHashForTest() string {
|
|
return dummyPasswordHash()
|
|
}
|
|
|
|
// HashAtShippedCostForTest makes HashPassword hash at the shipped
|
|
// memory cost until t ends. t must not run in parallel with other
|
|
// tests, which would hash at that cost alongside it.
|
|
func HashAtShippedCostForTest(t *testing.T) {
|
|
t.Helper()
|
|
|
|
hashAtShippedCostInTest = true
|
|
|
|
t.Cleanup(func() { hashAtShippedCostInTest = false })
|
|
}
|