101 lines
2.9 KiB
Go
101 lines
2.9 KiB
Go
|
// Copyright (C) 2018 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information.
|
||
|
|
||
|
package kademlia
|
||
|
|
||
|
import (
|
||
|
"math/rand"
|
||
|
"strconv"
|
||
|
"testing"
|
||
|
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
|
||
|
"storj.io/storj/pkg/pb"
|
||
|
"storj.io/storj/pkg/storj"
|
||
|
)
|
||
|
|
||
|
func TestDiscoveryQueue(t *testing.T) {
|
||
|
target := storj.NodeID{1, 1} // 00000001
|
||
|
|
||
|
// // id -> id ^ target
|
||
|
nodeA := &pb.Node{Id: storj.NodeID{3, 2}} // 00000011:00000010 -> 00000010:00000011
|
||
|
nodeB := &pb.Node{Id: storj.NodeID{6, 5}} // 00000110:00000101 -> 00000111:00000100
|
||
|
nodeC := &pb.Node{Id: storj.NodeID{7, 7}} // 00000111:00000111 -> 00000110:00000110
|
||
|
nodeD := &pb.Node{Id: storj.NodeID{8, 4}} // 00001000:00000100 -> 00001001:00000101
|
||
|
nodeE := &pb.Node{Id: storj.NodeID{12, 1}} // 00001100:00000001 -> 00001101:00000000
|
||
|
nodeF := &pb.Node{Id: storj.NodeID{15, 16}} // 00001111:00010000 -> 00001110:00010001
|
||
|
nodeG := &pb.Node{Id: storj.NodeID{18, 74}} // 00010010:01001010 -> 00010011:01001011
|
||
|
nodeH := &pb.Node{Id: storj.NodeID{25, 61}} // 00011001:00111101 -> 00011000:00111100
|
||
|
|
||
|
nodes := []*pb.Node{nodeA, nodeB, nodeC, nodeD, nodeE, nodeF, nodeG, nodeH}
|
||
|
|
||
|
expected := []*pb.Node{
|
||
|
nodeA, // 00000011:00000010 -> 00000010:00000011
|
||
|
nodeC, // 00000111:00000111 -> 00000110:00000110
|
||
|
nodeB, // 00000110:00000101 -> 00000111:00000100
|
||
|
nodeD, // 00001000:00000100 -> 00001001:00000101
|
||
|
nodeE, // 00001100:00000001 -> 00001101:00000000
|
||
|
nodeF, // 00001111:00010000 -> 00001110:00010001
|
||
|
// nodeG, // 00010010:01001010 -> 00010011:01001011
|
||
|
// nodeH, // 00011001:00111101 -> 00011000:00111100
|
||
|
}
|
||
|
|
||
|
// // code for outputting the bits above
|
||
|
// for _, node := range nodes {
|
||
|
// xor := xorNodeID(target, node.Id)
|
||
|
// t.Logf("%08b,%08b -> %08b,%08b", node.Id[0], node.Id[1], xor[0], xor[1])
|
||
|
// }
|
||
|
|
||
|
queue := newDiscoveryQueue(6)
|
||
|
queue.Insert(target, nodes...)
|
||
|
|
||
|
assert.Equal(t, queue.Len(), 6)
|
||
|
|
||
|
for i, expect := range expected {
|
||
|
node := queue.Closest()
|
||
|
assert.Equal(t, node.Id, expect.Id, strconv.Itoa(i))
|
||
|
}
|
||
|
|
||
|
assert.Nil(t, queue.Closest())
|
||
|
}
|
||
|
|
||
|
func TestDiscoveryQueueRandom(t *testing.T) {
|
||
|
const maxLen = 8
|
||
|
|
||
|
seed := int64(rand.Uint64())
|
||
|
t.Logf("seed %v", seed)
|
||
|
|
||
|
r := rand.New(rand.NewSource(seed))
|
||
|
|
||
|
for i := 0; i < 100; i++ {
|
||
|
var target storj.NodeID
|
||
|
_, _ = r.Read(target[:])
|
||
|
|
||
|
var initial []*pb.Node
|
||
|
for k := 0; k < 10; k++ {
|
||
|
var nodeID storj.NodeID
|
||
|
_, _ = r.Read(nodeID[:])
|
||
|
initial = append(initial, &pb.Node{Id: nodeID})
|
||
|
}
|
||
|
|
||
|
queue := newDiscoveryQueue(maxLen)
|
||
|
queue.Insert(target, initial...)
|
||
|
|
||
|
for k := 0; k < 10; k++ {
|
||
|
var nodeID storj.NodeID
|
||
|
_, _ = r.Read(nodeID[:])
|
||
|
queue.Insert(target, &pb.Node{Id: nodeID})
|
||
|
}
|
||
|
|
||
|
assert.Equal(t, queue.Len(), maxLen)
|
||
|
|
||
|
previousPriority := storj.NodeID{}
|
||
|
for queue.Len() > 0 {
|
||
|
next := queue.Closest()
|
||
|
priority := xorNodeID(target, next.Id)
|
||
|
// ensure that priority is monotonically increasing
|
||
|
assert.False(t, priority.Less(previousPriority))
|
||
|
}
|
||
|
}
|
||
|
}
|