// Copyright (c) 2026 Zeni Kim // Use of this source code is governed by MIT-style // license that can be found in the LICENSE file. package core import ( "fmt" "os" "testing" "time" ) func TestNewCacheNilDoesNotPanic(t *testing.T) { // With caching disabled, a failed Redis ping must NOT panic. prevHost := os.Getenv("REDIS_HOST") prevPort := os.Getenv("REDIS_PORT") prevDB := os.Getenv("REDIS_DB") os.Setenv("REDIS_HOST", "127.0.0.1") os.Setenv("REDIS_PORT", "6379") os.Setenv("REDIS_DB", "0") t.Cleanup(func() { os.Setenv("REDIS_HOST", prevHost) os.Setenv("REDIS_PORT", prevPort) os.Setenv("REDIS_DB", prevDB) }) defer func() { if r := recover(); r != nil { t.Errorf("NewCache should not panic when cache is disabled: %v", r) } }() c := NewCache(CacheConfig{EnableCache: false}) if c == nil { t.Errorf("expected a non-nil Cache instance") } } func TestNewCacheInvalidDBPanics(t *testing.T) { prevDB := os.Getenv("REDIS_DB") os.Setenv("REDIS_DB", "not-a-number") t.Cleanup(func() { os.Setenv("REDIS_DB", prevDB) }) defer func() { if r := recover(); r == nil { t.Errorf("expected NewCache to panic on an invalid REDIS_DB value") } }() _ = NewCache(CacheConfig{EnableCache: false}) } func TestCacheSetGetDelete(t *testing.T) { c := newTestCache(t) key := fmt.Sprintf("goffee_cache_test_%d", time.Now().UnixNano()) t.Cleanup(func() { _ = c.Delete(key) }) if err := c.Set(key, "hello"); err != nil { t.Fatalf("failed cache set: %v", err) } got, err := c.Get(key) if err != nil { t.Fatalf("failed cache get: %v", err) } if got != "hello" { t.Errorf("expected 'hello', got %q", got) } if err := c.Delete(key); err != nil { t.Fatalf("failed cache delete: %v", err) } if _, err := c.Get(key); err == nil { t.Errorf("expected error getting a deleted key") } } func TestCacheGetMissingKey(t *testing.T) { c := newTestCache(t) if _, err := c.Get(fmt.Sprintf("goffee_missing_%d", time.Now().UnixNano())); err == nil { t.Errorf("expected error getting a missing key") } } func TestCacheSetWithExpiration(t *testing.T) { c := newTestCache(t) key := fmt.Sprintf("goffee_cache_exp_%d", time.Now().UnixNano()) t.Cleanup(func() { _ = c.Delete(key) }) if err := c.SetWithExpiration(key, "expiring", 2*time.Second); err != nil { t.Fatalf("failed cache set with expiration: %v", err) } got, err := c.Get(key) if err != nil { t.Fatalf("failed cache get: %v", err) } if got != "expiring" { t.Errorf("expected 'expiring', got %q", got) } } func TestCacheOverwrite(t *testing.T) { c := newTestCache(t) key := fmt.Sprintf("goffee_cache_overwrite_%d", time.Now().UnixNano()) t.Cleanup(func() { _ = c.Delete(key) }) if err := c.Set(key, "first"); err != nil { t.Fatalf("failed first set: %v", err) } if err := c.Set(key, "second"); err != nil { t.Fatalf("failed second set: %v", err) } got, err := c.Get(key) if err != nil { t.Fatalf("failed get: %v", err) } if got != "second" { t.Errorf("expected 'second', got %q", got) } }