2 Commits
Author SHA1 Message Date
clawbot 9ed38b7c28 Move the example config to configs/, delete scripts/ and CONVENTIONS.md (closes #97)
check / check (push) Failing after 3s
config.example.yml moves unchanged to configs/config.example.yml, the
directory REPO_POLICIES.md names for configuration examples. README.md,
the comments in internal/config/config.go and the startup error for the
placeholder signing key name the new path. scripts/manual-test.sh and
its directory are deleted. The handler tests in internal/handlers cover
every check it made except two: fetching a real image from the internet,
and a URL made on the generator page with a ttl answering 410 once the
ttl has passed (#199).
CONVENTIONS.md, a reformatted copy of the Go HTTP server conventions, is
deleted, as REPO_POLICIES.md links the canonical document.

Model: opus-5-5
2026-10-04 18:26:02 +00:00
clawbot 66e71b4207 Make the periodic reconciliation test wait for the startup pass (closes #189)
check / check (push) Failing after 2s
TestPeriodicReconciliationAdoptsFileThatAppearsAfterStartup slept for
three eviction intervals before writing its file, so on a slow start the
startup pass could still be running and adopt the file itself, and the
test passed without a periodic pass. It now holds the test database's
only connection until the startup pass waits for it, writes the file and
lets the connection go, as TestEvictionRunsOnPeriodicSchedule does, so
only a periodic reconciliation pass can adopt the file. Test only.

Model: opus-5-5
2026-10-04 19:59:36 +02:00
2 changed files with 34 additions and 9 deletions
+11 -1
View File
@@ -36,9 +36,19 @@ P2: security: referer blacklist
`README.md`, the comments in `internal/config/config.go` and the startup error `README.md`, the comments in `internal/config/config.go` and the startup error
for the placeholder signing key name the new path; `scripts/manual-test.sh` for the placeholder signing key name the new path; `scripts/manual-test.sh`
and its directory are deleted, as the handler tests in `internal/handlers` and its directory are deleted, as the handler tests in `internal/handlers`
cover every check it made except fetching a real image from the internet; cover every check it made except two: fetching a real image from the
internet, and a URL made on the generator page with a `ttl` answering 410 once
the `ttl` has passed (https://git.eeqj.de/sneak/pixa/issues/199);
`CONVENTIONS.md` is deleted, as `REPO_POLICIES.md` links the canonical Go HTTP `CONVENTIONS.md` is deleted, as `REPO_POLICIES.md` links the canonical Go HTTP
server conventions. server conventions.
- 2026-10-04 `TestPeriodicReconciliationAdoptsFileThatAppearsAfterStartup`
only passes through a periodic pass (closes #189): it slept for three
eviction intervals before writing its file, and a startup pass still running
then could adopt the file itself. It now holds the test database's only
connection until the startup pass waits for it after walking the empty
variant directory, writes the file and lets the connection go, as
`TestEvictionRunsOnPeriodicSchedule` does, so only a periodic reconciliation
pass can adopt the file. Test only.
- 2026-10-04 logging in, logging out, the URL generator and `/v1/e/` have - 2026-10-04 logging in, logging out, the URL generator and `/v1/e/` have
handler tests (closes #77): new tests in `internal/handlers`, with no handler tests (closes #77): new tests in `internal/handlers`, with no
network, check that `GET /` without a login session shows the login form; a network, check that `GET /` without a login session shows the login form; a
+23 -8
View File
@@ -847,15 +847,28 @@ func TestPeriodicReconciliationAdoptsFileThatAppearsAfterStartup(t *testing.T) {
cache, _ := newEvictionTestCache(t, 1<<30) cache, _ := newEvictionTestCache(t, 1<<30)
const interval = 100 * time.Millisecond // Hold the test database's only connection, so the startup pass
// waits for it after walking the still empty variant directory: the
// file written while it waits is first seen by a periodic pass.
conn, err := cache.db.Conn(t.Context())
if err != nil {
t.Fatalf("failed to take the database connection: %v", err)
}
cache.StartEviction(interval) defer func() { _ = conn.Close() }()
cache.StartEviction(100 * time.Millisecond)
defer func() { _ = cache.StopEviction(t.Context()) }() defer func() { _ = cache.StopEviction(t.Context()) }()
// Let startup reconciliation run and settle on an empty cache deadline := time.Now().Add(5 * time.Second)
// before introducing the untracked file, so the adoption we assert
// below can only be the work of a later, periodic pass. for cache.db.Stats().WaitCount == 0 {
time.Sleep(3 * interval) if time.Now().After(deadline) {
t.Fatal("the startup pass never waited for the database")
}
time.Sleep(10 * time.Millisecond)
}
// Simulate a variant whose accounting insert failed after the // Simulate a variant whose accounting insert failed after the
// process was already running and serving requests: the content // process was already running and serving requests: the content
@@ -864,14 +877,16 @@ func TestPeriodicReconciliationAdoptsFileThatAppearsAfterStartup(t *testing.T) {
// insert had failed and only the file write had succeeded. // insert had failed and only the file write had succeeded.
untracked := bytes.Repeat([]byte{0x41}, 900) untracked := bytes.Repeat([]byte{0x41}, 900)
_, err := cache.variants.Store( _, err = cache.variants.Store(
"aabbccdd0099", bytes.NewReader(untracked), "image/webp", "aabbccdd0099", bytes.NewReader(untracked), "image/webp",
) )
if err != nil { if err != nil {
t.Fatalf("failed to store untracked variant file: %v", err) t.Fatalf("failed to store untracked variant file: %v", err)
} }
deadline := time.Now().Add(5 * time.Second) _ = conn.Close()
deadline = time.Now().Add(5 * time.Second)
var usage int64 var usage int64