p2p/discover: fix off by one error causing buckets to contain duplicates

This commit is contained in:
Felix Lange 2015-03-30 17:23:28 +02:00
parent de7af720d6
commit a77c431e37
2 changed files with 43 additions and 1 deletions

View File

@ -328,7 +328,7 @@ func (b *bucket) bump(n *Node) bool {
if b.entries[i].ID == n.ID { if b.entries[i].ID == n.ID {
n.bumpActive() n.bumpActive()
// move it to the front // move it to the front
copy(b.entries[1:], b.entries[:i+1]) copy(b.entries[1:], b.entries[:i])
b.entries[0] = n b.entries[0] = n
return true return true
} }

View File

@ -66,6 +66,48 @@ func TestTable_pingReplace(t *testing.T) {
doit(false, false) 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) { func fillBucket(tab *Table, ld int) (last *Node) {
b := tab.buckets[ld] b := tab.buckets[ld]
for len(b.entries) < bucketSize { for len(b.entries) < bucketSize {