storj/pkg/kademlia/routing_test.go
Dennis Coyle dee2c137c8
Remove BKAD dependency from pkg/kademlia (#294)
* slowly but surely

* hardcode ID for tests so we can get predictable results

* skipping bad test

* removing tests of bkad

* wip

* new algorithm for worker

* clean up

* remove skipped test

* changes

* uncomment

* fixed conflicts

* maybe done ?

* cleanup

* boot bkad

* wip

* cleanup

* undo change

* fixes

* wip

* wip

* moving nodeID around

* wip

* wip

* fixes

* fixes after merge

* added TODO

* fixed tests post identity

* linter fixes

* wip

* PR review comments

* wip

* fixing tests

* fix tests

* force db directory

* bad test

* fixes race condition

* small cleanups

* adding db folder

* testing

* wip

* cleanup

* cleanup

* linters

* export Restrict

* add timeout

* testing

* linters

* forgot one

* moar fixes from master merge

* PR comments

* moar PR comments

* removed stun flag

* remove duplicate declaration

* remove old tests

* remove timeout

* fix tests

* missed one

* changed StringToID >> IDFromString

* PR comments

* stupid linter

* moevd overlay mock

* fixed merge conflicts

* fixes

* linter
2018-10-08 11:09:37 -04:00

223 lines
5.1 KiB
Go

// Copyright (C) 2018 Storj Labs, Inc.
// See LICENSE for copying information
package kademlia
import (
"testing"
"time"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/assert"
"storj.io/storj/pkg/node"
"storj.io/storj/pkg/pb"
"storj.io/storj/storage"
)
func TestLocal(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
local := rt.Local()
assert.Equal(t, *rt.self, local)
}
func TestK(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
k := rt.K()
assert.Equal(t, rt.bucketSize, k)
}
func TestCacheSize(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
expected := rt.rcBucketSize
result := rt.CacheSize()
assert.Equal(t, expected, result)
}
func TestGetBucket(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
node := mockNode("AA")
node2 := mockNode("BB")
ok, err := rt.addNode(node2)
assert.True(t, ok)
assert.NoError(t, err)
cases := []struct {
nodeID string
expected *KBucket
ok bool
}{
{nodeID: node.Id,
expected: &KBucket{nodes: []*pb.Node{node, node2}},
ok: true,
},
{nodeID: node2.Id,
expected: &KBucket{nodes: []*pb.Node{node, node2}},
ok: true,
},
}
for i, v := range cases {
b, e := rt.GetBucket(node2.Id)
for j, w := range v.expected.nodes {
if !assert.True(t, proto.Equal(w, b.Nodes()[j])) {
t.Logf("case %v failed expected: ", i)
}
}
if !assert.Equal(t, v.ok, e) {
t.Logf("case %v failed ok: ", i)
}
}
}
func TestGetBuckets(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
node := mockNode("AA")
node2 := mockNode("BB")
ok, err := rt.addNode(node2)
assert.True(t, ok)
assert.NoError(t, err)
expected := []*pb.Node{node, node2}
buckets, err := rt.GetBuckets()
assert.NoError(t, err)
for _, v := range buckets {
for j, w := range v.Nodes() {
assert.True(t, proto.Equal(expected[j], w))
}
}
}
func TestFindNear(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
node1 := mockNode("AA")
node2 := mockNode("BB")
node3 := mockNode("CC")
ok, err := rt.addNode(node2)
assert.True(t, ok)
assert.NoError(t, err)
cases := []struct {
testID string
node pb.Node
expectedNodes []*pb.Node
limit int
}{
{testID: "limit 1 on node1: return node1",
node: *node1,
expectedNodes: []*pb.Node{node1},
limit: 1,
},
{testID: "limit 2 on node3: return nodes2, node1",
node: *node3,
expectedNodes: []*pb.Node{node2, node1},
limit: 2,
},
{testID: "limit 1 on node3: return node2",
node: *node3,
expectedNodes: []*pb.Node{node2},
limit: 1,
},
{testID: "limit 3 on node3: return node2, node1",
node: *node3,
expectedNodes: []*pb.Node{node2, node1},
limit: 3,
},
}
for _, c := range cases {
t.Run(c.testID, func(t *testing.T) {
ns, err := rt.FindNear(node.IDFromString(c.node.Id), c.limit)
assert.NoError(t, err)
assert.Equal(t, c.expectedNodes, ns)
})
}
}
func TestConnectionSuccess(t *testing.T) {
id := "AA"
rt, cleanup := createRoutingTable(t, []byte(id))
defer cleanup()
id2 := "BB"
address1 := &pb.NodeAddress{Address: "a"}
address2 := &pb.NodeAddress{Address: "b"}
node1 := &pb.Node{Id: id, Address: address1}
node2 := &pb.Node{Id: id2, Address: address2}
cases := []struct {
testID string
node *pb.Node
id string
address *pb.NodeAddress
}{
{testID: "Update Node",
node: node1,
id: id,
address: address1,
},
{testID: "Add Node",
node: node2,
id: id2,
address: address2,
},
}
for _, c := range cases {
t.Run(c.testID, func(t *testing.T) {
err := rt.ConnectionSuccess(c.node)
assert.NoError(t, err)
v, err := rt.nodeBucketDB.Get([]byte(c.id))
assert.NoError(t, err)
n, err := unmarshalNodes(storage.Keys{storage.Key(c.id)}, []storage.Value{v})
assert.NoError(t, err)
assert.Equal(t, c.address.Address, n[0].Address.Address)
})
}
}
func TestConnectionFailed(t *testing.T) {
id := "AA"
node := mockNode(id)
rt, cleanup := createRoutingTable(t, []byte(id))
defer cleanup()
err := rt.ConnectionFailed(node)
assert.NoError(t, err)
v, err := rt.nodeBucketDB.Get([]byte(id))
assert.Error(t, err)
assert.Nil(t, v)
}
func TestSetBucketTimestamp(t *testing.T) {
id := []byte("AA")
idStr := string(id)
rt, cleanup := createRoutingTable(t, id)
defer cleanup()
now := time.Now().UTC()
err := rt.createOrUpdateKBucket(id, now)
assert.NoError(t, err)
ti, err := rt.GetBucketTimestamp(idStr, nil)
assert.Equal(t, now, ti)
assert.NoError(t, err)
now = time.Now().UTC()
err = rt.SetBucketTimestamp(idStr, now)
assert.NoError(t, err)
ti, err = rt.GetBucketTimestamp(idStr, nil)
assert.Equal(t, now, ti)
assert.NoError(t, err)
}
func TestGetBucketTimestamp(t *testing.T) {
rt, cleanup := createRoutingTable(t, []byte("AA"))
defer cleanup()
now := time.Now().UTC()
id := "AA"
err := rt.createOrUpdateKBucket([]byte(id), now)
assert.NoError(t, err)
ti, err := rt.GetBucketTimestamp(id, nil)
assert.Equal(t, now, ti)
assert.NoError(t, err)
}