| package executor |
|
|
| import ( |
| "context" |
| "errors" |
| "testing" |
| "time" |
| ) |
|
|
| type mockCodexKVStore struct { |
| data map[string]string |
| getErr error |
| setErr error |
| lastSetK string |
| lastTTL time.Duration |
| } |
|
|
| func (m *mockCodexKVStore) Get(_ context.Context, key string) (string, error) { |
| if m.getErr != nil { |
| return "", m.getErr |
| } |
| if m.data == nil { |
| return "", nil |
| } |
| return m.data[key], nil |
| } |
|
|
| func (m *mockCodexKVStore) Set(_ context.Context, key, value string, ttl time.Duration) error { |
| m.lastSetK = key |
| m.lastTTL = ttl |
| if m.setErr != nil { |
| return m.setErr |
| } |
| if m.data == nil { |
| m.data = make(map[string]string) |
| } |
| m.data[key] = value |
| return nil |
| } |
|
|
| func (m *mockCodexKVStore) Del(_ context.Context, _ ...string) error { return nil } |
| func (m *mockCodexKVStore) Ping(_ context.Context) error { return nil } |
|
|
| func TestGetCodexCache_RedisHit(t *testing.T) { |
| defer SetCodexKVStore(nil) |
| store := &mockCodexKVStore{} |
| SetCodexKVStore(store) |
|
|
| exp := time.Now().Add(10 * time.Minute).UTC().Format(time.RFC3339Nano) |
| store.data = map[string]string{ |
| "codex:model:user": `{"ID":"abc","Expire":"` + exp + `"}`, |
| } |
|
|
| entry, ok := getCodexCache("model:user") |
| if !ok { |
| t.Fatalf("expected cache hit") |
| } |
| if entry.ID != "abc" { |
| t.Fatalf("expected id abc, got %s", entry.ID) |
| } |
| } |
|
|
| func TestGetCodexCache_FallbackToMemoryOnRedisError(t *testing.T) { |
| defer SetCodexKVStore(nil) |
| store := &mockCodexKVStore{getErr: errors.New("boom")} |
| SetCodexKVStore(store) |
|
|
| codexCacheMu.Lock() |
| codexCacheMap = map[string]codexCache{ |
| "m:u": {ID: "mem", Expire: time.Now().Add(10 * time.Minute)}, |
| } |
| codexCacheMu.Unlock() |
|
|
| entry, ok := getCodexCache("m:u") |
| if !ok { |
| t.Fatalf("expected memory fallback hit") |
| } |
| if entry.ID != "mem" { |
| t.Fatalf("expected memory id mem, got %s", entry.ID) |
| } |
| } |
|
|
| func TestSetCodexCache_WritesRedisAndMemory(t *testing.T) { |
| defer SetCodexKVStore(nil) |
| store := &mockCodexKVStore{} |
| SetCodexKVStore(store) |
|
|
| entry := codexCache{ID: "cid", Expire: time.Now().Add(time.Hour)} |
| setCodexCache("m:u", entry) |
|
|
| if store.lastSetK != "codex:m:u" { |
| t.Fatalf("expected redis key codex:m:u, got %s", store.lastSetK) |
| } |
| if store.lastTTL <= 0 { |
| t.Fatalf("expected positive ttl") |
| } |
|
|
| codexCacheMu.RLock() |
| mem, ok := codexCacheMap["m:u"] |
| codexCacheMu.RUnlock() |
| if !ok || mem.ID != "cid" { |
| t.Fatalf("expected memory cache write") |
| } |
| } |
|
|