github.com/fufuok/freelru@v0.13.3/shardedlru_test.go (about) 1 // nolint: dupl 2 package freelru 3 4 import ( 5 "fmt" 6 "math/rand" 7 "sync" 8 "testing" 9 "time" 10 ) 11 12 // TestShardedRaceCondition tests that the sharded LRU is safe to use concurrently. 13 // Test with 'go test . -race'. 14 func TestShardedRaceCondition(t *testing.T) { 15 const CAP = 4 16 17 lru, err := NewShardedDefault[uint64, int](CAP) 18 if err != nil { 19 t.Fatalf("err: %v", err) 20 } 21 22 wg := sync.WaitGroup{} 23 24 call := func(fn func()) { 25 wg.Add(1) 26 go func() { 27 fn() 28 wg.Done() 29 }() 30 } 31 32 call(func() { lru.SetLifetime(0) }) 33 call(func() { lru.SetOnEvict(nil) }) 34 call(func() { _ = lru.Len() }) 35 call(func() { _ = lru.AddWithLifetime(1, 1, 0) }) 36 call(func() { _ = lru.Add(1, 1) }) 37 call(func() { _, _ = lru.Get(1) }) 38 call(func() { _, _ = lru.Peek(1) }) 39 call(func() { _ = lru.Contains(1) }) 40 call(func() { _ = lru.Remove(1) }) 41 call(func() { _ = lru.Keys() }) 42 call(func() { lru.Purge() }) 43 call(func() { lru.Metrics() }) 44 call(func() { _ = lru.ResetMetrics() }) 45 call(func() { lru.dump() }) 46 call(func() { lru.PrintStats() }) 47 48 wg.Wait() 49 } 50 51 func TestShardedLRUMetrics(t *testing.T) { 52 cache, _ := NewShardedDefault[uint64, uint64](1) 53 testMetrics(t, cache) 54 55 lru, _ := NewShardedDefault[string, struct{}](7, time.Second*7) 56 m := lru.Metrics() 57 FatalIf(t, m.Capacity != 7, "Unexpected capacity: %d (!= %d)", m.Capacity, 7) 58 FatalIf(t, m.Lifetime != "7s", "Unexpected lifetime: %s (!= %s)", m.Lifetime, "7s") 59 60 lru.ResetMetrics() 61 m = lru.Metrics() 62 FatalIf(t, m.Capacity != 7, "Unexpected capacity: %d (!= %d)", m.Capacity, 7) 63 FatalIf(t, m.Lifetime != "7s", "Unexpected lifetime: %s (!= %s)", m.Lifetime, "7s") 64 } 65 66 func TestStressWithLifetime(t *testing.T) { 67 const CAP = 1024 68 69 lru, err := NewShardedDefault[string, int](CAP, time.Millisecond*10) 70 if err != nil { 71 t.Fatalf("err: %v", err) 72 } 73 74 const NTHREADS = 10 75 const RUNS = 1000 76 77 wg := sync.WaitGroup{} 78 79 for i := 0; i < NTHREADS; i++ { 80 wg.Add(1) 81 go func() { 82 for i := 0; i < RUNS; i++ { 83 lru.Add(fmt.Sprintf("key-%d", rand.Int()%1000), rand.Int()) //nolint:gosec 84 time.Sleep(time.Millisecond * 1) 85 } 86 wg.Done() 87 }() 88 } 89 90 for i := 0; i < NTHREADS; i++ { 91 wg.Add(1) 92 go func() { 93 for i := 0; i < RUNS; i++ { 94 _, _ = lru.Get(fmt.Sprintf("key-%d", rand.Int()%1000)) //nolint:gosec 95 time.Sleep(time.Millisecond * 1) 96 } 97 wg.Done() 98 }() 99 } 100 101 wg.Wait() 102 }