p2p/discover: fix off by one error causing buckets to contain duplicates
This commit is contained in:
		@@ -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
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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 {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user