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  }