Skip to content

Commit 19d5bc2

Browse files
authored
[test] Add tests for syncutil.TTLCache.GetOrCreate with maxSize <= 0 (#7491)
## Test Coverage Improvement: `TTLCache.GetOrCreate` ### Function Analyzed - **Package**: `internal/syncutil` - **Function**: `(*TTLCache[K, V]).GetOrCreate` - **Previous Coverage**: 97.7% (package), 96.2% (function) - **New Coverage**: 100.0% (package), 100.0% (function) - **Complexity**: Medium — TTL eviction, LRU eviction, concurrent locking, and now the passthrough (`maxSize <= 0`) code path ### Why This Function? Running `go test -coverprofile=coverage.out ./internal/syncutil/...` revealed that `TTLCache.GetOrCreate` had one uncovered branch: ```go func (c *TTLCache[K, V]) GetOrCreate(key K, create func() V) V { if c.maxSize <= 0 { return create() // ← NOT COVERED } // ... cache lookup, TTL eviction, LRU eviction ... } ``` When `maxSize` is zero or negative, `GetOrCreate` intentionally becomes a passthrough: it calls `create()` on every invocation and never stores anything. This is a deliberate design choice that lets callers disable caching without modifying call-sites. The branch existed but had zero test coverage. ### Tests Added - ✅ `maxSize = 0` — boundary value; cache is fully disabled - ✅ `maxSize = -1` — negative value; cache is disabled - ✅ `maxSize = -100` — large negative; cache is disabled - ✅ Verifies `create()` is called on **every** invocation (no caching) - ✅ Verifies successive calls return fresh values (not a cached result) - ✅ Verifies `Len()` always returns 0 (nothing is stored) ### Coverage Report ``` Before: github.com/github/gh-aw-mcpg/internal/syncutil/ttl_cache.go:56: GetOrCreate 96.2% total: (statements) 97.7% After: github.com/github/gh-aw-mcpg/internal/syncutil/ttl_cache.go:56: GetOrCreate 100.0% total: (statements) 100.0% Improvement: +2.3pp (package), +3.8pp (function) ``` ### Test Execution All tests pass: ``` === RUN TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache === RUN TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache/zero_disables_cache === RUN TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache/negative_one_disables_cache === RUN TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache/large_negative_disables_cache --- PASS: TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache (0.00s) ok github.com/github/gh-aw-mcpg/internal/syncutil 0.205s coverage: 100.0% of statements ``` --- *Generated by Test Coverage Improver* *Next run will target the next most complex under-tested function* > [!WARNING] > <details> > <summary>Firewall blocked 9 domains</summary> > > The following domains were blocked by the firewall during workflow execution: > > - `go.googlesource.com` > - `go.opentelemetry.io` > - `go.yaml.in` > - `golang.org` > - `google.golang.org` > - `gopkg.in` > - `goproxy.io` > - `proxy.golang.org` > - `releaseassets.githubusercontent.com` >> To allow these domains, add them to the `network.allowed` list in your workflow frontmatter: > > ```yaml > network: > allowed: > - defaults > - "go.googlesource.com" > - "go.opentelemetry.io" > - "go.yaml.in" > - "golang.org" > - "google.golang.org" > - "gopkg.in" > - "goproxy.io" > - "proxy.golang.org" > - "releaseassets.githubusercontent.com" > ``` > > See [Network Configuration](https://github.github.com/gh-aw/reference/network/) for more information. > > </details> > Generated by [Test Coverage Improver](https://github.com/github/gh-aw-mcpg/actions/runs/27473008462) · 1.8K AIC · ⊞ 28.7K · [◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw-mcpg+%22gh-aw-workflow-id%3A+test-coverage-improver%22&type=pullrequests) <!-- gh-aw-agentic-workflow: Test Coverage Improver, engine: copilot, version: 1.0.60, model: claude-sonnet-4.6, id: 27473008462, workflow_id: test-coverage-improver, run: https://github.com/github/gh-aw-mcpg/actions/runs/27473008462 --> <!-- gh-aw-workflow-id: test-coverage-improver --> <!-- gh-aw-workflow-call-id: github/gh-aw-mcpg/test-coverage-improver -->
2 parents a5b5c18 + 71ca070 commit 19d5bc2

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

internal/syncutil/ttl_cache_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,44 @@ func TestTTLCache_ConcurrentAccess(t *testing.T) {
207207
assert.LessOrEqual(t, createCount.Load(), int32(10), "at most 10 unique keys")
208208
}
209209

210+
// TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache verifies that
211+
// when maxSize is zero or negative every GetOrCreate call invokes create()
212+
// directly without caching the result, and Len() always reports zero entries.
213+
//
214+
// A maxSize <= 0 cache is intentionally a passthrough: useful for testing code
215+
// that accepts a *TTLCache or for runtime-disabling the cache without changing
216+
// call-sites.
217+
func TestTTLCache_GetOrCreate_MaxSizeZeroOrNegativeBypassesCache(t *testing.T) {
218+
tests := []struct {
219+
name string
220+
maxSize int
221+
}{
222+
{name: "zero disables cache", maxSize: 0},
223+
{name: "negative one disables cache", maxSize: -1},
224+
{name: "large negative disables cache", maxSize: -100},
225+
}
226+
227+
for _, tt := range tests {
228+
t.Run(tt.name, func(t *testing.T) {
229+
cache := NewTTLCache[string, int](time.Hour, tt.maxSize)
230+
231+
createCount := 0
232+
233+
// First call: create must be invoked.
234+
first := cache.GetOrCreate("key", func() int { createCount++; return 42 })
235+
assert.Equal(t, 42, first)
236+
assert.Equal(t, 1, createCount, "create should be called on first access")
237+
assert.Equal(t, 0, cache.Len(), "nothing should be stored when maxSize <= 0")
238+
239+
// Second call with the same key: create must be invoked again (no caching).
240+
second := cache.GetOrCreate("key", func() int { createCount++; return 99 })
241+
assert.Equal(t, 99, second, "second call should return the new value (not a cached result)")
242+
assert.Equal(t, 2, createCount, "create should be called on every access when maxSize <= 0")
243+
assert.Equal(t, 0, cache.Len(), "cache must remain empty after second access")
244+
})
245+
}
246+
}
247+
210248
// TestTTLCache_MaxSizeOne verifies edge behaviour when maxSize is 1.
211249
func TestTTLCache_MaxSizeOne(t *testing.T) {
212250
clk := newFakeClock()

0 commit comments

Comments
 (0)