github.com/theQRL/go-zond@v0.1.1/common/lru/basiclru_test.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package lru
    18  
    19  import (
    20  	crand "crypto/rand"
    21  	"fmt"
    22  	"io"
    23  	"math/rand"
    24  	"testing"
    25  )
    26  
    27  // Some of these test cases were adapted
    28  // from https://github.com/hashicorp/golang-lru/blob/master/simplelru/lru_test.go
    29  
    30  func TestBasicLRU(t *testing.T) {
    31  	cache := NewBasicLRU[int, int](128)
    32  
    33  	for i := 0; i < 256; i++ {
    34  		cache.Add(i, i)
    35  	}
    36  	if cache.Len() != 128 {
    37  		t.Fatalf("bad len: %v", cache.Len())
    38  	}
    39  
    40  	// Check that Keys returns least-recent key first.
    41  	keys := cache.Keys()
    42  	if len(keys) != 128 {
    43  		t.Fatal("wrong Keys() length", len(keys))
    44  	}
    45  	for i, k := range keys {
    46  		v, ok := cache.Peek(k)
    47  		if !ok {
    48  			t.Fatalf("expected key %d be present", i)
    49  		}
    50  		if v != k {
    51  			t.Fatalf("expected %d == %d", k, v)
    52  		}
    53  		if v != i+128 {
    54  			t.Fatalf("wrong value at key %d: %d, want %d", i, v, i+128)
    55  		}
    56  	}
    57  
    58  	for i := 0; i < 128; i++ {
    59  		_, ok := cache.Get(i)
    60  		if ok {
    61  			t.Fatalf("%d should be evicted", i)
    62  		}
    63  	}
    64  	for i := 128; i < 256; i++ {
    65  		_, ok := cache.Get(i)
    66  		if !ok {
    67  			t.Fatalf("%d should not be evicted", i)
    68  		}
    69  	}
    70  
    71  	for i := 128; i < 192; i++ {
    72  		ok := cache.Remove(i)
    73  		if !ok {
    74  			t.Fatalf("%d should be in cache", i)
    75  		}
    76  		ok = cache.Remove(i)
    77  		if ok {
    78  			t.Fatalf("%d should not be in cache", i)
    79  		}
    80  		_, ok = cache.Get(i)
    81  		if ok {
    82  			t.Fatalf("%d should be deleted", i)
    83  		}
    84  	}
    85  
    86  	// Request item 192.
    87  	cache.Get(192)
    88  	// It should be the last item returned by Keys().
    89  	for i, k := range cache.Keys() {
    90  		if (i < 63 && k != i+193) || (i == 63 && k != 192) {
    91  			t.Fatalf("out of order key: %v", k)
    92  		}
    93  	}
    94  
    95  	cache.Purge()
    96  	if cache.Len() != 0 {
    97  		t.Fatalf("bad len: %v", cache.Len())
    98  	}
    99  	if _, ok := cache.Get(200); ok {
   100  		t.Fatalf("should contain nothing")
   101  	}
   102  }
   103  
   104  func TestBasicLRUAddExistingKey(t *testing.T) {
   105  	cache := NewBasicLRU[int, int](1)
   106  
   107  	cache.Add(1, 1)
   108  	cache.Add(1, 2)
   109  
   110  	v, _ := cache.Get(1)
   111  	if v != 2 {
   112  		t.Fatal("wrong value:", v)
   113  	}
   114  }
   115  
   116  // This test checks GetOldest and RemoveOldest.
   117  func TestBasicLRUGetOldest(t *testing.T) {
   118  	cache := NewBasicLRU[int, int](128)
   119  	for i := 0; i < 256; i++ {
   120  		cache.Add(i, i)
   121  	}
   122  
   123  	k, _, ok := cache.GetOldest()
   124  	if !ok {
   125  		t.Fatalf("missing")
   126  	}
   127  	if k != 128 {
   128  		t.Fatalf("bad: %v", k)
   129  	}
   130  
   131  	k, _, ok = cache.RemoveOldest()
   132  	if !ok {
   133  		t.Fatalf("missing")
   134  	}
   135  	if k != 128 {
   136  		t.Fatalf("bad: %v", k)
   137  	}
   138  
   139  	k, _, ok = cache.RemoveOldest()
   140  	if !ok {
   141  		t.Fatalf("missing oldest item")
   142  	}
   143  	if k != 129 {
   144  		t.Fatalf("wrong oldest item: %v", k)
   145  	}
   146  }
   147  
   148  // Test that Add returns true/false if an eviction occurred
   149  func TestBasicLRUAddReturnValue(t *testing.T) {
   150  	cache := NewBasicLRU[int, int](1)
   151  	if cache.Add(1, 1) {
   152  		t.Errorf("first add shouldn't have evicted")
   153  	}
   154  	if !cache.Add(2, 2) {
   155  		t.Errorf("second add should have evicted")
   156  	}
   157  }
   158  
   159  // This test verifies that Contains doesn't change item recency.
   160  func TestBasicLRUContains(t *testing.T) {
   161  	cache := NewBasicLRU[int, int](2)
   162  	cache.Add(1, 1)
   163  	cache.Add(2, 2)
   164  	if !cache.Contains(1) {
   165  		t.Errorf("1 should be in the cache")
   166  	}
   167  	cache.Add(3, 3)
   168  	if cache.Contains(1) {
   169  		t.Errorf("Contains should not have updated recency of 1")
   170  	}
   171  }
   172  
   173  // Test that Peek doesn't update recent-ness
   174  func TestBasicLRUPeek(t *testing.T) {
   175  	cache := NewBasicLRU[int, int](2)
   176  	cache.Add(1, 1)
   177  	cache.Add(2, 2)
   178  	if v, ok := cache.Peek(1); !ok || v != 1 {
   179  		t.Errorf("1 should be set to 1")
   180  	}
   181  	cache.Add(3, 3)
   182  	if cache.Contains(1) {
   183  		t.Errorf("should not have updated recent-ness of 1")
   184  	}
   185  }
   186  
   187  func BenchmarkLRU(b *testing.B) {
   188  	var (
   189  		capacity = 1000
   190  		indexes  = make([]int, capacity*20)
   191  		keys     = make([]string, capacity)
   192  		values   = make([][]byte, capacity)
   193  	)
   194  	for i := range indexes {
   195  		indexes[i] = rand.Intn(capacity)
   196  	}
   197  	for i := range keys {
   198  		b := make([]byte, 32)
   199  		crand.Read(b)
   200  		keys[i] = string(b)
   201  		crand.Read(b)
   202  		values[i] = b
   203  	}
   204  
   205  	var sink []byte
   206  
   207  	b.Run("Add/BasicLRU", func(b *testing.B) {
   208  		cache := NewBasicLRU[int, int](capacity)
   209  		for i := 0; i < b.N; i++ {
   210  			cache.Add(i, i)
   211  		}
   212  	})
   213  	b.Run("Get/BasicLRU", func(b *testing.B) {
   214  		cache := NewBasicLRU[string, []byte](capacity)
   215  		for i := 0; i < capacity; i++ {
   216  			index := indexes[i]
   217  			cache.Add(keys[index], values[index])
   218  		}
   219  
   220  		b.ResetTimer()
   221  		for i := 0; i < b.N; i++ {
   222  			k := keys[indexes[i%len(indexes)]]
   223  			v, ok := cache.Get(k)
   224  			if ok {
   225  				sink = v
   226  			}
   227  		}
   228  	})
   229  
   230  	// // vs. github.com/hashicorp/golang-lru/simplelru
   231  	// b.Run("Add/simplelru.LRU", func(b *testing.B) {
   232  	//	cache, _ := simplelru.NewLRU(capacity, nil)
   233  	//	for i := 0; i < b.N; i++ {
   234  	//		cache.Add(i, i)
   235  	//	}
   236  	// })
   237  	// b.Run("Get/simplelru.LRU", func(b *testing.B) {
   238  	//	cache, _ := simplelru.NewLRU(capacity, nil)
   239  	//	for i := 0; i < capacity; i++ {
   240  	//		index := indexes[i]
   241  	//		cache.Add(keys[index], values[index])
   242  	//	}
   243  	//
   244  	//	b.ResetTimer()
   245  	//	for i := 0; i < b.N; i++ {
   246  	//		k := keys[indexes[i%len(indexes)]]
   247  	//		v, ok := cache.Get(k)
   248  	//		if ok {
   249  	//			sink = v.([]byte)
   250  	//		}
   251  	//	}
   252  	// })
   253  
   254  	fmt.Fprintln(io.Discard, sink)
   255  }