github.com/xgzlucario/GigaCache@v0.0.0-20240508025442-54204e9c8a6b/cache_test.go (about) 1 package cache 2 3 import ( 4 "fmt" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 func genKV(i int) (string, []byte) { 12 k := fmt.Sprintf("%08x", i) 13 return k, []byte(k) 14 } 15 16 func getOptions(num, interval int) Options { 17 opt := DefaultOptions 18 opt.ShardCount = 1 19 opt.EvictInterval = interval 20 opt.IndexSize = num 21 return opt 22 } 23 24 func checkValidData(assert *assert.Assertions, m *GigaCache, start, end int) { 25 for i := start; i < end; i++ { 26 k, _ := genKV(i) 27 val, ts, ok := m.Get(k) 28 assert.True(ok) 29 assert.Equal(string(val), k) 30 assert.GreaterOrEqual(ts, int64(0)) 31 } 32 // scan 33 beginKey, _ := genKV(start) 34 endKey, _ := genKV(end) 35 36 var count int 37 m.Scan(func(key, val []byte, i int64) bool { 38 if string(key) < beginKey || string(key) >= endKey { 39 assert.Fail("invalid data") 40 } 41 assert.Equal(key, val) 42 count++ 43 return true 44 }) 45 assert.Equal(count, end-start) 46 47 // scan break 48 count = 0 49 m.Scan(func(key, val []byte, i int64) bool { 50 count++ 51 return count < (end-start)/2 52 }) 53 assert.Equal(count, (end-start)/2) 54 } 55 56 func checkInvalidData(assert *assert.Assertions, m *GigaCache, start, end int) { 57 // range 58 for i := start; i < end; i++ { 59 k, _ := genKV(i) 60 val, ts, ok := m.Get(k) 61 assert.False(ok) 62 assert.Nil(val) 63 assert.Equal(ts, int64(0)) 64 // setTTL 65 ok = m.SetTTL(k, time.Now().UnixNano()) 66 assert.False(ok) 67 // remove 68 m.Remove(k) 69 } 70 // scan 71 beginKey, _ := genKV(start) 72 endKey, _ := genKV(end) 73 74 m.Scan(func(key, val []byte, i int64) bool { 75 if string(key) >= beginKey && string(key) < endKey { 76 assert.Fail("invalid data") 77 } 78 assert.Equal(key, val) 79 return true 80 }) 81 } 82 83 func TestCache(t *testing.T) { 84 assert := assert.New(t) 85 const num = 1000 86 m := New(getOptions(num, 3)) 87 88 // init cache. 89 for i := 0; i < num/3; i++ { 90 k, v := genKV(i) 91 m.Set(k, v) 92 } 93 for i := num / 3; i < num*2/3; i++ { 94 k, v := genKV(i) 95 m.SetEx(k, v, time.Hour) 96 } 97 for i := num * 2 / 3; i < num; i++ { 98 k, v := genKV(i) 99 m.SetEx(k, v, time.Second) 100 } 101 102 // wait for expired. 103 time.Sleep(time.Second * 2) 104 105 // check. 106 { 107 checkValidData(assert, m, 0, num*2/3) 108 checkInvalidData(assert, m, num*2/3, num) 109 m.Migrate() 110 checkValidData(assert, m, 0, num*2/3) 111 checkInvalidData(assert, m, num*2/3, num) 112 } 113 114 // setTTL 115 ts := time.Now().UnixNano() 116 for i := num / 3; i < num*2/3; i++ { 117 k, _ := genKV(i) 118 assert.True(m.SetTTL(k, ts)) 119 } 120 time.Sleep(time.Second) 121 122 // check. 123 { 124 checkValidData(assert, m, 0, num/3) 125 checkInvalidData(assert, m, num/3, num) 126 m.Migrate() 127 checkValidData(assert, m, 0, num/3) 128 checkInvalidData(assert, m, num/3, num) 129 } 130 131 // remove all. 132 for i := 0; i < num/3; i++ { 133 k, _ := genKV(i) 134 m.Remove(k) 135 } 136 for i := num / 3; i < num; i++ { 137 k, _ := genKV(i) 138 m.Remove(k) 139 } 140 141 // check. 142 { 143 checkInvalidData(assert, m, 0, num) 144 m.Migrate() 145 checkInvalidData(assert, m, 0, num) 146 } 147 148 assert.Panics(func() { 149 opt := DefaultOptions 150 opt.ShardCount = 0 151 New(opt) 152 }) 153 154 assert.Panics(func() { 155 opt := DefaultOptions 156 opt.EvictInterval = -1 157 New(opt) 158 }) 159 } 160 161 func TestEvict(t *testing.T) { 162 assert := assert.New(t) 163 const num = 1000 164 opt := getOptions(num, 1) 165 m := New(opt) 166 167 // set data. 168 for i := 0; i < num; i++ { 169 k, v := genKV(i) 170 m.SetEx(k, v, time.Second) 171 } 172 time.Sleep(time.Second * 2) 173 174 // stat 175 stat := m.Stat() 176 assert.Equal(stat.Len, num) 177 assert.Equal(stat.Alloc, uint64(stat.Len*(16+2))) 178 assert.Equal(stat.Unused, uint64(0)) 179 assert.Equal(stat.Evict, uint64(0)) 180 assert.Greater(stat.Probe, uint64(0)) 181 assert.Equal(stat.EvictRate(), float64(0)) 182 assert.Equal(stat.UnusedRate(), float64(0)) 183 184 // trig evict. 185 m.Set("trig1234", []byte("trig1234")) 186 187 stat = m.Stat() 188 assert.Equal(stat.Len, int(num-stat.Evict+1)) 189 assert.Equal(stat.Alloc, uint64(16+2)) 190 assert.Equal(stat.Unused, uint64(0)) 191 assert.Equal(stat.Migrates, uint64(1)) 192 } 193 194 func TestDataAlloc(t *testing.T) { 195 assert := assert.New(t) 196 197 t.Run("memhash", func(t *testing.T) { 198 opt := DefaultOptions 199 opt.ShardCount = 1 200 opt.DisableEvict = true 201 m := New(opt) 202 m.Set("hello", []byte("world")) 203 204 m.Set("abc", []byte("123")) 205 // stat 206 stat := m.Stat() 207 assert.Equal(stat.Len, 2) 208 assert.Equal(stat.Alloc, uint64(12+8)) 209 assert.Equal(stat.Unused, uint64(0)) 210 211 // set same data(update inplaced). 212 m.Set("abc", []byte("234")) 213 214 stat = m.Stat() 215 assert.Equal(stat.Len, 2) 216 assert.Equal(stat.Alloc, uint64(12+8)) 217 assert.Equal(stat.Unused, uint64(0)) 218 219 // set great. 220 m.Set("abc", []byte("12345")) 221 222 stat = m.Stat() 223 assert.Equal(stat.Len, 2) 224 assert.Equal(stat.Alloc, uint64(12+8+10)) 225 assert.Equal(stat.Unused, uint64(8)) 226 }) 227 228 t.Run("testHash", func(t *testing.T) { 229 opt := DefaultOptions 230 opt.ShardCount = 1 231 opt.DisableEvict = true 232 opt.HashFn = func(s string) uint64 { 233 return 0 234 } 235 m := New(opt) 236 m.Set("hello", []byte("world")) 237 238 m.Set("abc", []byte("123")) 239 // stat 240 stat := m.Stat() 241 assert.Equal(stat.Len, 2) 242 assert.Equal(stat.Alloc, uint64(12+8)) 243 assert.Equal(stat.Unused, uint64(0)) 244 245 // set same data(update inplaced). 246 m.Set("abc", []byte("234")) 247 248 stat = m.Stat() 249 assert.Equal(stat.Len, 2) 250 assert.Equal(stat.Alloc, uint64(12+8)) 251 assert.Equal(stat.Unused, uint64(0)) 252 253 // set great. 254 m.Set("abc", []byte("12345")) 255 256 stat = m.Stat() 257 assert.Equal(stat.Len, 2) 258 assert.Equal(stat.Alloc, uint64(12+8+10)) 259 assert.Equal(stat.Unused, uint64(8)) 260 }) 261 } 262 263 func TestScanSmall(t *testing.T) { 264 assert := assert.New(t) 265 opt := DefaultOptions 266 opt.ShardCount = 1024 267 m := New(opt) 268 269 for i := 0; i < 100; i++ { 270 k, v := genKV(i) 271 m.Set(k, v) 272 } 273 274 var count int 275 m.Scan(func(key, val []byte, ttl int64) (next bool) { 276 assert.Equal(key, val) 277 assert.Equal(ttl, int64(0)) 278 count++ 279 return true 280 }) 281 assert.Equal(count, 100) 282 } 283 284 func TestUtils(t *testing.T) { 285 _ = SizeUvarint(1) 286 }