github.com/Finschia/finschia-sdk@v0.48.1/store/iavl/store_test.go (about) 1 package iavl 2 3 import ( 4 crand "crypto/rand" 5 "fmt" 6 "testing" 7 8 "github.com/cosmos/iavl" 9 "github.com/stretchr/testify/require" 10 dbm "github.com/tendermint/tm-db" 11 12 "github.com/Finschia/ostracon/libs/log" 13 abci "github.com/tendermint/tendermint/abci/types" 14 15 "github.com/Finschia/finschia-sdk/store/cachekv" 16 "github.com/Finschia/finschia-sdk/store/types" 17 "github.com/Finschia/finschia-sdk/types/kv" 18 ) 19 20 var ( 21 cacheSize = 100 22 treeData = map[string]string{ 23 "hello": "goodbye", 24 "aloha": "shalom", 25 } 26 nMoreData = 0 27 ) 28 29 func randBytes(numBytes int) []byte { 30 b := make([]byte, numBytes) 31 _, _ = crand.Read(b) 32 return b 33 } 34 35 // make a tree with data from above and save it 36 func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { 37 tree, err := iavl.NewMutableTree(db, cacheSize, false) 38 require.NoError(t, err) 39 40 for k, v := range treeData { 41 tree.Set([]byte(k), []byte(v)) 42 } 43 44 for i := 0; i < nMoreData; i++ { 45 key := randBytes(12) 46 value := randBytes(50) 47 tree.Set(key, value) 48 } 49 50 hash, ver, err := tree.SaveVersion() 51 require.Nil(t, err) 52 53 return tree, types.CommitID{Version: ver, Hash: hash} 54 } 55 56 func TestLoadStore(t *testing.T) { 57 db := dbm.NewMemDB() 58 tree, _ := newAlohaTree(t, db) 59 store := UnsafeNewStore(tree) 60 61 // Create non-pruned height H 62 updated, err := tree.Set([]byte("hello"), []byte("hallo")) 63 require.NoError(t, err) 64 require.True(t, updated) 65 hash, verH, err := tree.SaveVersion() 66 cIDH := types.CommitID{Version: verH, Hash: hash} 67 require.Nil(t, err) 68 69 // Create pruned height Hp 70 updated, err = tree.Set([]byte("hello"), []byte("hola")) 71 require.NoError(t, err) 72 require.True(t, updated) 73 hash, verHp, err := tree.SaveVersion() 74 cIDHp := types.CommitID{Version: verHp, Hash: hash} 75 require.Nil(t, err) 76 77 // TODO: Prune this height 78 79 // Create current height Hc 80 updated, err = tree.Set([]byte("hello"), []byte("ciao")) 81 require.NoError(t, err) 82 require.True(t, updated) 83 hash, verHc, err := tree.SaveVersion() 84 cIDHc := types.CommitID{Version: verHc, Hash: hash} 85 require.Nil(t, err) 86 87 // Querying an existing store at some previous non-pruned height H 88 hStore, err := store.GetImmutable(verH) 89 require.NoError(t, err) 90 require.Equal(t, string(hStore.Get([]byte("hello"))), "hallo") 91 92 // Querying an existing store at some previous pruned height Hp 93 hpStore, err := store.GetImmutable(verHp) 94 require.NoError(t, err) 95 require.Equal(t, string(hpStore.Get([]byte("hello"))), "hola") 96 97 // Querying an existing store at current height Hc 98 hcStore, err := store.GetImmutable(verHc) 99 require.NoError(t, err) 100 require.Equal(t, string(hcStore.Get([]byte("hello"))), "ciao") 101 102 // Querying a new store at some previous non-pruned height H 103 newHStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDH, false, DefaultIAVLCacheSize, false) 104 require.NoError(t, err) 105 require.Equal(t, string(newHStore.Get([]byte("hello"))), "hallo") 106 107 // Querying a new store at some previous pruned height Hp 108 newHpStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHp, false, DefaultIAVLCacheSize, false) 109 require.NoError(t, err) 110 require.Equal(t, string(newHpStore.Get([]byte("hello"))), "hola") 111 112 // Querying a new store at current height H 113 newHcStore, err := LoadStore(db, log.NewNopLogger(), types.NewKVStoreKey("test"), cIDHc, false, DefaultIAVLCacheSize, false) 114 require.NoError(t, err) 115 require.Equal(t, string(newHcStore.Get([]byte("hello"))), "ciao") 116 } 117 118 func TestGetImmutable(t *testing.T) { 119 db := dbm.NewMemDB() 120 tree, cID := newAlohaTree(t, db) 121 store := UnsafeNewStore(tree) 122 123 updated, err := tree.Set([]byte("hello"), []byte("adios")) 124 require.True(t, updated) 125 hash, ver, err := tree.SaveVersion() 126 cID = types.CommitID{Version: ver, Hash: hash} 127 require.Nil(t, err) 128 129 _, err = store.GetImmutable(cID.Version + 1) 130 require.NoError(t, err) 131 132 newStore, err := store.GetImmutable(cID.Version - 1) 133 require.NoError(t, err) 134 require.Equal(t, newStore.Get([]byte("hello")), []byte("goodbye")) 135 136 newStore, err = store.GetImmutable(cID.Version) 137 require.NoError(t, err) 138 require.Equal(t, newStore.Get([]byte("hello")), []byte("adios")) 139 140 res := newStore.Query(abci.RequestQuery{Data: []byte("hello"), Height: cID.Version, Path: "/key", Prove: true}) 141 require.Equal(t, res.Value, []byte("adios")) 142 require.NotNil(t, res.ProofOps) 143 144 require.Panics(t, func() { newStore.Set(nil, nil) }) 145 require.Panics(t, func() { newStore.Delete(nil) }) 146 require.Panics(t, func() { newStore.Commit() }) 147 } 148 149 func TestTestGetImmutableIterator(t *testing.T) { 150 db := dbm.NewMemDB() 151 tree, cID := newAlohaTree(t, db) 152 store := UnsafeNewStore(tree) 153 154 newStore, err := store.GetImmutable(cID.Version) 155 require.NoError(t, err) 156 157 iter := newStore.Iterator([]byte("aloha"), []byte("hellz")) 158 expected := []string{"aloha", "hello"} 159 var i int 160 161 for i = 0; iter.Valid(); iter.Next() { 162 expectedKey := expected[i] 163 key, value := iter.Key(), iter.Value() 164 require.EqualValues(t, key, expectedKey) 165 require.EqualValues(t, value, treeData[expectedKey]) 166 i++ 167 } 168 169 require.Equal(t, len(expected), i) 170 } 171 172 func TestIAVLStoreGetSetHasDelete(t *testing.T) { 173 db := dbm.NewMemDB() 174 tree, _ := newAlohaTree(t, db) 175 iavlStore := UnsafeNewStore(tree) 176 177 key := "hello" 178 179 exists := iavlStore.Has([]byte(key)) 180 require.True(t, exists) 181 182 value := iavlStore.Get([]byte(key)) 183 require.EqualValues(t, value, treeData[key]) 184 185 value2 := "notgoodbye" 186 iavlStore.Set([]byte(key), []byte(value2)) 187 188 value = iavlStore.Get([]byte(key)) 189 require.EqualValues(t, value, value2) 190 191 iavlStore.Delete([]byte(key)) 192 193 exists = iavlStore.Has([]byte(key)) 194 require.False(t, exists) 195 } 196 197 func TestIAVLStoreNoNilSet(t *testing.T) { 198 db := dbm.NewMemDB() 199 tree, _ := newAlohaTree(t, db) 200 iavlStore := UnsafeNewStore(tree) 201 202 require.Panics(t, func() { iavlStore.Set(nil, []byte("value")) }, "setting a nil key should panic") 203 require.Panics(t, func() { iavlStore.Set([]byte(""), []byte("value")) }, "setting an empty key should panic") 204 205 require.Panics(t, func() { iavlStore.Set([]byte("key"), nil) }, "setting a nil value should panic") 206 } 207 208 func TestIAVLIterator(t *testing.T) { 209 db := dbm.NewMemDB() 210 tree, _ := newAlohaTree(t, db) 211 iavlStore := UnsafeNewStore(tree) 212 iter := iavlStore.Iterator([]byte("aloha"), []byte("hellz")) 213 expected := []string{"aloha", "hello"} 214 var i int 215 216 for i = 0; iter.Valid(); iter.Next() { 217 expectedKey := expected[i] 218 key, value := iter.Key(), iter.Value() 219 require.EqualValues(t, key, expectedKey) 220 require.EqualValues(t, value, treeData[expectedKey]) 221 i++ 222 } 223 require.Equal(t, len(expected), i) 224 225 iter = iavlStore.Iterator([]byte("golang"), []byte("rocks")) 226 expected = []string{"hello"} 227 for i = 0; iter.Valid(); iter.Next() { 228 expectedKey := expected[i] 229 key, value := iter.Key(), iter.Value() 230 require.EqualValues(t, key, expectedKey) 231 require.EqualValues(t, value, treeData[expectedKey]) 232 i++ 233 } 234 require.Equal(t, len(expected), i) 235 236 iter = iavlStore.Iterator(nil, []byte("golang")) 237 expected = []string{"aloha"} 238 for i = 0; iter.Valid(); iter.Next() { 239 expectedKey := expected[i] 240 key, value := iter.Key(), iter.Value() 241 require.EqualValues(t, key, expectedKey) 242 require.EqualValues(t, value, treeData[expectedKey]) 243 i++ 244 } 245 require.Equal(t, len(expected), i) 246 247 iter = iavlStore.Iterator(nil, []byte("shalom")) 248 expected = []string{"aloha", "hello"} 249 for i = 0; iter.Valid(); iter.Next() { 250 expectedKey := expected[i] 251 key, value := iter.Key(), iter.Value() 252 require.EqualValues(t, key, expectedKey) 253 require.EqualValues(t, value, treeData[expectedKey]) 254 i++ 255 } 256 require.Equal(t, len(expected), i) 257 258 iter = iavlStore.Iterator(nil, nil) 259 expected = []string{"aloha", "hello"} 260 for i = 0; iter.Valid(); iter.Next() { 261 expectedKey := expected[i] 262 key, value := iter.Key(), iter.Value() 263 require.EqualValues(t, key, expectedKey) 264 require.EqualValues(t, value, treeData[expectedKey]) 265 i++ 266 } 267 require.Equal(t, len(expected), i) 268 269 iter = iavlStore.Iterator([]byte("golang"), nil) 270 expected = []string{"hello"} 271 for i = 0; iter.Valid(); iter.Next() { 272 expectedKey := expected[i] 273 key, value := iter.Key(), iter.Value() 274 require.EqualValues(t, key, expectedKey) 275 require.EqualValues(t, value, treeData[expectedKey]) 276 i++ 277 } 278 require.Equal(t, len(expected), i) 279 } 280 281 func TestIAVLReverseIterator(t *testing.T) { 282 db := dbm.NewMemDB() 283 284 tree, err := iavl.NewMutableTree(db, cacheSize, false) 285 require.NoError(t, err) 286 287 iavlStore := UnsafeNewStore(tree) 288 289 iavlStore.Set([]byte{0x00}, []byte("0")) 290 iavlStore.Set([]byte{0x00, 0x00}, []byte("0 0")) 291 iavlStore.Set([]byte{0x00, 0x01}, []byte("0 1")) 292 iavlStore.Set([]byte{0x00, 0x02}, []byte("0 2")) 293 iavlStore.Set([]byte{0x01}, []byte("1")) 294 295 testReverseIterator := func(t *testing.T, start []byte, end []byte, expected []string) { 296 iter := iavlStore.ReverseIterator(start, end) 297 var i int 298 for i = 0; iter.Valid(); iter.Next() { 299 expectedValue := expected[i] 300 value := iter.Value() 301 require.EqualValues(t, string(value), expectedValue) 302 i++ 303 } 304 require.Equal(t, len(expected), i) 305 } 306 307 testReverseIterator(t, nil, nil, []string{"1", "0 2", "0 1", "0 0", "0"}) 308 testReverseIterator(t, []byte{0x00}, nil, []string{"1", "0 2", "0 1", "0 0", "0"}) 309 testReverseIterator(t, []byte{0x00}, []byte{0x00, 0x01}, []string{"0 0", "0"}) 310 testReverseIterator(t, []byte{0x00}, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"}) 311 testReverseIterator(t, []byte{0x00, 0x01}, []byte{0x01}, []string{"0 2", "0 1"}) 312 testReverseIterator(t, nil, []byte{0x01}, []string{"0 2", "0 1", "0 0", "0"}) 313 } 314 315 func TestIAVLPrefixIterator(t *testing.T) { 316 db := dbm.NewMemDB() 317 tree, err := iavl.NewMutableTree(db, cacheSize, false) 318 require.NoError(t, err) 319 320 iavlStore := UnsafeNewStore(tree) 321 322 iavlStore.Set([]byte("test1"), []byte("test1")) 323 iavlStore.Set([]byte("test2"), []byte("test2")) 324 iavlStore.Set([]byte("test3"), []byte("test3")) 325 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4")) 326 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4")) 327 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4")) 328 iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4")) 329 iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4")) 330 iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4")) 331 332 var i int 333 334 iter := types.KVStorePrefixIterator(iavlStore, []byte("test")) 335 expected := []string{"test1", "test2", "test3"} 336 for i = 0; iter.Valid(); iter.Next() { 337 expectedKey := expected[i] 338 key, value := iter.Key(), iter.Value() 339 require.EqualValues(t, key, expectedKey) 340 require.EqualValues(t, value, expectedKey) 341 i++ 342 } 343 iter.Close() 344 require.Equal(t, len(expected), i) 345 346 iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) 347 expected2 := [][]byte{ 348 {byte(55), byte(255), byte(255), byte(0)}, 349 {byte(55), byte(255), byte(255), byte(1)}, 350 {byte(55), byte(255), byte(255), byte(255)}, 351 } 352 for i = 0; iter.Valid(); iter.Next() { 353 expectedKey := expected2[i] 354 key, value := iter.Key(), iter.Value() 355 require.EqualValues(t, key, expectedKey) 356 require.EqualValues(t, value, []byte("test4")) 357 i++ 358 } 359 iter.Close() 360 require.Equal(t, len(expected), i) 361 362 iter = types.KVStorePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) 363 expected2 = [][]byte{ 364 {byte(255), byte(255), byte(0)}, 365 {byte(255), byte(255), byte(1)}, 366 {byte(255), byte(255), byte(255)}, 367 } 368 for i = 0; iter.Valid(); iter.Next() { 369 expectedKey := expected2[i] 370 key, value := iter.Key(), iter.Value() 371 require.EqualValues(t, key, expectedKey) 372 require.EqualValues(t, value, []byte("test4")) 373 i++ 374 } 375 iter.Close() 376 require.Equal(t, len(expected), i) 377 } 378 379 func TestIAVLReversePrefixIterator(t *testing.T) { 380 db := dbm.NewMemDB() 381 tree, err := iavl.NewMutableTree(db, cacheSize, false) 382 require.NoError(t, err) 383 384 iavlStore := UnsafeNewStore(tree) 385 386 iavlStore.Set([]byte("test1"), []byte("test1")) 387 iavlStore.Set([]byte("test2"), []byte("test2")) 388 iavlStore.Set([]byte("test3"), []byte("test3")) 389 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(0)}, []byte("test4")) 390 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(1)}, []byte("test4")) 391 iavlStore.Set([]byte{byte(55), byte(255), byte(255), byte(255)}, []byte("test4")) 392 iavlStore.Set([]byte{byte(255), byte(255), byte(0)}, []byte("test4")) 393 iavlStore.Set([]byte{byte(255), byte(255), byte(1)}, []byte("test4")) 394 iavlStore.Set([]byte{byte(255), byte(255), byte(255)}, []byte("test4")) 395 396 var i int 397 398 iter := types.KVStoreReversePrefixIterator(iavlStore, []byte("test")) 399 expected := []string{"test3", "test2", "test1"} 400 for i = 0; iter.Valid(); iter.Next() { 401 expectedKey := expected[i] 402 key, value := iter.Key(), iter.Value() 403 require.EqualValues(t, key, expectedKey) 404 require.EqualValues(t, value, expectedKey) 405 i++ 406 } 407 require.Equal(t, len(expected), i) 408 409 iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(55), byte(255), byte(255)}) 410 expected2 := [][]byte{ 411 {byte(55), byte(255), byte(255), byte(255)}, 412 {byte(55), byte(255), byte(255), byte(1)}, 413 {byte(55), byte(255), byte(255), byte(0)}, 414 } 415 for i = 0; iter.Valid(); iter.Next() { 416 expectedKey := expected2[i] 417 key, value := iter.Key(), iter.Value() 418 require.EqualValues(t, key, expectedKey) 419 require.EqualValues(t, value, []byte("test4")) 420 i++ 421 } 422 require.Equal(t, len(expected), i) 423 424 iter = types.KVStoreReversePrefixIterator(iavlStore, []byte{byte(255), byte(255)}) 425 expected2 = [][]byte{ 426 {byte(255), byte(255), byte(255)}, 427 {byte(255), byte(255), byte(1)}, 428 {byte(255), byte(255), byte(0)}, 429 } 430 for i = 0; iter.Valid(); iter.Next() { 431 expectedKey := expected2[i] 432 key, value := iter.Key(), iter.Value() 433 require.EqualValues(t, key, expectedKey) 434 require.EqualValues(t, value, []byte("test4")) 435 i++ 436 } 437 require.Equal(t, len(expected), i) 438 } 439 440 func nextVersion(iavl *Store) { 441 key := []byte(fmt.Sprintf("Key for tree: %d", iavl.LastCommitID().Version)) 442 value := []byte(fmt.Sprintf("Value for tree: %d", iavl.LastCommitID().Version)) 443 iavl.Set(key, value) 444 iavl.Commit() 445 } 446 447 func TestIAVLNoPrune(t *testing.T) { 448 db := dbm.NewMemDB() 449 tree, err := iavl.NewMutableTree(db, cacheSize, false) 450 require.NoError(t, err) 451 452 iavlStore := UnsafeNewStore(tree) 453 nextVersion(iavlStore) 454 455 for i := 1; i < 100; i++ { 456 for j := 1; j <= i; j++ { 457 require.True(t, iavlStore.VersionExists(int64(j)), 458 "Missing version %d with latest version %d. Should be storing all versions", 459 j, i) 460 } 461 462 nextVersion(iavlStore) 463 } 464 } 465 466 func TestIAVLGetAllVersions(t *testing.T) { 467 db := dbm.NewMemDB() 468 tree, err := iavl.NewMutableTree(db, cacheSize, false) 469 require.NoError(t, err) 470 471 iavlStore := UnsafeNewStore(tree) 472 nextVersion(iavlStore) 473 474 for i := 1; i < 100; i++ { 475 for _, ver := range iavlStore.GetAllVersions() { 476 require.True(t, iavlStore.VersionExists(int64(ver)), 477 "Missing version %d with latest version %d. Should be storing all versions", 478 ver, i) 479 480 } 481 482 nextVersion(iavlStore) 483 } 484 } 485 486 func TestIAVLStoreQuery(t *testing.T) { 487 db := dbm.NewMemDB() 488 tree, err := iavl.NewMutableTree(db, cacheSize, false) 489 require.NoError(t, err) 490 491 iavlStore := UnsafeNewStore(tree) 492 493 k1, v1 := []byte("key1"), []byte("val1") 494 k2, v2 := []byte("key2"), []byte("val2") 495 v3 := []byte("val3") 496 497 ksub := []byte("key") 498 KVs0 := kv.Pairs{} 499 KVs1 := kv.Pairs{ 500 Pairs: []kv.Pair{ 501 {Key: k1, Value: v1}, 502 {Key: k2, Value: v2}, 503 }, 504 } 505 KVs2 := kv.Pairs{ 506 Pairs: []kv.Pair{ 507 {Key: k1, Value: v3}, 508 {Key: k2, Value: v2}, 509 }, 510 } 511 512 valExpSubEmpty, err := KVs0.Marshal() 513 require.NoError(t, err) 514 515 valExpSub1, err := KVs1.Marshal() 516 require.NoError(t, err) 517 518 valExpSub2, err := KVs2.Marshal() 519 require.NoError(t, err) 520 521 cid := iavlStore.Commit() 522 ver := cid.Version 523 query := abci.RequestQuery{Path: "/key", Data: k1, Height: ver} 524 querySub := abci.RequestQuery{Path: "/subspace", Data: ksub, Height: ver} 525 526 // query subspace before anything set 527 qres := iavlStore.Query(querySub) 528 require.Equal(t, uint32(0), qres.Code) 529 require.Equal(t, valExpSubEmpty, qres.Value) 530 531 // set data 532 iavlStore.Set(k1, v1) 533 iavlStore.Set(k2, v2) 534 535 // set data without commit, doesn't show up 536 qres = iavlStore.Query(query) 537 require.Equal(t, uint32(0), qres.Code) 538 require.Nil(t, qres.Value) 539 540 // commit it, but still don't see on old version 541 cid = iavlStore.Commit() 542 qres = iavlStore.Query(query) 543 require.Equal(t, uint32(0), qres.Code) 544 require.Nil(t, qres.Value) 545 546 // but yes on the new version 547 query.Height = cid.Version 548 qres = iavlStore.Query(query) 549 require.Equal(t, uint32(0), qres.Code) 550 require.Equal(t, v1, qres.Value) 551 552 // and for the subspace 553 qres = iavlStore.Query(querySub) 554 require.Equal(t, uint32(0), qres.Code) 555 require.Equal(t, valExpSub1, qres.Value) 556 557 // modify 558 iavlStore.Set(k1, v3) 559 cid = iavlStore.Commit() 560 561 // query will return old values, as height is fixed 562 qres = iavlStore.Query(query) 563 require.Equal(t, uint32(0), qres.Code) 564 require.Equal(t, v1, qres.Value) 565 566 // update to latest in the query and we are happy 567 query.Height = cid.Version 568 qres = iavlStore.Query(query) 569 require.Equal(t, uint32(0), qres.Code) 570 require.Equal(t, v3, qres.Value) 571 query2 := abci.RequestQuery{Path: "/key", Data: k2, Height: cid.Version} 572 573 qres = iavlStore.Query(query2) 574 require.Equal(t, uint32(0), qres.Code) 575 require.Equal(t, v2, qres.Value) 576 // and for the subspace 577 qres = iavlStore.Query(querySub) 578 require.Equal(t, uint32(0), qres.Code) 579 require.Equal(t, valExpSub2, qres.Value) 580 581 // default (height 0) will show latest -1 582 query0 := abci.RequestQuery{Path: "/key", Data: k1} 583 qres = iavlStore.Query(query0) 584 require.Equal(t, uint32(0), qres.Code) 585 require.Equal(t, v1, qres.Value) 586 } 587 588 func BenchmarkIAVLIteratorNext(b *testing.B) { 589 b.ReportAllocs() 590 db := dbm.NewMemDB() 591 treeSize := 1000 592 tree, err := iavl.NewMutableTree(db, cacheSize, false) 593 require.NoError(b, err) 594 595 for i := 0; i < treeSize; i++ { 596 key := randBytes(4) 597 value := randBytes(50) 598 tree.Set(key, value) 599 } 600 601 iavlStore := UnsafeNewStore(tree) 602 iterators := make([]types.Iterator, b.N/treeSize) 603 604 for i := 0; i < len(iterators); i++ { 605 iterators[i] = iavlStore.Iterator([]byte{0}, []byte{255, 255, 255, 255, 255}) 606 } 607 608 b.ResetTimer() 609 for i := 0; i < len(iterators); i++ { 610 iter := iterators[i] 611 for j := 0; j < treeSize; j++ { 612 iter.Next() 613 } 614 } 615 } 616 617 func TestSetInitialVersion(t *testing.T) { 618 testCases := []struct { 619 name string 620 storeFn func(db *dbm.MemDB) *Store 621 expPanic bool 622 }{ 623 { 624 "works with a mutable tree", 625 func(db *dbm.MemDB) *Store { 626 tree, err := iavl.NewMutableTree(db, cacheSize, false) 627 require.NoError(t, err) 628 store := UnsafeNewStore(tree) 629 630 return store 631 }, false, 632 }, 633 { 634 "throws error on immutable tree", 635 func(db *dbm.MemDB) *Store { 636 tree, err := iavl.NewMutableTree(db, cacheSize, false) 637 require.NoError(t, err) 638 store := UnsafeNewStore(tree) 639 _, version, err := store.tree.SaveVersion() 640 require.NoError(t, err) 641 require.Equal(t, int64(1), version) 642 store, err = store.GetImmutable(1) 643 require.NoError(t, err) 644 645 return store 646 }, true, 647 }, 648 } 649 650 for _, tc := range testCases { 651 tc := tc 652 653 t.Run(tc.name, func(t *testing.T) { 654 db := dbm.NewMemDB() 655 store := tc.storeFn(db) 656 657 if tc.expPanic { 658 require.Panics(t, func() { store.SetInitialVersion(5) }) 659 } else { 660 store.SetInitialVersion(5) 661 cid := store.Commit() 662 require.Equal(t, int64(5), cid.GetVersion()) 663 } 664 }) 665 } 666 } 667 668 func TestCacheWraps(t *testing.T) { 669 db := dbm.NewMemDB() 670 tree, _ := newAlohaTree(t, db) 671 store := UnsafeNewStore(tree) 672 673 cacheWrapper := store.CacheWrap() 674 require.IsType(t, &cachekv.Store{}, cacheWrapper) 675 676 cacheWrappedWithTrace := store.CacheWrapWithTrace(nil, nil) 677 require.IsType(t, &cachekv.Store{}, cacheWrappedWithTrace) 678 679 cacheWrappedWithListeners := store.CacheWrapWithListeners(nil, nil) 680 require.IsType(t, &cachekv.Store{}, cacheWrappedWithListeners) 681 }