2020-07-27 13:22:00 +01:00
|
|
|
package mucp
|
2019-09-10 18:32:25 +01:00
|
|
|
|
2019-09-11 00:23:37 +01:00
|
|
|
import (
|
|
|
|
"testing"
|
2019-09-13 03:02:20 +01:00
|
|
|
"time"
|
2019-09-11 18:56:28 +01:00
|
|
|
|
2020-07-27 13:22:00 +01:00
|
|
|
"github.com/micro/go-micro/v3/network"
|
|
|
|
pb "github.com/micro/go-micro/v3/network/mucp/proto"
|
2019-09-11 00:23:37 +01:00
|
|
|
)
|
2019-09-10 18:32:25 +01:00
|
|
|
|
|
|
|
var (
|
|
|
|
testNodeId = "testNode"
|
|
|
|
testNodeAddress = "testAddress"
|
|
|
|
testNodeNetName = "testNetwork"
|
|
|
|
testNodePeerIds = []string{"peer1", "peer2", "peer3"}
|
|
|
|
testPeerOfPeerIds = []string{"peer11", "peer12"}
|
|
|
|
)
|
|
|
|
|
|
|
|
func testSetup() *node {
|
|
|
|
testNode := &node{
|
|
|
|
id: testNodeId,
|
|
|
|
address: testNodeAddress,
|
|
|
|
peers: make(map[string]*node),
|
2020-07-27 13:22:00 +01:00
|
|
|
network: NewNetwork(network.Name(testNodeNetName)),
|
2020-01-14 18:22:58 +00:00
|
|
|
status: newStatus(),
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// add some peers to the node
|
|
|
|
for _, id := range testNodePeerIds {
|
|
|
|
testNode.peers[id] = &node{
|
|
|
|
id: id,
|
|
|
|
address: testNode.address + "-" + id,
|
|
|
|
peers: make(map[string]*node),
|
|
|
|
network: testNode.network,
|
2020-01-14 18:22:58 +00:00
|
|
|
status: newStatus(),
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// add peers to peer1
|
|
|
|
// NOTE: these are peers of peers!
|
|
|
|
for _, id := range testPeerOfPeerIds {
|
|
|
|
testNode.peers["peer1"].peers[id] = &node{
|
|
|
|
id: id,
|
|
|
|
address: testNode.address + "-" + id,
|
|
|
|
peers: make(map[string]*node),
|
|
|
|
network: testNode.network,
|
2020-01-14 18:22:58 +00:00
|
|
|
status: newStatus(),
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// connect peer1 with peer2
|
|
|
|
testNode.peers["peer1"].peers["peer2"] = testNode.peers["peer2"]
|
|
|
|
// connect peer2 with peer3
|
|
|
|
testNode.peers["peer2"].peers["peer3"] = testNode.peers["peer3"]
|
|
|
|
|
|
|
|
return testNode
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodeId(t *testing.T) {
|
|
|
|
node := testSetup()
|
|
|
|
if node.Id() != testNodeId {
|
|
|
|
t.Errorf("Expected id: %s, found: %s", testNodeId, node.Id())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodeAddress(t *testing.T) {
|
|
|
|
node := testSetup()
|
|
|
|
if node.Address() != testNodeAddress {
|
|
|
|
t.Errorf("Expected address: %s, found: %s", testNodeAddress, node.Address())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func TestNodeNetwork(t *testing.T) {
|
|
|
|
node := testSetup()
|
|
|
|
if node.Network().Name() != testNodeNetName {
|
|
|
|
t.Errorf("Expected network: %s, found: %s", testNodeNetName, node.Network().Name())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestNodes(t *testing.T) {
|
|
|
|
// single node
|
|
|
|
single := &node{
|
|
|
|
id: testNodeId,
|
|
|
|
address: testNodeAddress,
|
|
|
|
peers: make(map[string]*node),
|
2020-07-27 13:22:00 +01:00
|
|
|
network: NewNetwork(network.Name(testNodeNetName)),
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
// get all the nodes including yourself
|
|
|
|
nodes := single.Nodes()
|
|
|
|
nodeCount := 1
|
|
|
|
|
|
|
|
if len(nodes) != nodeCount {
|
|
|
|
t.Errorf("Expected to find %d nodes, found: %d", nodeCount, len(nodes))
|
|
|
|
}
|
|
|
|
|
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
|
|
|
// get all the nodes including yourself
|
|
|
|
nodes = node.Nodes()
|
|
|
|
|
|
|
|
// compile a list of ids of all nodes in the network into map for easy indexing
|
|
|
|
nodeIds := make(map[string]bool)
|
|
|
|
// add yourself
|
|
|
|
nodeIds[node.id] = true
|
|
|
|
// add peer Ids
|
|
|
|
for _, id := range testNodePeerIds {
|
|
|
|
nodeIds[id] = true
|
|
|
|
}
|
|
|
|
// add peer1 peers i.e. peers of peer
|
|
|
|
for _, id := range testPeerOfPeerIds {
|
|
|
|
nodeIds[id] = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// we should return the correct number of nodes
|
|
|
|
if len(nodes) != len(nodeIds) {
|
|
|
|
t.Errorf("Expected %d nodes, found: %d", len(nodeIds), len(nodes))
|
|
|
|
}
|
|
|
|
|
|
|
|
// iterate through the list of nodes and makes sure all have been returned
|
|
|
|
for _, node := range nodes {
|
|
|
|
if _, ok := nodeIds[node.Id()]; !ok {
|
|
|
|
t.Errorf("Expected to find %s node", node.Id())
|
|
|
|
}
|
|
|
|
}
|
2019-09-13 18:46:24 +01:00
|
|
|
|
|
|
|
// this is a leaf node
|
|
|
|
id := "peer11"
|
|
|
|
if nodePeer := node.GetPeerNode(id); nodePeer == nil {
|
|
|
|
t.Errorf("Expected to find %s node", id)
|
|
|
|
}
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
|
2020-07-27 13:22:00 +01:00
|
|
|
func collectPeerIds(peer network.Node, ids map[string]bool) map[string]bool {
|
2019-09-11 23:03:27 +01:00
|
|
|
if len(peer.Peers()) == 0 {
|
2019-09-11 01:22:40 +01:00
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
|
|
|
// iterate through the whole graph
|
2019-09-11 23:03:27 +01:00
|
|
|
for _, peer := range peer.Peers() {
|
|
|
|
ids = collectPeerIds(peer, ids)
|
|
|
|
if _, ok := ids[peer.Id()]; !ok {
|
|
|
|
ids[peer.Id()] = true
|
2019-09-11 01:22:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ids
|
|
|
|
}
|
|
|
|
|
2019-09-11 23:03:27 +01:00
|
|
|
func TestPeers(t *testing.T) {
|
2019-09-10 18:32:25 +01:00
|
|
|
// single node
|
|
|
|
single := &node{
|
|
|
|
id: testNodeId,
|
|
|
|
address: testNodeAddress,
|
|
|
|
peers: make(map[string]*node),
|
2020-07-27 13:22:00 +01:00
|
|
|
network: NewNetwork(network.Name(testNodeNetName)),
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
2019-09-11 23:03:27 +01:00
|
|
|
// get node peers
|
|
|
|
peers := single.Peers()
|
|
|
|
// there should be no peers
|
|
|
|
peerCount := 0
|
2019-09-10 18:32:25 +01:00
|
|
|
|
2019-09-11 23:03:27 +01:00
|
|
|
if len(peers) != peerCount {
|
|
|
|
t.Errorf("Expected to find %d nodes, found: %d", peerCount, len(peers))
|
2019-09-11 00:23:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
2019-09-11 23:03:27 +01:00
|
|
|
// list of ids of nodes of MaxDepth
|
2019-09-11 00:23:37 +01:00
|
|
|
peerIds := make(map[string]bool)
|
|
|
|
// add peer Ids
|
|
|
|
for _, id := range testNodePeerIds {
|
|
|
|
peerIds[id] = true
|
|
|
|
}
|
|
|
|
// add peers of peers to peerIds
|
|
|
|
for _, id := range testPeerOfPeerIds {
|
|
|
|
peerIds[id] = true
|
|
|
|
}
|
2019-09-11 23:03:27 +01:00
|
|
|
// get node peers
|
|
|
|
peers = node.Peers()
|
2019-09-11 00:23:37 +01:00
|
|
|
|
2019-09-11 23:03:27 +01:00
|
|
|
// we will collect all returned Peer Ids into this map
|
|
|
|
resPeerIds := make(map[string]bool)
|
|
|
|
for _, peer := range peers {
|
|
|
|
resPeerIds[peer.Id()] = true
|
|
|
|
resPeerIds = collectPeerIds(peer, resPeerIds)
|
|
|
|
}
|
2019-09-11 01:22:40 +01:00
|
|
|
|
2019-09-11 23:03:27 +01:00
|
|
|
// if correct, we must collect all peerIds
|
|
|
|
if len(resPeerIds) != len(peerIds) {
|
|
|
|
t.Errorf("Expected to find %d peers, found: %d", len(peerIds), len(resPeerIds))
|
2019-09-11 01:22:40 +01:00
|
|
|
}
|
|
|
|
|
2019-09-11 23:03:27 +01:00
|
|
|
for id := range resPeerIds {
|
|
|
|
if _, ok := peerIds[id]; !ok {
|
2019-09-11 01:22:40 +01:00
|
|
|
t.Errorf("Expected to find %s peer", id)
|
2019-09-11 00:23:37 +01:00
|
|
|
}
|
2019-09-10 18:32:25 +01:00
|
|
|
}
|
|
|
|
}
|
2019-09-11 18:56:28 +01:00
|
|
|
|
2019-09-16 19:22:55 +01:00
|
|
|
func TestDeletePeerNode(t *testing.T) {
|
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
|
|
|
|
|
|
|
nodeCount := len(node.Nodes())
|
|
|
|
|
|
|
|
// should not find non-existent peer node
|
|
|
|
if err := node.DeletePeerNode("foobar"); err != ErrPeerNotFound {
|
|
|
|
t.Errorf("Expected: %v, got: %v", ErrPeerNotFound, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// lets pick one of the peer1 peers
|
|
|
|
if err := node.DeletePeerNode(testPeerOfPeerIds[0]); err != nil {
|
|
|
|
t.Errorf("Error deleting peer node: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeDelCount := len(node.Nodes())
|
|
|
|
|
|
|
|
if nodeDelCount != nodeCount-1 {
|
|
|
|
t.Errorf("Expected node count: %d, got: %d", nodeCount-1, nodeDelCount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-13 20:02:56 +00:00
|
|
|
func TestPrunePeer(t *testing.T) {
|
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
|
|
|
|
|
|
|
before := node.Nodes()
|
|
|
|
|
|
|
|
node.PrunePeer("peer3")
|
|
|
|
|
|
|
|
now := node.Nodes()
|
|
|
|
|
|
|
|
if len(now) != len(before)-1 {
|
|
|
|
t.Errorf("Expected pruned node count: %d, got: %d", len(before)-1, len(now))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestPruneStalePeers(t *testing.T) {
|
2019-09-16 19:22:55 +01:00
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
|
|
|
nodes := node.Nodes()
|
2020-01-14 10:49:34 +00:00
|
|
|
// this will delete all nodes besides the root node
|
2019-09-16 19:22:55 +01:00
|
|
|
pruneTime := 10 * time.Millisecond
|
|
|
|
time.Sleep(pruneTime)
|
|
|
|
|
2020-01-13 20:02:56 +00:00
|
|
|
// should delete all nodes besides (root) node
|
2019-12-07 19:54:29 +00:00
|
|
|
pruned := node.PruneStalePeers(pruneTime)
|
2019-09-16 19:22:55 +01:00
|
|
|
|
|
|
|
if len(pruned) != len(nodes)-1 {
|
|
|
|
t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-1, len(pruned))
|
|
|
|
}
|
2020-01-14 10:49:34 +00:00
|
|
|
|
|
|
|
// complicated node graph
|
|
|
|
node = testSetup()
|
|
|
|
nodes = node.Nodes()
|
|
|
|
|
|
|
|
// set prune time to 100ms and wait for half of it
|
|
|
|
pruneTime = 100 * time.Millisecond
|
|
|
|
time.Sleep(pruneTime)
|
|
|
|
|
|
|
|
// update the time of peer1
|
|
|
|
node.peers["peer1"].lastSeen = time.Now()
|
|
|
|
|
|
|
|
// should prune all but the root nodes and peer1
|
|
|
|
pruned = node.PruneStalePeers(pruneTime)
|
|
|
|
|
|
|
|
if len(pruned) != len(nodes)-2 {
|
|
|
|
t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-2, len(pruned))
|
|
|
|
}
|
2019-09-16 19:22:55 +01:00
|
|
|
}
|
|
|
|
|
2019-09-13 03:02:20 +01:00
|
|
|
func TestUnpackPeerTopology(t *testing.T) {
|
2019-09-11 18:56:28 +01:00
|
|
|
pbPeer := &pb.Peer{
|
|
|
|
Node: &pb.Node{
|
|
|
|
Id: "newPeer",
|
|
|
|
Address: "newPeerAddress",
|
2020-01-14 18:22:58 +00:00
|
|
|
Status: &pb.Status{
|
|
|
|
Error: &pb.Error{},
|
|
|
|
},
|
2019-09-11 18:56:28 +01:00
|
|
|
},
|
|
|
|
Peers: make([]*pb.Peer, 0),
|
|
|
|
}
|
|
|
|
// it should add pbPeer to the single node peers
|
2019-09-13 03:02:20 +01:00
|
|
|
peer := UnpackPeerTopology(pbPeer, time.Now(), 5)
|
|
|
|
if peer.id != pbPeer.Node.Id {
|
|
|
|
t.Errorf("Expected peer id %s, found: %s", pbPeer.Node.Id, peer.id)
|
2019-09-11 18:56:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
node := testSetup()
|
|
|
|
// build a simple topology to update node peer1
|
|
|
|
peer1 := node.peers["peer1"]
|
|
|
|
pbPeer1Node := &pb.Node{
|
|
|
|
Id: peer1.id,
|
|
|
|
Address: peer1.address,
|
2020-01-14 18:22:58 +00:00
|
|
|
Status: &pb.Status{
|
|
|
|
Error: &pb.Error{},
|
|
|
|
},
|
2019-09-11 18:56:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pbPeer111 := &pb.Peer{
|
|
|
|
Node: &pb.Node{
|
|
|
|
Id: "peer111",
|
|
|
|
Address: "peer111Address",
|
2020-01-14 18:22:58 +00:00
|
|
|
Status: &pb.Status{
|
|
|
|
Error: &pb.Error{},
|
|
|
|
},
|
2019-09-11 18:56:28 +01:00
|
|
|
},
|
|
|
|
Peers: make([]*pb.Peer, 0),
|
|
|
|
}
|
|
|
|
|
|
|
|
pbPeer121 := &pb.Peer{
|
|
|
|
Node: &pb.Node{
|
|
|
|
Id: "peer121",
|
|
|
|
Address: "peer121Address",
|
2020-01-14 18:22:58 +00:00
|
|
|
Status: &pb.Status{
|
|
|
|
Error: &pb.Error{},
|
|
|
|
},
|
2019-09-11 18:56:28 +01:00
|
|
|
},
|
|
|
|
Peers: make([]*pb.Peer, 0),
|
|
|
|
}
|
|
|
|
// topology to update
|
|
|
|
pbPeer1 := &pb.Peer{
|
|
|
|
Node: pbPeer1Node,
|
|
|
|
Peers: []*pb.Peer{pbPeer111, pbPeer121},
|
|
|
|
}
|
2019-09-13 03:02:20 +01:00
|
|
|
// unpack peer1 topology
|
|
|
|
peer = UnpackPeerTopology(pbPeer1, time.Now(), 5)
|
2019-09-11 18:56:28 +01:00
|
|
|
// make sure peer1 topology has been correctly updated
|
|
|
|
newPeerIds := []string{pbPeer111.Node.Id, pbPeer121.Node.Id}
|
|
|
|
for _, id := range newPeerIds {
|
2019-09-13 03:02:20 +01:00
|
|
|
if _, ok := peer.peers[id]; !ok {
|
2019-09-11 18:56:28 +01:00
|
|
|
t.Errorf("Expected %s to be a peer of %s", id, "peer1")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-11 23:56:57 +01:00
|
|
|
func TestPeersToProto(t *testing.T) {
|
2019-09-11 18:56:28 +01:00
|
|
|
// single node
|
|
|
|
single := &node{
|
|
|
|
id: testNodeId,
|
|
|
|
address: testNodeAddress,
|
|
|
|
peers: make(map[string]*node),
|
2020-07-27 13:22:00 +01:00
|
|
|
network: NewNetwork(network.Name(testNodeNetName)),
|
2020-01-14 18:22:58 +00:00
|
|
|
status: newStatus(),
|
2019-09-11 18:56:28 +01:00
|
|
|
}
|
|
|
|
topCount := 0
|
|
|
|
|
2019-09-13 03:02:20 +01:00
|
|
|
protoPeers := PeersToProto(single, 0)
|
2019-09-11 23:19:29 +01:00
|
|
|
|
2019-09-11 23:56:57 +01:00
|
|
|
if len(protoPeers.Peers) != topCount {
|
|
|
|
t.Errorf("Expected to find %d nodes, found: %d", topCount, len(protoPeers.Peers))
|
2019-09-11 18:56:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// complicated node graph
|
|
|
|
node := testSetup()
|
|
|
|
topCount = 3
|
|
|
|
// list of ids of nodes of depth 1 i.e. node peers
|
|
|
|
peerIds := make(map[string]bool)
|
|
|
|
// add peer Ids
|
|
|
|
for _, id := range testNodePeerIds {
|
|
|
|
peerIds[id] = true
|
|
|
|
}
|
|
|
|
// depth 1 should give us immmediate neighbours only
|
2019-09-13 03:02:20 +01:00
|
|
|
protoPeers = PeersToProto(node, 1)
|
2019-09-11 23:19:29 +01:00
|
|
|
|
2019-09-11 23:56:57 +01:00
|
|
|
if len(protoPeers.Peers) != topCount {
|
|
|
|
t.Errorf("Expected to find %d nodes, found: %d", topCount, len(protoPeers.Peers))
|
2019-09-11 18:56:28 +01:00
|
|
|
}
|
|
|
|
}
|