github.com/metacubex/mihomo@v1.18.5/common/lru/lrucache_test.go (about)

     1  package lru
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  )
     9  
    10  var entries = []struct {
    11  	key   string
    12  	value string
    13  }{
    14  	{"1", "one"},
    15  	{"2", "two"},
    16  	{"3", "three"},
    17  	{"4", "four"},
    18  	{"5", "five"},
    19  }
    20  
    21  func TestLRUCache(t *testing.T) {
    22  	c := New[string, string]()
    23  
    24  	for _, e := range entries {
    25  		c.Set(e.key, e.value)
    26  	}
    27  
    28  	c.Delete("missing")
    29  	_, ok := c.Get("missing")
    30  	assert.False(t, ok)
    31  
    32  	for _, e := range entries {
    33  		value, ok := c.Get(e.key)
    34  		if assert.True(t, ok) {
    35  			assert.Equal(t, e.value, value)
    36  		}
    37  	}
    38  
    39  	for _, e := range entries {
    40  		c.Delete(e.key)
    41  
    42  		_, ok := c.Get(e.key)
    43  		assert.False(t, ok)
    44  	}
    45  }
    46  
    47  func TestLRUMaxAge(t *testing.T) {
    48  	c := New[string, string](WithAge[string, string](86400))
    49  
    50  	now := time.Now().Unix()
    51  	expected := now + 86400
    52  
    53  	// Add one expired entry
    54  	c.Set("foo", "bar")
    55  	c.lru.Back().Value.expires = now
    56  
    57  	// Reset
    58  	c.Set("foo", "bar")
    59  	e := c.lru.Back().Value
    60  	assert.True(t, e.expires >= now)
    61  	c.lru.Back().Value.expires = now
    62  
    63  	// Set a few and verify expiration times
    64  	for _, s := range entries {
    65  		c.Set(s.key, s.value)
    66  		e := c.lru.Back().Value
    67  		assert.True(t, e.expires >= expected && e.expires <= expected+10)
    68  	}
    69  
    70  	// Make sure we can get them all
    71  	for _, s := range entries {
    72  		_, ok := c.Get(s.key)
    73  		assert.True(t, ok)
    74  	}
    75  
    76  	// Expire all entries
    77  	for _, s := range entries {
    78  		le, ok := c.cache[s.key]
    79  		if assert.True(t, ok) {
    80  			le.Value.expires = now
    81  		}
    82  	}
    83  
    84  	// Get one expired entry, which should clear all expired entries
    85  	_, ok := c.Get("3")
    86  	assert.False(t, ok)
    87  	assert.Equal(t, c.lru.Len(), 0)
    88  }
    89  
    90  func TestLRUpdateOnGet(t *testing.T) {
    91  	c := New[string, string](WithAge[string, string](86400), WithUpdateAgeOnGet[string, string]())
    92  
    93  	now := time.Now().Unix()
    94  	expires := now + 86400/2
    95  
    96  	// Add one expired entry
    97  	c.Set("foo", "bar")
    98  	c.lru.Back().Value.expires = expires
    99  
   100  	_, ok := c.Get("foo")
   101  	assert.True(t, ok)
   102  	assert.True(t, c.lru.Back().Value.expires > expires)
   103  }
   104  
   105  func TestMaxSize(t *testing.T) {
   106  	c := New[string, string](WithSize[string, string](2))
   107  	// Add one expired entry
   108  	c.Set("foo", "bar")
   109  	_, ok := c.Get("foo")
   110  	assert.True(t, ok)
   111  
   112  	c.Set("bar", "foo")
   113  	c.Set("baz", "foo")
   114  
   115  	_, ok = c.Get("foo")
   116  	assert.False(t, ok)
   117  }
   118  
   119  func TestExist(t *testing.T) {
   120  	c := New[int, int](WithSize[int, int](1))
   121  	c.Set(1, 2)
   122  	assert.True(t, c.Exist(1))
   123  	c.Set(2, 3)
   124  	assert.False(t, c.Exist(1))
   125  }
   126  
   127  func TestEvict(t *testing.T) {
   128  	temp := 0
   129  	evict := func(key int, value int) {
   130  		temp = key + value
   131  	}
   132  
   133  	c := New[int, int](WithEvict[int, int](evict), WithSize[int, int](1))
   134  	c.Set(1, 2)
   135  	c.Set(2, 3)
   136  
   137  	assert.Equal(t, temp, 3)
   138  }
   139  
   140  func TestSetWithExpire(t *testing.T) {
   141  	c := New[int, *struct{}](WithAge[int, *struct{}](1))
   142  	now := time.Now().Unix()
   143  
   144  	tenSecBefore := time.Unix(now-10, 0)
   145  	c.SetWithExpire(1, &struct{}{}, tenSecBefore)
   146  
   147  	// res is expected not to exist, and expires should be empty time.Time
   148  	res, expires, exist := c.GetWithExpire(1)
   149  
   150  	assert.True(t, nil == res)
   151  	assert.Equal(t, time.Time{}, expires)
   152  	assert.Equal(t, false, exist)
   153  }
   154  
   155  func TestStale(t *testing.T) {
   156  	c := New[int, int](WithAge[int, int](1), WithStale[int, int](true))
   157  	now := time.Now().Unix()
   158  
   159  	tenSecBefore := time.Unix(now-10, 0)
   160  	c.SetWithExpire(1, 2, tenSecBefore)
   161  
   162  	res, expires, exist := c.GetWithExpire(1)
   163  	assert.Equal(t, 2, res)
   164  	assert.Equal(t, tenSecBefore, expires)
   165  	assert.Equal(t, true, exist)
   166  }
   167  
   168  func TestCloneTo(t *testing.T) {
   169  	o := New[string, int](WithSize[string, int](10))
   170  	o.Set("1", 1)
   171  	o.Set("2", 2)
   172  
   173  	n := New[string, int](WithSize[string, int](2))
   174  	n.Set("3", 3)
   175  	n.Set("4", 4)
   176  
   177  	o.CloneTo(n)
   178  
   179  	assert.False(t, n.Exist("3"))
   180  	assert.True(t, n.Exist("1"))
   181  
   182  	n.Set("5", 5)
   183  	assert.False(t, n.Exist("1"))
   184  }