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  }