Adding upstream version 2.2.2.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a6909e3829
commit
02ef45af86
19 changed files with 3024 additions and 0 deletions
129
janitor_test.go
Normal file
129
janitor_test.go
Normal file
|
@ -0,0 +1,129 @@
|
|||
package gocache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCache_StartJanitor(t *testing.T) {
|
||||
cache := NewCache()
|
||||
cache.SetWithTTL("1", "1", time.Nanosecond)
|
||||
if cacheSize := cache.Count(); cacheSize != 1 {
|
||||
t.Errorf("expected cacheSize to be 1, but was %d", cacheSize)
|
||||
}
|
||||
err := cache.StartJanitor()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cache.StopJanitor()
|
||||
time.Sleep(JanitorMinShiftBackOff * 2)
|
||||
if cacheSize := cache.Count(); cacheSize != 0 {
|
||||
t.Errorf("expected cacheSize to be 0, but was %d", cacheSize)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCache_StartJanitorWhenAlreadyStarted(t *testing.T) {
|
||||
cache := NewCache()
|
||||
if err := cache.StartJanitor(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := cache.StartJanitor(); err == nil {
|
||||
t.Fatal("expected StartJanitor to return an error, because the janitor is already started")
|
||||
}
|
||||
cache.StopJanitor()
|
||||
}
|
||||
|
||||
func TestCache_StopJanitor(t *testing.T) {
|
||||
cache := NewCache()
|
||||
_ = cache.StartJanitor()
|
||||
if cache.stopJanitor == nil {
|
||||
t.Error("starting the janitor should've initialized cache.stopJanitor")
|
||||
}
|
||||
cache.StopJanitor()
|
||||
if cache.stopJanitor != nil {
|
||||
t.Error("stopping the janitor should've set cache.stopJanitor to nil")
|
||||
}
|
||||
// Check if stopping the janitor even though it's already stopped causes a panic
|
||||
cache.StopJanitor()
|
||||
}
|
||||
|
||||
func TestJanitor(t *testing.T) {
|
||||
cache := NewCache().WithMaxSize(3 * JanitorMaxIterationsPerShift)
|
||||
defer cache.Clear()
|
||||
for i := 0; i < 3*JanitorMaxIterationsPerShift; i++ {
|
||||
if i < JanitorMaxIterationsPerShift && i%2 == 0 {
|
||||
cache.SetWithTTL(fmt.Sprintf("%d", i), "value", time.Millisecond)
|
||||
} else {
|
||||
cache.SetWithTTL(fmt.Sprintf("%d", i), "value", time.Hour)
|
||||
}
|
||||
}
|
||||
cacheSize := cache.Count()
|
||||
err := cache.StartJanitor()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cache.StopJanitor()
|
||||
time.Sleep(JanitorMinShiftBackOff * 4)
|
||||
if cacheSize <= cache.Count() {
|
||||
t.Error("The janitor should be deleting expired cache entries")
|
||||
}
|
||||
cacheSize = cache.Count()
|
||||
time.Sleep(JanitorMinShiftBackOff * 4)
|
||||
if cacheSize <= cache.Count() {
|
||||
t.Error("The janitor should be deleting expired cache entries")
|
||||
}
|
||||
cacheSize = cache.Count()
|
||||
time.Sleep(JanitorMinShiftBackOff * 4)
|
||||
if cacheSize <= cache.Count() {
|
||||
t.Error("The janitor should be deleting expired cache entries")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJanitorIsLoopingProperly(t *testing.T) {
|
||||
cache := NewCache().WithMaxSize(JanitorMaxIterationsPerShift + 3)
|
||||
defer cache.Clear()
|
||||
for i := 0; i < JanitorMaxIterationsPerShift; i++ {
|
||||
cache.SetWithTTL(fmt.Sprintf("%d", i), "value", time.Hour)
|
||||
}
|
||||
cache.SetWithTTL("key-to-expire-1", "value", JanitorMinShiftBackOff*2)
|
||||
cache.SetWithTTL("key-to-expire-2", "value", JanitorMinShiftBackOff*2)
|
||||
cache.SetWithTTL("key-to-expire-3", "value", JanitorMinShiftBackOff*2)
|
||||
err := cache.StartJanitor()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer cache.StopJanitor()
|
||||
if cache.Count() != JanitorMaxIterationsPerShift+3 {
|
||||
t.Error("The janitor shouldn't have had enough time to remove anything from the cache yet", cache.Count())
|
||||
}
|
||||
const timeout = JanitorMinShiftBackOff * 20
|
||||
threeKeysExpiredWithinOneSecond := false
|
||||
for start := time.Now(); time.Since(start) < timeout; {
|
||||
if cache.Stats().ExpiredKeys == 3 {
|
||||
threeKeysExpiredWithinOneSecond = true
|
||||
break
|
||||
}
|
||||
time.Sleep(JanitorMinShiftBackOff)
|
||||
}
|
||||
if !threeKeysExpiredWithinOneSecond {
|
||||
t.Error("expected 3 keys to expire within 1 second")
|
||||
}
|
||||
if cache.Count() != JanitorMaxIterationsPerShift {
|
||||
t.Error("The janitor should've deleted 3 entries")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJanitorDoesNotThrowATantrumWhenThereIsNothingToClean(t *testing.T) {
|
||||
cache := NewCache()
|
||||
start := time.Now()
|
||||
_ = cache.StartJanitor()
|
||||
defer cache.StopJanitor()
|
||||
time.Sleep(JanitorMaxShiftBackOff * 3)
|
||||
// Technically, if the janitor doesn't backoff properly, the sleep above is likely to take more time than the sleep
|
||||
// below because it would be eating up the CPU.
|
||||
// This is a far-fetched test, but it's a good sanity check.
|
||||
if time.Since(start) > JanitorMaxShiftBackOff*4 {
|
||||
t.Error("The janitor should've backed off and prevented CPU usage from throttling the application")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue