github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/boring/bcache/cache_test.go (about) 1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bcache 6 7 import ( 8 "fmt" 9 "runtime" 10 "sync" 11 "sync/atomic" 12 "testing" 13 ) 14 15 var registeredCache Cache[int, int32] 16 17 func init() { 18 registeredCache.Register() 19 } 20 21 var seq atomic.Uint32 22 23 func next[T int | int32]() *T { 24 x := new(T) 25 *x = T(seq.Add(1)) 26 return x 27 } 28 29 func str[T int | int32](x *T) string { 30 if x == nil { 31 return "nil" 32 } 33 return fmt.Sprint(*x) 34 } 35 36 func TestCache(t *testing.T) { 37 // Use unregistered cache for functionality tests, 38 // to keep the runtime from clearing behind our backs. 39 c := new(Cache[int, int32]) 40 41 // Create many entries. 42 m := make(map[*int]*int32) 43 for i := 0; i < 10000; i++ { 44 k := next[int]() 45 v := next[int32]() 46 m[k] = v 47 c.Put(k, v) 48 } 49 50 // Overwrite a random 20% of those. 51 n := 0 52 for k := range m { 53 v := next[int32]() 54 m[k] = v 55 c.Put(k, v) 56 if n++; n >= 2000 { 57 break 58 } 59 } 60 61 // Check results. 62 for k, v := range m { 63 if cv := c.Get(k); cv != v { 64 t.Fatalf("c.Get(%v) = %v, want %v", str(k), str(cv), str(v)) 65 } 66 } 67 68 c.Clear() 69 for k := range m { 70 if cv := c.Get(k); cv != nil { 71 t.Fatalf("after GC, c.Get(%v) = %v, want nil", str(k), str(cv)) 72 } 73 } 74 75 // Check that registered cache is cleared at GC. 76 c = ®isteredCache 77 for k, v := range m { 78 c.Put(k, v) 79 } 80 runtime.GC() 81 for k := range m { 82 if cv := c.Get(k); cv != nil { 83 t.Fatalf("after Clear, c.Get(%v) = %v, want nil", str(k), str(cv)) 84 } 85 } 86 87 // Check that cache works for concurrent access. 88 // Lists are discarded if they reach 1000 entries, 89 // and there are cacheSize list heads, so we should be 90 // able to do 100 * cacheSize entries with no problem at all. 91 c = new(Cache[int, int32]) 92 var barrier, wg sync.WaitGroup 93 const N = 100 94 barrier.Add(N) 95 wg.Add(N) 96 var lost int32 97 for i := 0; i < N; i++ { 98 go func() { 99 defer wg.Done() 100 101 m := make(map[*int]*int32) 102 for j := 0; j < cacheSize; j++ { 103 k, v := next[int](), next[int32]() 104 m[k] = v 105 c.Put(k, v) 106 } 107 barrier.Done() 108 barrier.Wait() 109 110 for k, v := range m { 111 if cv := c.Get(k); cv != v { 112 t.Errorf("c.Get(%v) = %v, want %v", str(k), str(cv), str(v)) 113 atomic.AddInt32(&lost, +1) 114 } 115 } 116 }() 117 } 118 wg.Wait() 119 if lost != 0 { 120 t.Errorf("lost %d entries", lost) 121 } 122 }