github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/trie/iterator_test.go (about) 1 // Copyright 2014 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 trie 18 19 import ( 20 "testing" 21 22 "github.com/ethereum/go-ethereum/common" 23 "github.com/ethereum/go-ethereum/ethdb" 24 ) 25 26 func TestIterator(t *testing.T) { 27 trie := newEmpty() 28 vals := []struct{ k, v string }{ 29 {"do", "verb"}, 30 {"ether", "wookiedoo"}, 31 {"horse", "stallion"}, 32 {"shaman", "horse"}, 33 {"doge", "coin"}, 34 {"dog", "puppy"}, 35 {"somethingveryoddindeedthis is", "myothernodedata"}, 36 } 37 all := make(map[string]string) 38 for _, val := range vals { 39 all[val.k] = val.v 40 trie.Update([]byte(val.k), []byte(val.v)) 41 } 42 trie.Commit() 43 44 found := make(map[string]string) 45 it := NewIterator(trie) 46 for it.Next() { 47 found[string(it.Key)] = string(it.Value) 48 } 49 50 for k, v := range all { 51 if found[k] != v { 52 t.Errorf("iterator value mismatch for %s: got %q want %q", k, found[k], v) 53 } 54 } 55 } 56 57 type kv struct { 58 k, v []byte 59 t bool 60 } 61 62 func TestIteratorLargeData(t *testing.T) { 63 trie := newEmpty() 64 vals := make(map[string]*kv) 65 66 for i := byte(0); i < 255; i++ { 67 value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false} 68 value2 := &kv{common.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false} 69 trie.Update(value.k, value.v) 70 trie.Update(value2.k, value2.v) 71 vals[string(value.k)] = value 72 vals[string(value2.k)] = value2 73 } 74 75 it := NewIterator(trie) 76 for it.Next() { 77 vals[string(it.Key)].t = true 78 } 79 80 var untouched []*kv 81 for _, value := range vals { 82 if !value.t { 83 untouched = append(untouched, value) 84 } 85 } 86 87 if len(untouched) > 0 { 88 t.Errorf("Missed %d nodes", len(untouched)) 89 for _, value := range untouched { 90 t.Error(value) 91 } 92 } 93 } 94 95 // Tests that the node iterator indeed walks over the entire database contents. 96 func TestNodeIteratorCoverage(t *testing.T) { 97 // Create some arbitrary test trie to iterate 98 db, trie, _ := makeTestTrie() 99 100 // Gather all the node hashes found by the iterator 101 hashes := make(map[common.Hash]struct{}) 102 for it := NewNodeIterator(trie); it.Next(true); { 103 if it.Hash() != (common.Hash{}) { 104 hashes[it.Hash()] = struct{}{} 105 } 106 } 107 // Cross check the hashes and the database itself 108 for hash := range hashes { 109 if _, err := db.Get(hash.Bytes()); err != nil { 110 t.Errorf("failed to retrieve reported node %x: %v", hash, err) 111 } 112 } 113 for _, key := range db.(*ethdb.MemDatabase).Keys() { 114 if _, ok := hashes[common.BytesToHash(key)]; !ok { 115 t.Errorf("state entry not reported %x", key) 116 } 117 } 118 } 119 120 func TestDifferenceIterator(t *testing.T) { 121 triea := newEmpty() 122 valsa := []struct{ k, v string }{ 123 {"bar", "b"}, 124 {"barb", "ba"}, 125 {"bars", "bb"}, 126 {"bard", "bc"}, 127 {"fab", "z"}, 128 {"foo", "a"}, 129 {"food", "ab"}, 130 {"foos", "aa"}, 131 } 132 for _, val := range valsa { 133 triea.Update([]byte(val.k), []byte(val.v)) 134 } 135 triea.Commit() 136 137 trieb := newEmpty() 138 valsb := []struct{ k, v string }{ 139 {"aardvark", "c"}, 140 {"bar", "b"}, 141 {"barb", "bd"}, 142 {"bars", "be"}, 143 {"fab", "z"}, 144 {"foo", "a"}, 145 {"foos", "aa"}, 146 {"food", "ab"}, 147 {"jars", "d"}, 148 } 149 for _, val := range valsb { 150 trieb.Update([]byte(val.k), []byte(val.v)) 151 } 152 trieb.Commit() 153 154 found := make(map[string]string) 155 di, _ := NewDifferenceIterator(NewNodeIterator(triea), NewNodeIterator(trieb)) 156 it := NewIteratorFromNodeIterator(di) 157 for it.Next() { 158 found[string(it.Key)] = string(it.Value) 159 } 160 161 all := []struct{ k, v string }{ 162 {"aardvark", "c"}, 163 {"barb", "bd"}, 164 {"bars", "be"}, 165 {"jars", "d"}, 166 } 167 for _, item := range all { 168 if found[item.k] != item.v { 169 t.Errorf("iterator value mismatch for %s: got %q want %q", item.k, found[item.k], item.v) 170 } 171 } 172 if len(found) != len(all) { 173 t.Errorf("iterator count mismatch: got %d values, want %d", len(found), len(all)) 174 } 175 }