Files
2026-05-31 20:17:49 -05:00

77 lines
1.7 KiB
Go

package httpapi
import (
"bytes"
"sync"
"sync/atomic"
"testing"
"time"
)
func TestRawContentCacheCoalescesConcurrentLoads(t *testing.T) {
t.Parallel()
cache := newRawContentCache(8, 8*1024*1024)
var loads int32
want := []byte("coalesced")
var wg sync.WaitGroup
for i := 0; i < 12; i++ {
wg.Add(1)
go func() {
defer wg.Done()
got, err, _ := cache.GetOrLoad("shared-id", func() ([]byte, error) {
atomic.AddInt32(&loads, 1)
time.Sleep(15 * time.Millisecond)
return want, nil
})
if err != nil {
t.Errorf("GetOrLoad() error = %v", err)
return
}
if !bytes.Equal(got, want) {
t.Errorf("GetOrLoad() content mismatch = %q, want %q", got, want)
}
}()
}
wg.Wait()
if got := atomic.LoadInt32(&loads); got != 1 {
t.Fatalf("loader call count = %d, want 1", got)
}
}
func TestRawContentCacheEvictionCausesReload(t *testing.T) {
t.Parallel()
cache := newRawContentCache(1, 3)
var loadsA int32
var loadsB int32
if _, err, _ := cache.GetOrLoad("a", func() ([]byte, error) {
atomic.AddInt32(&loadsA, 1)
return []byte("aaa"), nil
}); err != nil {
t.Fatalf("GetOrLoad(a) error = %v", err)
}
if _, err, _ := cache.GetOrLoad("b", func() ([]byte, error) {
atomic.AddInt32(&loadsB, 1)
return []byte("bbb"), nil
}); err != nil {
t.Fatalf("GetOrLoad(b) error = %v", err)
}
if _, err, _ := cache.GetOrLoad("a", func() ([]byte, error) {
atomic.AddInt32(&loadsA, 1)
return []byte("aaa"), nil
}); err != nil {
t.Fatalf("GetOrLoad(a second) error = %v", err)
}
if got := atomic.LoadInt32(&loadsB); got != 1 {
t.Fatalf("loadsB = %d, want 1", got)
}
if got := atomic.LoadInt32(&loadsA); got != 2 {
t.Fatalf("loadsA = %d, want 2", got)
}
}