mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +00:00
parent
4b4980d949
commit
a9d4fffc97
1 changed files with 49 additions and 16 deletions
|
|
@ -23,6 +23,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"reflect"
|
||||
|
|
@ -292,8 +293,9 @@ func TestRandomCases(t *testing.T) {
|
|||
{op: 1, key: common.Hex2Bytes("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268"), value: common.Hex2Bytes("")}, // step 24
|
||||
{op: 1, key: common.Hex2Bytes("fd"), value: common.Hex2Bytes("")}, // step 25
|
||||
}
|
||||
runRandTest(rt)
|
||||
|
||||
if err := runRandTest(rt); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// randTest performs random trie operations.
|
||||
|
|
@ -319,36 +321,53 @@ const (
|
|||
)
|
||||
|
||||
func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
|
||||
var finishedFn = func() bool {
|
||||
size--
|
||||
return size > 0
|
||||
}
|
||||
return reflect.ValueOf(generateSteps(finishedFn, r))
|
||||
}
|
||||
|
||||
func generateSteps(finished func() bool, r io.Reader) randTest {
|
||||
var allKeys [][]byte
|
||||
var one = []byte{0}
|
||||
genKey := func() []byte {
|
||||
if len(allKeys) < 2 || r.Intn(100) < 10 {
|
||||
r.Read(one)
|
||||
if len(allKeys) < 2 || one[0]%100 > 90 {
|
||||
// new key
|
||||
key := make([]byte, r.Intn(50))
|
||||
size := one[0] % 50
|
||||
key := make([]byte, size)
|
||||
r.Read(key)
|
||||
allKeys = append(allKeys, key)
|
||||
return key
|
||||
}
|
||||
// use existing key
|
||||
return allKeys[r.Intn(len(allKeys))]
|
||||
idx := int(one[0]) % len(allKeys)
|
||||
return allKeys[idx]
|
||||
}
|
||||
|
||||
var steps randTest
|
||||
for i := 0; i < size; i++ {
|
||||
step := randTestStep{op: r.Intn(opMax)}
|
||||
for !finished() {
|
||||
r.Read(one)
|
||||
step := randTestStep{op: int(one[0]) % opMax}
|
||||
switch step.op {
|
||||
case opUpdate:
|
||||
step.key = genKey()
|
||||
step.value = make([]byte, 8)
|
||||
binary.BigEndian.PutUint64(step.value, uint64(i))
|
||||
binary.BigEndian.PutUint64(step.value, uint64(len(steps)))
|
||||
case opGet, opDelete:
|
||||
step.key = genKey()
|
||||
}
|
||||
steps = append(steps, step)
|
||||
}
|
||||
return reflect.ValueOf(steps)
|
||||
return steps
|
||||
}
|
||||
|
||||
func runRandTest(rt randTest) bool {
|
||||
// runRandTestBool coerces error to boolean, for use in quick.Check
|
||||
func runRandTestBool(rt randTest) bool {
|
||||
return runRandTest(rt) == nil
|
||||
}
|
||||
|
||||
func runRandTest(rt randTest) error {
|
||||
triedb := NewDatabase(memorydb.New())
|
||||
|
||||
tr, _ := New(common.Hash{}, triedb)
|
||||
|
|
@ -378,12 +397,12 @@ func runRandTest(rt randTest) bool {
|
|||
hash, err := tr.Commit(nil)
|
||||
if err != nil {
|
||||
rt[i].err = err
|
||||
return false
|
||||
return err
|
||||
}
|
||||
newtr, err := New(hash, triedb)
|
||||
if err != nil {
|
||||
rt[i].err = err
|
||||
return false
|
||||
return err
|
||||
}
|
||||
tr = newtr
|
||||
case opItercheckhash:
|
||||
|
|
@ -398,14 +417,14 @@ func runRandTest(rt randTest) bool {
|
|||
}
|
||||
// Abort the test on error.
|
||||
if rt[i].err != nil {
|
||||
return false
|
||||
return rt[i].err
|
||||
}
|
||||
}
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestRandom(t *testing.T) {
|
||||
if err := quick.Check(runRandTest, nil); err != nil {
|
||||
if err := quick.Check(runRandTestBool, nil); err != nil {
|
||||
if cerr, ok := err.(*quick.CheckError); ok {
|
||||
t.Fatalf("random test iteration %d failed: %s", cerr.Count, spew.Sdump(cerr.In))
|
||||
}
|
||||
|
|
@ -841,3 +860,17 @@ func TestDecodeNode(t *testing.T) {
|
|||
decodeNode(hash, elems)
|
||||
}
|
||||
}
|
||||
|
||||
func FuzzTrie(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
var steps = 500
|
||||
var input = bytes.NewReader(data)
|
||||
var finishedFn = func() bool {
|
||||
steps--
|
||||
return steps < 0 || input.Len() == 0
|
||||
}
|
||||
if err := runRandTest(generateSteps(finishedFn, input)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue