@ -21,8 +21,11 @@ import (
"encoding/binary"
"fmt"
"io/ioutil"
"math/rand"
"os"
"reflect"
"testing"
"testing/quick"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
@ -297,41 +300,6 @@ func TestReplication(t *testing.T) {
}
}
func paranoiaCheck ( t1 * Trie ) ( bool , * Trie ) {
t2 := new ( Trie )
it := NewIterator ( t1 )
for it . Next ( ) {
t2 . Update ( it . Key , it . Value )
}
return t2 . Hash ( ) == t1 . Hash ( ) , t2
}
func TestParanoia ( t * testing . T ) {
t . Skip ( )
trie := newEmpty ( )
vals := [ ] struct { k , v string } {
{ "do" , "verb" } ,
{ "ether" , "wookiedoo" } ,
{ "horse" , "stallion" } ,
{ "shaman" , "horse" } ,
{ "doge" , "coin" } ,
{ "ether" , "" } ,
{ "dog" , "puppy" } ,
{ "shaman" , "" } ,
{ "somethingveryoddindeedthis is" , "myothernodedata" } ,
}
for _ , val := range vals {
updateString ( trie , val . k , val . v )
}
trie . Commit ( )
ok , t2 := paranoiaCheck ( trie )
if ! ok {
t . Errorf ( "trie paranoia check failed %x %x" , trie . Hash ( ) , t2 . Hash ( ) )
}
}
// Not an actual test
func TestOutput ( t * testing . T ) {
t . Skip ( )
@ -356,7 +324,128 @@ func TestLargeValue(t *testing.T) {
trie . Update ( [ ] byte ( "key1" ) , [ ] byte { 99 , 99 , 99 , 99 } )
trie . Update ( [ ] byte ( "key2" ) , bytes . Repeat ( [ ] byte { 1 } , 32 ) )
trie . Hash ( )
}
type randTestStep struct {
op int
key [ ] byte // for opUpdate, opDelete, opGet
value [ ] byte // for opUpdate
}
type randTest [ ] randTestStep
const (
opUpdate = iota
opDelete
opGet
opCommit
opHash
opReset
opItercheckhash
opMax // boundary value, not an actual op
)
func ( randTest ) Generate ( r * rand . Rand , size int ) reflect . Value {
var allKeys [ ] [ ] byte
genKey := func ( ) [ ] byte {
if len ( allKeys ) < 2 || r . Intn ( 100 ) < 10 {
// new key
key := make ( [ ] byte , r . Intn ( 50 ) )
randRead ( r , key )
allKeys = append ( allKeys , key )
return key
}
// use existing key
return allKeys [ r . Intn ( len ( allKeys ) ) ]
}
var steps randTest
for i := 0 ; i < size ; i ++ {
step := randTestStep { op : r . Intn ( opMax ) }
switch step . op {
case opUpdate :
step . key = genKey ( )
step . value = make ( [ ] byte , 8 )
binary . BigEndian . PutUint64 ( step . value , uint64 ( i ) )
case opGet , opDelete :
step . key = genKey ( )
}
steps = append ( steps , step )
}
return reflect . ValueOf ( steps )
}
// rand.Rand provides a Read method in Go 1.7 and later, but
// we can't use it yet.
func randRead ( r * rand . Rand , b [ ] byte ) {
pos := 0
val := 0
for n := 0 ; n < len ( b ) ; n ++ {
if pos == 0 {
val = r . Int ( )
pos = 7
}
b [ n ] = byte ( val )
val >>= 8
pos --
}
}
func runRandTest ( rt randTest ) bool {
db , _ := ethdb . NewMemDatabase ( )
tr , _ := New ( common . Hash { } , db )
values := make ( map [ string ] string ) // tracks content of the trie
for _ , step := range rt {
switch step . op {
case opUpdate :
tr . Update ( step . key , step . value )
values [ string ( step . key ) ] = string ( step . value )
case opDelete :
tr . Delete ( step . key )
delete ( values , string ( step . key ) )
case opGet :
v := tr . Get ( step . key )
want := values [ string ( step . key ) ]
if string ( v ) != want {
fmt . Printf ( "mismatch for key 0x%x, got 0x%x want 0x%x" , step . key , v , want )
return false
}
case opCommit :
if _ , err := tr . Commit ( ) ; err != nil {
panic ( err )
}
case opHash :
tr . Hash ( )
case opReset :
hash , err := tr . Commit ( )
if err != nil {
panic ( err )
}
newtr , err := New ( hash , db )
if err != nil {
panic ( err )
}
tr = newtr
case opItercheckhash :
checktr , _ := New ( common . Hash { } , nil )
it := tr . Iterator ( )
for it . Next ( ) {
checktr . Update ( it . Key , it . Value )
}
if tr . Hash ( ) != checktr . Hash ( ) {
fmt . Println ( "hashes not equal" )
return false
}
}
}
return true
}
func TestRandom ( t * testing . T ) {
if err := quick . Check ( runRandTest , nil ) ; err != nil {
t . Fatal ( err )
}
}
func BenchmarkGet ( b * testing . B ) { benchGet ( b , false ) }