github.com/karalabe/go-ethereum@v0.8.5/trie/trie_test.go (about)

     1  package trie
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/ethereum/go-ethereum/crypto"
     9  	"github.com/ethereum/go-ethereum/ethutil"
    10  )
    11  
    12  type Db map[string][]byte
    13  
    14  func (self Db) Get(k []byte) ([]byte, error) { return self[string(k)], nil }
    15  func (self Db) Put(k, v []byte)              { self[string(k)] = v }
    16  
    17  // Used for testing
    18  func NewEmpty() *Trie {
    19  	return New(nil, make(Db))
    20  }
    21  
    22  func TestEmptyTrie(t *testing.T) {
    23  	trie := NewEmpty()
    24  	res := trie.Hash()
    25  	exp := crypto.Sha3(ethutil.Encode(""))
    26  	if !bytes.Equal(res, exp) {
    27  		t.Errorf("expected %x got %x", exp, res)
    28  	}
    29  }
    30  
    31  func TestInsert(t *testing.T) {
    32  	trie := NewEmpty()
    33  
    34  	trie.UpdateString("doe", "reindeer")
    35  	trie.UpdateString("dog", "puppy")
    36  	trie.UpdateString("dogglesworth", "cat")
    37  
    38  	exp := ethutil.Hex2Bytes("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3")
    39  	root := trie.Hash()
    40  	if !bytes.Equal(root, exp) {
    41  		t.Errorf("exp %x got %x", exp, root)
    42  	}
    43  
    44  	trie = NewEmpty()
    45  	trie.UpdateString("A", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    46  
    47  	exp = ethutil.Hex2Bytes("d23786fb4a010da3ce639d66d5e904a11dbc02746d1ce25029e53290cabf28ab")
    48  	root = trie.Hash()
    49  	if !bytes.Equal(root, exp) {
    50  		t.Errorf("exp %x got %x", exp, root)
    51  	}
    52  }
    53  
    54  func TestGet(t *testing.T) {
    55  	trie := NewEmpty()
    56  
    57  	trie.UpdateString("doe", "reindeer")
    58  	trie.UpdateString("dog", "puppy")
    59  	trie.UpdateString("dogglesworth", "cat")
    60  
    61  	res := trie.GetString("dog")
    62  	if !bytes.Equal(res, []byte("puppy")) {
    63  		t.Errorf("expected puppy got %x", res)
    64  	}
    65  
    66  	unknown := trie.GetString("unknown")
    67  	if unknown != nil {
    68  		t.Errorf("expected nil got %x", unknown)
    69  	}
    70  }
    71  
    72  func TestDelete(t *testing.T) {
    73  	trie := NewEmpty()
    74  
    75  	vals := []struct{ k, v string }{
    76  		{"do", "verb"},
    77  		{"ether", "wookiedoo"},
    78  		{"horse", "stallion"},
    79  		{"shaman", "horse"},
    80  		{"doge", "coin"},
    81  		{"ether", ""},
    82  		{"dog", "puppy"},
    83  		{"shaman", ""},
    84  	}
    85  	for _, val := range vals {
    86  		if val.v != "" {
    87  			trie.UpdateString(val.k, val.v)
    88  		} else {
    89  			trie.DeleteString(val.k)
    90  		}
    91  	}
    92  
    93  	hash := trie.Hash()
    94  	exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
    95  	if !bytes.Equal(hash, exp) {
    96  		t.Errorf("expected %x got %x", exp, hash)
    97  	}
    98  }
    99  
   100  func TestEmptyValues(t *testing.T) {
   101  	trie := NewEmpty()
   102  
   103  	vals := []struct{ k, v string }{
   104  		{"do", "verb"},
   105  		{"ether", "wookiedoo"},
   106  		{"horse", "stallion"},
   107  		{"shaman", "horse"},
   108  		{"doge", "coin"},
   109  		{"ether", ""},
   110  		{"dog", "puppy"},
   111  		{"shaman", ""},
   112  	}
   113  	for _, val := range vals {
   114  		trie.UpdateString(val.k, val.v)
   115  	}
   116  
   117  	hash := trie.Hash()
   118  	exp := ethutil.Hex2Bytes("5991bb8c6514148a29db676a14ac506cd2cd5775ace63c30a4fe457715e9ac84")
   119  	if !bytes.Equal(hash, exp) {
   120  		t.Errorf("expected %x got %x", exp, hash)
   121  	}
   122  }
   123  
   124  func TestReplication(t *testing.T) {
   125  	trie := NewEmpty()
   126  	vals := []struct{ k, v string }{
   127  		{"do", "verb"},
   128  		{"ether", "wookiedoo"},
   129  		{"horse", "stallion"},
   130  		{"shaman", "horse"},
   131  		{"doge", "coin"},
   132  		{"ether", ""},
   133  		{"dog", "puppy"},
   134  		{"shaman", ""},
   135  		{"somethingveryoddindeedthis is", "myothernodedata"},
   136  	}
   137  	for _, val := range vals {
   138  		trie.UpdateString(val.k, val.v)
   139  	}
   140  	trie.Commit()
   141  
   142  	trie2 := New(trie.roothash, trie.cache.backend)
   143  	if string(trie2.GetString("horse")) != "stallion" {
   144  		t.Error("expected to have horse => stallion")
   145  	}
   146  
   147  	hash := trie2.Hash()
   148  	exp := trie.Hash()
   149  	if !bytes.Equal(hash, exp) {
   150  		t.Errorf("root failure. expected %x got %x", exp, hash)
   151  	}
   152  
   153  }
   154  
   155  func TestReset(t *testing.T) {
   156  	trie := NewEmpty()
   157  	vals := []struct{ k, v string }{
   158  		{"do", "verb"},
   159  		{"ether", "wookiedoo"},
   160  		{"horse", "stallion"},
   161  	}
   162  	for _, val := range vals {
   163  		trie.UpdateString(val.k, val.v)
   164  	}
   165  	trie.Commit()
   166  
   167  	before := ethutil.CopyBytes(trie.roothash)
   168  	trie.UpdateString("should", "revert")
   169  	trie.Hash()
   170  	// Should have no effect
   171  	trie.Hash()
   172  	trie.Hash()
   173  	// ###
   174  
   175  	trie.Reset()
   176  	after := ethutil.CopyBytes(trie.roothash)
   177  
   178  	if !bytes.Equal(before, after) {
   179  		t.Errorf("expected roots to be equal. %x - %x", before, after)
   180  	}
   181  }
   182  
   183  func TestParanoia(t *testing.T) {
   184  	t.Skip()
   185  	trie := NewEmpty()
   186  
   187  	vals := []struct{ k, v string }{
   188  		{"do", "verb"},
   189  		{"ether", "wookiedoo"},
   190  		{"horse", "stallion"},
   191  		{"shaman", "horse"},
   192  		{"doge", "coin"},
   193  		{"ether", ""},
   194  		{"dog", "puppy"},
   195  		{"shaman", ""},
   196  		{"somethingveryoddindeedthis is", "myothernodedata"},
   197  	}
   198  	for _, val := range vals {
   199  		trie.UpdateString(val.k, val.v)
   200  	}
   201  	trie.Commit()
   202  
   203  	ok, t2 := ParanoiaCheck(trie, trie.cache.backend)
   204  	if !ok {
   205  		t.Errorf("trie paranoia check failed %x %x", trie.roothash, t2.roothash)
   206  	}
   207  }
   208  
   209  // Not an actual test
   210  func TestOutput(t *testing.T) {
   211  	t.Skip()
   212  
   213  	base := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
   214  	trie := NewEmpty()
   215  	for i := 0; i < 50; i++ {
   216  		trie.UpdateString(fmt.Sprintf("%s%d", base, i), "valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")
   217  	}
   218  	fmt.Println("############################## FULL ################################")
   219  	fmt.Println(trie.root)
   220  
   221  	trie.Commit()
   222  	fmt.Println("############################## SMALL ################################")
   223  	trie2 := New(trie.roothash, trie.cache.backend)
   224  	trie2.GetString(base + "20")
   225  	fmt.Println(trie2.root)
   226  }
   227  
   228  func BenchmarkGets(b *testing.B) {
   229  	trie := NewEmpty()
   230  	vals := []struct{ k, v string }{
   231  		{"do", "verb"},
   232  		{"ether", "wookiedoo"},
   233  		{"horse", "stallion"},
   234  		{"shaman", "horse"},
   235  		{"doge", "coin"},
   236  		{"ether", ""},
   237  		{"dog", "puppy"},
   238  		{"shaman", ""},
   239  		{"somethingveryoddindeedthis is", "myothernodedata"},
   240  	}
   241  	for _, val := range vals {
   242  		trie.UpdateString(val.k, val.v)
   243  	}
   244  
   245  	b.ResetTimer()
   246  	for i := 0; i < b.N; i++ {
   247  		trie.Get([]byte("horse"))
   248  	}
   249  }
   250  
   251  func BenchmarkUpdate(b *testing.B) {
   252  	trie := NewEmpty()
   253  
   254  	b.ResetTimer()
   255  	for i := 0; i < b.N; i++ {
   256  		trie.UpdateString(fmt.Sprintf("aaaaaaaaa%d", i), "value")
   257  	}
   258  	trie.Hash()
   259  }
   260  
   261  type kv struct {
   262  	k, v []byte
   263  	t    bool
   264  }
   265  
   266  func TestLargeData(t *testing.T) {
   267  	trie := NewEmpty()
   268  	vals := make(map[string]*kv)
   269  
   270  	for i := byte(1); i < 255; i++ {
   271  		value := &kv{ethutil.LeftPadBytes([]byte{i}, 32), []byte{i}, false}
   272  		value2 := &kv{ethutil.LeftPadBytes([]byte{10, i}, 32), []byte{i}, false}
   273  		trie.Update(value.k, value.v)
   274  		trie.Update(value2.k, value2.v)
   275  		vals[string(value.k)] = value
   276  		vals[string(value2.k)] = value2
   277  		fmt.Println(value, "\n", value2)
   278  	}
   279  
   280  	it := trie.Iterator()
   281  	for it.Next() {
   282  		vals[string(it.Key)].t = true
   283  	}
   284  
   285  	var untouched []*kv
   286  	for _, value := range vals {
   287  		if !value.t {
   288  			untouched = append(untouched, value)
   289  		}
   290  	}
   291  
   292  	if len(untouched) > 0 {
   293  		t.Errorf("Missed %d nodes", len(untouched))
   294  		for _, value := range untouched {
   295  			t.Error(value)
   296  		}
   297  	}
   298  }