81 lines
2.5 KiB
Go
81 lines
2.5 KiB
Go
package config
|
|
|
|
import (
|
|
"math"
|
|
"strconv"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestRollingCache(t *testing.T) {
|
|
size := 30
|
|
shardCount := 1
|
|
cache := newRollingCache(size, shardCount)
|
|
|
|
// Testing Set.
|
|
channel := "channel1"
|
|
value := channelOptionsResult{nsName: "value1"}
|
|
ttl := 200 * time.Millisecond
|
|
cache.Set(channel, value, ttl)
|
|
|
|
// Testing Get after Set.
|
|
gotValue, ok := cache.Get(channel)
|
|
require.True(t, ok)
|
|
require.Equal(t, value, gotValue)
|
|
|
|
// Testing Get after expiry.
|
|
time.Sleep(400 * time.Millisecond)
|
|
_, ok = cache.Get(channel)
|
|
require.False(t, ok)
|
|
|
|
// Testing if data rolls over.
|
|
// Setting more data than cache size, to see if rolling over works without errors.
|
|
for i := 0; i < size+10; i++ {
|
|
channel := "channel" + strconv.Itoa(i)
|
|
value := channelOptionsResult{nsName: "value" + strconv.Itoa(i)}
|
|
cache.Set(channel, value, ttl)
|
|
}
|
|
|
|
// The first 10 items should have been rolled over and replaced.
|
|
// So, channel0, channel1, ... channel9 should no longer be in the cache.
|
|
for i := 0; i < 10; i++ {
|
|
channel := "channel" + strconv.Itoa(i)
|
|
_, ok = cache.Get(channel)
|
|
require.False(t, ok, channel)
|
|
}
|
|
|
|
// Whereas, the items from channel10 onwards should still be there.
|
|
for i := 10; i < size+10; i++ {
|
|
channel := "channel" + strconv.Itoa(i)
|
|
gotValue, ok := cache.Get(channel)
|
|
require.True(t, ok)
|
|
require.Equal(t, channelOptionsResult{nsName: "value" + strconv.Itoa(i)}, gotValue)
|
|
}
|
|
}
|
|
|
|
// TestRollingCacheIndexOverflow guards against the rolling index wrapping into
|
|
// negative values. The index is bumped on every Set, so on a long-running node
|
|
// it eventually overflows; with a signed counter the wrap made the modulo
|
|
// negative and Set panicked with "index out of range".
|
|
func TestRollingCacheIndexOverflow(t *testing.T) {
|
|
cache := newRollingCache(channelOptionsCacheSize, 1)
|
|
shard := cache.shardForKey("channel")
|
|
shard.index.Store(math.MaxUint32) // Next Set wraps the index.
|
|
|
|
ttl := time.Minute
|
|
for i := 0; i < 2*channelOptionsCacheSize; i++ {
|
|
channel := "channel" + strconv.Itoa(i)
|
|
cache.Set(channel, channelOptionsResult{nsName: "value" + strconv.Itoa(i)}, ttl)
|
|
}
|
|
|
|
// The most recent shardSize items must still be readable after the wrap.
|
|
for i := channelOptionsCacheSize; i < 2*channelOptionsCacheSize; i++ {
|
|
channel := "channel" + strconv.Itoa(i)
|
|
gotValue, ok := cache.Get(channel)
|
|
require.True(t, ok, channel)
|
|
require.Equal(t, channelOptionsResult{nsName: "value" + strconv.Itoa(i)}, gotValue)
|
|
}
|
|
}
|