github.com/theQRL/go-zond@v0.1.1/core/state/iterator_test.go (about) 1 // Copyright 2016 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package state 18 19 import ( 20 "testing" 21 22 "github.com/theQRL/go-zond/common" 23 "github.com/theQRL/go-zond/core/rawdb" 24 "github.com/theQRL/go-zond/crypto" 25 ) 26 27 // Tests that the node iterator indeed walks over the entire database contents. 28 func TestNodeIteratorCoverage(t *testing.T) { 29 testNodeIteratorCoverage(t, rawdb.HashScheme) 30 testNodeIteratorCoverage(t, rawdb.PathScheme) 31 } 32 33 func testNodeIteratorCoverage(t *testing.T, scheme string) { 34 // Create some arbitrary test state to iterate 35 db, sdb, ndb, root, _ := makeTestState(scheme) 36 ndb.Commit(root, false) 37 38 state, err := New(root, sdb, nil) 39 if err != nil { 40 t.Fatalf("failed to create state trie at %x: %v", root, err) 41 } 42 // Gather all the node hashes found by the iterator 43 hashes := make(map[common.Hash]struct{}) 44 for it := newNodeIterator(state); it.Next(); { 45 if it.Hash != (common.Hash{}) { 46 hashes[it.Hash] = struct{}{} 47 } 48 } 49 // Check in-disk nodes 50 var ( 51 seenNodes = make(map[common.Hash]struct{}) 52 seenCodes = make(map[common.Hash]struct{}) 53 ) 54 it := db.NewIterator(nil, nil) 55 for it.Next() { 56 ok, hash := isTrieNode(scheme, it.Key(), it.Value()) 57 if !ok { 58 continue 59 } 60 seenNodes[hash] = struct{}{} 61 } 62 it.Release() 63 64 // Check in-disk codes 65 it = db.NewIterator(nil, nil) 66 for it.Next() { 67 ok, hash := rawdb.IsCodeKey(it.Key()) 68 if !ok { 69 continue 70 } 71 if _, ok := hashes[common.BytesToHash(hash)]; !ok { 72 t.Errorf("state entry not reported %x", it.Key()) 73 } 74 seenCodes[common.BytesToHash(hash)] = struct{}{} 75 } 76 it.Release() 77 78 // Cross check the iterated hashes and the database/nodepool content 79 for hash := range hashes { 80 _, ok := seenNodes[hash] 81 if !ok { 82 _, ok = seenCodes[hash] 83 } 84 if !ok { 85 t.Errorf("failed to retrieve reported node %x", hash) 86 } 87 } 88 } 89 90 // isTrieNode is a helper function which reports if the provided 91 // database entry belongs to a trie node or not. 92 func isTrieNode(scheme string, key, val []byte) (bool, common.Hash) { 93 if scheme == rawdb.HashScheme { 94 if rawdb.IsLegacyTrieNode(key, val) { 95 return true, common.BytesToHash(key) 96 } 97 } else { 98 ok := rawdb.IsAccountTrieNode(key) 99 if ok { 100 return true, crypto.Keccak256Hash(val) 101 } 102 ok = rawdb.IsStorageTrieNode(key) 103 if ok { 104 return true, crypto.Keccak256Hash(val) 105 } 106 } 107 return false, common.Hash{} 108 }