github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/network/mucp/node_test.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/tickoalcantara12/micro/v3/service/network/mucp/mucp_test.go
    14  
    15  package mucp
    16  
    17  import (
    18  	"testing"
    19  	"time"
    20  
    21  	"github.com/tickoalcantara12/micro/v3/service/network"
    22  	pb "github.com/tickoalcantara12/micro/v3/service/network/mucp/proto"
    23  )
    24  
    25  var (
    26  	testNodeId        = "testNode"
    27  	testNodeAddress   = "testAddress"
    28  	testNodeNetName   = "testNetwork"
    29  	testNodePeerIds   = []string{"peer1", "peer2", "peer3"}
    30  	testPeerOfPeerIds = []string{"peer11", "peer12"}
    31  )
    32  
    33  func testSetup() *node {
    34  	testNode := &node{
    35  		id:      testNodeId,
    36  		address: testNodeAddress,
    37  		peers:   make(map[string]*node),
    38  		network: NewNetwork(network.Name(testNodeNetName)),
    39  		status:  newStatus(),
    40  	}
    41  
    42  	// add some peers to the node
    43  	for _, id := range testNodePeerIds {
    44  		testNode.peers[id] = &node{
    45  			id:      id,
    46  			address: testNode.address + "-" + id,
    47  			peers:   make(map[string]*node),
    48  			network: testNode.network,
    49  			status:  newStatus(),
    50  		}
    51  	}
    52  
    53  	// add peers to peer1
    54  	// NOTE: these are peers of peers!
    55  	for _, id := range testPeerOfPeerIds {
    56  		testNode.peers["peer1"].peers[id] = &node{
    57  			id:      id,
    58  			address: testNode.address + "-" + id,
    59  			peers:   make(map[string]*node),
    60  			network: testNode.network,
    61  			status:  newStatus(),
    62  		}
    63  	}
    64  
    65  	// connect peer1 with peer2
    66  	testNode.peers["peer1"].peers["peer2"] = testNode.peers["peer2"]
    67  	// connect peer2 with peer3
    68  	testNode.peers["peer2"].peers["peer3"] = testNode.peers["peer3"]
    69  
    70  	return testNode
    71  }
    72  
    73  func TestNodeId(t *testing.T) {
    74  	node := testSetup()
    75  	if node.Id() != testNodeId {
    76  		t.Errorf("Expected id: %s, found: %s", testNodeId, node.Id())
    77  	}
    78  }
    79  
    80  func TestNodeAddress(t *testing.T) {
    81  	node := testSetup()
    82  	if node.Address() != testNodeAddress {
    83  		t.Errorf("Expected address: %s, found: %s", testNodeAddress, node.Address())
    84  	}
    85  }
    86  func TestNodeNetwork(t *testing.T) {
    87  	node := testSetup()
    88  	if node.Network().Name() != testNodeNetName {
    89  		t.Errorf("Expected network: %s, found: %s", testNodeNetName, node.Network().Name())
    90  	}
    91  }
    92  
    93  func TestNodes(t *testing.T) {
    94  	// single node
    95  	single := &node{
    96  		id:      testNodeId,
    97  		address: testNodeAddress,
    98  		peers:   make(map[string]*node),
    99  		network: NewNetwork(network.Name(testNodeNetName)),
   100  	}
   101  	// get all the nodes including yourself
   102  	nodes := single.Nodes()
   103  	nodeCount := 1
   104  
   105  	if len(nodes) != nodeCount {
   106  		t.Errorf("Expected to find %d nodes, found: %d", nodeCount, len(nodes))
   107  	}
   108  
   109  	// complicated node graph
   110  	node := testSetup()
   111  	// get all the nodes including yourself
   112  	nodes = node.Nodes()
   113  
   114  	// compile a list of ids of all nodes in the network into map for easy indexing
   115  	nodeIds := make(map[string]bool)
   116  	// add yourself
   117  	nodeIds[node.id] = true
   118  	// add peer Ids
   119  	for _, id := range testNodePeerIds {
   120  		nodeIds[id] = true
   121  	}
   122  	// add peer1 peers i.e. peers of peer
   123  	for _, id := range testPeerOfPeerIds {
   124  		nodeIds[id] = true
   125  	}
   126  
   127  	// we should return the correct number of nodes
   128  	if len(nodes) != len(nodeIds) {
   129  		t.Errorf("Expected %d nodes, found: %d", len(nodeIds), len(nodes))
   130  	}
   131  
   132  	// iterate through the list of nodes and makes sure all have been returned
   133  	for _, node := range nodes {
   134  		if _, ok := nodeIds[node.Id()]; !ok {
   135  			t.Errorf("Expected to find %s node", node.Id())
   136  		}
   137  	}
   138  
   139  	// this is a leaf node
   140  	id := "peer11"
   141  	if nodePeer := node.GetPeerNode(id); nodePeer == nil {
   142  		t.Errorf("Expected to find %s node", id)
   143  	}
   144  }
   145  
   146  func collectPeerIds(peer network.Node, ids map[string]bool) map[string]bool {
   147  	if len(peer.Peers()) == 0 {
   148  		return ids
   149  	}
   150  
   151  	// iterate through the whole graph
   152  	for _, peer := range peer.Peers() {
   153  		ids = collectPeerIds(peer, ids)
   154  		if _, ok := ids[peer.Id()]; !ok {
   155  			ids[peer.Id()] = true
   156  		}
   157  	}
   158  
   159  	return ids
   160  }
   161  
   162  func TestPeers(t *testing.T) {
   163  	// single node
   164  	single := &node{
   165  		id:      testNodeId,
   166  		address: testNodeAddress,
   167  		peers:   make(map[string]*node),
   168  		network: NewNetwork(network.Name(testNodeNetName)),
   169  	}
   170  	// get node peers
   171  	peers := single.Peers()
   172  	// there should be no peers
   173  	peerCount := 0
   174  
   175  	if len(peers) != peerCount {
   176  		t.Errorf("Expected to find %d nodes, found: %d", peerCount, len(peers))
   177  	}
   178  
   179  	// complicated node graph
   180  	node := testSetup()
   181  	// list of ids of nodes of MaxDepth
   182  	peerIds := make(map[string]bool)
   183  	// add peer Ids
   184  	for _, id := range testNodePeerIds {
   185  		peerIds[id] = true
   186  	}
   187  	// add peers of peers to peerIds
   188  	for _, id := range testPeerOfPeerIds {
   189  		peerIds[id] = true
   190  	}
   191  	// get node peers
   192  	peers = node.Peers()
   193  
   194  	// we will collect all returned Peer Ids into this map
   195  	resPeerIds := make(map[string]bool)
   196  	for _, peer := range peers {
   197  		resPeerIds[peer.Id()] = true
   198  		resPeerIds = collectPeerIds(peer, resPeerIds)
   199  	}
   200  
   201  	// if correct, we must collect all peerIds
   202  	if len(resPeerIds) != len(peerIds) {
   203  		t.Errorf("Expected to find %d peers, found: %d", len(peerIds), len(resPeerIds))
   204  	}
   205  
   206  	for id := range resPeerIds {
   207  		if _, ok := peerIds[id]; !ok {
   208  			t.Errorf("Expected to find %s peer", id)
   209  		}
   210  	}
   211  }
   212  
   213  func TestDeletePeerNode(t *testing.T) {
   214  	// complicated node graph
   215  	node := testSetup()
   216  
   217  	nodeCount := len(node.Nodes())
   218  
   219  	// should not find non-existent peer node
   220  	if err := node.DeletePeerNode("foobar"); err != ErrPeerNotFound {
   221  		t.Errorf("Expected: %v, got: %v", ErrPeerNotFound, err)
   222  	}
   223  
   224  	// lets pick one of the peer1 peers
   225  	if err := node.DeletePeerNode(testPeerOfPeerIds[0]); err != nil {
   226  		t.Errorf("Error deleting peer node: %v", err)
   227  	}
   228  
   229  	nodeDelCount := len(node.Nodes())
   230  
   231  	if nodeDelCount != nodeCount-1 {
   232  		t.Errorf("Expected node count: %d, got: %d", nodeCount-1, nodeDelCount)
   233  	}
   234  }
   235  
   236  func TestPrunePeer(t *testing.T) {
   237  	// complicated node graph
   238  	node := testSetup()
   239  
   240  	before := node.Nodes()
   241  
   242  	node.PrunePeer("peer3")
   243  
   244  	now := node.Nodes()
   245  
   246  	if len(now) != len(before)-1 {
   247  		t.Errorf("Expected pruned node count: %d, got: %d", len(before)-1, len(now))
   248  	}
   249  }
   250  
   251  func TestPruneStalePeers(t *testing.T) {
   252  	// complicated node graph
   253  	node := testSetup()
   254  	nodes := node.Nodes()
   255  	// this will delete all nodes besides the root node
   256  	pruneTime := 10 * time.Millisecond
   257  	time.Sleep(pruneTime)
   258  
   259  	// should delete all nodes besides (root) node
   260  	pruned := node.PruneStalePeers(pruneTime)
   261  
   262  	if len(pruned) != len(nodes)-1 {
   263  		t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-1, len(pruned))
   264  	}
   265  
   266  	// complicated node graph
   267  	node = testSetup()
   268  	nodes = node.Nodes()
   269  
   270  	// set prune time to 100ms and wait for half of it
   271  	pruneTime = 100 * time.Millisecond
   272  	time.Sleep(pruneTime)
   273  
   274  	// update the time of peer1
   275  	node.peers["peer1"].lastSeen = time.Now()
   276  
   277  	// should prune all but the root nodes and peer1
   278  	pruned = node.PruneStalePeers(pruneTime)
   279  
   280  	if len(pruned) != len(nodes)-2 {
   281  		t.Errorf("Expected pruned node count: %d, got: %d", len(nodes)-2, len(pruned))
   282  	}
   283  }
   284  
   285  func TestUnpackPeerTopology(t *testing.T) {
   286  	pbPeer := &pb.Peer{
   287  		Node: &pb.Node{
   288  			Id:      "newPeer",
   289  			Address: "newPeerAddress",
   290  			Status: &pb.Status{
   291  				Error: &pb.Error{},
   292  			},
   293  		},
   294  		Peers: make([]*pb.Peer, 0),
   295  	}
   296  	// it should add pbPeer to the single node peers
   297  	peer := UnpackPeerTopology(pbPeer, time.Now(), 5)
   298  	if peer.id != pbPeer.Node.Id {
   299  		t.Errorf("Expected peer id %s, found: %s", pbPeer.Node.Id, peer.id)
   300  	}
   301  
   302  	node := testSetup()
   303  	// build a simple topology to update node peer1
   304  	peer1 := node.peers["peer1"]
   305  	pbPeer1Node := &pb.Node{
   306  		Id:      peer1.id,
   307  		Address: peer1.address,
   308  		Status: &pb.Status{
   309  			Error: &pb.Error{},
   310  		},
   311  	}
   312  
   313  	pbPeer111 := &pb.Peer{
   314  		Node: &pb.Node{
   315  			Id:      "peer111",
   316  			Address: "peer111Address",
   317  			Status: &pb.Status{
   318  				Error: &pb.Error{},
   319  			},
   320  		},
   321  		Peers: make([]*pb.Peer, 0),
   322  	}
   323  
   324  	pbPeer121 := &pb.Peer{
   325  		Node: &pb.Node{
   326  			Id:      "peer121",
   327  			Address: "peer121Address",
   328  			Status: &pb.Status{
   329  				Error: &pb.Error{},
   330  			},
   331  		},
   332  		Peers: make([]*pb.Peer, 0),
   333  	}
   334  	// topology to update
   335  	pbPeer1 := &pb.Peer{
   336  		Node:  pbPeer1Node,
   337  		Peers: []*pb.Peer{pbPeer111, pbPeer121},
   338  	}
   339  	// unpack peer1 topology
   340  	peer = UnpackPeerTopology(pbPeer1, time.Now(), 5)
   341  	// make sure peer1 topology has been correctly updated
   342  	newPeerIds := []string{pbPeer111.Node.Id, pbPeer121.Node.Id}
   343  	for _, id := range newPeerIds {
   344  		if _, ok := peer.peers[id]; !ok {
   345  			t.Errorf("Expected %s to be a peer of %s", id, "peer1")
   346  		}
   347  	}
   348  }
   349  
   350  func TestPeersToProto(t *testing.T) {
   351  	// single node
   352  	single := &node{
   353  		id:      testNodeId,
   354  		address: testNodeAddress,
   355  		peers:   make(map[string]*node),
   356  		network: NewNetwork(network.Name(testNodeNetName)),
   357  		status:  newStatus(),
   358  	}
   359  	topCount := 0
   360  
   361  	protoPeers := PeersToProto(single, 0)
   362  
   363  	if len(protoPeers.Peers) != topCount {
   364  		t.Errorf("Expected to find %d nodes, found: %d", topCount, len(protoPeers.Peers))
   365  	}
   366  
   367  	// complicated node graph
   368  	node := testSetup()
   369  	topCount = 3
   370  	// list of ids of nodes of depth 1 i.e. node peers
   371  	peerIds := make(map[string]bool)
   372  	// add peer Ids
   373  	for _, id := range testNodePeerIds {
   374  		peerIds[id] = true
   375  	}
   376  	// depth 1 should give us immmediate neighbours only
   377  	protoPeers = PeersToProto(node, 1)
   378  
   379  	if len(protoPeers.Peers) != topCount {
   380  		t.Errorf("Expected to find %d nodes, found: %d", topCount, len(protoPeers.Peers))
   381  	}
   382  }