Skip to content

Commit

Permalink
Add some concurrency tests
Browse files Browse the repository at this point in the history
  • Loading branch information
illicitonion committed Apr 26, 2024
1 parent 9c714d6 commit 754169f
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ func NewCache[K comparable, V any](targetSize uint64, gcTicker <-chan time.Time)
if len(keysToDelete) > 0 {
cache.mu.Lock()
for _, keyToDelete := range keysToDelete {
if len(cache.values) <= int(targetSize) {
break
}
delete(cache.values, keyToDelete)
}
cache.mu.Unlock()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cache

import (
"fmt"
"sync"
"testing"
"time"

Expand All @@ -14,6 +15,8 @@ func TestPutThenGet(t *testing.T) {
previouslyExisted := cache.Put("greeting", "hello")
require.False(t, previouslyExisted)

// Write to the channel twice twice, because we know that once the second write has sent the first one must be done processing.
gcTicker <- time.Now()
gcTicker <- time.Now()

value, present := cache.Get("greeting")
Expand All @@ -37,6 +40,7 @@ func TestEviction_JustWrites(t *testing.T) {
cache.Put(fmt.Sprintf("entry-%d", i), "hello")
}

gcTicker <- time.Now()
gcTicker <- time.Now()

_, present0 := cache.Get("entry-0")
Expand All @@ -48,7 +52,70 @@ func TestEviction_JustWrites(t *testing.T) {
cache.Put("entry-10", "hello")

gcTicker <- time.Now()
gcTicker <- time.Now()

presentCount := 0
for key := 0; key < 11; key++ {
got, present := cache.Get(fmt.Sprintf("entry-%d", key))
if present {
presentCount++
require.Equal(t, "hello", *got)
}
}
require.Equal(t, 10, presentCount)

// entries 0, 9, and 10 were accessed a generation after the others, so should be present.
_, present0AfterGC := cache.Get("entry-0")
require.True(t, present0AfterGC)

_, present9AfterGC := cache.Get("entry-9")
require.True(t, present9AfterGC)

_, present10AfterGC := cache.Get("entry-10")
require.True(t, present10AfterGC)
}

func TestConcurrentWrites(t *testing.T) {
gcTicker := make(chan time.Time)
cache := NewCache[int, string](1, gcTicker)

var wg sync.WaitGroup

_, present1 := cache.Get("entry-1")
require.False(t, present1)
for iteration := 0; iteration < 100000; iteration++ {
wg.Add(1)
go func() {
for key := 0; key < 3; key++ {
cache.Put(key, fmt.Sprintf("entry-%d", key))
}
wg.Done()
}()
}

wg.Wait()

// No gc tick has happened, so all three keys should be present.
got0, present0 := cache.Get(0)
require.True(t, present0)
require.Equal(t, "entry-0", *got0)

got1, present1 := cache.Get(1)
require.True(t, present1)
require.Equal(t, "entry-1", *got1)

got2, present2 := cache.Get(2)
require.True(t, present2)
require.Equal(t, "entry-2", *got2)

gcTicker <- time.Now()
gcTicker <- time.Now()

presentCount := 0
for key := 0; key < 3; key++ {
got, present := cache.Get(key)
if present {
presentCount++
require.Equal(t, fmt.Sprintf("entry-%d", key), *got)
}
}
require.Equal(t, 1, presentCount)
}

0 comments on commit 754169f

Please sign in to comment.