github.com/iotexproject/iotex-core@v1.14.1-rc1/db/trie/mptrie/merklepatriciatrie_test.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package mptrie 7 8 import ( 9 "context" 10 "testing" 11 "time" 12 13 "github.com/pkg/errors" 14 "github.com/stretchr/testify/require" 15 16 "github.com/iotexproject/go-pkgs/hash" 17 18 "github.com/iotexproject/iotex-core/db" 19 "github.com/iotexproject/iotex-core/db/batch" 20 "github.com/iotexproject/iotex-core/db/trie" 21 "github.com/iotexproject/iotex-core/testutil" 22 ) 23 24 var ( 25 ham = []byte{1, 2, 3, 4, 2, 3, 4, 5} 26 car = []byte{1, 2, 3, 4, 5, 6, 7, 7} 27 cat = []byte{1, 2, 3, 4, 5, 6, 7, 8} 28 rat = []byte{1, 2, 3, 4, 5, 6, 7, 9} 29 egg = []byte{1, 2, 3, 4, 5, 8, 1, 0} 30 dog = []byte{1, 2, 3, 4, 6, 7, 1, 0} 31 fox = []byte{1, 2, 3, 5, 6, 7, 8, 9} 32 cow = []byte{1, 2, 5, 6, 7, 8, 9, 0} 33 ant = []byte{2, 3, 4, 5, 6, 7, 8, 9} 34 35 br1 = []byte{0, 3, 4, 5, 6, 7, 8, 9} 36 br2 = []byte{1, 3, 4, 5, 6, 7, 8, 9} 37 cl1 = []byte{0, 0, 4, 5, 6, 7, 8, 9} 38 cl2 = []byte{1, 0, 4, 5, 6, 7, 8, 9} 39 40 testV = [8][]byte{ 41 []byte("ham"), []byte("car"), []byte("cat"), []byte("dog"), 42 []byte("egg"), []byte("fox"), []byte("cow"), []byte("ant"), 43 } 44 45 emptyTrieRootHash = []byte{0x61, 0x8e, 0x1c, 0xe1, 0xff, 0xfb, 0x18, 0x25, 0x15, 0x9f, 0x9a, 0xa2, 0xc2, 0xe9, 0x37, 0x24, 0x2, 0xfb, 0xd0, 0xab} 46 ) 47 48 func TestEmptyTrie(t *testing.T) { 49 require := require.New(t) 50 tr, err := New() 51 require.NoError(err) 52 require.NoError(tr.Start(context.Background())) 53 defer require.NoError(tr.Stop(context.Background())) 54 require.True(tr.IsEmpty()) 55 rootHash, err := tr.RootHash() 56 require.NoError(err) 57 require.Equal(emptyTrieRootHash, rootHash) 58 } 59 60 func Test2Roots(t *testing.T) { 61 require := require.New(t) 62 63 // first trie 64 trieDB := trie.NewMemKVStore() 65 tr, err := New(KVStoreOption(trieDB), KeyLengthOption(8), AsyncOption()) 66 require.NoError(err) 67 require.NoError(tr.Start(context.Background())) 68 require.NoError(tr.Upsert(cat, testV[2])) 69 v, err := tr.Get(cat) 70 require.NoError(err) 71 require.Equal(testV[2], v) 72 require.NoError(tr.Upsert(car, testV[1])) 73 v, err = tr.Get(car) 74 require.NoError(err) 75 require.Equal(testV[1], v) 76 require.NoError(tr.Upsert(egg, testV[4])) 77 v, err = tr.Get(egg) 78 require.NoError(err) 79 require.Equal(testV[4], v) 80 root, err := tr.RootHash() 81 require.NoError(err) 82 require.NoError(tr.Stop(context.Background())) 83 84 // second trie 85 tr1, err := New(KVStoreOption(trieDB), KeyLengthOption(8)) 86 require.NoError(err) 87 require.NoError(tr1.Start(context.Background())) 88 require.NoError(tr1.Upsert(dog, testV[3])) 89 v, err = tr1.Get(dog) 90 require.NoError(err) 91 require.Equal(testV[3], v) 92 require.NoError(tr1.Upsert(ham, testV[0])) 93 v, err = tr1.Get(ham) 94 require.NoError(err) 95 require.Equal(testV[0], v) 96 require.NoError(tr1.Upsert(fox, testV[5])) 97 v, err = tr1.Get(fox) 98 require.NoError(err) 99 require.Equal(testV[5], v) 100 root1, err := tr1.RootHash() 101 require.NoError(err) 102 require.NotEqual(root, root1) 103 require.NoError(tr1.Stop(context.Background())) 104 105 // start first trie again 106 require.NoError(tr.Start(context.Background())) 107 v, err = tr.Get(cat) 108 require.NoError(err) 109 require.Equal(testV[2], v) 110 v, err = tr.Get(car) 111 require.NoError(err) 112 require.Equal(testV[1], v) 113 v, err = tr.Get(egg) 114 require.NoError(err) 115 require.Equal(testV[4], v) 116 // does not contain dog 117 _, err = tr.Get(dog) 118 require.Equal(trie.ErrNotExist, errors.Cause(err)) 119 120 // create a new one and load second trie's root 121 tr2, err := New(KVStoreOption(trieDB), KeyLengthOption(8)) 122 require.NoError(err) 123 require.NoError(tr2.Start(context.Background())) 124 require.NoError(tr2.SetRootHash(root1)) 125 root2, err := tr2.RootHash() 126 require.NoError(err) 127 require.Equal(root1, root2) 128 v, err = tr2.Get(dog) 129 require.NoError(err) 130 require.Equal(testV[3], v) 131 v, err = tr2.Get(ham) 132 require.NoError(err) 133 require.Equal(testV[0], v) 134 v, err = tr2.Get(fox) 135 require.NoError(err) 136 require.Equal(testV[5], v) 137 // does not contain cat 138 _, err = tr2.Get(cat) 139 require.Equal(trie.ErrNotExist, errors.Cause(err)) 140 require.NoError(tr.Stop(context.Background())) 141 require.NoError(tr2.Stop(context.Background())) 142 } 143 144 func TestInsert(t *testing.T) { 145 require := require.New(t) 146 147 tr, err := New(KVStoreOption(trie.NewMemKVStore()), KeyLengthOption(8)) 148 require.NotNil(tr) 149 require.NoError(err) 150 require.NoError(tr.Start(context.Background())) 151 // this adds one L to root R 152 t.Log("Put[cat]") 153 require.NoError(tr.Upsert(cat, testV[2])) 154 require.False(tr.IsEmpty()) 155 root, err := tr.RootHash() 156 require.NoError(err) 157 158 // this splits L --> E + B + 2L (cat, rat) 159 /* 160 * Root --1--> E --234567--> B --> (cat, rat) 161 */ 162 t.Log("Put[rat]") 163 require.NoError(tr.Upsert(rat, []byte("rat"))) 164 ratRoot, err := tr.RootHash() 165 require.NoError(err) 166 require.NotEqual(ratRoot, root) 167 b, err := tr.Get(cat) 168 require.NoError(err) 169 require.Equal(testV[2], b) 170 b, err = tr.Get(rat) 171 require.NoError(err) 172 require.Equal([]byte("rat"), b) 173 174 // it's OK to upsert a key with same value again 175 require.NoError(tr.Upsert(rat, []byte("rat"))) 176 require.NoError(tr.Upsert(cat, testV[2])) 177 b, err = tr.Get(cat) 178 require.NoError(err) 179 require.Equal(testV[2], b) 180 b, err = tr.Get(rat) 181 require.NoError(err) 182 require.Equal([]byte("rat"), b) 183 root, err = tr.RootHash() 184 require.NoError(err) 185 // root should keep the same since the value is same 186 require.Equal(root, ratRoot) 187 188 // this adds another L to B (car) 189 /* 190 * Root --1--> E --234567--> B --> (cat, rat, car) 191 */ 192 t.Log("Put[car]") 193 require.NoError(tr.Upsert(car, testV[1])) 194 newRoot, err := tr.RootHash() 195 require.NoError(err) 196 require.NotEqual(newRoot, root) 197 root = newRoot 198 b, err = tr.Get(car) 199 require.NoError(err) 200 require.Equal(testV[1], b) 201 // delete car 202 t.Log("Del[car]") 203 require.NoError(tr.Delete(car)) 204 newRoot, err = tr.RootHash() 205 require.NoError(err) 206 require.NotEqual(newRoot, root) 207 require.Equal(newRoot, ratRoot) 208 root = newRoot 209 210 // this splits E --> B1 + E1 + L (match = 3, div = 3) 211 /* 212 * Root --1--> E --234--> B1 --5--> E1 --67--> B --> (cat, rat) 213 * | --6--> L --710--> dog 214 */ 215 t.Log("Put[dog]") 216 require.NoError(tr.Upsert(dog, testV[3])) 217 newRoot, err = tr.RootHash() 218 require.NoError(err) 219 require.NotEqual(newRoot, root) 220 root = newRoot 221 // Get returns "dog" now 222 b, err = tr.Get(dog) 223 require.NoError(err) 224 require.Equal(testV[3], b) 225 b, err = tr.Get(cat) 226 require.NoError(err) 227 require.Equal(testV[2], b) 228 b, err = tr.Get(rat) 229 require.NoError(err) 230 require.Equal([]byte("rat"), b) 231 _, err = tr.Get(car) 232 require.Equal(trie.ErrNotExist, errors.Cause(err)) 233 234 // this deletes 'dog' and turns B1 into another E2 235 /* 236 * Root --1--> E --234--> E2 --5--> E1 --67--> B --> (cat, rat) 237 */ 238 t.Log("Del[dog]") 239 require.NoError(tr.Delete(dog)) 240 newRoot, err = tr.RootHash() 241 require.NoError(err) 242 require.NotEqual(newRoot, root) 243 root = newRoot 244 245 // this splits E1 --> B2 + E3 + L (match = 0, div = 2) 246 /* 247 * Root --1--> E --234--> E2 --5--> B2 --6--> E3 --7--> B --> (cat, rat) 248 * | --8--> L --10--> egg 249 */ 250 t.Log("Put[egg]") 251 require.NoError(tr.Upsert(egg, testV[4])) 252 newRoot, err = tr.RootHash() 253 require.NoError(err) 254 require.NotEqual(newRoot, root) 255 root = newRoot 256 b, err = tr.Get(egg) 257 require.NoError(err) 258 require.Equal(testV[4], b) 259 // delete egg 260 t.Log("Del[egg]") 261 require.NoError(tr.Delete(egg)) 262 eggRoot, err := tr.RootHash() 263 require.NoError(err) 264 require.NotEqual(eggRoot, root) 265 root = eggRoot 266 267 // this splits E (with match = 4, div = 1) 268 t.Log("Put[egg]") 269 require.NoError(tr.Upsert(egg, testV[4])) 270 newRoot, err = tr.RootHash() 271 require.NoError(err) 272 require.NotEqual(newRoot, root) 273 root = newRoot 274 b, err = tr.Get(egg) 275 require.NoError(err) 276 require.Equal(testV[4], b) 277 // delete egg 278 t.Log("Del[egg]") 279 require.NoError(tr.Delete(egg)) 280 newRoot, err = tr.RootHash() 281 require.NoError(err) 282 require.NotEqual(newRoot, root) 283 require.Equal(newRoot, eggRoot) 284 root = newRoot 285 _, err = tr.Get(dog) 286 require.Equal(trie.ErrNotExist, errors.Cause(err)) 287 _, err = tr.Get(egg) 288 require.Equal(trie.ErrNotExist, errors.Cause(err)) 289 290 // insert 'ham' 'fox' 'cow' 291 t.Log("Put[ham]") 292 require.NoError(tr.Upsert(ham, testV[0])) 293 newRoot, err = tr.RootHash() 294 require.NoError(err) 295 require.NotEqual(newRoot, root) 296 root = newRoot 297 b, err = tr.Get(ham) 298 require.NoError(err) 299 require.Equal(testV[0], b) 300 t.Log("Put[fox]") 301 require.NoError(tr.Upsert(fox, testV[5])) 302 newRoot, err = tr.RootHash() 303 require.NoError(err) 304 require.NotEqual(newRoot, root) 305 root = newRoot 306 b, err = tr.Get(fox) 307 require.NoError(err) 308 require.Equal(testV[5], b) 309 t.Log("Put[cow]") 310 require.NoError(tr.Upsert(cow, testV[6])) 311 newRoot, err = tr.RootHash() 312 require.NoError(err) 313 require.NotEqual(newRoot, root) 314 root = newRoot 315 b, err = tr.Get(cow) 316 require.NoError(err) 317 require.Equal(testV[6], b) 318 319 // delete fox rat cow 320 t.Log("Del[fox]") 321 require.NoError(tr.Delete(fox)) 322 newRoot, err = tr.RootHash() 323 require.NoError(err) 324 require.NotEqual(newRoot, root) 325 root = newRoot 326 t.Log("Del[rat]") 327 require.NoError(tr.Delete(rat)) 328 newRoot, err = tr.RootHash() 329 require.NoError(err) 330 require.NotEqual(newRoot, root) 331 root = newRoot 332 t.Log("Del[cow]") 333 require.NoError(tr.Delete(cow)) 334 newRoot, err = tr.RootHash() 335 require.NoError(err) 336 require.NotEqual(newRoot, root) 337 root = newRoot 338 _, err = tr.Get(fox) 339 require.Equal(trie.ErrNotExist, errors.Cause(err)) 340 _, err = tr.Get(rat) 341 require.Equal(trie.ErrNotExist, errors.Cause(err)) 342 _, err = tr.Get(cow) 343 require.Equal(trie.ErrNotExist, errors.Cause(err)) 344 b, err = tr.Get(ham) 345 require.NoError(err) 346 require.Equal(testV[0], b) 347 348 // this adds another path to root B 349 t.Log("Put[ant]") 350 require.NoError(tr.Upsert(ant, testV[7])) 351 newRoot, err = tr.RootHash() 352 require.NoError(err) 353 require.NotEqual(newRoot, root) 354 root = newRoot 355 b, err = tr.Get(ant) 356 require.NoError(err) 357 require.Equal(testV[7], b) 358 t.Log("Del[ant]") 359 require.NoError(tr.Delete(ant)) 360 newRoot, err = tr.RootHash() 361 require.NoError(err) 362 require.NotEqual(newRoot, root) 363 root = newRoot 364 365 // delete "ham" 366 t.Log("Del[ham]") 367 require.NoError(tr.Delete(ham)) 368 newRoot, err = tr.RootHash() 369 require.NoError(err) 370 require.NotEqual(newRoot, root) 371 _, err = tr.Get(ham) 372 require.Equal(trie.ErrNotExist, errors.Cause(err)) 373 _, err = tr.Get(ant) 374 require.Equal(trie.ErrNotExist, errors.Cause(err)) 375 b, err = tr.Get(cat) 376 require.NoError(err) 377 require.Equal(testV[2], b) 378 379 // delete "cat" 380 t.Log("Del[cat]") 381 require.NoError(tr.Delete(cat)) 382 require.True(tr.IsEmpty()) 383 require.NoError(tr.Stop(context.Background())) 384 } 385 386 func TestBatchCommit(t *testing.T) { 387 require := require.New(t) 388 389 trieDB := trie.NewMemKVStore() 390 tr, err := New(KeyLengthOption(8), KVStoreOption(trieDB)) 391 require.NoError(err) 392 require.NoError(tr.Start(context.Background())) 393 // insert 3 entries 394 require.NoError(tr.Upsert(cat, testV[2])) 395 require.NoError(tr.Upsert(car, testV[1])) 396 require.NoError(tr.Upsert(egg, testV[4])) 397 c, _ := tr.Get(cat) 398 require.Equal(testV[2], c) 399 // entries committed exist 400 v, _ := tr.Get(cat) 401 require.Equal(testV[2], v) 402 v, _ = tr.Get(car) 403 require.Equal(testV[1], v) 404 v, _ = tr.Get(egg) 405 require.Equal(testV[4], v) 406 // entries not committed won't exist 407 _, err = tr.Get(dog) 408 require.Equal(trie.ErrNotExist, errors.Cause(err)) 409 _, err = tr.Get(ham) 410 require.Equal(trie.ErrNotExist, errors.Cause(err)) 411 _, err = tr.Get(fox) 412 require.Equal(trie.ErrNotExist, errors.Cause(err)) 413 414 // insert 3 entries again 415 require.NoError(tr.Upsert(dog, testV[3])) 416 require.NoError(tr.Upsert(ham, testV[0])) 417 require.NoError(tr.Upsert(fox, testV[6])) 418 v, _ = tr.Get(fox) 419 require.Equal(testV[6], v) 420 require.NoError(tr.Upsert(fox, testV[5])) 421 v, _ = tr.Get(fox) 422 require.Equal(testV[5], v) 423 root, err := tr.RootHash() 424 require.NoError(err) 425 // commit and reopen 426 require.NoError(tr.Stop(context.Background())) 427 tr, err = New(KVStoreOption(trieDB), RootHashOption(root), KeyLengthOption(8)) 428 require.NoError(err) 429 require.NoError(tr.Start(context.Background())) 430 // all entries should exist now 431 v, _ = tr.Get(cat) 432 require.Equal(testV[2], v) 433 v, _ = tr.Get(car) 434 require.Equal(testV[1], v) 435 v, _ = tr.Get(egg) 436 require.Equal(testV[4], v) 437 v, _ = tr.Get(dog) 438 require.Equal(testV[3], v) 439 v, _ = tr.Get(ham) 440 require.Equal(testV[0], v) 441 v, _ = tr.Get(fox) 442 require.Equal(testV[5], v) 443 require.NoError(tr.Stop(context.Background())) 444 } 445 446 func TestHistoryTrie(t *testing.T) { 447 require := require.New(t) 448 cfg := db.DefaultConfig 449 AccountKVNamespace := "Account" 450 path := "test-history-trie.bolt" 451 testPath, err := testutil.PathOfTempFile(path) 452 require.NoError(err) 453 defer testutil.CleanupPath(testPath) 454 455 cfg.DbPath = testPath 456 opts := []db.KVStoreFlusherOption{ 457 db.FlushTranslateOption(func(wi *batch.WriteInfo) *batch.WriteInfo { 458 if wi.WriteType() == batch.Delete { 459 return nil 460 } 461 return wi 462 }), 463 } 464 dao := db.NewBoltDB(cfg) 465 ctx := context.Background() 466 require.NoError(dao.Start(ctx)) 467 flusher, err := db.NewKVStoreFlusher(dao, batch.NewCachedBatch(), opts...) 468 require.NoError(err) 469 addrKey := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20} 470 value1 := []byte{1} 471 value2 := []byte{2} 472 473 trieDB, err := trie.NewKVStore(AccountKVNamespace, flusher.KVStoreWithBuffer()) 474 require.NoError(err) 475 tr, err := New(KVStoreOption(trieDB), RootHashOption(nil)) 476 require.NoError(err) 477 require.NoError(tr.Start(ctx)) 478 479 // insert 1 entry 480 require.NoError(tr.Upsert(addrKey, value1)) 481 c, err := tr.Get(addrKey) 482 require.NoError(err) 483 require.Equal(value1, c) 484 oldRoot, err := tr.RootHash() 485 require.NoError(err) 486 487 // update entry 488 require.NoError(tr.Upsert(addrKey, value2)) 489 require.NoError(flusher.Flush()) 490 491 // get new value 492 c, err = tr.Get(addrKey) 493 require.NoError(err) 494 require.Equal(value2, c) 495 496 // get history value 497 require.NoError(tr.SetRootHash(oldRoot)) 498 c, err = tr.Get(addrKey) 499 require.NoError(err) 500 require.Equal(value1, c) 501 } 502 503 func TestCollision(t *testing.T) { 504 require := require.New(t) 505 506 tr, err := New(KeyLengthOption(8)) 507 require.NoError(err) 508 require.NoError(tr.Start(context.Background())) 509 defer func() { 510 require.NoError(tr.Stop(context.Background())) 511 }() 512 513 // this creates 2 leaf (with same value) on branch '0' and '1' 514 require.NoError(tr.Upsert(br1, testV[0])) 515 require.NoError(tr.Upsert(br2, testV[0])) 516 // this adds another 2 leaf (with same value), which splits the first 2 leaf 517 require.NoError(tr.Upsert(cl1, testV[0])) 518 require.NoError(tr.Upsert(cl2, testV[0])) 519 v, _ := tr.Get(br1) 520 require.Equal(testV[0], v) 521 v, _ = tr.Get(br2) 522 require.Equal(testV[0], v) 523 v, _ = tr.Get(cl1) 524 require.Equal(testV[0], v) 525 v, _ = tr.Get(cl2) 526 require.Equal(testV[0], v) 527 } 528 529 func Test4kEntries(t *testing.T) { 530 t.Run("test async mode", func(t *testing.T) { 531 test4kEntries(t, true) 532 }) 533 t.Run("test sync mode", func(t *testing.T) { 534 test4kEntries(t, false) 535 }) 536 } 537 538 func test4kEntries(t *testing.T, enableAsync bool) { 539 require := require.New(t) 540 541 var tr trie.Trie 542 var err error 543 if enableAsync { 544 tr, err = New(KeyLengthOption(4), AsyncOption()) 545 } else { 546 tr, err = New(KeyLengthOption(4)) 547 } 548 require.NoError(err) 549 require.NoError(tr.Start(context.Background())) 550 root, err := tr.RootHash() 551 require.NoError(err) 552 seed := time.Now().Nanosecond() 553 // insert 4k entries 554 var k [32]byte 555 k[0] = byte(seed) 556 c := 0 557 for c = 0; c < 1<<12; c++ { 558 k = hash.Hash256b(k[:]) 559 v := testV[k[0]&7] 560 if _, err := tr.Get(k[:4]); err == nil { 561 t.Logf("Warning: collision on k %x", k[:4]) 562 break 563 } 564 require.NoError(tr.Upsert(k[:4], v)) 565 newRoot, err := tr.RootHash() 566 require.NoError(err) 567 require.False(tr.IsEmpty()) 568 require.NotEqual(newRoot, root) 569 root = newRoot 570 b, err := tr.Get(k[:4]) 571 require.NoError(err) 572 require.Equal(v, b) 573 // update <k, v> 574 v = testV[7-k[0]&7] 575 require.NoError(tr.Upsert(k[:4], v)) 576 b, err = tr.Get(k[:4]) 577 require.NoError(err) 578 require.Equal(v, b) 579 if c%64 == 0 { 580 t.Logf("Put -- key: %x", k[:4]) 581 } 582 } 583 // delete 4k entries 584 var d [32]byte 585 d[0] = byte(seed) 586 // save the first 3, delete them last 587 d1 := hash.Hash256b(d[:]) 588 d2 := hash.Hash256b(d1[:]) 589 d3 := hash.Hash256b(d2[:]) 590 d = d3 591 for i := 0; i < c-3; i++ { 592 d = hash.Hash256b(d[:]) 593 require.NoError(tr.Delete(d[:4])) 594 newRoot, err := tr.RootHash() 595 require.NoError(err) 596 require.False(tr.IsEmpty()) 597 require.NotEqual(newRoot, root) 598 root = newRoot 599 _, err = tr.Get(d[:4]) 600 require.Equal(trie.ErrNotExist, errors.Cause(err)) 601 if i%64 == 0 { 602 t.Logf("Del -- key: %x", d[:4]) 603 } 604 } 605 require.NoError(tr.Delete(d1[:4])) 606 require.NoError(tr.Delete(d2[:4])) 607 require.NoError(tr.Delete(d3[:4])) 608 // trie should fallback to empty 609 require.True(tr.IsEmpty()) 610 require.NoError(tr.Stop(context.Background())) 611 } 612 613 func TestPressure(t *testing.T) { 614 if testing.Short() { 615 t.Skip("Skipping TestPressure in short mode.") 616 } 617 618 require := require.New(t) 619 620 tr, err := New(KeyLengthOption(4)) 621 require.NoError(err) 622 require.NoError(tr.Start(context.Background())) 623 root, err := tr.RootHash() 624 require.NoError(err) 625 seed := time.Now().Nanosecond() 626 // insert 128k entries 627 var k [32]byte 628 k[0] = byte(seed) 629 c := 0 630 for c = 0; c < 1<<17; c++ { 631 k = hash.Hash256b(k[:]) 632 v := testV[k[0]&7] 633 if _, err := tr.Get(k[:4]); err == nil { 634 t.Logf("Warning: collision on k %x", k[:4]) 635 break 636 } 637 require.NoError(tr.Upsert(k[:4], v)) 638 newRoot, err := tr.RootHash() 639 require.NoError(err) 640 require.False(tr.IsEmpty()) 641 require.NotEqual(newRoot, root) 642 root = newRoot 643 b, err := tr.Get(k[:4]) 644 require.NoError(err) 645 require.Equal(v, b) 646 if c%(2<<10) == 0 { 647 t.Logf("Put -- key: %x", k[:4]) 648 } 649 } 650 // delete 128k entries 651 var d [32]byte 652 d[0] = byte(seed) 653 // save the first 3, delete them last 654 d1 := hash.Hash256b(d[:]) 655 d2 := hash.Hash256b(d1[:]) 656 d3 := hash.Hash256b(d2[:]) 657 d = d3 658 for i := 0; i < c-3; i++ { 659 d = hash.Hash256b(d[:]) 660 require.NoError(tr.Delete(d[:4])) 661 newRoot, err := tr.RootHash() 662 require.NoError(err) 663 require.False(tr.IsEmpty()) 664 require.NotEqual(newRoot, root) 665 root = newRoot 666 _, err = tr.Get(d[:4]) 667 require.Equal(trie.ErrNotExist, errors.Cause(err)) 668 if i%(2<<10) == 0 { 669 t.Logf("Del -- key: %x", d[:4]) 670 } 671 } 672 require.NoError(tr.Delete(d1[:4])) 673 require.NoError(tr.Delete(d2[:4])) 674 require.NoError(tr.Delete(d3[:4])) 675 // trie should fallback to empty 676 require.True(tr.IsEmpty()) 677 require.NoError(tr.Stop(context.Background())) 678 t.Logf("Warning: test %d entries", c) 679 } 680 681 func TestTrieGet(t *testing.T) { 682 var ( 683 require = require.New(t) 684 tests = []struct{ k, v []byte }{ 685 {[]byte("iotex"), []byte("coin")}, 686 {[]byte("block"), []byte("chain")}, 687 {[]byte("puppy"), []byte("dog")}, 688 } 689 ) 690 691 trie, err := New(KeyLengthOption(5)) 692 require.NoError(err) 693 require.NoError(trie.Start(context.Background())) 694 defer require.NoError(trie.Stop(context.Background())) 695 696 for _, test := range tests { 697 require.NoError(trie.Upsert(test.k, test.v)) 698 } 699 for _, test := range tests { 700 val, err := trie.Get(test.k) 701 require.NoError(err) 702 require.Equal(test.v, val) 703 } 704 } 705 706 func TestTrieUpsert(t *testing.T) { 707 var ( 708 require = require.New(t) 709 key = []byte("puppy") 710 tests = []struct{ k, v []byte }{ 711 {key, []byte("dog")}, 712 {key, []byte("teddy")}, 713 {key, []byte("snoop")}, 714 {key, []byte("snooooooop")}, 715 } 716 ) 717 718 trie, err := New(KeyLengthOption(5)) 719 require.NoError(err) 720 require.NoError(trie.Start(context.Background())) 721 defer require.NoError(trie.Stop(context.Background())) 722 723 for _, test := range tests { 724 require.NoError(trie.Upsert(test.k, test.v)) 725 } 726 val, err := trie.Get(key) 727 require.NoError(err) 728 require.Equal(tests[len(tests)-1].v, val) 729 } 730 731 func TestTrieDelete(t *testing.T) { 732 var ( 733 require = require.New(t) 734 tests = []struct{ k, v []byte }{ 735 {[]byte("iotex"), []byte("coin")}, 736 {[]byte("block"), []byte("chain")}, 737 {[]byte("puppy"), []byte("dog")}, 738 } 739 ) 740 tr, err := New(KeyLengthOption(5)) 741 require.NoError(err) 742 require.NoError(tr.Start(context.Background())) 743 defer require.NoError(tr.Stop(context.Background())) 744 745 for _, test := range tests { 746 _, err = tr.Get(test.k) 747 require.Equal(trie.ErrNotExist, errors.Cause(err)) 748 749 require.NoError(tr.Upsert(test.k, test.v)) 750 } 751 for _, test := range tests { 752 val, err := tr.Get(test.k) 753 require.NoError(err) 754 require.Equal(test.v, val) 755 756 require.NoError(tr.Delete(test.k)) 757 _, err = tr.Get(test.k) 758 require.Equal(trie.ErrNotExist, errors.Cause(err)) 759 } 760 require.True(tr.IsEmpty()) 761 } 762 763 func TestTrieSetRootHash(t *testing.T) { 764 var ( 765 require = require.New(t) 766 tests = []struct{ k, v []byte }{ 767 {[]byte("iotex"), []byte("coin")}, 768 {[]byte("block"), []byte("chain")}, 769 {[]byte("chain"), []byte("link")}, 770 {[]byte("puppy"), []byte("dog")}, 771 {[]byte("night"), []byte("knight")}, 772 } 773 trieDB = trie.NewMemKVStore() 774 ) 775 776 tr, err := New(KVStoreOption(trieDB), KeyLengthOption(5)) 777 require.NoError(err) 778 require.NoError(tr.Start(context.Background())) 779 defer require.NoError(tr.Stop(context.Background())) 780 for _, test := range tests { 781 require.NoError(tr.Upsert(test.k, test.v)) 782 } 783 rootHash, err := tr.RootHash() 784 require.NoError(err) 785 require.NotEqual(emptyTrieRootHash, rootHash) 786 787 // new empty trie and load tr's rootHash 788 tr1, err := New(KVStoreOption(trieDB), KeyLengthOption(5)) 789 require.NoError(err) 790 require.NoError(tr1.Start(context.Background())) 791 defer require.NoError(tr1.Stop(context.Background())) 792 tr1Hash, err := tr1.RootHash() 793 require.NoError(err) 794 require.Equal(emptyTrieRootHash, tr1Hash) 795 require.NoError(tr1.SetRootHash(rootHash)) 796 for _, test := range tests { 797 val, err := tr1.Get(test.k) 798 require.NoError(err) 799 require.Equal(test.v, val) 800 } 801 }