aboutsummaryrefslogtreecommitdiffstats
path: root/p2p/discover
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-03-30 23:23:28 +0800
committerFelix Lange <fjl@twurst.com>2015-04-01 23:00:12 +0800
commita77c431e378a3cfcddb4b33317319412799c96cb (patch)
treeaa8a0bcf1715eac248954748de2648bcdb07fd88 /p2p/discover
parentde7af720d6bb10b93d716fb0c6cf3ee0e51dc71a (diff)
downloadgo-tangerine-a77c431e378a3cfcddb4b33317319412799c96cb.tar.gz
go-tangerine-a77c431e378a3cfcddb4b33317319412799c96cb.tar.zst
go-tangerine-a77c431e378a3cfcddb4b33317319412799c96cb.zip
p2p/discover: fix off by one error causing buckets to contain duplicates
Diffstat (limited to 'p2p/discover')
-rw-r--r--p2p/discover/table.go2
-rw-r--r--p2p/discover/table_test.go42
2 files changed, 43 insertions, 1 deletions
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 842f55d9f..dbf86c084 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -328,7 +328,7 @@ func (b *bucket) bump(n *Node) bool {
if b.entries[i].ID == n.ID {
n.bumpActive()
// move it to the front
- copy(b.entries[1:], b.entries[:i+1])
+ copy(b.entries[1:], b.entries[:i])
b.entries[0] = n
return true
}
diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go
index 95ec30bea..a98376bca 100644
--- a/p2p/discover/table_test.go
+++ b/p2p/discover/table_test.go
@@ -66,6 +66,48 @@ func TestTable_pingReplace(t *testing.T) {
doit(false, false)
}
+func TestBucket_bumpNoDuplicates(t *testing.T) {
+ t.Parallel()
+ cfg := &quick.Config{
+ MaxCount: 1000,
+ Rand: quickrand,
+ Values: func(args []reflect.Value, rand *rand.Rand) {
+ // generate a random list of nodes. this will be the content of the bucket.
+ n := rand.Intn(bucketSize-1) + 1
+ nodes := make([]*Node, n)
+ for i := range nodes {
+ nodes[i] = &Node{ID: randomID(NodeID{}, 200)}
+ }
+ args[0] = reflect.ValueOf(nodes)
+ // generate random bump positions.
+ bumps := make([]int, rand.Intn(100))
+ for i := range bumps {
+ bumps[i] = rand.Intn(len(nodes))
+ }
+ args[1] = reflect.ValueOf(bumps)
+ },
+ }
+
+ prop := func(nodes []*Node, bumps []int) (ok bool) {
+ b := &bucket{entries: make([]*Node, len(nodes))}
+ copy(b.entries, nodes)
+ for i, pos := range bumps {
+ b.bump(b.entries[pos])
+ if hasDuplicates(b.entries) {
+ t.Logf("bucket has duplicates after %d/%d bumps:", i+1, len(bumps))
+ for _, n := range b.entries {
+ t.Logf(" %p", n)
+ }
+ return false
+ }
+ }
+ return true
+ }
+ if err := quick.Check(prop, cfg); err != nil {
+ t.Error(err)
+ }
+}
+
func fillBucket(tab *Table, ld int) (last *Node) {
b := tab.buckets[ld]
for len(b.entries) < bucketSize {