@@ -21,8 +21,11 @@ import (
21
21
"encoding/binary"
22
22
"fmt"
23
23
"io/ioutil"
24
+ "math/rand"
24
25
"os"
26
+ "reflect"
25
27
"testing"
28
+ "testing/quick"
26
29
27
30
"github.com/davecgh/go-spew/spew"
28
31
"github.com/ethereum/go-ethereum/common"
@@ -297,41 +300,6 @@ func TestReplication(t *testing.T) {
297
300
}
298
301
}
299
302
300
- func paranoiaCheck (t1 * Trie ) (bool , * Trie ) {
301
- t2 := new (Trie )
302
- it := NewIterator (t1 )
303
- for it .Next () {
304
- t2 .Update (it .Key , it .Value )
305
- }
306
- return t2 .Hash () == t1 .Hash (), t2
307
- }
308
-
309
- func TestParanoia (t * testing.T ) {
310
- t .Skip ()
311
- trie := newEmpty ()
312
-
313
- vals := []struct { k , v string }{
314
- {"do" , "verb" },
315
- {"ether" , "wookiedoo" },
316
- {"horse" , "stallion" },
317
- {"shaman" , "horse" },
318
- {"doge" , "coin" },
319
- {"ether" , "" },
320
- {"dog" , "puppy" },
321
- {"shaman" , "" },
322
- {"somethingveryoddindeedthis is" , "myothernodedata" },
323
- }
324
- for _ , val := range vals {
325
- updateString (trie , val .k , val .v )
326
- }
327
- trie .Commit ()
328
-
329
- ok , t2 := paranoiaCheck (trie )
330
- if ! ok {
331
- t .Errorf ("trie paranoia check failed %x %x" , trie .Hash (), t2 .Hash ())
332
- }
333
- }
334
-
335
303
// Not an actual test
336
304
func TestOutput (t * testing.T ) {
337
305
t .Skip ()
@@ -356,7 +324,128 @@ func TestLargeValue(t *testing.T) {
356
324
trie .Update ([]byte ("key1" ), []byte {99 , 99 , 99 , 99 })
357
325
trie .Update ([]byte ("key2" ), bytes .Repeat ([]byte {1 }, 32 ))
358
326
trie .Hash ()
327
+ }
328
+
329
+ type randTestStep struct {
330
+ op int
331
+ key []byte // for opUpdate, opDelete, opGet
332
+ value []byte // for opUpdate
333
+ }
334
+
335
+ type randTest []randTestStep
336
+
337
+ const (
338
+ opUpdate = iota
339
+ opDelete
340
+ opGet
341
+ opCommit
342
+ opHash
343
+ opReset
344
+ opItercheckhash
345
+ opMax // boundary value, not an actual op
346
+ )
347
+
348
+ func (randTest ) Generate (r * rand.Rand , size int ) reflect.Value {
349
+ var allKeys [][]byte
350
+ genKey := func () []byte {
351
+ if len (allKeys ) < 2 || r .Intn (100 ) < 10 {
352
+ // new key
353
+ key := make ([]byte , r .Intn (50 ))
354
+ randRead (r , key )
355
+ allKeys = append (allKeys , key )
356
+ return key
357
+ }
358
+ // use existing key
359
+ return allKeys [r .Intn (len (allKeys ))]
360
+ }
361
+
362
+ var steps randTest
363
+ for i := 0 ; i < size ; i ++ {
364
+ step := randTestStep {op : r .Intn (opMax )}
365
+ switch step .op {
366
+ case opUpdate :
367
+ step .key = genKey ()
368
+ step .value = make ([]byte , 8 )
369
+ binary .BigEndian .PutUint64 (step .value , uint64 (i ))
370
+ case opGet , opDelete :
371
+ step .key = genKey ()
372
+ }
373
+ steps = append (steps , step )
374
+ }
375
+ return reflect .ValueOf (steps )
376
+ }
377
+
378
+ // rand.Rand provides a Read method in Go 1.7 and later, but
379
+ // we can't use it yet.
380
+ func randRead (r * rand.Rand , b []byte ) {
381
+ pos := 0
382
+ val := 0
383
+ for n := 0 ; n < len (b ); n ++ {
384
+ if pos == 0 {
385
+ val = r .Int ()
386
+ pos = 7
387
+ }
388
+ b [n ] = byte (val )
389
+ val >>= 8
390
+ pos --
391
+ }
392
+ }
359
393
394
+ func runRandTest (rt randTest ) bool {
395
+ db , _ := ethdb .NewMemDatabase ()
396
+ tr , _ := New (common.Hash {}, db )
397
+ values := make (map [string ]string ) // tracks content of the trie
398
+
399
+ for _ , step := range rt {
400
+ switch step .op {
401
+ case opUpdate :
402
+ tr .Update (step .key , step .value )
403
+ values [string (step .key )] = string (step .value )
404
+ case opDelete :
405
+ tr .Delete (step .key )
406
+ delete (values , string (step .key ))
407
+ case opGet :
408
+ v := tr .Get (step .key )
409
+ want := values [string (step .key )]
410
+ if string (v ) != want {
411
+ fmt .Printf ("mismatch for key 0x%x, got 0x%x want 0x%x" , step .key , v , want )
412
+ return false
413
+ }
414
+ case opCommit :
415
+ if _ , err := tr .Commit (); err != nil {
416
+ panic (err )
417
+ }
418
+ case opHash :
419
+ tr .Hash ()
420
+ case opReset :
421
+ hash , err := tr .Commit ()
422
+ if err != nil {
423
+ panic (err )
424
+ }
425
+ newtr , err := New (hash , db )
426
+ if err != nil {
427
+ panic (err )
428
+ }
429
+ tr = newtr
430
+ case opItercheckhash :
431
+ checktr , _ := New (common.Hash {}, nil )
432
+ it := tr .Iterator ()
433
+ for it .Next () {
434
+ checktr .Update (it .Key , it .Value )
435
+ }
436
+ if tr .Hash () != checktr .Hash () {
437
+ fmt .Println ("hashes not equal" )
438
+ return false
439
+ }
440
+ }
441
+ }
442
+ return true
443
+ }
444
+
445
+ func TestRandom (t * testing.T ) {
446
+ if err := quick .Check (runRandTest , nil ); err != nil {
447
+ t .Fatal (err )
448
+ }
360
449
}
361
450
362
451
func BenchmarkGet (b * testing.B ) { benchGet (b , false ) }
0 commit comments