You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.1 KiB
Go
191 lines
4.1 KiB
Go
package collection
|
|
|
|
import (
|
|
"errors"
|
|
"strconv"
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var errDummy = errors.New("dummy")
|
|
|
|
func TestCacheSet(t *testing.T) {
|
|
cache, err := NewCache(time.Second*2, WithName("any"))
|
|
assert.Nil(t, err)
|
|
|
|
cache.Set("first", "first element")
|
|
cache.Set("second", "second element")
|
|
|
|
value, ok := cache.Get("first")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "first element", value)
|
|
value, ok = cache.Get("second")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "second element", value)
|
|
}
|
|
|
|
func TestCacheDel(t *testing.T) {
|
|
cache, err := NewCache(time.Second * 2)
|
|
assert.Nil(t, err)
|
|
|
|
cache.Set("first", "first element")
|
|
cache.Set("second", "second element")
|
|
cache.Del("first")
|
|
|
|
_, ok := cache.Get("first")
|
|
assert.False(t, ok)
|
|
value, ok := cache.Get("second")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "second element", value)
|
|
}
|
|
|
|
func TestCacheTake(t *testing.T) {
|
|
cache, err := NewCache(time.Second * 2)
|
|
assert.Nil(t, err)
|
|
|
|
var count int32
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
cache.Take("first", func() (interface{}, error) {
|
|
atomic.AddInt32(&count, 1)
|
|
time.Sleep(time.Millisecond * 100)
|
|
return "first element", nil
|
|
})
|
|
wg.Done()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
assert.Equal(t, 1, cache.size())
|
|
assert.Equal(t, int32(1), atomic.LoadInt32(&count))
|
|
}
|
|
|
|
func TestCacheTakeExists(t *testing.T) {
|
|
cache, err := NewCache(time.Second * 2)
|
|
assert.Nil(t, err)
|
|
|
|
var count int32
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
cache.Set("first", "first element")
|
|
cache.Take("first", func() (interface{}, error) {
|
|
atomic.AddInt32(&count, 1)
|
|
time.Sleep(time.Millisecond * 100)
|
|
return "first element", nil
|
|
})
|
|
wg.Done()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
assert.Equal(t, 1, cache.size())
|
|
assert.Equal(t, int32(0), atomic.LoadInt32(&count))
|
|
}
|
|
|
|
func TestCacheTakeError(t *testing.T) {
|
|
cache, err := NewCache(time.Second * 2)
|
|
assert.Nil(t, err)
|
|
|
|
var count int32
|
|
var wg sync.WaitGroup
|
|
for i := 0; i < 100; i++ {
|
|
wg.Add(1)
|
|
go func() {
|
|
_, err := cache.Take("first", func() (interface{}, error) {
|
|
atomic.AddInt32(&count, 1)
|
|
time.Sleep(time.Millisecond * 100)
|
|
return "", errDummy
|
|
})
|
|
assert.Equal(t, errDummy, err)
|
|
wg.Done()
|
|
}()
|
|
}
|
|
wg.Wait()
|
|
|
|
assert.Equal(t, 0, cache.size())
|
|
assert.Equal(t, int32(1), atomic.LoadInt32(&count))
|
|
}
|
|
|
|
func TestCacheWithLruEvicts(t *testing.T) {
|
|
cache, err := NewCache(time.Minute, WithLimit(3))
|
|
assert.Nil(t, err)
|
|
|
|
cache.Set("first", "first element")
|
|
cache.Set("second", "second element")
|
|
cache.Set("third", "third element")
|
|
cache.Set("fourth", "fourth element")
|
|
|
|
_, ok := cache.Get("first")
|
|
assert.False(t, ok)
|
|
value, ok := cache.Get("second")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "second element", value)
|
|
value, ok = cache.Get("third")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "third element", value)
|
|
value, ok = cache.Get("fourth")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "fourth element", value)
|
|
}
|
|
|
|
func TestCacheWithLruEvicted(t *testing.T) {
|
|
cache, err := NewCache(time.Minute, WithLimit(3))
|
|
assert.Nil(t, err)
|
|
|
|
cache.Set("first", "first element")
|
|
cache.Set("second", "second element")
|
|
cache.Set("third", "third element")
|
|
cache.Set("fourth", "fourth element")
|
|
|
|
_, ok := cache.Get("first")
|
|
assert.False(t, ok)
|
|
value, ok := cache.Get("second")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "second element", value)
|
|
cache.Set("fifth", "fifth element")
|
|
cache.Set("sixth", "sixth element")
|
|
_, ok = cache.Get("third")
|
|
assert.False(t, ok)
|
|
_, ok = cache.Get("fourth")
|
|
assert.False(t, ok)
|
|
value, ok = cache.Get("second")
|
|
assert.True(t, ok)
|
|
assert.Equal(t, "second element", value)
|
|
}
|
|
|
|
func BenchmarkCache(b *testing.B) {
|
|
cache, err := NewCache(time.Second*5, WithLimit(100000))
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
for i := 0; i < 10000; i++ {
|
|
for j := 0; j < 10; j++ {
|
|
index := strconv.Itoa(i*10000 + j)
|
|
cache.Set("key:"+index, "value:"+index)
|
|
}
|
|
}
|
|
|
|
time.Sleep(time.Second * 5)
|
|
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
for i := 0; i < b.N; i++ {
|
|
index := strconv.Itoa(i % 10000)
|
|
cache.Get("key:" + index)
|
|
if i%100 == 0 {
|
|
cache.Set("key1:"+index, "value1:"+index)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|