github.com/xgzlucario/GigaCache@v0.0.0-20240508025442-54204e9c8a6b/bucket_test.go (about) 1 package cache 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 var ( 11 nilBytes []byte 12 ) 13 14 func getBucket(options ...Options) *bucket { 15 var opt Options 16 if len(options) > 0 { 17 opt = options[0] 18 } else { 19 opt = DefaultOptions 20 opt.EvictInterval = 1 21 } 22 m := newBucket(opt) 23 24 for i := 0; i < 100; i++ { 25 k, v := genKV(i) 26 key := Key(i / 10) 27 m.set(key, []byte(k), v, 0) 28 } 29 return m 30 } 31 32 func TestBucket(t *testing.T) { 33 assert := assert.New(t) 34 35 testHashFn := func(s string) uint64 { 36 return 0 37 } 38 39 for i, hashFn := range []HashFn{MemHash, testHashFn} { 40 opt := DefaultOptions 41 opt.HashFn = hashFn 42 43 m := getBucket(opt) 44 scanCheck := func() { 45 var count int 46 m.scan(func(key, val []byte, ttl int64) bool { 47 count++ 48 return true 49 }) 50 assert.Equal(100, count) 51 } 52 53 assert.Equal(10, len(m.index)) 54 assert.Equal(90, len(m.cmap)) 55 56 m.eliminate() 57 scanCheck() 58 m.migrate() 59 60 if i == 0 { 61 assert.Equal(100, len(m.index)) // migrate use memhash and migrate all keys to index. 62 assert.Equal(0, len(m.cmap)) 63 } else { 64 assert.Equal(10, len(m.index)) 65 assert.Equal(90, len(m.cmap)) 66 } 67 scanCheck() 68 } 69 } 70 71 func TestBucketExpired(t *testing.T) { 72 assert := assert.New(t) 73 74 t.Run("1", func(t *testing.T) { 75 m := getBucket() 76 ttl := time.Now().Add(time.Second).UnixNano() 77 for i := 0; i < 100; i++ { 78 k, v := genKV(i) 79 key := Key(i / 10) 80 // set 81 m.set(key, []byte(k), v, ttl) 82 // get 83 val, ts, ok := m.get(k, key) 84 assert.True(ok) 85 assert.Equal(val, v) 86 assert.Equal(ts, ttl/timeCarry*timeCarry) 87 } 88 89 assert.Equal(90, len(m.cmap)) 90 assert.Equal(10, len(m.index)) 91 92 // expired 93 time.Sleep(time.Second * 2) 94 95 var count int 96 m.scan(func(key, val []byte, ttl int64) (next bool) { 97 count++ 98 return true 99 }) 100 assert.Equal(count, 0) 101 102 m.eliminate() 103 assert.Equal(0, len(m.cmap)) 104 assert.Equal(0, len(m.index)) 105 }) 106 } 107 108 func TestBucketMigrate(t *testing.T) { 109 assert := assert.New(t) 110 111 m := getBucket() 112 ttl := time.Now().Add(time.Second).UnixNano() 113 for i := 0; i < 100; i++ { 114 k, v := genKV(i) 115 key := Key(i / 10) 116 // setTTL 117 ok := m.setTTL(key, k, ttl) 118 assert.True(ok) 119 // get 120 val, ts, ok := m.get(k, key) 121 assert.True(ok) 122 assert.Equal(val, v) 123 assert.Equal(ts, ttl/timeCarry*timeCarry) 124 } 125 126 time.Sleep(time.Second * 2) 127 assert.Equal(90, len(m.cmap)) 128 assert.Equal(10, len(m.index)) 129 m.migrate() 130 assert.Equal(0, len(m.cmap)) 131 assert.Equal(0, len(m.index)) 132 } 133 134 func TestBucketRemove(t *testing.T) { 135 assert := assert.New(t) 136 137 t.Run("remove", func(t *testing.T) { 138 m := getBucket() 139 for i := 0; i < 100; i++ { 140 k, _ := genKV(i) 141 key := Key(i / 10) 142 // remove 143 m.remove(key, k) 144 // get 145 val, ts, ok := m.get(k, key) 146 assert.False(ok) 147 assert.Equal(val, nilBytes) 148 assert.Equal(ts, int64(0)) 149 } 150 assert.Equal(0, len(m.cmap)) 151 assert.Equal(0, len(m.index)) 152 }) 153 154 t.Run("remove-ttl", func(t *testing.T) { 155 options := DefaultOptions 156 options.EvictInterval = 1 157 m := newBucket(options) 158 159 ts1 := time.Now().Add(time.Hour).UnixNano() 160 for i := 0; i < 100; i++ { 161 k, v := genKV(i) 162 key := Key(i / 10) 163 m.set(key, []byte(k), v, ts1) 164 } 165 ts2 := time.Now().UnixNano() 166 for i := 100; i < 200; i++ { 167 k, v := genKV(i) 168 key := Key(i / 10) 169 m.set(key, []byte(k), v, ts2) 170 } 171 172 time.Sleep(time.Second) 173 174 // remove 175 for i := 0; i < 100; i++ { 176 k, _ := genKV(i) 177 key := Key(i / 10) 178 ok := m.remove(key, k) 179 assert.True(ok) 180 } 181 for i := 100; i < 200; i++ { 182 k, _ := genKV(i) 183 key := Key(i / 10) 184 ok := m.remove(key, k) 185 assert.False(ok) // false because of expired. 186 } 187 }) 188 } 189 190 func TestBucketScan(t *testing.T) { 191 assert := assert.New(t) 192 m := getBucket() 193 194 t.Run("scan", func(t *testing.T) { 195 var count int 196 m.scan(func(key, val []byte, _ int64) bool { 197 assert.Equal(key, val) 198 count++ 199 return true 200 }) 201 assert.Equal(100, count) 202 }) 203 204 t.Run("scan-break", func(t *testing.T) { 205 var count int 206 m.scan(func(_, _ []byte, _ int64) bool { 207 count++ 208 return count < 50 209 }) 210 assert.Equal(50, count) 211 }) 212 }