|
|
|
@ -200,3 +200,41 @@ func TestOverlappingAnnouncements(t *testing.T) { |
|
|
|
|
t.Fatalf("synchronised block mismatch: have %v, want %v", imported, targetBlocks+1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that announces already being retrieved will not be duplicated.
|
|
|
|
|
func TestPendingDeduplication(t *testing.T) { |
|
|
|
|
// Create a hash and corresponding block
|
|
|
|
|
hashes := createHashes(1, knownHash) |
|
|
|
|
blocks := createBlocksFromHashes(hashes) |
|
|
|
|
|
|
|
|
|
// Assemble a tester with a built in counter and delayed fetcher
|
|
|
|
|
tester := newTester() |
|
|
|
|
fetcher := tester.makeFetcher(blocks) |
|
|
|
|
|
|
|
|
|
delay := 50 * time.Millisecond |
|
|
|
|
counter := uint32(0) |
|
|
|
|
wrapper := func(hashes []common.Hash) error { |
|
|
|
|
atomic.AddUint32(&counter, uint32(len(hashes))) |
|
|
|
|
|
|
|
|
|
// Simulate a long running fetch
|
|
|
|
|
go func() { |
|
|
|
|
time.Sleep(delay) |
|
|
|
|
fetcher(hashes) |
|
|
|
|
}() |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
// Announce the same block many times until it's fetched (wait for any pending ops)
|
|
|
|
|
for !tester.hasBlock(hashes[0]) { |
|
|
|
|
tester.fetcher.Notify("repeater", hashes[0], time.Now().Add(-arriveTimeout), wrapper) |
|
|
|
|
time.Sleep(time.Millisecond) |
|
|
|
|
} |
|
|
|
|
time.Sleep(delay) |
|
|
|
|
|
|
|
|
|
// Check that all blocks were imported and none fetched twice
|
|
|
|
|
if imported := len(tester.ownBlocks); imported != 2 { |
|
|
|
|
t.Fatalf("synchronised block mismatch: have %v, want %v", imported, 2) |
|
|
|
|
} |
|
|
|
|
if int(counter) != 1 { |
|
|
|
|
t.Fatalf("retrieval count mismatch: have %v, want %v", counter, 1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|