github.com/XiaoMi/Gaea@v1.2.5/util/cache/lru_cache_test.go (about) 1 /* 2 Copyright 2017 Google Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package cache 18 19 import ( 20 "encoding/json" 21 "testing" 22 "time" 23 ) 24 25 type CacheValue struct { 26 size int 27 } 28 29 func (cv *CacheValue) Size() int { 30 return cv.size 31 } 32 33 func TestInitialState(t *testing.T) { 34 cache := NewLRUCache(5) 35 l, sz, c, e, _ := cache.Stats() 36 if l != 0 { 37 t.Errorf("length = %v, want 0", l) 38 } 39 if sz != 0 { 40 t.Errorf("size = %v, want 0", sz) 41 } 42 if c != 5 { 43 t.Errorf("capacity = %v, want 5", c) 44 } 45 if e != 0 { 46 t.Errorf("evictions = %v, want 0", c) 47 } 48 } 49 50 func TestSetInsertsValue(t *testing.T) { 51 cache := NewLRUCache(100) 52 data := &CacheValue{0} 53 key := "key" 54 cache.Set(key, data) 55 56 v, ok := cache.Get(key) 57 if !ok || v.(*CacheValue) != data { 58 t.Errorf("Cache has incorrect value: %v != %v", data, v) 59 } 60 61 k := cache.Keys() 62 if len(k) != 1 || k[0] != key { 63 t.Errorf("Cache.Keys() returned incorrect values: %v", k) 64 } 65 values := cache.Items() 66 if len(values) != 1 || values[0].Key != key { 67 t.Errorf("Cache.Values() returned incorrect values: %v", values) 68 } 69 } 70 71 func TestSetIfAbsent(t *testing.T) { 72 cache := NewLRUCache(100) 73 data := &CacheValue{0} 74 key := "key" 75 cache.SetIfAbsent(key, data) 76 77 v, ok := cache.Get(key) 78 if !ok || v.(*CacheValue) != data { 79 t.Errorf("Cache has incorrect value: %v != %v", data, v) 80 } 81 82 cache.SetIfAbsent(key, &CacheValue{1}) 83 84 v, ok = cache.Get(key) 85 if !ok || v.(*CacheValue) != data { 86 t.Errorf("Cache has incorrect value: %v != %v", data, v) 87 } 88 } 89 90 func TestGetValueWithMultipleTypes(t *testing.T) { 91 cache := NewLRUCache(100) 92 data := &CacheValue{0} 93 key := "key" 94 cache.Set(key, data) 95 96 v, ok := cache.Get("key") 97 if !ok || v.(*CacheValue) != data { 98 t.Errorf("Cache has incorrect value for \"key\": %v != %v", data, v) 99 } 100 101 v, ok = cache.Get(string([]byte{'k', 'e', 'y'})) 102 if !ok || v.(*CacheValue) != data { 103 t.Errorf("Cache has incorrect value for []byte {'k','e','y'}: %v != %v", data, v) 104 } 105 } 106 107 func TestSetUpdatesSize(t *testing.T) { 108 cache := NewLRUCache(100) 109 emptyValue := &CacheValue{0} 110 key := "key1" 111 cache.Set(key, emptyValue) 112 if _, sz, _, _, _ := cache.Stats(); sz != 0 { 113 t.Errorf("cache.Size() = %v, expected 0", sz) 114 } 115 someValue := &CacheValue{20} 116 key = "key2" 117 cache.Set(key, someValue) 118 if _, sz, _, _, _ := cache.Stats(); sz != 20 { 119 t.Errorf("cache.Size() = %v, expected 20", sz) 120 } 121 } 122 123 func TestSetWithOldKeyUpdatesValue(t *testing.T) { 124 cache := NewLRUCache(100) 125 emptyValue := &CacheValue{0} 126 key := "key1" 127 cache.Set(key, emptyValue) 128 someValue := &CacheValue{20} 129 cache.Set(key, someValue) 130 131 v, ok := cache.Get(key) 132 if !ok || v.(*CacheValue) != someValue { 133 t.Errorf("Cache has incorrect value: %v != %v", someValue, v) 134 } 135 } 136 137 func TestSetWithOldKeyUpdatesSize(t *testing.T) { 138 cache := NewLRUCache(100) 139 emptyValue := &CacheValue{0} 140 key := "key1" 141 cache.Set(key, emptyValue) 142 143 if _, sz, _, _, _ := cache.Stats(); sz != 0 { 144 t.Errorf("cache.Size() = %v, expected %v", sz, 0) 145 } 146 147 someValue := &CacheValue{20} 148 cache.Set(key, someValue) 149 expected := int64(someValue.size) 150 if _, sz, _, _, _ := cache.Stats(); sz != expected { 151 t.Errorf("cache.Size() = %v, expected %v", sz, expected) 152 } 153 } 154 155 func TestGetNonExistent(t *testing.T) { 156 cache := NewLRUCache(100) 157 158 if _, ok := cache.Get("notthere"); ok { 159 t.Error("Cache returned a notthere value after no inserts.") 160 } 161 } 162 163 func TestPeek(t *testing.T) { 164 cache := NewLRUCache(2) 165 val1 := &CacheValue{1} 166 cache.Set("key1", val1) 167 val2 := &CacheValue{1} 168 cache.Set("key2", val2) 169 // Make key1 the most recent. 170 cache.Get("key1") 171 // Peek key2. 172 if v, ok := cache.Peek("key2"); ok && v.(*CacheValue) != val2 { 173 t.Errorf("key2 received: %v, want %v", v, val2) 174 } 175 // Push key2 out 176 cache.Set("key3", &CacheValue{1}) 177 if v, ok := cache.Peek("key2"); ok { 178 t.Errorf("key2 received: %v, want absent", v) 179 } 180 } 181 182 func TestDelete(t *testing.T) { 183 cache := NewLRUCache(100) 184 value := &CacheValue{1} 185 key := "key" 186 187 if cache.Delete(key) { 188 t.Error("Item unexpectedly already in cache.") 189 } 190 191 cache.Set(key, value) 192 193 if !cache.Delete(key) { 194 t.Error("Expected item to be in cache.") 195 } 196 197 if _, sz, _, _, _ := cache.Stats(); sz != 0 { 198 t.Errorf("cache.Size() = %v, expected 0", sz) 199 } 200 201 if _, ok := cache.Get(key); ok { 202 t.Error("Cache returned a value after deletion.") 203 } 204 } 205 206 func TestClear(t *testing.T) { 207 cache := NewLRUCache(100) 208 value := &CacheValue{1} 209 key := "key" 210 211 cache.Set(key, value) 212 cache.Clear() 213 214 if _, sz, _, _, _ := cache.Stats(); sz != 0 { 215 t.Errorf("cache.Size() = %v, expected 0 after Clear()", sz) 216 } 217 } 218 219 func TestCapacityIsObeyed(t *testing.T) { 220 size := int64(3) 221 cache := NewLRUCache(100) 222 cache.SetCapacity(size) 223 value := &CacheValue{1} 224 225 // Insert up to the cache's capacity. 226 cache.Set("key1", value) 227 cache.Set("key2", value) 228 cache.Set("key3", value) 229 if _, sz, _, _, _ := cache.Stats(); sz != size { 230 t.Errorf("cache.Size() = %v, expected %v", sz, size) 231 } 232 // Insert one more; something should be evicted to make room. 233 cache.Set("key4", value) 234 _, sz, _, evictions, _ := cache.Stats() 235 if sz != size { 236 t.Errorf("post-evict cache.Size() = %v, expected %v", sz, size) 237 } 238 if evictions != 1 { 239 t.Errorf("post-evict cache.evictions = %v, expected 1", evictions) 240 } 241 242 // Check json stats 243 data := cache.StatsJSON() 244 m := make(map[string]interface{}) 245 if err := json.Unmarshal([]byte(data), &m); err != nil { 246 t.Errorf("cache.StatsJSON() returned bad json data: %v %v", data, err) 247 } 248 if m["Size"].(float64) != float64(size) { 249 t.Errorf("cache.StatsJSON() returned bad size: %v", m) 250 } 251 252 // Check various other stats 253 if l := cache.Length(); l != size { 254 t.Errorf("cache.StatsJSON() returned bad length: %v", l) 255 } 256 if s := cache.Size(); s != size { 257 t.Errorf("cache.StatsJSON() returned bad size: %v", s) 258 } 259 if c := cache.Capacity(); c != size { 260 t.Errorf("cache.StatsJSON() returned bad length: %v", c) 261 } 262 263 // checks StatsJSON on nil 264 cache = nil 265 if s := cache.StatsJSON(); s != "{}" { 266 t.Errorf("cache.StatsJSON() on nil object returned %v", s) 267 } 268 } 269 270 func TestLRUIsEvicted(t *testing.T) { 271 size := int64(3) 272 cache := NewLRUCache(size) 273 274 cache.Set("key1", &CacheValue{1}) 275 cache.Set("key2", &CacheValue{1}) 276 cache.Set("key3", &CacheValue{1}) 277 // lru: [key3, key2, key1] 278 279 // Look up the elements. This will rearrange the LRU ordering. 280 cache.Get("key3") 281 beforeKey2 := time.Now() 282 cache.Get("key2") 283 afterKey2 := time.Now() 284 cache.Get("key1") 285 // lru: [key1, key2, key3] 286 287 cache.Set("key0", &CacheValue{1}) 288 // lru: [key0, key1, key2] 289 290 // The least recently used one should have been evicted. 291 if _, ok := cache.Get("key3"); ok { 292 t.Error("Least recently used element was not evicted.") 293 } 294 295 // Check oldest 296 if o := cache.Oldest(); o.Before(beforeKey2) || o.After(afterKey2) { 297 t.Errorf("cache.Oldest returned an unexpected value: got %v, expected a value between %v and %v", o, beforeKey2, afterKey2) 298 } 299 300 if e, want := cache.Evictions(), int64(1); e != want { 301 t.Errorf("evictions: %d, want: %d", e, want) 302 } 303 }