style: mechanical lint conformance for #55's code under the canonical config

No behavior changes. Covers the purely mechanical findings the canonical
v2.12.2 config raises on the cache-size/eviction work:

- nolintlint: deleted 7 dead //nolint:gosec directives (cachesize.go x2,
  config.go, eviction.go x2, storage.go x2). gosec never raises G115/G703
  on those lines under the pinned toolchain, exactly the defect class
  that failed round 2 of this PR. The 6 live gosec suppressions are
  untouched.
- funcorder: moved writeIfAbsent after Exists (storage.go) and
  touchVariant/touchSourceContent after IncrementStats (cache.go).
- lll: wrapped over-length signatures, calls and messages at 88 columns.
- paralleltest: t.Parallel() on the new eviction, contentlock and
  cache_max_bytes tests and their subtests. configFromYAML uses only
  t.TempDir, so the config cases are parallel-safe.
- noctx: test helper DB calls now use ExecContext/QueryContext/
  QueryRowContext with t.Context().
- goconst: extracted testHeaderContentType into the shared test constant
  block and testVariantKeyOne into the eviction tests; reused the
  existing testContentTypeJPEG and keyCacheMaxBytes constants.
- modernize: interface{} to any, atomic.Int32 for the contentlock
  counters, min/max in ComputeDefaultCacheMaxBytes.
- intrange: integer range loops in the contentlock tests.
- wsl_v5: whitespace before the contentlock rendezvous statements.
- sloglint: slog.DiscardHandler in the config test logger.
- cyclop/funlen: split TestZeroMaxBytesDisablesDiskCache into four
  assertion helpers and extracted the concurrent store goroutine from
  TestEvictSourceBlobExcludesConcurrentStoreOfIdenticalContent. Every
  assertion is preserved verbatim; only their grouping changed.
This commit is contained in:
2026-08-09 13:28:12 +00:00
parent 6ca8560995
commit ca47bb096c
10 changed files with 402 additions and 233 deletions

View File

@@ -2,7 +2,6 @@ package config
import (
"errors"
"io"
"log/slog"
"os"
"path/filepath"
@@ -13,7 +12,7 @@ import (
// discardLogger returns a logger that swallows all output, for tests
// that exercise code paths which log.
func discardLogger() *slog.Logger {
return slog.New(slog.NewTextHandler(io.Discard, nil))
return slog.New(slog.DiscardHandler)
}
// TestCacheMaxBytesExplicitValueUsedWithoutFloor verifies that an
@@ -21,6 +20,8 @@ func discardLogger() *slog.Logger {
// given: the 500 MiB floor applies only to the computed default, never
// to explicit values.
func TestCacheMaxBytesExplicitValueUsedWithoutFloor(t *testing.T) {
t.Parallel()
yamlContent := "signing_key: " + validTestSigningKey + "\ncache_max_bytes: 1024\n"
c, err := configFromYAML(t, yamlContent)
@@ -38,6 +39,8 @@ func TestCacheMaxBytesExplicitValueUsedWithoutFloor(t *testing.T) {
// explicit zero is a valid value (it disables the disk cache), not an
// error.
func TestCacheMaxBytesZeroIsValidAndDisablesCache(t *testing.T) {
t.Parallel()
yamlContent := "signing_key: " + validTestSigningKey + "\ncache_max_bytes: 0\n"
c, err := configFromYAML(t, yamlContent)
@@ -53,7 +56,10 @@ func TestCacheMaxBytesZeroIsValidAndDisablesCache(t *testing.T) {
// TestCacheMaxBytesLargeExplicitValueParses verifies that values above
// 32-bit range parse correctly (the field is an int64 byte count).
func TestCacheMaxBytesLargeExplicitValueParses(t *testing.T) {
yamlContent := "signing_key: " + validTestSigningKey + "\ncache_max_bytes: 10737418240\n"
t.Parallel()
yamlContent := "signing_key: " + validTestSigningKey +
"\ncache_max_bytes: 10737418240\n"
c, err := configFromYAML(t, yamlContent)
if err != nil {
@@ -70,6 +76,8 @@ func TestCacheMaxBytesLargeExplicitValueParses(t *testing.T) {
// offending value, per the no-silent-fallback rule: defaults apply
// only to omitted keys.
func TestCacheMaxBytesInvalidValuesAbortStartup(t *testing.T) {
t.Parallel()
signingKeyLine := "signing_key: " + validTestSigningKey + "\n"
cases := []struct {
@@ -81,45 +89,48 @@ func TestCacheMaxBytesInvalidValuesAbortStartup(t *testing.T) {
{
name: "negative",
yaml: signingKeyLine + "cache_max_bytes: -1024\n",
wantErrSubstrings: []string{"cache_max_bytes", "-1024"},
wantErrSubstrings: []string{keyCacheMaxBytes, "-1024"},
},
{
name: "float",
yaml: signingKeyLine + "cache_max_bytes: 3.5\n",
wantErrSubstrings: []string{"cache_max_bytes", "3.5"},
wantErrSubstrings: []string{keyCacheMaxBytes, "3.5"},
},
{
name: "non-numeric string",
yaml: signingKeyLine + "cache_max_bytes: banana\n",
wantErrSubstrings: []string{"cache_max_bytes", "banana"},
wantErrSubstrings: []string{keyCacheMaxBytes, "banana"},
},
{
name: "explicit null",
yaml: signingKeyLine + "cache_max_bytes: null\n",
wantErrSubstrings: []string{"cache_max_bytes", "null"},
wantErrSubstrings: []string{keyCacheMaxBytes, "null"},
},
{
name: "bare key no value",
yaml: signingKeyLine + "cache_max_bytes:\n",
wantErrSubstrings: []string{"cache_max_bytes", "null"},
wantErrSubstrings: []string{keyCacheMaxBytes, "null"},
},
{
name: "boolean",
yaml: signingKeyLine + "cache_max_bytes: true\n",
wantErrSubstrings: []string{"cache_max_bytes", "true"},
wantErrSubstrings: []string{keyCacheMaxBytes, "true"},
},
{
name: "list",
yaml: signingKeyLine + "cache_max_bytes:\n - 1\n",
wantErrSubstrings: []string{"cache_max_bytes"},
wantErrSubstrings: []string{keyCacheMaxBytes},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
c, err := configFromYAML(t, tc.yaml)
if err == nil {
t.Fatalf("config with %s cache_max_bytes must abort startup, got config: %+v",
t.Fatalf(
"config with %s cache_max_bytes must abort startup, got config: %+v",
tc.name, c)
}
@@ -138,6 +149,8 @@ func TestCacheMaxBytesInvalidValuesAbortStartup(t *testing.T) {
// computed default is 75% of the probed free space when that exceeds
// the floor.
func TestComputeDefaultCacheMaxBytesUses75PercentOfFreeSpace(t *testing.T) {
t.Parallel()
// 4 GiB free -> 3 GiB default.
probe := func(string) (uint64, error) { return 4294967296, nil }
@@ -147,7 +160,8 @@ func TestComputeDefaultCacheMaxBytesUses75PercentOfFreeSpace(t *testing.T) {
}
if got != 3221225472 {
t.Errorf("ComputeDefaultCacheMaxBytes = %d, want 3221225472 (75%% of 4 GiB)", got)
t.Errorf("ComputeDefaultCacheMaxBytes = %d, want 3221225472 (75%% of 4 GiB)",
got)
}
}
@@ -155,6 +169,8 @@ func TestComputeDefaultCacheMaxBytesUses75PercentOfFreeSpace(t *testing.T) {
// verifies that when 75% of free space is below 500 MiB, the computed
// default is floored at DefaultCacheMaxBytesFloor.
func TestComputeDefaultCacheMaxBytesAppliesFloorToComputedDefault(t *testing.T) {
t.Parallel()
cases := []struct {
name string
freeBytes uint64
@@ -166,6 +182,8 @@ func TestComputeDefaultCacheMaxBytesAppliesFloorToComputedDefault(t *testing.T)
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
probe := func(string) (uint64, error) { return tc.freeBytes, nil }
got, err := ComputeDefaultCacheMaxBytes(t.TempDir(), probe)
@@ -185,6 +203,8 @@ func TestComputeDefaultCacheMaxBytesAppliesFloorToComputedDefault(t *testing.T)
// failing free-space probe produces an error naming the config key,
// instead of a silently wrong default.
func TestComputeDefaultCacheMaxBytesPropagatesProbeError(t *testing.T) {
t.Parallel()
probe := func(string) (uint64, error) { return 0, errors.New("statfs failed") }
_, err := ComputeDefaultCacheMaxBytes(t.TempDir(), probe)
@@ -194,7 +214,7 @@ func TestComputeDefaultCacheMaxBytesPropagatesProbeError(t *testing.T) {
t.Logf("got expected error: %v", err)
if !strings.Contains(err.Error(), "cache_max_bytes") {
if !strings.Contains(err.Error(), keyCacheMaxBytes) {
t.Errorf("error %q does not name the config key cache_max_bytes", err.Error())
}
}
@@ -205,6 +225,8 @@ func TestComputeDefaultCacheMaxBytesPropagatesProbeError(t *testing.T) {
// first so statfs measures the right filesystem), and that the result
// lands on the Config.
func TestResolveCacheMaxBytesComputesDefaultWhenOmitted(t *testing.T) {
t.Parallel()
c, err := configFromYAML(t, "signing_key: "+validTestSigningKey+"\n")
if err != nil {
t.Fatalf("minimal config should be valid, got error: %v", err)
@@ -227,11 +249,13 @@ func TestResolveCacheMaxBytesComputesDefaultWhenOmitted(t *testing.T) {
}
if c.CacheMaxBytes != 3221225472 {
t.Errorf("CacheMaxBytes = %d, want computed default 3221225472", c.CacheMaxBytes)
t.Errorf("CacheMaxBytes = %d, want computed default 3221225472",
c.CacheMaxBytes)
}
if probedPath != wantCacheDir {
t.Errorf("free space probed at %q, want cache directory %q", probedPath, wantCacheDir)
t.Errorf("free space probed at %q, want cache directory %q",
probedPath, wantCacheDir)
}
info, err := os.Stat(wantCacheDir)
@@ -245,6 +269,8 @@ func TestResolveCacheMaxBytesComputesDefaultWhenOmitted(t *testing.T) {
// an explicitly configured value survives resolution untouched and
// that the free-space probe is never consulted for it.
func TestResolveCacheMaxBytesDoesNotOverrideExplicitValue(t *testing.T) {
t.Parallel()
yamlContent := "signing_key: " + validTestSigningKey + "\ncache_max_bytes: 1024\n"
c, err := configFromYAML(t, yamlContent)

View File

@@ -44,7 +44,7 @@ func defaultFreeSpaceProbe(path string) (uint64, error) {
return 0, fmt.Errorf("statfs reported negative block size %d for %q", stat.Bsize, path)
}
blockSize := uint64(stat.Bsize) //nolint:gosec // G115: negative Bsize rejected above
blockSize := uint64(stat.Bsize)
return stat.Bavail * blockSize, nil
}
@@ -52,7 +52,9 @@ func defaultFreeSpaceProbe(path string) (uint64, error) {
// ComputeDefaultCacheMaxBytes returns the default cache size limit for
// the filesystem containing cacheDir: 75% of the free bytes reported
// by probe, with a floor of DefaultCacheMaxBytesFloor.
func ComputeDefaultCacheMaxBytes(cacheDir string, probe FreeSpaceProbeFunc) (int64, error) {
func ComputeDefaultCacheMaxBytes(
cacheDir string, probe FreeSpaceProbeFunc,
) (int64, error) {
freeBytes, err := probe(cacheDir)
if err != nil {
return 0, fmt.Errorf("config key %q: cannot determine free space for %q: %w",
@@ -60,15 +62,10 @@ func ComputeDefaultCacheMaxBytes(cacheDir string, probe FreeSpaceProbeFunc) (int
}
computed := freeBytes / freeSpaceFractionDenominator * freeSpaceFractionNumerator
if computed > math.MaxInt64 {
computed = math.MaxInt64
}
computed = min(computed, math.MaxInt64)
limit := int64(computed) //nolint:gosec // G115: clamped to MaxInt64 above
if limit < DefaultCacheMaxBytesFloor {
limit = DefaultCacheMaxBytesFloor
}
limit := int64(computed)
limit = max(limit, DefaultCacheMaxBytesFloor)
return limit, nil
}
@@ -79,7 +76,9 @@ func ComputeDefaultCacheMaxBytes(cacheDir string, probe FreeSpaceProbeFunc) (int
// on free space in <state_dir>/cache/. The cache directory is created
// first so statfs measures the filesystem that will actually hold the
// cache. The effective limit is logged either way.
func (c *Config) resolveCacheMaxBytes(log *slog.Logger, probe FreeSpaceProbeFunc) error {
func (c *Config) resolveCacheMaxBytes(
log *slog.Logger, probe FreeSpaceProbeFunc,
) error {
if !c.cacheMaxBytesExplicit {
cacheDir := filepath.Join(c.StateDir, "cache")

View File

@@ -622,7 +622,7 @@ func getInt64(sc *smartconfig.Config, key string, defaultVal int64) (int64, erro
key, val)
}
return int64(val), nil //nolint:gosec // G115: bounds checked above
return int64(val), nil
case float64:
if val != math.Trunc(val) {
return 0, fmt.Errorf("config key %q: value %v is not an integer", key, val)