github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/kvcache/simple_lru_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package ekvcache
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"testing"
    20  
    21  	. "github.com/whtcorpsinc/check"
    22  	"github.com/whtcorpsinc/milevadb/soliton/memory"
    23  )
    24  
    25  func TestT(t *testing.T) {
    26  	CustomVerboseFlag = true
    27  	TestingT(t)
    28  }
    29  
    30  var _ = Suite(&testLRUCacheSuite{})
    31  
    32  type testLRUCacheSuite struct {
    33  }
    34  
    35  type mockCacheKey struct {
    36  	hash []byte
    37  	key  int64
    38  }
    39  
    40  func (mk *mockCacheKey) Hash() []byte {
    41  	if mk.hash != nil {
    42  		return mk.hash
    43  	}
    44  	mk.hash = make([]byte, 8)
    45  	for i := uint(0); i < 8; i++ {
    46  		mk.hash[i] = byte((mk.key >> ((i - 1) * 8)) & 0xff)
    47  	}
    48  	return mk.hash
    49  }
    50  
    51  func newMockHashKey(key int64) *mockCacheKey {
    52  	return &mockCacheKey{
    53  		key: key,
    54  	}
    55  }
    56  
    57  func (s *testLRUCacheSuite) TestPut(c *C) {
    58  	maxMem, err := memory.MemTotal()
    59  	c.Assert(err, IsNil)
    60  
    61  	lru := NewSimpleLRUCache(3, 0, maxMem)
    62  	c.Assert(lru.capacity, Equals, uint(3))
    63  
    64  	keys := make([]*mockCacheKey, 5)
    65  	vals := make([]int64, 5)
    66  
    67  	for i := 0; i < 5; i++ {
    68  		keys[i] = newMockHashKey(int64(i))
    69  		vals[i] = int64(i)
    70  		lru.Put(keys[i], vals[i])
    71  	}
    72  	c.Assert(lru.size, Equals, lru.capacity)
    73  	c.Assert(lru.size, Equals, uint(3))
    74  
    75  	// test for non-existent elements
    76  	for i := 0; i < 2; i++ {
    77  		element, exists := lru.elements[string(keys[i].Hash())]
    78  		c.Assert(exists, IsFalse)
    79  		c.Assert(element, IsNil)
    80  	}
    81  
    82  	// test for existent elements
    83  	root := lru.cache.Front()
    84  	c.Assert(root, NotNil)
    85  	for i := 4; i >= 2; i-- {
    86  		entry, ok := root.Value.(*cacheEntry)
    87  		c.Assert(ok, IsTrue)
    88  		c.Assert(entry, NotNil)
    89  
    90  		// test key
    91  		key := entry.key
    92  		c.Assert(key, NotNil)
    93  		c.Assert(key, Equals, keys[i])
    94  
    95  		element, exists := lru.elements[string(keys[i].Hash())]
    96  		c.Assert(exists, IsTrue)
    97  		c.Assert(element, NotNil)
    98  		c.Assert(element, Equals, root)
    99  
   100  		// test value
   101  		value, ok := entry.value.(int64)
   102  		c.Assert(ok, IsTrue)
   103  		c.Assert(value, Equals, vals[i])
   104  
   105  		root = root.Next()
   106  	}
   107  	// test for end of double-linked list
   108  	c.Assert(root, IsNil)
   109  }
   110  
   111  func (s *testLRUCacheSuite) TestZeroQuota(c *C) {
   112  	lru := NewSimpleLRUCache(100, 0, 0)
   113  	c.Assert(lru.capacity, Equals, uint(100))
   114  
   115  	keys := make([]*mockCacheKey, 100)
   116  	vals := make([]int64, 100)
   117  
   118  	for i := 0; i < 100; i++ {
   119  		keys[i] = newMockHashKey(int64(i))
   120  		vals[i] = int64(i)
   121  		lru.Put(keys[i], vals[i])
   122  	}
   123  	c.Assert(lru.size, Equals, lru.capacity)
   124  	c.Assert(lru.size, Equals, uint(100))
   125  }
   126  
   127  func (s *testLRUCacheSuite) TestOOMGuard(c *C) {
   128  	maxMem, err := memory.MemTotal()
   129  	c.Assert(err, IsNil)
   130  
   131  	lru := NewSimpleLRUCache(3, 1.0, maxMem)
   132  	c.Assert(lru.capacity, Equals, uint(3))
   133  
   134  	keys := make([]*mockCacheKey, 5)
   135  	vals := make([]int64, 5)
   136  
   137  	for i := 0; i < 5; i++ {
   138  		keys[i] = newMockHashKey(int64(i))
   139  		vals[i] = int64(i)
   140  		lru.Put(keys[i], vals[i])
   141  	}
   142  	c.Assert(lru.size, Equals, uint(0))
   143  
   144  	// test for non-existent elements
   145  	for i := 0; i < 5; i++ {
   146  		element, exists := lru.elements[string(keys[i].Hash())]
   147  		c.Assert(exists, IsFalse)
   148  		c.Assert(element, IsNil)
   149  	}
   150  }
   151  
   152  func (s *testLRUCacheSuite) TestGet(c *C) {
   153  	maxMem, err := memory.MemTotal()
   154  	c.Assert(err, IsNil)
   155  
   156  	lru := NewSimpleLRUCache(3, 0, maxMem)
   157  
   158  	keys := make([]*mockCacheKey, 5)
   159  	vals := make([]int64, 5)
   160  
   161  	for i := 0; i < 5; i++ {
   162  		keys[i] = newMockHashKey(int64(i))
   163  		vals[i] = int64(i)
   164  		lru.Put(keys[i], vals[i])
   165  	}
   166  
   167  	// test for non-existent elements
   168  	for i := 0; i < 2; i++ {
   169  		value, exists := lru.Get(keys[i])
   170  		c.Assert(exists, IsFalse)
   171  		c.Assert(value, IsNil)
   172  	}
   173  
   174  	for i := 2; i < 5; i++ {
   175  		value, exists := lru.Get(keys[i])
   176  		c.Assert(exists, IsTrue)
   177  		c.Assert(value, NotNil)
   178  		c.Assert(value, Equals, vals[i])
   179  		c.Assert(lru.size, Equals, uint(3))
   180  		c.Assert(lru.capacity, Equals, uint(3))
   181  
   182  		root := lru.cache.Front()
   183  		c.Assert(root, NotNil)
   184  
   185  		entry, ok := root.Value.(*cacheEntry)
   186  		c.Assert(ok, IsTrue)
   187  		c.Assert(entry.key, Equals, keys[i])
   188  
   189  		value, ok = entry.value.(int64)
   190  		c.Assert(ok, IsTrue)
   191  		c.Assert(value, Equals, vals[i])
   192  	}
   193  }
   194  
   195  func (s *testLRUCacheSuite) TestDelete(c *C) {
   196  	maxMem, err := memory.MemTotal()
   197  	c.Assert(err, IsNil)
   198  
   199  	lru := NewSimpleLRUCache(3, 0, maxMem)
   200  
   201  	keys := make([]*mockCacheKey, 3)
   202  	vals := make([]int64, 3)
   203  
   204  	for i := 0; i < 3; i++ {
   205  		keys[i] = newMockHashKey(int64(i))
   206  		vals[i] = int64(i)
   207  		lru.Put(keys[i], vals[i])
   208  	}
   209  	c.Assert(int(lru.size), Equals, 3)
   210  
   211  	lru.Delete(keys[1])
   212  	value, exists := lru.Get(keys[1])
   213  	c.Assert(exists, IsFalse)
   214  	c.Assert(value, IsNil)
   215  	c.Assert(int(lru.size), Equals, 2)
   216  
   217  	_, exists = lru.Get(keys[0])
   218  	c.Assert(exists, IsTrue)
   219  
   220  	_, exists = lru.Get(keys[2])
   221  	c.Assert(exists, IsTrue)
   222  }
   223  
   224  func (s *testLRUCacheSuite) TestDeleteAll(c *C) {
   225  	maxMem, err := memory.MemTotal()
   226  	c.Assert(err, IsNil)
   227  
   228  	lru := NewSimpleLRUCache(3, 0, maxMem)
   229  
   230  	keys := make([]*mockCacheKey, 3)
   231  	vals := make([]int64, 3)
   232  
   233  	for i := 0; i < 3; i++ {
   234  		keys[i] = newMockHashKey(int64(i))
   235  		vals[i] = int64(i)
   236  		lru.Put(keys[i], vals[i])
   237  	}
   238  	c.Assert(int(lru.size), Equals, 3)
   239  
   240  	lru.DeleteAll()
   241  
   242  	for i := 0; i < 3; i++ {
   243  		value, exists := lru.Get(keys[i])
   244  		c.Assert(exists, IsFalse)
   245  		c.Assert(value, IsNil)
   246  		c.Assert(int(lru.size), Equals, 0)
   247  	}
   248  }
   249  
   250  func (s *testLRUCacheSuite) TestValues(c *C) {
   251  	maxMem, err := memory.MemTotal()
   252  	c.Assert(err, IsNil)
   253  
   254  	lru := NewSimpleLRUCache(5, 0, maxMem)
   255  
   256  	keys := make([]*mockCacheKey, 5)
   257  	vals := make([]int64, 5)
   258  
   259  	for i := 0; i < 5; i++ {
   260  		keys[i] = newMockHashKey(int64(i))
   261  		vals[i] = int64(i)
   262  		lru.Put(keys[i], vals[i])
   263  	}
   264  
   265  	values := lru.Values()
   266  	c.Assert(len(values), Equals, 5)
   267  	for i := 0; i < 5; i++ {
   268  		c.Assert(values[i], Equals, int64(4-i))
   269  	}
   270  }
   271  
   272  func (s *testLRUCacheSuite) TestPutProfileName(c *C) {
   273  	lru := NewSimpleLRUCache(3, 0, 10)
   274  	c.Assert(lru.capacity, Equals, uint(3))
   275  	t := reflect.TypeOf(*lru)
   276  	pt := reflect.TypeOf(lru)
   277  	functionName := ""
   278  	for i := 0; i < pt.NumMethod(); i++ {
   279  		if pt.Method(i).Name == "Put" {
   280  			functionName = "Put"
   281  		}
   282  	}
   283  	pName := fmt.Sprintf("%s.(*%s).%s", t.PkgPath(), t.Name(), functionName)
   284  	c.Assert(pName, Equals, ProfileName)
   285  }