All checks were successful
check / check (push) Successful in 2m3s
Replace .golangci.yml with the canonical v2-schema config (default: all minus six disabled linters, lll 88, tests included) and bump every golangci-lint pin to v2.12.2: - Dockerfile: golangci/golangci-lint:v2.12.2-alpine (hash-pinned) - script/bootstrap: GOLANGCI_LINT_VERSION 2.12.2 with new linux-amd64/arm64 release-archive sha256 pins Fix all 747 findings the stricter config surfaces, with no behavior changes: t.Parallel() throughout the test suite, static sentinel errors and errors.Is comparisons, checked error returns, context propagation (contextcheck/noctx), 88-column wrapping, extracted constants and helpers for goconst/dupl/funlen/cyclop, exhaustive switch cases replicating existing defaults, and white-box test files renamed to *_internal_test.go for testpackage. Three nolint:tagliatelle directives preserve the existing snake_case JSON wire and on-disk metadata formats.
104 lines
1.9 KiB
Go
104 lines
1.9 KiB
Go
package imgcache
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/pixa/internal/database"
|
|
)
|
|
|
|
func setupStatsTestDB(t *testing.T) *sql.DB {
|
|
t.Helper()
|
|
|
|
db, err := sql.Open("sqlite", ":memory:")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
err = database.ApplyMigrations(context.Background(), db, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
t.Cleanup(func() { _ = db.Close() })
|
|
|
|
return db
|
|
}
|
|
|
|
func TestStats_HitRateIsRatio(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := setupStatsTestDB(t)
|
|
dir := t.TempDir()
|
|
|
|
cache, err := NewCache(db, CacheConfig{
|
|
StateDir: dir,
|
|
CacheTTL: time.Hour,
|
|
NegativeTTL: 5 * time.Minute,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
ctx := context.Background()
|
|
|
|
// Set some hit/miss counts and a transform_count
|
|
_, err = db.ExecContext(ctx, `
|
|
UPDATE cache_stats
|
|
SET hit_count = 75, miss_count = 25, transform_count = 9999
|
|
WHERE id = 1
|
|
`)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
stats, err := cache.Stats(ctx)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if stats.HitCount != 75 {
|
|
t.Errorf("HitCount = %d, want 75", stats.HitCount)
|
|
}
|
|
|
|
if stats.MissCount != 25 {
|
|
t.Errorf("MissCount = %d, want 25", stats.MissCount)
|
|
}
|
|
|
|
// HitRate should be 0.75, NOT 9999 (transform_count)
|
|
expectedRate := 0.75
|
|
if math.Abs(stats.HitRate-expectedRate) > 0.001 {
|
|
t.Errorf("HitRate = %f, want %f (was it scanning transform_count?)",
|
|
stats.HitRate, expectedRate)
|
|
}
|
|
}
|
|
|
|
func TestStats_ZeroCounts(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
db := setupStatsTestDB(t)
|
|
dir := t.TempDir()
|
|
|
|
cache, err := NewCache(db, CacheConfig{
|
|
StateDir: dir,
|
|
CacheTTL: time.Hour,
|
|
NegativeTTL: 5 * time.Minute,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
stats, err := cache.Stats(context.Background())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// With zero hits and misses, HitRate should be 0, not some garbage value
|
|
if stats.HitRate != 0.0 {
|
|
t.Errorf("HitRate = %f, want 0.0 for zero counts", stats.HitRate)
|
|
}
|
|
}
|