aboutsummaryrefslogtreecommitdiffstats
path: root/eth/fetcher/fetcher_test.go
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-06-17 21:53:28 +0800
committerPéter Szilágyi <peterke@gmail.com>2015-06-18 20:56:08 +0800
commit37c5ff392f71fddaa6acd92925f69e81876fe22e (patch)
tree30602b2ab8bd498ba3ace24d2d6447fcee107eb9 /eth/fetcher/fetcher_test.go
parent2a7411bc9605dae9798ed29ed237e28c8fc98895 (diff)
downloaddexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar.gz
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar.bz2
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar.lz
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar.xz
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.tar.zst
dexon-37c5ff392f71fddaa6acd92925f69e81876fe22e.zip
eth/fetcher: build longest chain until proven otherwise
Diffstat (limited to 'eth/fetcher/fetcher_test.go')
-rw-r--r--eth/fetcher/fetcher_test.go57
1 files changed, 57 insertions, 0 deletions
diff --git a/eth/fetcher/fetcher_test.go b/eth/fetcher/fetcher_test.go
index af2652a86..00fad3498 100644
--- a/eth/fetcher/fetcher_test.go
+++ b/eth/fetcher/fetcher_test.go
@@ -91,9 +91,15 @@ func (f *fetcherTester) hasBlock(hash common.Hash) bool {
// importBlock injects a new blocks into the simulated chain.
func (f *fetcherTester) importBlock(peer string, block *types.Block) error {
+ // Make sure the parent in known
if _, ok := f.ownBlocks[block.ParentHash()]; !ok {
return errors.New("unknown parent")
}
+ // Discard any new blocks if the same height already exists
+ if block.NumberU64() <= f.ownBlocks[f.ownHashes[len(f.ownHashes)-1]].NumberU64() {
+ return nil
+ }
+ // Otherwise build our current chain
f.ownHashes = append(f.ownHashes, block.Hash())
f.ownBlocks[block.Hash()] = block
return nil
@@ -363,3 +369,54 @@ func TestDistantDiscarding(t *testing.T) {
t.Fatalf("fetcher queued future block")
}
}
+
+// Tests that if multiple uncles (i.e. blocks at the same height) are queued for
+// importing, then they will get inserted in phases, previous heights needing to
+// complete before the next numbered blocks can begin.
+func TestCompetingImports(t *testing.T) {
+ // Generate a few soft-forks for concurrent imports
+ hashesA := createHashes(16, knownHash)
+ hashesB := createHashes(16, knownHash)
+ hashesC := createHashes(16, knownHash)
+
+ blocksA := createBlocksFromHashes(hashesA)
+ blocksB := createBlocksFromHashes(hashesB)
+ blocksC := createBlocksFromHashes(hashesC)
+
+ // Create a tester, and override the import to check number reversals
+ tester := newTester()
+
+ first := int32(1)
+ height := uint64(1)
+ tester.fetcher.importBlock = func(peer string, block *types.Block) error {
+ // Check for any phase reordering
+ if prev := atomic.LoadUint64(&height); block.NumberU64() < prev {
+ t.Errorf("phase reversal: have %v, want %v", block.NumberU64(), prev)
+ }
+ atomic.StoreUint64(&height, block.NumberU64())
+
+ // Sleep a bit on the first import not to race with the enqueues
+ if atomic.CompareAndSwapInt32(&first, 1, 0) {
+ time.Sleep(50 * time.Millisecond)
+ }
+ return tester.importBlock(peer, block)
+ }
+ // Queue up everything but with a missing link
+ for i := 0; i < len(hashesA)-2; i++ {
+ tester.fetcher.Enqueue("chain A", blocksA[hashesA[i]])
+ tester.fetcher.Enqueue("chain B", blocksB[hashesB[i]])
+ tester.fetcher.Enqueue("chain C", blocksC[hashesC[i]])
+ }
+ // Add the three missing links, and wait for a full import
+ tester.fetcher.Enqueue("chain A", blocksA[hashesA[len(hashesA)-2]])
+ tester.fetcher.Enqueue("chain B", blocksB[hashesB[len(hashesB)-2]])
+ tester.fetcher.Enqueue("chain C", blocksC[hashesC[len(hashesC)-2]])
+
+ start := time.Now()
+ for len(tester.ownHashes) != len(hashesA) && time.Since(start) < time.Second {
+ time.Sleep(50 * time.Millisecond)
+ }
+ if len(tester.ownHashes) != len(hashesA) {
+ t.Fatalf("chain length mismatch: have %v, want %v", len(tester.ownHashes), len(hashesA))
+ }
+}