590 lines
16 KiB
Go
590 lines
16 KiB
Go
|
// Copyright (C) 2018 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information
|
||
|
|
||
|
package kademlia
|
||
|
|
||
|
import (
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/stretchr/testify/assert"
|
||
|
|
||
|
proto "storj.io/storj/protos/overlay"
|
||
|
"storj.io/storj/storage"
|
||
|
)
|
||
|
|
||
|
func tempfile(fileName string) string {
|
||
|
f, err := ioutil.TempFile("", fileName)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
f.Close()
|
||
|
err = os.Remove(f.Name())
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return f.Name()
|
||
|
}
|
||
|
|
||
|
func createRT() *RoutingTable {
|
||
|
localNodeID, _ := newID()
|
||
|
localNode := proto.Node{Id: string(localNodeID)}
|
||
|
rt, _ := NewRoutingTable(&localNode, tempfile("Kadbucket"), tempfile("Nodebucket"), 16, 6)
|
||
|
return rt
|
||
|
}
|
||
|
|
||
|
func mockNodes(id string) *proto.Node {
|
||
|
var node proto.Node
|
||
|
node.Id = id
|
||
|
return &node
|
||
|
}
|
||
|
|
||
|
func TestAddNode(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
//add local node
|
||
|
rt.self = mockNodes("OO") //[79, 79] or [01001111, 01001111]
|
||
|
localNode := rt.self
|
||
|
err := rt.addNode(localNode)
|
||
|
assert.NoError(t, err)
|
||
|
bucket, err := rt.kadBucketDB.Get(storage.Key([]byte{255, 255}))
|
||
|
assert.NoError(t, err)
|
||
|
assert.NotNil(t, bucket)
|
||
|
//add node to unfilled kbucket
|
||
|
node1 := mockNodes("PO") //[80, 79] or [01010000, 01001111]
|
||
|
err = rt.addNode(node1)
|
||
|
assert.NoError(t, err)
|
||
|
kadKeys, err := rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err := rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, len(kadKeys))
|
||
|
assert.Equal(t, 2, len(nodeKeys))
|
||
|
|
||
|
//add node to full kbucket and split
|
||
|
node2 := mockNodes("NO") //[78, 79] or [01001110, 01001111]
|
||
|
err = rt.addNode(node2)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node3 := mockNodes("MO") //[77, 79] or [01001101, 01001111]
|
||
|
err = rt.addNode(node3)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node4 := mockNodes("LO") //[76, 79] or [01001100, 01001111]
|
||
|
err = rt.addNode(node4)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node5 := mockNodes("QO") //[81, 79] or [01010001, 01001111]
|
||
|
err = rt.addNode(node5)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, len(kadKeys))
|
||
|
assert.Equal(t, 6, len(nodeKeys))
|
||
|
|
||
|
//splitting here
|
||
|
node6 := mockNodes("SO")
|
||
|
err = rt.addNode(node6)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 5, len(kadKeys))
|
||
|
assert.Equal(t, 7, len(nodeKeys))
|
||
|
|
||
|
// //check how many keys in each bucket
|
||
|
a, err := rt.getNodeIDsWithinKBucket(kadKeys[0])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, len(a))
|
||
|
b, err := rt.getNodeIDsWithinKBucket(kadKeys[1])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 4, len(b))
|
||
|
c, err := rt.getNodeIDsWithinKBucket(kadKeys[2])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 3, len(c))
|
||
|
d, err := rt.getNodeIDsWithinKBucket(kadKeys[3])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, len(d))
|
||
|
e, err := rt.getNodeIDsWithinKBucket(kadKeys[4])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, len(e))
|
||
|
|
||
|
//add node to full kbucket and drop
|
||
|
node7 := mockNodes("?O")
|
||
|
err = rt.addNode(node7)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node8 := mockNodes(">O")
|
||
|
err = rt.addNode(node8)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node9 := mockNodes("=O")
|
||
|
err = rt.addNode(node9)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node10 := mockNodes(";O")
|
||
|
err = rt.addNode(node10)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node11 := mockNodes(":O")
|
||
|
err = rt.addNode(node11)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
node12 := mockNodes("9O")
|
||
|
err = rt.addNode(node12)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 5, len(kadKeys))
|
||
|
assert.Equal(t, 13, len(nodeKeys))
|
||
|
|
||
|
a, err = rt.getNodeIDsWithinKBucket(kadKeys[0])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 6, len(a))
|
||
|
|
||
|
//should drop
|
||
|
node13 := mockNodes("8O")
|
||
|
err = rt.addNode(node13)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 5, len(kadKeys))
|
||
|
assert.Equal(t, 13, len(nodeKeys))
|
||
|
a, err = rt.getNodeIDsWithinKBucket(kadKeys[0])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 6, len(a))
|
||
|
|
||
|
//add node to highly unbalanced tree
|
||
|
//adding to bucket 1
|
||
|
node14 := mockNodes("KO") //75
|
||
|
err = rt.addNode(node14)
|
||
|
assert.NoError(t, err)
|
||
|
node15 := mockNodes("JO") //74
|
||
|
err = rt.addNode(node15)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
//adding to bucket 2
|
||
|
node16 := mockNodes("]O") //93
|
||
|
err = rt.addNode(node16)
|
||
|
assert.NoError(t, err)
|
||
|
node17 := mockNodes("^O") //94
|
||
|
err = rt.addNode(node17)
|
||
|
assert.NoError(t, err)
|
||
|
node18 := mockNodes("_O") //95
|
||
|
err = rt.addNode(node18)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
b, err = rt.getNodeIDsWithinKBucket(kadKeys[1])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 6, len(b))
|
||
|
c, err = rt.getNodeIDsWithinKBucket(kadKeys[2])
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 6, len(c))
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 5, len(kadKeys))
|
||
|
assert.Equal(t, 18, len(nodeKeys))
|
||
|
|
||
|
//split bucket 2
|
||
|
node19 := mockNodes("@O")
|
||
|
err = rt.addNode(node19)
|
||
|
assert.NoError(t, err)
|
||
|
kadKeys, err = rt.kadBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
nodeKeys, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, 6, len(kadKeys))
|
||
|
assert.Equal(t, 19, len(nodeKeys))
|
||
|
}
|
||
|
|
||
|
func TestCreateOrUpdateKBucket(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
id := []byte{255, 255}
|
||
|
err := rt.createOrUpdateKBucket(storage.Key(id), time.Now())
|
||
|
assert.NoError(t, err)
|
||
|
val, e := rt.kadBucketDB.Get(storage.Key(id))
|
||
|
assert.NotNil(t, val)
|
||
|
assert.NoError(t, e)
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestGetKBucketID(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
|
||
|
kadIDA := storage.Key([]byte{255, 255})
|
||
|
kadIDB := storage.Key([]byte{127, 255})
|
||
|
kadIDC := storage.Key([]byte{63, 255})
|
||
|
now := time.Now()
|
||
|
rt.createOrUpdateKBucket(kadIDA, now)
|
||
|
rt.createOrUpdateKBucket(kadIDB, now)
|
||
|
rt.createOrUpdateKBucket(kadIDC, now)
|
||
|
nodeIDA := []byte{183, 255} //[10110111, 1111111]
|
||
|
nodeIDB := []byte{111, 255} //[01101111, 1111111]
|
||
|
nodeIDC := []byte{47, 255} //[00101111, 1111111]
|
||
|
|
||
|
keyA, _ := rt.getKBucketID(nodeIDA)
|
||
|
assert.Equal(t, kadIDA, keyA)
|
||
|
|
||
|
keyB, _ := rt.getKBucketID(nodeIDB)
|
||
|
assert.Equal(t, kadIDB, keyB)
|
||
|
|
||
|
keyC, _ := rt.getKBucketID(nodeIDC)
|
||
|
assert.Equal(t, kadIDC, keyC)
|
||
|
}
|
||
|
|
||
|
func TestXorTwoIds(t *testing.T) {
|
||
|
x := xorTwoIds([]byte{191}, []byte{159})
|
||
|
assert.Equal(t, []byte{32}, x) //00100000
|
||
|
}
|
||
|
|
||
|
func TestSortByXOR(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
node1 := []byte{127, 255} //xor 0
|
||
|
rt.self.Id = string(node1)
|
||
|
rt.nodeBucketDB.Put(node1, []byte(""))
|
||
|
node2 := []byte{143, 255} //xor 240
|
||
|
rt.nodeBucketDB.Put(node2, []byte(""))
|
||
|
node3 := []byte{255, 255} //xor 128
|
||
|
rt.nodeBucketDB.Put(node3, []byte(""))
|
||
|
node4 := []byte{191, 255} //xor 192
|
||
|
rt.nodeBucketDB.Put(node4, []byte(""))
|
||
|
node5 := []byte{133, 255} //xor 250
|
||
|
rt.nodeBucketDB.Put(node5, []byte(""))
|
||
|
nodes, err := rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
expectedNodes := storage.Keys{node1, node5, node2, node4, node3}
|
||
|
assert.Equal(t, expectedNodes, nodes)
|
||
|
sortedNodes := rt.sortByXOR(nodes)
|
||
|
expectedSorted := storage.Keys{node1, node3, node4, node2, node5}
|
||
|
assert.Equal(t, expectedSorted, sortedNodes)
|
||
|
nodes, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, expectedNodes, nodes)
|
||
|
}
|
||
|
|
||
|
func TestDetermineFurthestIDWithinK(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
node1 := []byte{127, 255} //xor 0
|
||
|
rt.self.Id = string(node1)
|
||
|
rt.nodeBucketDB.Put(node1, []byte(""))
|
||
|
expectedFurthest := node1
|
||
|
nodes, err := rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
furthest, err := rt.determineFurthestIDWithinK(nodes)
|
||
|
assert.Equal(t, expectedFurthest, furthest)
|
||
|
|
||
|
node2 := []byte{143, 255} //xor 240
|
||
|
rt.nodeBucketDB.Put(node2, []byte(""))
|
||
|
expectedFurthest = node2
|
||
|
nodes, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
furthest, err = rt.determineFurthestIDWithinK(nodes)
|
||
|
assert.Equal(t, expectedFurthest, furthest)
|
||
|
|
||
|
node3 := []byte{255, 255} //xor 128
|
||
|
rt.nodeBucketDB.Put(node3, []byte(""))
|
||
|
expectedFurthest = node2
|
||
|
nodes, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
furthest, err = rt.determineFurthestIDWithinK(nodes)
|
||
|
assert.Equal(t, expectedFurthest, furthest)
|
||
|
|
||
|
node4 := []byte{191, 255} //xor 192
|
||
|
rt.nodeBucketDB.Put(node4, []byte(""))
|
||
|
expectedFurthest = node2
|
||
|
nodes, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
furthest, err = rt.determineFurthestIDWithinK(nodes)
|
||
|
assert.Equal(t, expectedFurthest, furthest)
|
||
|
|
||
|
node5 := []byte{133, 255} //xor 250
|
||
|
rt.nodeBucketDB.Put(node5, []byte(""))
|
||
|
expectedFurthest = node5
|
||
|
nodes, err = rt.nodeBucketDB.List(nil, 0)
|
||
|
assert.NoError(t, err)
|
||
|
furthest, err = rt.determineFurthestIDWithinK(nodes)
|
||
|
assert.Equal(t, expectedFurthest, furthest)
|
||
|
}
|
||
|
|
||
|
func TestNodeIsWithinNearestK(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
rt.bucketSize = 2
|
||
|
|
||
|
selfNode := []byte{127, 255}
|
||
|
rt.self.Id = string(selfNode)
|
||
|
rt.nodeBucketDB.Put(selfNode, []byte(""))
|
||
|
expectTrue, err := rt.nodeIsWithinNearestK(selfNode)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, expectTrue)
|
||
|
|
||
|
furthestNode := []byte{143, 255}
|
||
|
expectTrue, err = rt.nodeIsWithinNearestK(furthestNode)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, expectTrue)
|
||
|
rt.nodeBucketDB.Put(furthestNode, []byte(""))
|
||
|
|
||
|
node1 := []byte{255, 255}
|
||
|
expectTrue, err = rt.nodeIsWithinNearestK(node1)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, expectTrue)
|
||
|
rt.nodeBucketDB.Put(node1, []byte(""))
|
||
|
|
||
|
node2 := []byte{191, 255}
|
||
|
expectTrue, err = rt.nodeIsWithinNearestK(node2)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, expectTrue)
|
||
|
rt.nodeBucketDB.Put(node1, []byte(""))
|
||
|
|
||
|
node3 := []byte{133, 255}
|
||
|
expectFalse, err := rt.nodeIsWithinNearestK(node3)
|
||
|
assert.NoError(t, err)
|
||
|
assert.False(t, expectFalse)
|
||
|
}
|
||
|
|
||
|
func TestKadBucketContainsLocalNode(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
kadIDA := storage.Key([]byte{255, 255})
|
||
|
kadIDB := storage.Key([]byte{127, 255})
|
||
|
now := time.Now()
|
||
|
err := rt.createOrUpdateKBucket(kadIDA, now)
|
||
|
assert.NoError(t, err)
|
||
|
err = rt.createOrUpdateKBucket(kadIDB, now)
|
||
|
assert.NoError(t, err)
|
||
|
nodeIDA := []byte{183, 255} //[10110111, 1111111]
|
||
|
err = rt.nodeBucketDB.Put(nodeIDA, []byte(""))
|
||
|
assert.NoError(t, err)
|
||
|
rt.self.Id = string(nodeIDA)
|
||
|
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) {
|
||
|
//valid when kad bucket has >0 nodes in it due to ../storage/boltdb/client.go:99
|
||
|
rt := createRT()
|
||
|
kadIDA := storage.Key([]byte{255, 255})
|
||
|
now := time.Now()
|
||
|
rt.createOrUpdateKBucket(kadIDA, now)
|
||
|
node1 := []byte{255, 255}
|
||
|
node2 := []byte{191, 255}
|
||
|
node3 := []byte{127, 255}
|
||
|
node4 := []byte{63, 255}
|
||
|
node5 := []byte{159, 255}
|
||
|
node6 := []byte{0, 127}
|
||
|
rt.nodeBucketDB.Put(node1, []byte(""))
|
||
|
resultA, err := rt.kadBucketHasRoom(kadIDA)
|
||
|
assert.NoError(t, err)
|
||
|
assert.True(t, resultA)
|
||
|
rt.nodeBucketDB.Put(node2, []byte(""))
|
||
|
rt.nodeBucketDB.Put(node3, []byte(""))
|
||
|
rt.nodeBucketDB.Put(node4, []byte(""))
|
||
|
rt.nodeBucketDB.Put(node5, []byte(""))
|
||
|
rt.nodeBucketDB.Put(node6, []byte(""))
|
||
|
resultB, err := rt.kadBucketHasRoom(kadIDA)
|
||
|
assert.NoError(t, err)
|
||
|
assert.False(t, resultB)
|
||
|
}
|
||
|
|
||
|
func TestGetNodeIDsWithinKBucket(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
kadIDA := storage.Key([]byte{255, 255})
|
||
|
kadIDB := storage.Key([]byte{127, 255})
|
||
|
now := time.Now()
|
||
|
rt.createOrUpdateKBucket(kadIDA, now)
|
||
|
rt.createOrUpdateKBucket(kadIDB, now)
|
||
|
|
||
|
nodeIDA := []byte{183, 255} //[10110111, 1111111]
|
||
|
nodeIDB := []byte{111, 255} //[01101111, 1111111]
|
||
|
nodeIDC := []byte{47, 255} //[00101111, 1111111]
|
||
|
|
||
|
rt.nodeBucketDB.Put(nodeIDA, []byte(""))
|
||
|
rt.nodeBucketDB.Put(nodeIDB, []byte(""))
|
||
|
rt.nodeBucketDB.Put(nodeIDC, []byte(""))
|
||
|
|
||
|
expectedA := storage.Keys{nodeIDA}
|
||
|
expectedB := storage.Keys{nodeIDC, nodeIDB}
|
||
|
|
||
|
A, err := rt.getNodeIDsWithinKBucket(kadIDA)
|
||
|
assert.NoError(t, err)
|
||
|
B, err := rt.getNodeIDsWithinKBucket(kadIDB)
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
assert.Equal(t, expectedA, A)
|
||
|
assert.Equal(t, expectedB, B)
|
||
|
}
|
||
|
|
||
|
func TestGetKBucketRange(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
idA := []byte{255, 255}
|
||
|
idB := []byte{127, 255}
|
||
|
idC := []byte{63, 255}
|
||
|
rt.kadBucketDB.Put(idA, []byte(""))
|
||
|
rt.kadBucketDB.Put(idB, []byte(""))
|
||
|
rt.kadBucketDB.Put(idC, []byte(""))
|
||
|
expectedA := storage.Keys{idB, idA}
|
||
|
expectedB := storage.Keys{idC, idB}
|
||
|
expectedC := storage.Keys{rt.createZeroAsStorageKey(), idC}
|
||
|
|
||
|
endpointsA, err := rt.getKBucketRange(idA)
|
||
|
assert.NoError(t, err)
|
||
|
endpointsB, err := rt.getKBucketRange(idB)
|
||
|
assert.NoError(t, err)
|
||
|
endpointsC, err := rt.getKBucketRange(idC)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, expectedA, endpointsA)
|
||
|
assert.Equal(t, expectedB, endpointsB)
|
||
|
assert.Equal(t, expectedC, endpointsC)
|
||
|
}
|
||
|
|
||
|
func TestCreateFirstBucketID(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
x := rt.createFirstBucketID()
|
||
|
expected := []byte{255, 255}
|
||
|
assert.Equal(t, x, expected)
|
||
|
}
|
||
|
|
||
|
func TestCreateZeroAsStorageKey(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
zero := rt.createZeroAsStorageKey()
|
||
|
expected := []byte{0, 0}
|
||
|
assert.Equal(t, zero, storage.Key(expected))
|
||
|
}
|
||
|
|
||
|
func TestDetermineLeafDepth(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
idA := []byte{255, 255}
|
||
|
idB := []byte{127, 255}
|
||
|
idC := []byte{63, 255}
|
||
|
|
||
|
err := rt.kadBucketDB.Put(idA, []byte(""))
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
first, err := rt.determineLeafDepth(idA)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, first)
|
||
|
|
||
|
err = rt.kadBucketDB.Put(idB, []byte(""))
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
second, err := rt.determineLeafDepth(idB)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, second)
|
||
|
|
||
|
err = rt.kadBucketDB.Put(idC, []byte(""))
|
||
|
assert.NoError(t, err)
|
||
|
|
||
|
one, err := rt.determineLeafDepth(idA)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, one)
|
||
|
|
||
|
two, err := rt.determineLeafDepth(idB)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, two)
|
||
|
|
||
|
alsoTwo, err := rt.determineLeafDepth(idC)
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, alsoTwo)
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestDetermineDifferingBitIndex(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
diff, err := rt.determineDifferingBitIndex([]byte{191, 255}, []byte{255, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{255, 255}, []byte{191, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{95, 255}, []byte{127, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{95, 255}, []byte{79, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 3, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{95, 255}, []byte{63, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{95, 255}, []byte{79, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 3, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{255, 255}, []byte{255, 255})
|
||
|
assert.Error(t, err)
|
||
|
assert.Equal(t, -2, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{255, 255}, []byte{0, 0})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, -1, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{127, 255}, []byte{0, 0})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 0, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{63, 255}, []byte{0, 0})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 1, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{31, 255}, []byte{0, 0})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, diff)
|
||
|
|
||
|
diff, err = rt.determineDifferingBitIndex([]byte{95, 255}, []byte{63, 255})
|
||
|
assert.NoError(t, err)
|
||
|
assert.Equal(t, 2, diff)
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestSplitBucket(t *testing.T) {
|
||
|
rt := createRT()
|
||
|
id1 := []byte{255, 255}
|
||
|
id2 := []byte{191, 255}
|
||
|
id3 := []byte{127, 255}
|
||
|
id4 := []byte{63, 255}
|
||
|
id5 := []byte{159, 255}
|
||
|
id6 := []byte{0, 127}
|
||
|
id7 := []byte{0, 255}
|
||
|
id8 := []byte{95, 255}
|
||
|
id9 := []byte{87, 255}
|
||
|
|
||
|
newID1 := rt.splitBucket(id1, 1) //[11111111, 11111111] -> [10111111, 11111111]
|
||
|
assert.Equal(t, id2, newID1)
|
||
|
|
||
|
newID2 := rt.splitBucket(id2, 2) //[10111111, 11111111] -> [10011111, 11111111]
|
||
|
assert.Equal(t, id5, newID2)
|
||
|
|
||
|
newID3 := rt.splitBucket(id3, 1) //[01111111, 11111111] -> [00111111, 11111111]
|
||
|
assert.Equal(t, id4, newID3)
|
||
|
|
||
|
newID4 := rt.splitBucket(id7, 8) //[00000000, 11111111] -> [00000000, 01111111]
|
||
|
assert.Equal(t, id6, newID4)
|
||
|
|
||
|
newID5 := rt.splitBucket(id8, 4) //[01011111, 11111111] -> [01010111, 11111111]
|
||
|
assert.Equal(t, id9, newID5)
|
||
|
|
||
|
newID6 := rt.splitBucket(id8, 3)
|
||
|
assert.Equal(t, []byte{79, 255}, newID6)
|
||
|
}
|