From 35e771e2b61b6f4c718788528e4aef6bed23a78d Mon Sep 17 00:00:00 2001 From: clawbot <35+clawbot@noreply.example.org> Date: Sun, 4 Oct 2026 15:27:55 +0000 Subject: [PATCH] Test that the default cache_max_bytes counts what the cache holds With a fake free-space probe, an empty cache with 4 GiB free gets a 3 GiB default, and the same cache once it holds those 3 GiB, with 1 GiB left free, must keep 3 GiB. The default is still 75% of the free space alone, so the second check fails: this is the bug in https://git.eeqj.de/sneak/pixa/issues/184. computeDefaultMaxBytes only calls the config's existing computation so the test compiles. Model: opus-5-5 --- internal/imgcache/cachesize.go | 17 +++++++ internal/imgcache/cachesize_internal_test.go | 52 ++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 internal/imgcache/cachesize.go create mode 100644 internal/imgcache/cachesize_internal_test.go diff --git a/internal/imgcache/cachesize.go b/internal/imgcache/cachesize.go new file mode 100644 index 0000000..bba06d8 --- /dev/null +++ b/internal/imgcache/cachesize.go @@ -0,0 +1,17 @@ +package imgcache + +import ( + "context" + "path/filepath" + + "sneak.berlin/go/pixa/internal/config" +) + +// computeDefaultMaxBytes returns the default cache size limit for an +// omitted cache_max_bytes, for the filesystem holding /cache/. +func (c *Cache) computeDefaultMaxBytes( + _ context.Context, probe config.FreeSpaceProbeFunc, +) (int64, error) { + return config.ComputeDefaultCacheMaxBytes( + filepath.Join(c.config.StateDir, "cache"), probe) +} diff --git a/internal/imgcache/cachesize_internal_test.go b/internal/imgcache/cachesize_internal_test.go new file mode 100644 index 0000000..668e51d --- /dev/null +++ b/internal/imgcache/cachesize_internal_test.go @@ -0,0 +1,52 @@ +package imgcache + +import ( + "testing" +) + +// TestComputeDefaultMaxBytesCountsWhatTheCacheHolds verifies that the +// default limit is 75% of the free space plus what the cache already +// holds, so a cache filled to its limit keeps that limit across a +// restart instead of shrinking to 75% of the space left free. +func TestComputeDefaultMaxBytesCountsWhatTheCacheHolds(t *testing.T) { + t.Parallel() + + cache, _ := newEvictionTestCache(t, 1<<30) + + // Empty cache, 4 GiB free -> 3 GiB default. + got, err := cache.computeDefaultMaxBytes(t.Context(), + func(string) (uint64, error) { return 4294967296, nil }) + if err != nil { + t.Fatalf("computeDefaultMaxBytes returned error: %v", err) + } + + t.Logf("default for an empty cache with 4 GiB free: %d", got) + + if got != 3221225472 { + t.Errorf("default for an empty cache = %d, want 3221225472 (75%% of 4 GiB)", + got) + } + + // The cache now holds those 3 GiB, which leaves 1 GiB free. + _, err = cache.db.ExecContext(t.Context(), + `INSERT INTO variant_content (cache_key, size_bytes, content_type) + VALUES (?, ?, ?)`, + string(testVariantKeyOne), 3221225472, testContentTypeWebP, + ) + if err != nil { + t.Fatalf("failed to insert variant accounting row: %v", err) + } + + got, err = cache.computeDefaultMaxBytes(t.Context(), + func(string) (uint64, error) { return 1073741824, nil }) + if err != nil { + t.Fatalf("computeDefaultMaxBytes returned error: %v", err) + } + + t.Logf("default for a cache holding 3 GiB with 1 GiB free: %d", got) + + if got != 3221225472 { + t.Errorf("default for a cache holding 3 GiB with 1 GiB free = %d, "+ + "want 3221225472 (75%% of 1 GiB + 3 GiB)", got) + } +}