lnd.xprv/routing/manager_test.go

240 lines
6.1 KiB
Go
Raw Normal View History

// 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()
}