初始提交:OCI 面板后端(含 GenAI 网关一期)
This commit is contained in:
Vendored
+95
@@ -0,0 +1,95 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGetSetExpiry(t *testing.T) {
|
||||
c := New(10)
|
||||
if _, ok := c.Get("k"); ok {
|
||||
t.Fatal("空缓存不应命中")
|
||||
}
|
||||
c.Set("k", "v", 50*time.Millisecond)
|
||||
if v, ok := c.Get("k"); !ok || v.(string) != "v" {
|
||||
t.Fatalf("Get = %v %v, want v true", v, ok)
|
||||
}
|
||||
// jitter ≤ TTL/10,60ms 覆盖 50+5ms 上限
|
||||
time.Sleep(60 * time.Millisecond)
|
||||
if _, ok := c.Get("k"); ok {
|
||||
t.Error("过期后不应命中")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeletePrefix(t *testing.T) {
|
||||
c := New(10)
|
||||
c.Set("t1|a", 1, time.Minute)
|
||||
c.Set("t1|b", 2, time.Minute)
|
||||
c.Set("t2|a", 3, time.Minute)
|
||||
c.DeletePrefix("t1|")
|
||||
if _, ok := c.Get("t1|a"); ok {
|
||||
t.Error("t1|a 应被前缀删除")
|
||||
}
|
||||
if _, ok := c.Get("t2|a"); !ok {
|
||||
t.Error("t2|a 不应被删除")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvictAtMax(t *testing.T) {
|
||||
c := New(2)
|
||||
c.Set("a", 1, time.Minute)
|
||||
c.Set("b", 2, time.Minute)
|
||||
c.Set("c", 3, time.Minute)
|
||||
if n := len(c.items); n > 2 {
|
||||
t.Errorf("键数 = %d, 应不超过上限 2", n)
|
||||
}
|
||||
if _, ok := c.Get("c"); !ok {
|
||||
t.Error("最新写入的键应存在")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoSingleflight(t *testing.T) {
|
||||
c := New(10)
|
||||
var calls atomic.Int32
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 8; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
v, err := Do(c, "k", time.Minute, func() (int, error) {
|
||||
calls.Add(1)
|
||||
time.Sleep(30 * time.Millisecond)
|
||||
return 42, nil
|
||||
})
|
||||
if err != nil || v != 42 {
|
||||
t.Errorf("Do = %d, %v", v, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
if n := calls.Load(); n != 1 {
|
||||
t.Errorf("并发 miss 回源 %d 次, want 1", n)
|
||||
}
|
||||
// 命中缓存不再回源
|
||||
if _, err := Do(c, "k", time.Minute, func() (int, error) { calls.Add(1); return 0, nil }); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if n := calls.Load(); n != 1 {
|
||||
t.Errorf("命中后回源 %d 次, want 1", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDoErrorNotCached(t *testing.T) {
|
||||
c := New(10)
|
||||
boom := errors.New("boom")
|
||||
if _, err := Do(c, "k", time.Minute, func() (int, error) { return 0, boom }); !errors.Is(err, boom) {
|
||||
t.Fatalf("err = %v, want boom", err)
|
||||
}
|
||||
v, err := Do(c, "k", time.Minute, func() (int, error) { return 7, nil })
|
||||
if err != nil || v != 7 {
|
||||
t.Errorf("错误不应入缓存,重试 = %d, %v", v, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user