2019-01-24 20:15:10 +00:00
|
|
|
// Copyright (C) 2019 Storj Labs, Inc.
|
2018-07-30 20:25:18 +01:00
|
|
|
// See LICENSE for copying information
|
|
|
|
|
|
|
|
package kademlia
|
|
|
|
|
|
|
|
import (
|
2018-11-29 18:39:27 +00:00
|
|
|
"bytes"
|
2018-10-26 17:54:00 +01:00
|
|
|
"sync"
|
2018-07-30 20:25:18 +01:00
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2018-11-20 18:29:07 +00:00
|
|
|
"github.com/gogo/protobuf/proto"
|
2018-07-30 20:25:18 +01:00
|
|
|
"github.com/stretchr/testify/assert"
|
2019-02-26 16:07:53 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2018-10-26 17:54:00 +01:00
|
|
|
"go.uber.org/zap"
|
2018-09-18 05:39:06 +01:00
|
|
|
|
2019-02-22 18:39:29 +00:00
|
|
|
"storj.io/storj/internal/testcontext"
|
2018-11-29 18:39:27 +00:00
|
|
|
"storj.io/storj/internal/teststorj"
|
2019-04-22 10:07:50 +01:00
|
|
|
"storj.io/storj/pkg/overlay"
|
2018-09-18 05:39:06 +01:00
|
|
|
"storj.io/storj/pkg/pb"
|
2018-11-29 18:39:27 +00:00
|
|
|
"storj.io/storj/pkg/storj"
|
2018-07-30 20:25:18 +01:00
|
|
|
"storj.io/storj/storage"
|
2018-10-26 17:54:00 +01:00
|
|
|
"storj.io/storj/storage/storelogger"
|
2018-10-18 17:20:23 +01:00
|
|
|
"storj.io/storj/storage/teststore"
|
2018-07-30 20:25:18 +01:00
|
|
|
)
|
|
|
|
|
2019-02-22 18:39:29 +00:00
|
|
|
type routingTableOpts struct {
|
|
|
|
bucketSize int
|
|
|
|
cacheSize int
|
|
|
|
}
|
|
|
|
|
2018-10-26 17:54:00 +01:00
|
|
|
// newTestRoutingTable returns a newly configured instance of a RoutingTable
|
2019-04-22 10:07:50 +01:00
|
|
|
func newTestRoutingTable(local *overlay.NodeDossier, opts routingTableOpts) (*RoutingTable, error) {
|
2019-02-22 18:39:29 +00:00
|
|
|
if opts.bucketSize == 0 {
|
|
|
|
opts.bucketSize = 6
|
|
|
|
}
|
|
|
|
if opts.cacheSize == 0 {
|
|
|
|
opts.cacheSize = 2
|
|
|
|
}
|
2018-10-26 17:54:00 +01:00
|
|
|
rt := &RoutingTable{
|
2019-04-22 10:07:50 +01:00
|
|
|
self: local,
|
2018-12-12 15:39:16 +00:00
|
|
|
kadBucketDB: storelogger.New(zap.L().Named("rt.kad"), teststore.New()),
|
|
|
|
nodeBucketDB: storelogger.New(zap.L().Named("rt.node"), teststore.New()),
|
2018-11-20 16:54:52 +00:00
|
|
|
transport: &defaultTransport,
|
|
|
|
|
2018-10-26 17:54:00 +01:00
|
|
|
mutex: &sync.Mutex{},
|
2019-02-22 18:39:29 +00:00
|
|
|
rcMutex: &sync.Mutex{},
|
2018-11-29 18:39:27 +00:00
|
|
|
seen: make(map[storj.NodeID]*pb.Node),
|
|
|
|
replacementCache: make(map[bucketID][]*pb.Node),
|
2018-11-20 16:54:52 +00:00
|
|
|
|
2019-02-22 18:39:29 +00:00
|
|
|
bucketSize: opts.bucketSize,
|
|
|
|
rcBucketSize: opts.cacheSize,
|
2018-10-26 17:54:00 +01:00
|
|
|
}
|
2019-04-22 10:07:50 +01:00
|
|
|
ok, err := rt.addNode(&local.Node)
|
2018-10-26 17:54:00 +01:00
|
|
|
if !ok || err != nil {
|
|
|
|
return nil, RoutingErr.New("could not add localNode to routing table: %s", err)
|
|
|
|
}
|
|
|
|
return rt, nil
|
|
|
|
}
|
|
|
|
|
2019-02-22 18:39:29 +00:00
|
|
|
func createRoutingTableWith(localNodeID storj.NodeID, opts routingTableOpts) *RoutingTable {
|
2018-11-29 18:39:27 +00:00
|
|
|
if localNodeID == (storj.NodeID{}) {
|
2019-02-22 18:39:29 +00:00
|
|
|
panic("empty local node id")
|
2018-08-09 20:20:39 +01:00
|
|
|
}
|
2019-04-22 10:07:50 +01:00
|
|
|
local := &overlay.NodeDossier{Node: pb.Node{Id: localNodeID}}
|
2018-10-18 17:20:23 +01:00
|
|
|
|
2019-04-22 10:07:50 +01:00
|
|
|
rt, err := newTestRoutingTable(local, opts)
|
2018-09-11 14:57:12 +01:00
|
|
|
if err != nil {
|
2019-02-22 18:39:29 +00:00
|
|
|
panic(err)
|
2018-09-11 14:57:12 +01:00
|
|
|
}
|
2019-02-22 18:39:29 +00:00
|
|
|
return rt
|
|
|
|
}
|
2018-10-26 17:54:00 +01:00
|
|
|
|
2019-02-22 18:39:29 +00:00
|
|
|
func createRoutingTable(localNodeID storj.NodeID) *RoutingTable {
|
|
|
|
return createRoutingTableWith(localNodeID, routingTableOpts{})
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestAddNode(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("OO"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-02-26 16:07:53 +00:00
|
|
|
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
|
|
|
node *pb.Node
|
|
|
|
added bool
|
|
|
|
kadIDs [][]byte
|
|
|
|
nodeIDs [][]string
|
|
|
|
}{
|
|
|
|
{testID: "PO: add node to unfilled kbucket",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("PO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{255, 255}},
|
|
|
|
nodeIDs: [][]string{{"OO", "PO"}},
|
|
|
|
},
|
|
|
|
{testID: "NO: add node to full kbucket and split",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("NO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{255, 255}},
|
|
|
|
nodeIDs: [][]string{{"NO", "OO", "PO"}},
|
|
|
|
},
|
|
|
|
{testID: "MO",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("MO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{255, 255}},
|
|
|
|
nodeIDs: [][]string{{"MO", "NO", "OO", "PO"}},
|
|
|
|
},
|
|
|
|
{testID: "LO",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("LO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{255, 255}},
|
|
|
|
nodeIDs: [][]string{{"LO", "MO", "NO", "OO", "PO"}},
|
|
|
|
},
|
|
|
|
{testID: "QO",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("QO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{255, 255}},
|
|
|
|
nodeIDs: [][]string{{"LO", "MO", "NO", "OO", "PO", "QO"}},
|
|
|
|
},
|
|
|
|
{testID: "SO: split bucket",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("SO"),
|
2018-09-19 19:37:28 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
|
|
|
nodeIDs: [][]string{{}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
|
|
|
},
|
|
|
|
{testID: "?O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("?O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
|
|
|
nodeIDs: [][]string{{"?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: ">O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode(">O"),
|
|
|
|
added: true,
|
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}}, nodeIDs: [][]string{{">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "=O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("=O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"=O", ">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: ";O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode(";O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{";O", "=O", ">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: ":O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode(":O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{":O", ";O", "=O", ">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "9O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("9O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "8O: should drop",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("8O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: false,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "KO",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("KO"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "JO",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("JO"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"JO", "KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "]O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("]O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"JO", "KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO", "]O"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "^O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("^O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"JO", "KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO", "]O", "^O"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "_O",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("_O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"JO", "KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO", "]O", "^O", "_O"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "@O: split bucket 2",
|
2018-11-29 18:39:27 +00:00
|
|
|
node: teststorj.MockNode("@O"),
|
2018-10-11 21:25:54 +01:00
|
|
|
added: true,
|
2018-11-29 18:39:27 +00:00
|
|
|
kadIDs: [][]byte{{63, 255}, {71, 255}, {79, 255}, {95, 255}, {127, 255}, {255, 255}},
|
2018-10-11 21:25:54 +01:00
|
|
|
nodeIDs: [][]string{{"9O", ":O", ";O", "=O", ">O", "?O"}, {"@O"}, {"JO", "KO", "LO", "MO", "NO", "OO"}, {"PO", "QO", "SO", "]O", "^O", "_O"}, {}, {}},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
ok, err := rt.addNode(testCase.node)
|
2019-02-26 16:07:53 +00:00
|
|
|
require.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
require.Equal(t, testCase.added, ok)
|
2019-06-05 15:23:10 +01:00
|
|
|
kadKeys, err := rt.kadBucketDB.List(ctx, nil, 0)
|
2019-02-26 16:07:53 +00:00
|
|
|
require.NoError(t, err)
|
2018-09-19 19:37:28 +01:00
|
|
|
for i, v := range kadKeys {
|
2019-05-29 14:30:16 +01:00
|
|
|
require.True(t, bytes.Equal(testCase.kadIDs[i], v[:2]))
|
2018-11-29 18:39:27 +00:00
|
|
|
ids, err := rt.getNodeIDsWithinKBucket(keyToBucketID(v))
|
2019-02-26 16:07:53 +00:00
|
|
|
require.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
require.True(t, len(ids) == len(testCase.nodeIDs[i]))
|
2018-11-29 18:39:27 +00:00
|
|
|
for j, id := range ids {
|
2019-05-29 14:30:16 +01:00
|
|
|
require.True(t, bytes.Equal(teststorj.NodeIDFromString(testCase.nodeIDs[i][j]).Bytes(), id.Bytes()))
|
2018-09-19 19:37:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-29 14:30:16 +01:00
|
|
|
if testCase.testID == "8O" {
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeID80 := teststorj.NodeIDFromString("8O")
|
|
|
|
n := rt.replacementCache[keyToBucketID(nodeID80.Bytes())]
|
2019-02-26 16:07:53 +00:00
|
|
|
require.Equal(t, nodeID80.Bytes(), n[0].Id.Bytes())
|
2018-09-19 19:37:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
})
|
|
|
|
}
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
2018-08-17 20:11:46 +01:00
|
|
|
func TestUpdateNode(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2018-11-29 18:39:27 +00:00
|
|
|
node := teststorj.MockNode("BB")
|
2018-08-17 20:11:46 +01:00
|
|
|
ok, err := rt.addNode(node)
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.NoError(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val, err := rt.nodeBucketDB.Get(ctx, node.Id.Bytes())
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
unmarshaled, err := unmarshalNodes([]storage.Value{val})
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
x := unmarshaled[0].Address
|
|
|
|
assert.Nil(t, x)
|
|
|
|
|
2018-09-18 05:39:06 +01:00
|
|
|
node.Address = &pb.NodeAddress{Address: "BB"}
|
2018-08-17 20:11:46 +01:00
|
|
|
err = rt.updateNode(node)
|
|
|
|
assert.NoError(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val, err = rt.nodeBucketDB.Get(ctx, node.Id.Bytes())
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
unmarshaled, err = unmarshalNodes([]storage.Value{val})
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
y := unmarshaled[0].Address.Address
|
|
|
|
assert.Equal(t, "BB", y)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestRemoveNode(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
kadBucketID := firstBucketID
|
2018-11-29 18:39:27 +00:00
|
|
|
node := teststorj.MockNode("BB")
|
2018-08-17 20:11:46 +01:00
|
|
|
ok, err := rt.addNode(node)
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.NoError(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val, err := rt.nodeBucketDB.Get(ctx, node.Id.Bytes())
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, val)
|
2018-11-29 18:39:27 +00:00
|
|
|
node2 := teststorj.MockNode("CC")
|
2018-08-17 20:11:46 +01:00
|
|
|
rt.addToReplacementCache(kadBucketID, node2)
|
2019-02-22 18:39:29 +00:00
|
|
|
err = rt.removeNode(node)
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val, err = rt.nodeBucketDB.Get(ctx, node.Id.Bytes())
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.Nil(t, val)
|
|
|
|
assert.Error(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val2, err := rt.nodeBucketDB.Get(ctx, node2.Id.Bytes())
|
2018-08-17 20:11:46 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotNil(t, val2)
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.Equal(t, 0, len(rt.replacementCache[kadBucketID]))
|
2018-08-21 19:44:42 +01:00
|
|
|
|
|
|
|
//try to remove node not in rt
|
2019-02-22 18:39:29 +00:00
|
|
|
err = rt.removeNode(&pb.Node{
|
|
|
|
Id: teststorj.NodeIDFromString("DD"),
|
|
|
|
Address: &pb.NodeAddress{Address: "address:1"},
|
|
|
|
})
|
2018-08-21 19:44:42 +01:00
|
|
|
assert.NoError(t, err)
|
2018-08-17 20:11:46 +01:00
|
|
|
}
|
|
|
|
|
2018-07-30 20:25:18 +01:00
|
|
|
func TestCreateOrUpdateKBucket(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-01-02 18:57:11 +00:00
|
|
|
id := bucketID{255, 255}
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-06-05 15:23:10 +01:00
|
|
|
err := rt.createOrUpdateKBucket(ctx, id, time.Now())
|
2018-07-30 20:25:18 +01:00
|
|
|
assert.NoError(t, err)
|
2019-06-05 15:23:10 +01:00
|
|
|
val, e := rt.kadBucketDB.Get(ctx, id[:])
|
2018-07-30 20:25:18 +01:00
|
|
|
assert.NotNil(t, val)
|
|
|
|
assert.NoError(t, e)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetKBucketID(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-01-02 18:57:11 +00:00
|
|
|
kadIDA := bucketID{255, 255}
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeIDA := teststorj.NodeIDFromString("AA")
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeIDA)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-06-05 15:23:10 +01:00
|
|
|
keyA, err := rt.getKBucketID(ctx, nodeIDA)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.Equal(t, kadIDA[:2], keyA[:2])
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
2019-02-26 16:07:53 +00:00
|
|
|
func TestWouldBeInNearestK(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-02-26 16:07:53 +00:00
|
|
|
rt := createRoutingTableWith(storj.NodeID{127, 255}, routingTableOpts{bucketSize: 2})
|
2019-02-22 18:39:29 +00:00
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
2019-01-02 18:57:11 +00:00
|
|
|
nodeID storj.NodeID
|
2018-09-19 19:37:28 +01:00
|
|
|
closest bool
|
|
|
|
}{
|
|
|
|
{testID: "A",
|
2019-02-26 16:07:53 +00:00
|
|
|
nodeID: storj.NodeID{127, 255}, //XOR from [127, 255] is 0
|
2018-09-19 19:37:28 +01:00
|
|
|
closest: true,
|
|
|
|
},
|
|
|
|
{testID: "B",
|
2019-02-26 16:07:53 +00:00
|
|
|
nodeID: storj.NodeID{143, 255}, //XOR from [127, 255] is 240
|
2018-09-19 19:37:28 +01:00
|
|
|
closest: true,
|
|
|
|
},
|
|
|
|
{testID: "C",
|
2019-02-26 16:07:53 +00:00
|
|
|
nodeID: storj.NodeID{255, 255}, //XOR from [127, 255] is 128
|
2018-09-19 19:37:28 +01:00
|
|
|
closest: true,
|
|
|
|
},
|
|
|
|
{testID: "D",
|
2019-02-26 16:07:53 +00:00
|
|
|
nodeID: storj.NodeID{191, 255}, //XOR from [127, 255] is 192
|
|
|
|
closest: false,
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "E",
|
2019-02-26 16:07:53 +00:00
|
|
|
nodeID: storj.NodeID{133, 255}, //XOR from [127, 255] is 250
|
2018-09-19 19:37:28 +01:00
|
|
|
closest: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
result, err := rt.wouldBeInNearestK(testCase.nodeID)
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
assert.Equal(t, testCase.closest, result)
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, testCase.nodeID.Bytes(), []byte("")))
|
2018-09-19 19:37:28 +01:00
|
|
|
})
|
|
|
|
}
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestKadBucketContainsLocalNode(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-01-02 18:57:11 +00:00
|
|
|
nodeIDA := storj.NodeID{183, 255} //[10110111, 1111111]
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeIDA)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
kadIDA := firstBucketID
|
2018-11-29 18:39:27 +00:00
|
|
|
var kadIDB bucketID
|
|
|
|
copy(kadIDB[:], kadIDA[:])
|
|
|
|
kadIDB[0] = 127
|
2018-07-30 20:25:18 +01:00
|
|
|
now := time.Now()
|
2019-06-05 15:23:10 +01:00
|
|
|
err := rt.createOrUpdateKBucket(ctx, kadIDB, now)
|
2018-07-30 20:25:18 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
resultTrue, err := rt.kadBucketContainsLocalNode(kadIDA)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
resultFalse, err := rt.kadBucketContainsLocalNode(kadIDB)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, resultTrue)
|
|
|
|
assert.False(t, resultFalse)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestKadBucketHasRoom(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-01-02 18:57:11 +00:00
|
|
|
node1 := storj.NodeID{255, 255}
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(node1)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
kadIDA := firstBucketID
|
|
|
|
node2 := storj.NodeID{191, 255}
|
|
|
|
node3 := storj.NodeID{127, 255}
|
|
|
|
node4 := storj.NodeID{63, 255}
|
|
|
|
node5 := storj.NodeID{159, 255}
|
|
|
|
node6 := storj.NodeID{0, 127}
|
2018-07-30 20:25:18 +01:00
|
|
|
resultA, err := rt.kadBucketHasRoom(kadIDA)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.True(t, resultA)
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, node2.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, node3.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, node4.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, node5.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, node6.Bytes(), []byte("")))
|
2018-07-30 20:25:18 +01:00
|
|
|
resultB, err := rt.kadBucketHasRoom(kadIDA)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.False(t, resultB)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetNodeIDsWithinKBucket(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2019-01-02 18:57:11 +00:00
|
|
|
nodeIDA := storj.NodeID{183, 255} //[10110111, 1111111]
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeIDA)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
kadIDA := firstBucketID
|
2018-11-29 18:39:27 +00:00
|
|
|
var kadIDB bucketID
|
|
|
|
copy(kadIDB[:], kadIDA[:])
|
|
|
|
kadIDB[0] = 127
|
2018-07-30 20:25:18 +01:00
|
|
|
now := time.Now()
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.createOrUpdateKBucket(ctx, kadIDB, now))
|
2018-07-30 20:25:18 +01:00
|
|
|
|
2019-01-02 18:57:11 +00:00
|
|
|
nodeIDB := storj.NodeID{111, 255} //[01101111, 1111111]
|
|
|
|
nodeIDC := storj.NodeID{47, 255} //[00101111, 1111111]
|
2018-07-30 20:25:18 +01:00
|
|
|
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeIDB.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeIDC.Bytes(), []byte("")))
|
2018-07-30 20:25:18 +01:00
|
|
|
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
2018-11-29 18:39:27 +00:00
|
|
|
kadID bucketID
|
2018-09-19 19:37:28 +01:00
|
|
|
expected storage.Keys
|
|
|
|
}{
|
|
|
|
{testID: "A",
|
|
|
|
kadID: kadIDA,
|
2018-11-29 18:39:27 +00:00
|
|
|
expected: storage.Keys{nodeIDA.Bytes()},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "B",
|
|
|
|
kadID: kadIDB,
|
2018-11-29 18:39:27 +00:00
|
|
|
expected: storage.Keys{nodeIDC.Bytes(), nodeIDB.Bytes()},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
n, err := rt.getNodeIDsWithinKBucket(testCase.kadID)
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
for i, id := range testCase.expected {
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.True(t, id.Equal(n[i].Bytes()))
|
|
|
|
}
|
2018-09-19 19:37:28 +01:00
|
|
|
})
|
|
|
|
}
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
2018-08-09 20:20:39 +01:00
|
|
|
func TestGetNodesFromIDs(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeA := teststorj.MockNode("AA")
|
|
|
|
nodeB := teststorj.MockNode("BB")
|
|
|
|
nodeC := teststorj.MockNode("CC")
|
2018-09-18 05:39:06 +01:00
|
|
|
a, err := proto.Marshal(nodeA)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-09-18 05:39:06 +01:00
|
|
|
b, err := proto.Marshal(nodeB)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-09-18 05:39:06 +01:00
|
|
|
c, err := proto.Marshal(nodeC)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeA.Id)
|
|
|
|
defer ctx.Check(rt.Close)
|
2018-08-09 20:20:39 +01:00
|
|
|
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeA.Id.Bytes(), a))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeB.Id.Bytes(), b))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeC.Id.Bytes(), c))
|
2018-11-29 18:39:27 +00:00
|
|
|
expected := []*pb.Node{nodeA, nodeB, nodeC}
|
2018-08-09 20:20:39 +01:00
|
|
|
|
2019-06-05 15:23:10 +01:00
|
|
|
nodeKeys, err := rt.nodeBucketDB.List(ctx, nil, 0)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
values, err := rt.getNodesFromIDsBytes(teststorj.NodeIDsFromBytes(nodeKeys.ByteSlices()...))
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
for i, n := range expected {
|
|
|
|
assert.True(t, bytes.Equal(n.Id.Bytes(), values[i].Id.Bytes()))
|
|
|
|
}
|
2018-08-09 20:20:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalNodes(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeA := teststorj.MockNode("AA")
|
|
|
|
nodeB := teststorj.MockNode("BB")
|
|
|
|
nodeC := teststorj.MockNode("CC")
|
2018-08-09 20:20:39 +01:00
|
|
|
|
2018-09-18 05:39:06 +01:00
|
|
|
a, err := proto.Marshal(nodeA)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-09-18 05:39:06 +01:00
|
|
|
b, err := proto.Marshal(nodeB)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-09-18 05:39:06 +01:00
|
|
|
c, err := proto.Marshal(nodeC)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeA.Id)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeA.Id.Bytes(), a))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeB.Id.Bytes(), b))
|
|
|
|
assert.NoError(t, rt.nodeBucketDB.Put(ctx, nodeC.Id.Bytes(), c))
|
|
|
|
nodeKeys, err := rt.nodeBucketDB.List(ctx, nil, 0)
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-11-29 18:39:27 +00:00
|
|
|
nodes, err := rt.getNodesFromIDsBytes(teststorj.NodeIDsFromBytes(nodeKeys.ByteSlices()...))
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
2018-09-18 05:39:06 +01:00
|
|
|
expected := []*pb.Node{nodeA, nodeB, nodeC}
|
2018-08-09 20:20:39 +01:00
|
|
|
for i, v := range expected {
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.True(t, bytes.Equal(v.Id.Bytes(), nodes[i].Id.Bytes()))
|
2018-08-09 20:20:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGetUnmarshaledNodesFromBucket(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeA := teststorj.MockNode("AA")
|
2019-02-22 18:39:29 +00:00
|
|
|
rt := createRoutingTable(nodeA.Id)
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
bucketID := firstBucketID
|
2018-11-29 18:39:27 +00:00
|
|
|
nodeB := teststorj.MockNode("BB")
|
|
|
|
nodeC := teststorj.MockNode("CC")
|
2018-09-11 14:13:25 +01:00
|
|
|
var err error
|
|
|
|
_, err = rt.addNode(nodeB)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
_, err = rt.addNode(nodeC)
|
|
|
|
assert.NoError(t, err)
|
2018-08-09 20:20:39 +01:00
|
|
|
nodes, err := rt.getUnmarshaledNodesFromBucket(bucketID)
|
2018-09-18 05:39:06 +01:00
|
|
|
expected := []*pb.Node{nodeA, nodeB, nodeC}
|
2018-08-09 20:20:39 +01:00
|
|
|
assert.NoError(t, err)
|
|
|
|
for i, v := range expected {
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.True(t, bytes.Equal(v.Id.Bytes(), nodes[i].Id.Bytes()))
|
2018-08-09 20:20:39 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-30 20:25:18 +01:00
|
|
|
func TestGetKBucketRange(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-01-02 18:57:11 +00:00
|
|
|
idA := storj.NodeID{255, 255}
|
|
|
|
idB := storj.NodeID{127, 255}
|
|
|
|
idC := storj.NodeID{63, 255}
|
2019-06-05 15:23:10 +01:00
|
|
|
assert.NoError(t, rt.kadBucketDB.Put(ctx, idA.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.kadBucketDB.Put(ctx, idB.Bytes(), []byte("")))
|
|
|
|
assert.NoError(t, rt.kadBucketDB.Put(ctx, idC.Bytes(), []byte("")))
|
2018-11-29 18:39:27 +00:00
|
|
|
zeroBID := bucketID{}
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
2018-11-29 18:39:27 +00:00
|
|
|
id storj.NodeID
|
2018-09-19 19:37:28 +01:00
|
|
|
expected storage.Keys
|
|
|
|
}{
|
|
|
|
{testID: "A",
|
|
|
|
id: idA,
|
2018-11-29 18:39:27 +00:00
|
|
|
expected: storage.Keys{idB.Bytes(), idA.Bytes()},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
{testID: "B",
|
|
|
|
id: idB,
|
2018-11-29 18:39:27 +00:00
|
|
|
expected: storage.Keys{idC.Bytes(), idB.Bytes()}},
|
2018-09-19 19:37:28 +01:00
|
|
|
{testID: "C",
|
|
|
|
id: idC,
|
2018-11-29 18:39:27 +00:00
|
|
|
expected: storage.Keys{zeroBID[:], idC.Bytes()},
|
2018-09-19 19:37:28 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
ep, err := rt.getKBucketRange(keyToBucketID(testCase.id.Bytes()))
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
for i, k := range testCase.expected {
|
2018-11-29 18:39:27 +00:00
|
|
|
assert.True(t, k.Equal(ep[i][:]))
|
|
|
|
}
|
2018-09-19 19:37:28 +01:00
|
|
|
})
|
|
|
|
}
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
2018-11-29 18:39:27 +00:00
|
|
|
func TestBucketIDZeroValue(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
zero := bucketID{}
|
2018-11-29 18:39:27 +00:00
|
|
|
expected := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
|
|
|
assert.True(t, bytes.Equal(zero[:], expected))
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDetermineLeafDepth(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2019-02-26 16:07:53 +00:00
|
|
|
idA, idB, idC := firstBucketID, firstBucketID, firstBucketID
|
2019-01-02 18:57:11 +00:00
|
|
|
idA[0] = 255
|
|
|
|
idB[0] = 127
|
|
|
|
idC[0] = 63
|
2018-07-30 20:25:18 +01:00
|
|
|
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
2018-11-29 18:39:27 +00:00
|
|
|
id storj.NodeID
|
2018-09-19 19:37:28 +01:00
|
|
|
depth int
|
|
|
|
addNode func()
|
|
|
|
}{
|
|
|
|
{testID: "A",
|
|
|
|
id: idA,
|
|
|
|
depth: 0,
|
|
|
|
addNode: func() {
|
2019-06-05 15:23:10 +01:00
|
|
|
e := rt.kadBucketDB.Put(ctx, idA.Bytes(), []byte(""))
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, e)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{testID: "B",
|
|
|
|
id: idB,
|
|
|
|
depth: 1,
|
|
|
|
addNode: func() {
|
2019-06-05 15:23:10 +01:00
|
|
|
e := rt.kadBucketDB.Put(ctx, idB.Bytes(), []byte(""))
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, e)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{testID: "C",
|
|
|
|
id: idA,
|
|
|
|
depth: 1,
|
|
|
|
addNode: func() {
|
2019-06-05 15:23:10 +01:00
|
|
|
e := rt.kadBucketDB.Put(ctx, idC.Bytes(), []byte(""))
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, e)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
{testID: "D",
|
|
|
|
id: idB,
|
|
|
|
depth: 2,
|
|
|
|
addNode: func() {},
|
|
|
|
},
|
|
|
|
{testID: "E",
|
|
|
|
id: idC,
|
|
|
|
depth: 2,
|
|
|
|
addNode: func() {},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
testCase.addNode()
|
|
|
|
d, err := rt.determineLeafDepth(testCase.id)
|
2018-09-19 19:37:28 +01:00
|
|
|
assert.NoError(t, err)
|
2019-05-29 14:30:16 +01:00
|
|
|
assert.Equal(t, testCase.depth, d)
|
2018-09-19 19:37:28 +01:00
|
|
|
})
|
|
|
|
}
|
2018-07-30 20:25:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestSplitBucket(t *testing.T) {
|
2019-02-22 18:39:29 +00:00
|
|
|
ctx := testcontext.New(t)
|
|
|
|
defer ctx.Cleanup()
|
|
|
|
rt := createRoutingTable(teststorj.NodeIDFromString("AA"))
|
|
|
|
defer ctx.Check(rt.Close)
|
2018-09-19 19:37:28 +01:00
|
|
|
cases := []struct {
|
|
|
|
testID string
|
|
|
|
idA []byte
|
|
|
|
idB []byte
|
|
|
|
depth int
|
|
|
|
}{
|
|
|
|
{testID: "A: [11111111, 11111111] -> [10111111, 11111111]",
|
|
|
|
idA: []byte{255, 255},
|
|
|
|
idB: []byte{191, 255},
|
|
|
|
depth: 1,
|
|
|
|
},
|
|
|
|
{testID: "B: [10111111, 11111111] -> [10011111, 11111111]",
|
|
|
|
idA: []byte{191, 255},
|
|
|
|
idB: []byte{159, 255},
|
|
|
|
depth: 2,
|
|
|
|
},
|
|
|
|
{testID: "C: [01111111, 11111111] -> [00111111, 11111111]",
|
|
|
|
idA: []byte{127, 255},
|
|
|
|
idB: []byte{63, 255},
|
|
|
|
depth: 1,
|
|
|
|
},
|
|
|
|
{testID: "D: [00000000, 11111111] -> [00000000, 01111111]",
|
|
|
|
idA: []byte{0, 255},
|
|
|
|
idB: []byte{0, 127},
|
|
|
|
depth: 8,
|
|
|
|
},
|
|
|
|
{testID: "E: [01011111, 11111111] -> [01010111, 11111111]",
|
|
|
|
idA: []byte{95, 255},
|
|
|
|
idB: []byte{87, 255},
|
|
|
|
depth: 4,
|
|
|
|
},
|
|
|
|
{testID: "F: [01011111, 11111111] -> [01001111, 11111111]",
|
|
|
|
idA: []byte{95, 255},
|
|
|
|
idB: []byte{79, 255},
|
|
|
|
depth: 3,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, c := range cases {
|
2019-05-29 14:30:16 +01:00
|
|
|
testCase := c
|
|
|
|
t.Run(testCase.testID, func(t *testing.T) {
|
|
|
|
newID := rt.splitBucket(keyToBucketID(testCase.idA), testCase.depth)
|
|
|
|
assert.Equal(t, testCase.idB, newID[:2])
|
2018-09-19 19:37:28 +01:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|