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  }