github.com/Finschia/finschia-sdk@v0.48.1/store/prefix/store_test.go (about) 1 package prefix 2 3 import ( 4 "crypto/rand" 5 "testing" 6 7 "github.com/stretchr/testify/require" 8 9 liavl "github.com/cosmos/iavl" 10 "github.com/Finschia/finschia-sdk/store/cachekv" 11 dbm "github.com/tendermint/tm-db" 12 13 "github.com/Finschia/finschia-sdk/store/dbadapter" 14 "github.com/Finschia/finschia-sdk/store/gaskv" 15 "github.com/Finschia/finschia-sdk/store/iavl" 16 "github.com/Finschia/finschia-sdk/store/types" 17 sdk "github.com/Finschia/finschia-sdk/types" 18 ) 19 20 // copied from iavl/store_test.go 21 var ( 22 cacheSize = 100 23 ) 24 25 func bz(s string) []byte { return []byte(s) } 26 27 type kvpair struct { 28 key []byte 29 value []byte 30 } 31 32 func genRandomKVPairs(t *testing.T) []kvpair { 33 kvps := make([]kvpair, 20) 34 35 for i := 0; i < 20; i++ { 36 kvps[i].key = make([]byte, 32) 37 _, err := rand.Read(kvps[i].key) 38 require.NoError(t, err) 39 kvps[i].value = make([]byte, 32) 40 _, err = rand.Read(kvps[i].value) 41 require.NoError(t, err) 42 } 43 44 return kvps 45 } 46 47 func setRandomKVPairs(t *testing.T, store types.KVStore) []kvpair { 48 kvps := genRandomKVPairs(t) 49 for _, kvp := range kvps { 50 store.Set(kvp.key, kvp.value) 51 } 52 return kvps 53 } 54 55 func testPrefixStore(t *testing.T, baseStore types.KVStore, prefix []byte) { 56 prefixStore := NewStore(baseStore, prefix) 57 prefixPrefixStore := NewStore(prefixStore, []byte("prefix")) 58 59 require.Panics(t, func() { prefixStore.Get(nil) }) 60 require.Panics(t, func() { prefixStore.Set(nil, []byte{}) }) 61 62 kvps := setRandomKVPairs(t, prefixPrefixStore) 63 64 for i := 0; i < 20; i++ { 65 key := kvps[i].key 66 value := kvps[i].value 67 require.True(t, prefixPrefixStore.Has(key)) 68 require.Equal(t, value, prefixPrefixStore.Get(key)) 69 70 key = append([]byte("prefix"), key...) 71 require.True(t, prefixStore.Has(key)) 72 require.Equal(t, value, prefixStore.Get(key)) 73 key = append(prefix, key...) 74 require.True(t, baseStore.Has(key)) 75 require.Equal(t, value, baseStore.Get(key)) 76 77 key = kvps[i].key 78 prefixPrefixStore.Delete(key) 79 require.False(t, prefixPrefixStore.Has(key)) 80 require.Nil(t, prefixPrefixStore.Get(key)) 81 key = append([]byte("prefix"), key...) 82 require.False(t, prefixStore.Has(key)) 83 require.Nil(t, prefixStore.Get(key)) 84 key = append(prefix, key...) 85 require.False(t, baseStore.Has(key)) 86 require.Nil(t, baseStore.Get(key)) 87 } 88 } 89 90 func TestIAVLStorePrefix(t *testing.T) { 91 db := dbm.NewMemDB() 92 tree, err := liavl.NewMutableTree(db, cacheSize, false) 93 require.NoError(t, err) 94 iavlStore := iavl.UnsafeNewStore(tree) 95 96 testPrefixStore(t, iavlStore, []byte("test")) 97 } 98 99 func TestPrefixKVStoreNoNilSet(t *testing.T) { 100 meter := types.NewGasMeter(100000000) 101 mem := dbadapter.Store{DB: dbm.NewMemDB()} 102 gasStore := gaskv.NewStore(mem, meter, types.KVGasConfig()) 103 require.Panics(t, func() { gasStore.Set([]byte("key"), nil) }, "setting a nil value should panic") 104 } 105 106 func TestPrefixStoreIterate(t *testing.T) { 107 db := dbm.NewMemDB() 108 baseStore := dbadapter.Store{DB: db} 109 prefix := []byte("test") 110 prefixStore := NewStore(baseStore, prefix) 111 112 setRandomKVPairs(t, prefixStore) 113 114 bIter := types.KVStorePrefixIterator(baseStore, prefix) 115 pIter := types.KVStorePrefixIterator(prefixStore, nil) 116 117 for bIter.Valid() && pIter.Valid() { 118 require.Equal(t, bIter.Key(), append(prefix, pIter.Key()...)) 119 require.Equal(t, bIter.Value(), pIter.Value()) 120 121 bIter.Next() 122 pIter.Next() 123 } 124 125 bIter.Close() 126 pIter.Close() 127 } 128 129 func incFirstByte(bz []byte) { 130 bz[0]++ 131 } 132 133 func TestCloneAppend(t *testing.T) { 134 kvps := genRandomKVPairs(t) 135 for _, kvp := range kvps { 136 bz := cloneAppend(kvp.key, kvp.value) 137 require.Equal(t, bz, append(kvp.key, kvp.value...)) 138 139 incFirstByte(bz) 140 require.NotEqual(t, bz, append(kvp.key, kvp.value...)) 141 142 bz = cloneAppend(kvp.key, kvp.value) 143 incFirstByte(kvp.key) 144 require.NotEqual(t, bz, append(kvp.key, kvp.value...)) 145 146 bz = cloneAppend(kvp.key, kvp.value) 147 incFirstByte(kvp.value) 148 require.NotEqual(t, bz, append(kvp.key, kvp.value...)) 149 } 150 } 151 152 func TestPrefixStoreIteratorEdgeCase(t *testing.T) { 153 db := dbm.NewMemDB() 154 baseStore := dbadapter.Store{DB: db} 155 156 // overflow in cpIncr 157 prefix := []byte{0xAA, 0xFF, 0xFF} 158 prefixStore := NewStore(baseStore, prefix) 159 160 // ascending order 161 baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) 162 baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{}) 163 baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{}) 164 baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{}) 165 baseStore.Set([]byte{0xAB}, []byte{}) 166 baseStore.Set([]byte{0xAB, 0x00}, []byte{}) 167 baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) 168 169 iter := prefixStore.Iterator(nil, nil) 170 171 checkDomain(t, iter, nil, nil) 172 checkItem(t, iter, []byte{}, bz("")) 173 checkNext(t, iter, true) 174 checkItem(t, iter, []byte{0x00}, bz("")) 175 checkNext(t, iter, false) 176 177 checkInvalid(t, iter) 178 179 iter.Close() 180 } 181 182 func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { 183 db := dbm.NewMemDB() 184 baseStore := dbadapter.Store{DB: db} 185 186 // overflow in cpIncr 187 prefix := []byte{0xAA, 0xFF, 0xFF} 188 prefixStore := NewStore(baseStore, prefix) 189 190 // descending order 191 baseStore.Set([]byte{0xAB, 0x00, 0x00}, []byte{}) 192 baseStore.Set([]byte{0xAB, 0x00}, []byte{}) 193 baseStore.Set([]byte{0xAB}, []byte{}) 194 baseStore.Set([]byte{0xAA, 0xFF, 0xFF, 0x00}, []byte{}) 195 baseStore.Set([]byte{0xAA, 0xFF, 0xFF}, []byte{}) 196 baseStore.Set([]byte{0xAA, 0xFF, 0xFE, 0x00}, []byte{}) 197 baseStore.Set([]byte{0xAA, 0xFF, 0xFE}, []byte{}) 198 199 iter := prefixStore.ReverseIterator(nil, nil) 200 201 checkDomain(t, iter, nil, nil) 202 checkItem(t, iter, []byte{0x00}, bz("")) 203 checkNext(t, iter, true) 204 checkItem(t, iter, []byte{}, bz("")) 205 checkNext(t, iter, false) 206 207 checkInvalid(t, iter) 208 209 iter.Close() 210 211 db = dbm.NewMemDB() 212 baseStore = dbadapter.Store{DB: db} 213 214 // underflow in cpDecr 215 prefix = []byte{0xAA, 0x00, 0x00} 216 prefixStore = NewStore(baseStore, prefix) 217 218 baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00, 0x00}, []byte{}) 219 baseStore.Set([]byte{0xAB, 0x00, 0x01, 0x00}, []byte{}) 220 baseStore.Set([]byte{0xAB, 0x00, 0x01}, []byte{}) 221 baseStore.Set([]byte{0xAA, 0x00, 0x00, 0x00}, []byte{}) 222 baseStore.Set([]byte{0xAA, 0x00, 0x00}, []byte{}) 223 baseStore.Set([]byte{0xA9, 0xFF, 0xFF, 0x00}, []byte{}) 224 baseStore.Set([]byte{0xA9, 0xFF, 0xFF}, []byte{}) 225 226 iter = prefixStore.ReverseIterator(nil, nil) 227 228 checkDomain(t, iter, nil, nil) 229 checkItem(t, iter, []byte{0x00}, bz("")) 230 checkNext(t, iter, true) 231 checkItem(t, iter, []byte{}, bz("")) 232 checkNext(t, iter, false) 233 234 checkInvalid(t, iter) 235 236 iter.Close() 237 } 238 239 // Tests below are ported from https://github.com/tendermint/tendermint/blob/master/libs/db/prefix_db_test.go 240 241 func mockStoreWithStuff() types.KVStore { 242 db := dbm.NewMemDB() 243 store := dbadapter.Store{DB: db} 244 // Under "key" prefix 245 store.Set(bz("key"), bz("value")) 246 store.Set(bz("key1"), bz("value1")) 247 store.Set(bz("key2"), bz("value2")) 248 store.Set(bz("key3"), bz("value3")) 249 store.Set(bz("something"), bz("else")) 250 store.Set(bz("k"), bz(sdk.PrefixValidator)) 251 store.Set(bz("ke"), bz("valu")) 252 store.Set(bz("kee"), bz("valuu")) 253 return store 254 } 255 256 func checkValue(t *testing.T, store types.KVStore, key []byte, expected []byte) { 257 bz := store.Get(key) 258 require.Equal(t, expected, bz) 259 } 260 261 func checkValid(t *testing.T, itr types.Iterator, expected bool) { 262 valid := itr.Valid() 263 require.Equal(t, expected, valid) 264 } 265 266 func checkNext(t *testing.T, itr types.Iterator, expected bool) { 267 itr.Next() 268 valid := itr.Valid() 269 require.Equal(t, expected, valid) 270 } 271 272 func checkDomain(t *testing.T, itr types.Iterator, start, end []byte) { 273 ds, de := itr.Domain() 274 require.Equal(t, start, ds) 275 require.Equal(t, end, de) 276 } 277 278 func checkItem(t *testing.T, itr types.Iterator, key, value []byte) { 279 require.Exactly(t, key, itr.Key()) 280 require.Exactly(t, value, itr.Value()) 281 } 282 283 func checkInvalid(t *testing.T, itr types.Iterator) { 284 checkValid(t, itr, false) 285 checkKeyPanics(t, itr) 286 checkValuePanics(t, itr) 287 checkNextPanics(t, itr) 288 } 289 290 func checkKeyPanics(t *testing.T, itr types.Iterator) { 291 require.Panics(t, func() { itr.Key() }) 292 } 293 294 func checkValuePanics(t *testing.T, itr types.Iterator) { 295 require.Panics(t, func() { itr.Value() }) 296 } 297 298 func checkNextPanics(t *testing.T, itr types.Iterator) { 299 require.Panics(t, func() { itr.Next() }) 300 } 301 302 func TestPrefixDBSimple(t *testing.T) { 303 store := mockStoreWithStuff() 304 pstore := NewStore(store, bz("key")) 305 306 checkValue(t, pstore, bz("key"), nil) 307 checkValue(t, pstore, bz(""), bz("value")) 308 checkValue(t, pstore, bz("key1"), nil) 309 checkValue(t, pstore, bz("1"), bz("value1")) 310 checkValue(t, pstore, bz("key2"), nil) 311 checkValue(t, pstore, bz("2"), bz("value2")) 312 checkValue(t, pstore, bz("key3"), nil) 313 checkValue(t, pstore, bz("3"), bz("value3")) 314 checkValue(t, pstore, bz("something"), nil) 315 checkValue(t, pstore, bz("k"), nil) 316 checkValue(t, pstore, bz("ke"), nil) 317 checkValue(t, pstore, bz("kee"), nil) 318 } 319 320 func TestPrefixDBIterator1(t *testing.T) { 321 store := mockStoreWithStuff() 322 pstore := NewStore(store, bz("key")) 323 324 itr := pstore.Iterator(nil, nil) 325 checkDomain(t, itr, nil, nil) 326 checkItem(t, itr, bz(""), bz("value")) 327 checkNext(t, itr, true) 328 checkItem(t, itr, bz("1"), bz("value1")) 329 checkNext(t, itr, true) 330 checkItem(t, itr, bz("2"), bz("value2")) 331 checkNext(t, itr, true) 332 checkItem(t, itr, bz("3"), bz("value3")) 333 checkNext(t, itr, false) 334 checkInvalid(t, itr) 335 itr.Close() 336 } 337 338 func TestPrefixDBIterator2(t *testing.T) { 339 store := mockStoreWithStuff() 340 pstore := NewStore(store, bz("key")) 341 342 itr := pstore.Iterator(nil, bz("")) 343 checkDomain(t, itr, nil, bz("")) 344 checkInvalid(t, itr) 345 itr.Close() 346 } 347 348 func TestPrefixDBIterator3(t *testing.T) { 349 store := mockStoreWithStuff() 350 pstore := NewStore(store, bz("key")) 351 352 itr := pstore.Iterator(bz(""), nil) 353 checkDomain(t, itr, bz(""), nil) 354 checkItem(t, itr, bz(""), bz("value")) 355 checkNext(t, itr, true) 356 checkItem(t, itr, bz("1"), bz("value1")) 357 checkNext(t, itr, true) 358 checkItem(t, itr, bz("2"), bz("value2")) 359 checkNext(t, itr, true) 360 checkItem(t, itr, bz("3"), bz("value3")) 361 checkNext(t, itr, false) 362 checkInvalid(t, itr) 363 itr.Close() 364 } 365 366 func TestPrefixDBIterator4(t *testing.T) { 367 store := mockStoreWithStuff() 368 pstore := NewStore(store, bz("key")) 369 370 itr := pstore.Iterator(bz(""), bz("")) 371 checkDomain(t, itr, bz(""), bz("")) 372 checkInvalid(t, itr) 373 itr.Close() 374 } 375 376 func TestPrefixDBReverseIterator1(t *testing.T) { 377 store := mockStoreWithStuff() 378 pstore := NewStore(store, bz("key")) 379 380 itr := pstore.ReverseIterator(nil, nil) 381 checkDomain(t, itr, nil, nil) 382 checkItem(t, itr, bz("3"), bz("value3")) 383 checkNext(t, itr, true) 384 checkItem(t, itr, bz("2"), bz("value2")) 385 checkNext(t, itr, true) 386 checkItem(t, itr, bz("1"), bz("value1")) 387 checkNext(t, itr, true) 388 checkItem(t, itr, bz(""), bz("value")) 389 checkNext(t, itr, false) 390 checkInvalid(t, itr) 391 itr.Close() 392 } 393 394 func TestPrefixDBReverseIterator2(t *testing.T) { 395 store := mockStoreWithStuff() 396 pstore := NewStore(store, bz("key")) 397 398 itr := pstore.ReverseIterator(bz(""), nil) 399 checkDomain(t, itr, bz(""), nil) 400 checkItem(t, itr, bz("3"), bz("value3")) 401 checkNext(t, itr, true) 402 checkItem(t, itr, bz("2"), bz("value2")) 403 checkNext(t, itr, true) 404 checkItem(t, itr, bz("1"), bz("value1")) 405 checkNext(t, itr, true) 406 checkItem(t, itr, bz(""), bz("value")) 407 checkNext(t, itr, false) 408 checkInvalid(t, itr) 409 itr.Close() 410 } 411 412 func TestPrefixDBReverseIterator3(t *testing.T) { 413 store := mockStoreWithStuff() 414 pstore := NewStore(store, bz("key")) 415 416 itr := pstore.ReverseIterator(nil, bz("")) 417 checkDomain(t, itr, nil, bz("")) 418 checkInvalid(t, itr) 419 itr.Close() 420 } 421 422 func TestPrefixDBReverseIterator4(t *testing.T) { 423 store := mockStoreWithStuff() 424 pstore := NewStore(store, bz("key")) 425 426 itr := pstore.ReverseIterator(bz(""), bz("")) 427 checkInvalid(t, itr) 428 itr.Close() 429 } 430 431 func TestCacheWraps(t *testing.T) { 432 db := dbm.NewMemDB() 433 store := dbadapter.Store{DB: db} 434 435 cacheWrapper := store.CacheWrap() 436 require.IsType(t, &cachekv.Store{}, cacheWrapper) 437 438 cacheWrappedWithTrace := store.CacheWrapWithTrace(nil, nil) 439 require.IsType(t, &cachekv.Store{}, cacheWrappedWithTrace) 440 441 cacheWrappedWithListeners := store.CacheWrapWithListeners(nil, nil) 442 require.IsType(t, &cachekv.Store{}, cacheWrappedWithListeners) 443 }