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