lnd.xprv/routing/manager_test.go
BitfuryLightning 327768f4ad routing: Move tools inside lnd. Refactor and delete unneeded stuff
Use [33]byte for graph vertex representation.
Delete unneeded stuff:
1. DeepEqual for graph comparison
2. EdgePath
3. 2-thread BFS
4. Table transfer messages and neighborhood radius
5. Beacons

Refactor:
1. Change ID to Vertex
2. Test use table driven approach
3. Add comments
4. Make graph internal representation private
5. Use wire.OutPoint as  EdgeId
6. Decouple routing messages from routing implementation
7. Delete Async methods
8. Delete unneeded channels and priority buffer from manager
9. Delete unneeded interfaces in internal graph realisation
10. Renamed ID to Vertex
2016-11-23 20:37:43 -06:00

240 lines
6.1 KiB
Go

// Copyright (c) 2016 Bitfury Group Limited
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php
package routing
import (
"fmt"
"github.com/lightningnetwork/lnd/routing/rt/graph"
"reflect"
"testing"
"time"
)
func abs(x int) int {
if x < 0 {
return -x
}
return x
}
func vertexFromInt(x int) graph.Vertex {
s := fmt.Sprintf("%v", x)
return graph.NewVertex([]byte(s))
}
func edgeIdFromString(s string) graph.EdgeID {
e := graph.EdgeID{}
copy(e.Hash[:], []byte(s))
return e
}
var sampleEdgeId graph.EdgeID = edgeIdFromString("EdgeId")
func createLinearNetwork(n int) (*MockNetwork, []*RoutingManager) {
// Creates linear graph 0->1->2->..->n-1
nodes := make([]*RoutingManager, 0)
net := NewMockNetwork(false)
net.Start()
for i := 0; i < n; i++ {
node := NewRoutingManager(vertexFromInt(i), nil)
nodes = append(nodes, node)
node.Start()
net.Add(node)
}
for i := 0; i < n-1; i++ {
nodes[i].OpenChannel(nodes[i+1].Id, sampleEdgeId, nil)
nodes[i+1].OpenChannel(nodes[i].Id, sampleEdgeId, nil)
}
return net, nodes
}
func createCompleteNetwork(n int) (*MockNetwork, []*RoutingManager) {
nodes := make([]*RoutingManager, 0)
net := NewMockNetwork(false)
net.Start()
for i := 0; i < n; i++ {
node := NewRoutingManager(vertexFromInt(i), nil)
nodes = append(nodes, node)
node.Start()
net.Add(node)
}
for i := 0; i < n-1; i++ {
for j := i + 1; j < n; j++ {
nodes[i].OpenChannel(nodes[j].Id, sampleEdgeId, nil)
nodes[j].OpenChannel(nodes[i].Id, sampleEdgeId, nil)
}
}
return net, nodes
}
func createNetwork(desc [][2]int, idFunc func(int) graph.Vertex) (*MockNetwork, map[int]*RoutingManager, []graph.Edge) {
// Creates network of nodes from graph description
net := NewMockNetwork(false)
net.Start()
// create unique nodes
nodes := make(map[int]*RoutingManager)
for i := 0; i < len(desc); i++ {
for j := 0; j < 2; j++ {
nodeId := desc[i][j]
if _, ok := nodes[nodeId]; !ok {
var id graph.Vertex
if idFunc != nil {
id = idFunc(nodeId)
} else {
id = vertexFromInt(nodeId)
}
node := NewRoutingManager(id, nil)
nodes[nodeId] = node
node.Start()
net.Add(node)
}
}
}
edges := make([]graph.Edge, 0, len(desc))
for i := 0; i < len(desc); i++ {
edgeID := edgeIdFromString(fmt.Sprintf("edge-%v", i))
nodes[desc[i][0]].OpenChannel(nodes[desc[i][1]].Id, edgeID, &graph.ChannelInfo{1, 1})
nodes[desc[i][1]].OpenChannel(nodes[desc[i][0]].Id, edgeID, &graph.ChannelInfo{1, 1})
edges = append(edges, graph.NewEdge(
nodes[desc[i][0]].Id,
nodes[desc[i][1]].Id,
edgeID,
&graph.ChannelInfo{1, 1},
))
}
return net, nodes, edges
}
func TestNeighborsScanLinearGraph(t *testing.T) {
n := 4
net, nodes := createLinearNetwork(n)
time.Sleep(10 * time.Millisecond)
// Each node should know about all channels
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
for k := 0; k < n; k++ {
ans := nodes[i].HasChannel(nodes[j].Id, nodes[k].Id, sampleEdgeId)
correctAns := abs(j-k) == 1
if ans != correctAns {
t.Errorf("nodes[%v].HasChannel(%v, %v)==%v, want %v", i, j, k, ans, correctAns)
}
}
}
}
net.Stop()
}
func TestNeighborsScanCompleteGraph(t *testing.T) {
n := 4
net, nodes := createCompleteNetwork(n)
time.Sleep(10 * time.Millisecond)
// Each node should know about all channels
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
for k := 0; k < n; k++ {
ans := nodes[i].HasChannel(nodes[j].Id, nodes[k].Id, sampleEdgeId)
correctAns := j != k
if ans != correctAns {
t.Errorf("nodes[%v].HasChannel(%v, %v)==%v, want %v", i, j, k, ans, correctAns)
}
}
}
}
net.Stop()
}
func TestNeighborsRemoveChannel(t *testing.T) {
// Create complete graph, than delete channels to make it linear
n := 4
net, nodes := createCompleteNetwork(n)
time.Sleep(10 * time.Millisecond)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
if abs(i-j) != 1 {
nodes[i].RemoveChannel(nodes[i].Id, nodes[j].Id, sampleEdgeId)
}
}
}
time.Sleep(10 * time.Millisecond)
// Each node should know about all channels
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
for k := 0; k < n; k++ {
ans := nodes[i].HasChannel(nodes[j].Id, nodes[k].Id, sampleEdgeId)
correctAns := abs(j-k) == 1
if ans != correctAns {
t.Errorf("nodes[%v].HasChannel(%v, %v)==%v, want %v", i, j, k, ans, correctAns)
}
}
}
}
net.Stop()
}
func TestFindPath(t *testing.T) {
// Create linear graph
n := 6
net, nodes := createLinearNetwork(n)
time.Sleep(10 * time.Millisecond) // Each node should know about all channels
path, err := nodes[0].FindPath(nodes[5].Id)
if err != nil {
t.Errorf("err = %v, want %v", err)
}
correctPath := []graph.Vertex{}
for i := 0; i < n; i++ {
correctPath = append(correctPath, nodes[i].Id)
}
if !reflect.DeepEqual(path, correctPath) {
t.Errorf("path = %v, want %v", path, correctPath)
}
// Case when path do not exist
path, err = nodes[0].FindPath(vertexFromInt(7))
if path != nil {
t.Errorf("path = %v, want %v", path, nil)
}
if err != graph.PathNotFoundError {
t.Errorf("err = %v, want %v", err, graph.PathNotFoundError)
}
net.Stop()
}
func TestKShortestPaths(t *testing.T) {
net, nodes, _ := createNetwork([][2]int{
[2]int{0, 1},
[2]int{1, 2},
[2]int{2, 3},
[2]int{1, 3},
[2]int{4, 5},
}, nil)
time.Sleep(10 * time.Millisecond) // Each node should know about all channels
// There was bug in lnd when second search of the same path leads to lncli/lnd freeze
for iter := 1; iter <= 3; iter++ {
paths, err := nodes[0].FindKShortestPaths(nodes[3].Id, 2)
if err != nil {
t.Errorf("err = %v, want %v", err, nil)
}
correctPaths := [][]graph.Vertex{
[]graph.Vertex{vertexFromInt(0), vertexFromInt(1), vertexFromInt(3)},
[]graph.Vertex{vertexFromInt(0), vertexFromInt(1), vertexFromInt(2), vertexFromInt(3)},
}
if !reflect.DeepEqual(paths, correctPaths) {
t.Errorf("on iteration: %v paths = %v, want %v", iter, paths, correctPaths)
}
}
// Case when path do not exist
paths, _ := nodes[0].FindKShortestPaths(vertexFromInt(7), 3)
if len(paths) != 0 {
t.Errorf("path = %v, want %v", paths, []graph.Vertex{})
}
net.Stop()
}