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