@@ -23,6 +23,7 @@ import (
23
23
"errors"
24
24
"fmt"
25
25
"hash"
26
+ "io"
26
27
"math/big"
27
28
"math/rand"
28
29
"reflect"
@@ -292,8 +293,9 @@ func TestRandomCases(t *testing.T) {
292
293
{op : 1 , key : common .Hex2Bytes ("980c393656413a15c8da01978ed9f89feb80b502f58f2d640e3a2f5f7a99a7018f1b573befd92053ac6f78fca4a87268" ), value : common .Hex2Bytes ("" )}, // step 24
293
294
{op : 1 , key : common .Hex2Bytes ("fd" ), value : common .Hex2Bytes ("" )}, // step 25
294
295
}
295
- runRandTest (rt )
296
-
296
+ if err := runRandTest (rt ); err != nil {
297
+ t .Fatal (err )
298
+ }
297
299
}
298
300
299
301
// randTest performs random trie operations.
@@ -319,36 +321,53 @@ const (
319
321
)
320
322
321
323
func (randTest ) Generate (r * rand.Rand , size int ) reflect.Value {
324
+ var finishedFn = func () bool {
325
+ size --
326
+ return size > 0
327
+ }
328
+ return reflect .ValueOf (generateSteps (finishedFn , r ))
329
+ }
330
+
331
+ func generateSteps (finished func () bool , r io.Reader ) randTest {
322
332
var allKeys [][]byte
333
+ var one = []byte {0 }
323
334
genKey := func () []byte {
324
- if len (allKeys ) < 2 || r .Intn (100 ) < 10 {
335
+ r .Read (one )
336
+ if len (allKeys ) < 2 || one [0 ]% 100 > 90 {
325
337
// new key
326
- key := make ([]byte , r .Intn (50 ))
338
+ size := one [0 ] % 50
339
+ key := make ([]byte , size )
327
340
r .Read (key )
328
341
allKeys = append (allKeys , key )
329
342
return key
330
343
}
331
344
// use existing key
332
- return allKeys [r .Intn (len (allKeys ))]
345
+ idx := int (one [0 ]) % len (allKeys )
346
+ return allKeys [idx ]
333
347
}
334
-
335
348
var steps randTest
336
- for i := 0 ; i < size ; i ++ {
337
- step := randTestStep {op : r .Intn (opMax )}
349
+ for ! finished () {
350
+ r .Read (one )
351
+ step := randTestStep {op : int (one [0 ]) % opMax }
338
352
switch step .op {
339
353
case opUpdate :
340
354
step .key = genKey ()
341
355
step .value = make ([]byte , 8 )
342
- binary .BigEndian .PutUint64 (step .value , uint64 (i ))
356
+ binary .BigEndian .PutUint64 (step .value , uint64 (len ( steps ) ))
343
357
case opGet , opDelete :
344
358
step .key = genKey ()
345
359
}
346
360
steps = append (steps , step )
347
361
}
348
- return reflect . ValueOf ( steps )
362
+ return steps
349
363
}
350
364
351
- func runRandTest (rt randTest ) bool {
365
+ // runRandTestBool coerces error to boolean, for use in quick.Check
366
+ func runRandTestBool (rt randTest ) bool {
367
+ return runRandTest (rt ) == nil
368
+ }
369
+
370
+ func runRandTest (rt randTest ) error {
352
371
triedb := NewDatabase (memorydb .New ())
353
372
354
373
tr , _ := New (common.Hash {}, triedb )
@@ -378,12 +397,12 @@ func runRandTest(rt randTest) bool {
378
397
hash , err := tr .Commit (nil )
379
398
if err != nil {
380
399
rt [i ].err = err
381
- return false
400
+ return err
382
401
}
383
402
newtr , err := New (hash , triedb )
384
403
if err != nil {
385
404
rt [i ].err = err
386
- return false
405
+ return err
387
406
}
388
407
tr = newtr
389
408
case opItercheckhash :
@@ -398,14 +417,14 @@ func runRandTest(rt randTest) bool {
398
417
}
399
418
// Abort the test on error.
400
419
if rt [i ].err != nil {
401
- return false
420
+ return rt [ i ]. err
402
421
}
403
422
}
404
- return true
423
+ return nil
405
424
}
406
425
407
426
func TestRandom (t * testing.T ) {
408
- if err := quick .Check (runRandTest , nil ); err != nil {
427
+ if err := quick .Check (runRandTestBool , nil ); err != nil {
409
428
if cerr , ok := err .(* quick.CheckError ); ok {
410
429
t .Fatalf ("random test iteration %d failed: %s" , cerr .Count , spew .Sdump (cerr .In ))
411
430
}
@@ -841,3 +860,17 @@ func TestDecodeNode(t *testing.T) {
841
860
decodeNode (hash , elems )
842
861
}
843
862
}
863
+
864
+ func FuzzTrie (f * testing.F ) {
865
+ f .Fuzz (func (t * testing.T , data []byte ) {
866
+ var steps = 500
867
+ var input = bytes .NewReader (data )
868
+ var finishedFn = func () bool {
869
+ steps --
870
+ return steps < 0 || input .Len () == 0
871
+ }
872
+ if err := runRandTest (generateSteps (finishedFn , input )); err != nil {
873
+ t .Fatal (err )
874
+ }
875
+ })
876
+ }
0 commit comments