aboutsummaryrefslogtreecommitdiff
path: root/internal/clock/concurrent_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/clock/concurrent_test.go')
-rw-r--r--internal/clock/concurrent_test.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/internal/clock/concurrent_test.go b/internal/clock/concurrent_test.go
new file mode 100644
index 00000000..86283a9b
--- /dev/null
+++ b/internal/clock/concurrent_test.go
@@ -0,0 +1,103 @@
+package clock //nolint:testpackage
+
+import (
+ "sync"
+ "testing"
+)
+
+func keyValue(key int) int {
+ return key*1000003 + 7
+}
+
+func TestConcurrentStress(t *testing.T) {
+ t.Parallel()
+
+ const (
+ maxWeight = 512
+ keys = 400
+ workers = 8
+ rounds = 5000
+ )
+
+ cache := New(maxWeight, func(_ int, _ int) uint64 { return 1 })
+
+ var wg sync.WaitGroup
+
+ for worker := range workers {
+ wg.Go(func() {
+ for i := range rounds {
+ key := (worker*7 + i) % keys
+
+ switch i % 4 {
+ case 0, 1:
+ cache.Add(key, keyValue(key))
+ case 2:
+ if got, ok := cache.Get(key); ok && got != keyValue(key) {
+ t.Errorf("Get(%d) = %d, want %d", key, got, keyValue(key))
+ }
+ case 3:
+ if got, ok := cache.Peek(key); ok && got != keyValue(key) {
+ t.Errorf("Peek(%d) = %d, want %d", key, got, keyValue(key))
+ }
+ }
+ }
+ })
+ }
+
+ wg.Wait()
+
+ checkCache(t, cache)
+
+ if got := cache.Weight(); got > maxWeight {
+ t.Fatalf("weight %d exceeds max %d", got, maxWeight)
+ }
+}
+
+func TestReadDuringEviction(t *testing.T) {
+ t.Parallel()
+
+ const (
+ maxWeight = 8
+ hot = 64
+ writers = 2
+ readers = 6
+ rounds = 20000
+ )
+
+ cache := New(maxWeight, func(_ int, _ int) uint64 { return 1 })
+
+ var wg sync.WaitGroup
+
+ for range writers {
+ wg.Go(func() {
+ for i := range rounds {
+ key := i % hot
+ cache.Add(key, keyValue(key))
+ }
+ })
+ }
+
+ for range readers {
+ wg.Go(func() {
+ for i := range rounds {
+ key := i % hot
+
+ if got, ok := cache.Get(key); ok && got != keyValue(key) {
+ t.Errorf("Get(%d) = %d, want %d", key, got, keyValue(key))
+ }
+
+ if got, ok := cache.Peek(key); ok && got != keyValue(key) {
+ t.Errorf("Peek(%d) = %d, want %d", key, got, keyValue(key))
+ }
+ }
+ })
+ }
+
+ wg.Wait()
+
+ checkCache(t, cache)
+
+ if got := cache.Weight(); got > maxWeight {
+ t.Fatalf("weight %d exceeds max %d", got, maxWeight)
+ }
+}