github.com/searKing/golang/go@v1.2.74/exp/sync/lru_test.go (about) 1 // Copyright 2022 The searKing Author. 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 sync_test 6 7 import ( 8 "testing" 9 10 "github.com/searKing/golang/go/exp/sync" 11 ) 12 13 func TestLRU(t *testing.T) { 14 evictCounter := 0 15 onEvicted := func(k int, v int) { 16 if k != v { 17 t.Fatalf("Evict values not equal (%v!=%v)", k, v) 18 } 19 evictCounter++ 20 } 21 l := sync.NewLRU[int, int](128) 22 l.SetEvictCallback(onEvicted) 23 24 for i := 0; i < 256; i++ { 25 l.Add(i, i) 26 } 27 if l.Len() != 128 { 28 t.Fatalf("bad len: %v", l.Len()) 29 } 30 31 if evictCounter != 128 { 32 t.Fatalf("bad evict count: %v", evictCounter) 33 } 34 35 for i, k := range l.Keys() { 36 if v, ok := l.Get(k); !ok || v != k || v != i+128 { 37 t.Fatalf("bad key: %v", k) 38 } 39 } 40 for i := 0; i < 128; i++ { 41 _, ok := l.Get(i) 42 if ok { 43 t.Fatalf("should be evicted") 44 } 45 } 46 for i := 128; i < 256; i++ { 47 _, ok := l.Get(i) 48 if !ok { 49 t.Fatalf("should not be evicted") 50 } 51 } 52 for i := 128; i < 192; i++ { 53 ok := l.Remove(i) 54 if !ok { 55 t.Fatalf("should be contained") 56 } 57 ok = l.Remove(i) 58 if ok { 59 t.Fatalf("should not be contained") 60 } 61 _, ok = l.Get(i) 62 if ok { 63 t.Fatalf("should be deleted") 64 } 65 } 66 67 l.Get(192) // expect 192 to be last key in l.Keys() 68 69 for i, k := range l.Keys() { 70 if (i < 63 && k != i+193) || (i == 63 && k != 192) { 71 t.Fatalf("out of order key: %v", k) 72 } 73 } 74 75 l.Purge() 76 if l.Len() != 0 { 77 t.Fatalf("bad len: %v", l.Len()) 78 } 79 if _, ok := l.Get(200); ok { 80 t.Fatalf("should contain nothing") 81 } 82 } 83 84 func TestLRU_GetOldest_RemoveOldest(t *testing.T) { 85 l := sync.NewLRU[int, int](128) 86 87 for i := 0; i < 256; i++ { 88 l.Add(i, i) 89 } 90 k, _, ok := l.GetOldest() 91 if !ok { 92 t.Fatalf("missing") 93 } 94 if k != 128 { 95 t.Fatalf("bad: %v", k) 96 } 97 98 k, _, ok = l.RemoveOldest() 99 if !ok { 100 t.Fatalf("missing") 101 } 102 if k != 128 { 103 t.Fatalf("bad: %v", k) 104 } 105 106 k, _, ok = l.RemoveOldest() 107 if !ok { 108 t.Fatalf("missing") 109 } 110 if k != 129 { 111 t.Fatalf("bad: %v", k) 112 } 113 } 114 115 // Test that Add returns true/false if an eviction occurred 116 func TestLRU_Add(t *testing.T) { 117 evictCounter := 0 118 onEvicted := func(k int, v int) { 119 evictCounter++ 120 } 121 122 l := sync.NewLRU[int, int](1).SetEvictCallback(onEvicted) 123 124 if l.Add(1, 1) == true || evictCounter != 0 { 125 t.Errorf("should not have an eviction") 126 } 127 if l.Add(2, 2) == false || evictCounter != 1 { 128 t.Errorf("should have an eviction") 129 } 130 } 131 132 // Test that Contains doesn't update recent-ness 133 func TestLRU_Contains(t *testing.T) { 134 l := sync.NewLRU[int, int](2) 135 136 l.Add(1, 1) 137 l.Add(2, 2) 138 if !l.Contains(1) { 139 t.Errorf("1 should be contained") 140 } 141 142 l.Add(3, 3) 143 if l.Contains(1) { 144 t.Errorf("Contains should not have updated recent-ness of 1") 145 } 146 } 147 148 // Test that Peek doesn't update recent-ness 149 func TestLRU_Peek(t *testing.T) { 150 l := sync.NewLRU[int, int](2) 151 152 l.Add(1, 1) 153 l.Add(2, 2) 154 if v, ok := l.Peek(1); !ok || v != 1 { 155 t.Errorf("1 should be set to 1: %v, %v", v, ok) 156 } 157 158 l.Add(3, 3) 159 if l.Contains(1) { 160 t.Errorf("should not have updated recent-ness of 1") 161 } 162 } 163 164 // Test that Resize can upsize and downsize 165 func TestLRU_Resize(t *testing.T) { 166 onEvictCounter := 0 167 onEvicted := func(k int, v int) { 168 onEvictCounter++ 169 } 170 171 l := sync.NewLRU[int, int](2).SetEvictCallback(onEvicted) 172 173 // Downsize 174 l.Add(1, 1) 175 l.Add(2, 2) 176 evicted := l.Resize(1) 177 if evicted != 1 { 178 t.Errorf("1 element should have been evicted: %v", evicted) 179 } 180 if onEvictCounter != 1 { 181 t.Errorf("onEvicted should have been called 1 time: %v", onEvictCounter) 182 } 183 184 l.Add(3, 3) 185 if l.Contains(1) { 186 t.Errorf("Element 1 should have been evicted") 187 } 188 189 // Upsize 190 evicted = l.Resize(2) 191 if evicted != 0 { 192 t.Errorf("0 elements should have been evicted: %v", evicted) 193 } 194 195 l.Add(4, 4) 196 if !l.Contains(3) || !l.Contains(4) { 197 t.Errorf("Cache should have contained 2 elements") 198 } 199 }