package cache import ( "errors" "fmt" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require") var ( called = 0 errSentinel = errors.New("an error") errCached = errors.New("a cached error")) func setup(t *testing.T) (*Cache, CreateFunc) { called = 0 create := func(path string) (interface{}, bool, error) { assert.Equal(t, 0, called) called++ switch path { case "/": return "/", true, nil case "/file.txt": return "/file.txt", true, errCached case "/error": return nil, false, errSentinel } panic(fmt.Sprintf("Unknown path %q", path)) } c := New() return c, create} func TestGet(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, len(c.cache)) f, err := c.Get("/", create) require.NoError(t, err) assert.Equal(t, 1, len(c.cache)) f2, err := c.Get("/", create) require.NoError(t, err) assert.Equal(t, f, f2)} func TestGetFile(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, len(c.cache)) f, err := c.Get("/file.txt", create) require.Equal(t, errCached, err) assert.Equal(t, 1, len(c.cache)) f2, err := c.Get("/file.txt", create) require.Equal(t, errCached, err) assert.Equal(t, f, f2)} func TestGetError(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, len(c.cache)) f, err := c.Get("/error", create) require.Equal(t, errSentinel, err) require.Equal(t, nil, f) assert.Equal(t, 0, len(c.cache))} func TestPut(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, len(c.cache)) c.Put("/alien", "slime") assert.Equal(t, 1, len(c.cache)) fNew, err := c.Get("/alien", create) require.NoError(t, err) require.Equal(t, "slime", fNew) assert.Equal(t, 1, len(c.cache))} func TestCacheExpire(t *testing.T) { c, create := setup(t) c.expireInterval = time.Millisecond assert.Equal(t, false, c.expireRunning) _, err := c.Get("/", create) require.NoError(t, err) c.mu.Lock() entry := c.cache["/"] assert.Equal(t, 1, len(c.cache)) c.mu.Unlock() c.cacheExpire() c.mu.Lock() assert.Equal(t, 1, len(c.cache)) entry.lastUsed = time.Now().Add(-c.expireDuration - 60*time.Second) assert.Equal(t, true, c.expireRunning) c.mu.Unlock() time.Sleep(250 * time.Millisecond) c.mu.Lock() assert.Equal(t, false, c.expireRunning) assert.Equal(t, 0, len(c.cache)) c.mu.Unlock()} func TestClear(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, len(c.cache)) _, err := c.Get("/", create) require.NoError(t, err) assert.Equal(t, 1, len(c.cache)) c.Clear() assert.Equal(t, 0, len(c.cache))} func TestEntries(t *testing.T) { c, create := setup(t) assert.Equal(t, 0, c.Entries()) _, err := c.Get("/", create) require.NoError(t, err) assert.Equal(t, 1, c.Entries()) c.Clear() assert.Equal(t, 0, c.Entries())} func TestGetMaybe(t *testing.T) { c, create := setup(t) value, found := c.GetMaybe("/") assert.Equal(t, false, found) assert.Nil(t, value) f, err := c.Get("/", create) require.NoError(t, err) value, found = c.GetMaybe("/") assert.Equal(t, true, found) assert.Equal(t, f, value) c.Clear() value, found = c.GetMaybe("/") assert.Equal(t, false, found) assert.Nil(t, value)}
package cache
import (
"errors"
"fmt"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
called = 0
errSentinel = errors.New("an error")
errCached = errors.New("a cached error")
)
func setup(t *testing.T) (*Cache, CreateFunc) {
called = 0
create := func(path string) (interface{}, bool, error) {
assert.Equal(t, 0, called)
called++
switch path {
case "/":
return "/", true, nil
case "/file.txt":
return "/file.txt", true, errCached
case "/error":
return nil, false, errSentinel
}
panic(fmt.Sprintf("Unknown path %q", path))
}
c := New()
return c, create
}
func TestGet(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, len(c.cache))
f, err := c.Get("/", create)
require.NoError(t, err)
assert.Equal(t, 1, len(c.cache))
f2, err := c.Get("/", create)
require.NoError(t, err)
assert.Equal(t, f, f2)
}
func TestGetFile(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, len(c.cache))
f, err := c.Get("/file.txt", create)
require.Equal(t, errCached, err)
assert.Equal(t, 1, len(c.cache))
f2, err := c.Get("/file.txt", create)
require.Equal(t, errCached, err)
assert.Equal(t, f, f2)
}
func TestGetError(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, len(c.cache))
f, err := c.Get("/error", create)
require.Equal(t, errSentinel, err)
require.Equal(t, nil, f)
assert.Equal(t, 0, len(c.cache))
}
func TestPut(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, len(c.cache))
c.Put("/alien", "slime")
assert.Equal(t, 1, len(c.cache))
fNew, err := c.Get("/alien", create)
require.NoError(t, err)
require.Equal(t, "slime", fNew)
assert.Equal(t, 1, len(c.cache))
}
func TestCacheExpire(t *testing.T) {
c, create := setup(t)
c.expireInterval = time.Millisecond
assert.Equal(t, false, c.expireRunning)
_, err := c.Get("/", create)
require.NoError(t, err)
c.mu.Lock()
entry := c.cache["/"]
assert.Equal(t, 1, len(c.cache))
c.mu.Unlock()
c.cacheExpire()
c.mu.Lock()
assert.Equal(t, 1, len(c.cache))
entry.lastUsed = time.Now().Add(-c.expireDuration - 60*time.Second)
assert.Equal(t, true, c.expireRunning)
c.mu.Unlock()
time.Sleep(250 * time.Millisecond)
c.mu.Lock()
assert.Equal(t, false, c.expireRunning)
assert.Equal(t, 0, len(c.cache))
c.mu.Unlock()
}
func TestClear(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, len(c.cache))
_, err := c.Get("/", create)
require.NoError(t, err)
assert.Equal(t, 1, len(c.cache))
c.Clear()
assert.Equal(t, 0, len(c.cache))
}
func TestEntries(t *testing.T) {
c, create := setup(t)
assert.Equal(t, 0, c.Entries())
_, err := c.Get("/", create)
require.NoError(t, err)
assert.Equal(t, 1, c.Entries())
c.Clear()
assert.Equal(t, 0, c.Entries())
}
func TestGetMaybe(t *testing.T) {
c, create := setup(t)
value, found := c.GetMaybe("/")
assert.Equal(t, false, found)
assert.Nil(t, value)
f, err := c.Get("/", create)
require.NoError(t, err)
value, found = c.GetMaybe("/")
assert.Equal(t, true, found)
assert.Equal(t, f, value)
c.Clear()
value, found = c.GetMaybe("/")
assert.Equal(t, false, found)
assert.Nil(t, value)
}