fix(cache): harden nil receiver handling
Some checks failed
CI / test (push) Failing after 2s
CI / auto-fix (push) Failing after 0s
CI / auto-merge (push) Failing after 0s

This commit is contained in:
Virgil 2026-03-30 00:31:21 +00:00
parent 529e60f3ff
commit 41150c0548
2 changed files with 55 additions and 2 deletions

View file

@ -29,8 +29,8 @@ type Cache struct {
// Entry is the serialized cache record written to the backing Medium.
type Entry struct {
Data json.RawMessage `json:"data"`
CachedAt time.Time `json:"cached_at"`
ExpiresAt time.Time `json:"expires_at"`
CachedAt time.Time `json:"cached_at"`
ExpiresAt time.Time `json:"expires_at"`
}
// New creates a cache and applies default Medium, base directory, and TTL values
@ -73,6 +73,10 @@ func New(medium coreio.Medium, baseDir string, ttl time.Duration) (*Cache, error
//
// path, err := c.Path("github/acme/repos")
func (c *Cache) Path(key string) (string, error) {
if c == nil {
return "", core.E("cache.Path", "cache is nil", nil)
}
baseDir := absolutePath(c.baseDir)
path := absolutePath(core.JoinPath(baseDir, key+".json"))
pathPrefix := normalizePath(core.Concat(baseDir, pathSeparator()))
@ -88,6 +92,10 @@ func (c *Cache) Path(key string) (string, error) {
//
// found, err := c.Get("github/acme/repos", &repos)
func (c *Cache) Get(key string, dest any) (bool, error) {
if c == nil {
return false, core.E("cache.Get", "cache is nil", nil)
}
path, err := c.Path(key)
if err != nil {
return false, err
@ -122,6 +130,10 @@ func (c *Cache) Get(key string, dest any) (bool, error) {
//
// err := c.Set("github/acme/repos", repos)
func (c *Cache) Set(key string, data any) error {
if c == nil {
return core.E("cache.Set", "cache is nil", nil)
}
path, err := c.Path(key)
if err != nil {
return err
@ -157,6 +169,10 @@ func (c *Cache) Set(key string, data any) error {
//
// err := c.Delete("github/acme/repos")
func (c *Cache) Delete(key string) error {
if c == nil {
return core.E("cache.Delete", "cache is nil", nil)
}
path, err := c.Path(key)
if err != nil {
return err
@ -176,6 +192,10 @@ func (c *Cache) Delete(key string) error {
//
// err := c.Clear()
func (c *Cache) Clear() error {
if c == nil {
return core.E("cache.Clear", "cache is nil", nil)
}
if err := c.medium.DeleteAll(c.baseDir); err != nil {
return core.E("cache.Clear", "failed to clear cache", err)
}
@ -186,6 +206,10 @@ func (c *Cache) Clear() error {
//
// age := c.Age("github/acme/repos")
func (c *Cache) Age(key string) time.Duration {
if c == nil {
return -1
}
path, err := c.Path(key)
if err != nil {
return -1

View file

@ -145,6 +145,35 @@ func TestCache_Age_Good(t *testing.T) {
}
}
func TestCache_NilReceiver_Good(t *testing.T) {
var c *cache.Cache
var target map[string]string
if _, err := c.Path("x"); err == nil {
t.Fatal("expected Path to fail on nil receiver")
}
if _, err := c.Get("x", &target); err == nil {
t.Fatal("expected Get to fail on nil receiver")
}
if err := c.Set("x", map[string]string{"foo": "bar"}); err == nil {
t.Fatal("expected Set to fail on nil receiver")
}
if err := c.Delete("x"); err == nil {
t.Fatal("expected Delete to fail on nil receiver")
}
if err := c.Clear(); err == nil {
t.Fatal("expected Clear to fail on nil receiver")
}
if age := c.Age("x"); age != -1 {
t.Fatalf("expected Age to return -1 on nil receiver, got %v", age)
}
}
func TestCache_Delete_Good(t *testing.T) {
c, _ := newTestCache(t, "/tmp/cache-delete", time.Minute)