LCOV - code coverage report
Current view: top level - test/unitTest/swarm - routing_table.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 710 741 95.8 %
Date: 2024-12-21 08:56:24 Functions: 64 76 84.2 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : #include <cppunit/TestAssert.h>
      18             : #include <cppunit/TestFixture.h>
      19             : #include <cppunit/extensions/HelperMacros.h>
      20             : 
      21             : #include "../../test_runner.h"
      22             : #include "jami.h"
      23             : #include "../common.h"
      24             : #include "jamidht/swarm/swarm_manager.h"
      25             : #include <algorithm>
      26             : 
      27             : #include <dhtnet/multiplexed_socket.h>
      28             : #include "nodes.h"
      29             : 
      30             : #include <opendht/thread_pool.h>
      31             : 
      32             : using namespace std::string_literals;
      33             : using namespace std::chrono_literals;
      34             : using namespace dht;
      35             : using NodeId = dht::PkId;
      36             : 
      37             : namespace jami {
      38             : namespace test {
      39             : 
      40             : constexpr size_t nNodes = 6;
      41             : constexpr size_t mNodes = 3;
      42             : constexpr size_t kNodes = 4;
      43             : 
      44             : constexpr size_t BOOTSTRAP_SIZE = 2;
      45             : constexpr int time = 10;
      46             : 
      47             : struct Counter
      48             : {
      49           5 :     Counter(unsigned t)
      50           5 :         : target(t)
      51           5 :     {}
      52             :     const unsigned target;
      53             :     unsigned added {0};
      54             :     std::mutex mutex;
      55             :     std::condition_variable cv;
      56             : 
      57          45 :     void count()
      58             :     {
      59          45 :         std::lock_guard lock(mutex);
      60          45 :         ++added;
      61          45 :         if (added == target)
      62           5 :             cv.notify_one();
      63          45 :     }
      64             :     bool wait(std::chrono::steady_clock::duration timeout)
      65             :     {
      66             :         std::unique_lock lock(mutex);
      67             :         return cv.wait_for(lock, timeout, [&] { return added == target; });
      68             :     }
      69           5 :     void wait()
      70             :     {
      71           5 :         std::unique_lock lock(mutex);
      72          20 :         return cv.wait(lock, [&] { return added == target; });
      73           5 :     }
      74             : };
      75             : 
      76             : class RoutingTableTest : public CppUnit::TestFixture
      77             : {
      78             : public:
      79          36 :     ~RoutingTableTest() { libjami::fini(); }
      80           2 :     static std::string name() { return "RoutingTable"; }
      81             : 
      82             :     void setUp();
      83             :     void tearDown();
      84             : 
      85             : private:
      86             :     // ################# METHODS AND VARIABLES GENERATING DATA #################//
      87             : 
      88             :     std::mt19937_64 rd {dht::crypto::getSeededRandomEngine<std::mt19937_64>()};
      89             :     std::mutex channelSocketsMtx_;
      90             :     std::vector<NodeId> randomNodeIds;
      91             :     std::map<NodeId, std::map<NodeId, std::shared_ptr<dhtnet::ChannelSocketTest>>> channelSockets_;
      92             :     std::map<NodeId, std::shared_ptr<jami::SwarmManager>> swarmManagers;
      93             :     std::map<NodeId, std::set<NodeId>> nodesToConnect;
      94             :     std::set<NodeId> messageNode;
      95             : 
      96             :     void generaterandomNodeIds();
      97             :     void generateSwarmManagers();
      98         375 :     std::shared_ptr<jami::SwarmManager> getManager(const NodeId& id)
      99             :     {
     100         375 :         auto it = swarmManagers.find(id);
     101         750 :         return it == swarmManagers.end() ? nullptr : it->second;
     102             :     }
     103             :     void setKnownNodesToManager(const std::shared_ptr<SwarmManager>& sm);
     104             :     void needSocketCallBack(const std::shared_ptr<SwarmManager>& sm);
     105             : 
     106             :     // ################# METHODS AND VARIABLES TO TEST DATA #################//
     107             : 
     108             :     std::map<std::shared_ptr<jami::SwarmManager>, std::vector<NodeId>> knownNodesSwarmManager;
     109             :     std::map<NodeId, std::shared_ptr<jami::SwarmManager>> swarmManagersTest_;
     110             :     std::vector<NodeId> discoveredNodes;
     111             : 
     112             :     void crossNodes(NodeId nodeId);
     113             :     void distribution();
     114             : 
     115             :     // ################# UNIT TEST METHODES #################//
     116             : 
     117             :     void testBucketMainFunctions();
     118             :     void testRoutingTableMainFunctions();
     119             :     void testBucketKnownNodes();
     120             :     void testSwarmManagerConnectingNodes_1b();
     121             :     void testClosestNodes_1b();
     122             :     void testClosestNodes_multipleb();
     123             :     void testSendKnownNodes_1b();
     124             :     void testSendKnownNodes_multipleb();
     125             :     void testMobileNodeFunctions();
     126             :     void testMobileNodeAnnouncement();
     127             :     void testMobileNodeSplit();
     128             :     void testSendMobileNodes();
     129             :     void testBucketSplit_1n();
     130             :     void testSwarmManagersSmallBootstrapList();
     131             :     void testRoutingTableForConnectingNode();
     132             :     void testRoutingTableForShuttingNode();
     133             :     void testRoutingTableForMassShuttingsNodes();
     134             :     void testSwarmManagersWMobileModes();
     135             : 
     136           2 :     CPPUNIT_TEST_SUITE(RoutingTableTest);
     137           1 :     CPPUNIT_TEST(testBucketMainFunctions);
     138           1 :     CPPUNIT_TEST(testRoutingTableMainFunctions);
     139           1 :     CPPUNIT_TEST(testClosestNodes_multipleb);
     140           1 :     CPPUNIT_TEST(testBucketSplit_1n);
     141           1 :     CPPUNIT_TEST(testBucketKnownNodes);
     142           1 :     CPPUNIT_TEST(testSendKnownNodes_1b);
     143           1 :     CPPUNIT_TEST(testSendKnownNodes_multipleb);
     144           1 :     CPPUNIT_TEST(testClosestNodes_1b);
     145           1 :     CPPUNIT_TEST(testSwarmManagersSmallBootstrapList);
     146           1 :     CPPUNIT_TEST(testSwarmManagerConnectingNodes_1b);
     147           1 :     CPPUNIT_TEST(testRoutingTableForConnectingNode);
     148           1 :     CPPUNIT_TEST(testMobileNodeFunctions);
     149           1 :     CPPUNIT_TEST(testMobileNodeAnnouncement);
     150           1 :     CPPUNIT_TEST(testMobileNodeSplit);
     151           1 :     CPPUNIT_TEST(testSendMobileNodes);
     152           1 :     CPPUNIT_TEST(testSwarmManagersWMobileModes);
     153           1 :     CPPUNIT_TEST(testRoutingTableForMassShuttingsNodes);
     154           1 :     CPPUNIT_TEST(testRoutingTableForShuttingNode);
     155           4 :     CPPUNIT_TEST_SUITE_END();
     156             : };
     157             : 
     158             : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(RoutingTableTest, RoutingTableTest::name());
     159             : 
     160             : void
     161          18 : RoutingTableTest::setUp()
     162             : {
     163          18 :     libjami::init(
     164             :         libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
     165          18 :     if (not Manager::instance().initialized) {
     166           1 :         CPPUNIT_ASSERT(libjami::start("jami-sample.yml"));
     167             :     }
     168             : 
     169          18 :     generaterandomNodeIds();
     170          18 :     generateSwarmManagers();
     171          18 : }
     172             : 
     173             : void
     174          18 : RoutingTableTest::tearDown()
     175             : {
     176          18 :     discoveredNodes.clear();
     177          18 :     swarmManagersTest_.clear();
     178          18 : }
     179             : 
     180             : void
     181          18 : RoutingTableTest::generaterandomNodeIds()
     182             : {
     183          18 :     auto total = nNodes + mNodes;
     184          18 :     randomNodeIds.reserve(total);
     185         180 :     for (size_t i = 0; i < total; i++) {
     186         162 :         NodeId node = Hash<32>::getRandom();
     187         162 :         randomNodeIds.emplace_back(node);
     188             :     }
     189          18 : }
     190             : 
     191             : void
     192          18 : RoutingTableTest::generateSwarmManagers()
     193             : {
     194          18 :     auto total = nNodes + mNodes;
     195         180 :     for (size_t i = 0; i < total; i++) {
     196         162 :         const NodeId& node = randomNodeIds.at(i);
     197         431 :         auto sm = std::make_shared<SwarmManager>(node, rd, std::move([](auto) {return false;}));
     198         162 :         i >= nNodes ? sm->setMobility(true) : sm->setMobility(false);
     199         162 :         swarmManagers[node] = sm;
     200         162 :     }
     201          18 : }
     202             : 
     203             : void
     204           0 : RoutingTableTest::setKnownNodesToManager(const std::shared_ptr<SwarmManager>& sm)
     205             : {
     206           0 :     std::uniform_int_distribution<> distrib(1, kNodes - 1);
     207             : 
     208           0 :     int numberKnownNodesToAdd = distrib(rd);
     209             : 
     210           0 :     std::uniform_int_distribution<> distribBis(0, kNodes - 1);
     211             :     int indexNodeIdToAdd;
     212           0 :     std::vector<NodeId> kNodesToAdd;
     213           0 :     knownNodesSwarmManager.insert({sm, {}});
     214             : 
     215           0 :     int counter = 0;
     216             : 
     217           0 :     while (counter < numberKnownNodesToAdd) {
     218           0 :         indexNodeIdToAdd = distribBis(rd);
     219             : 
     220           0 :         NodeId node = randomNodeIds.at(indexNodeIdToAdd);
     221           0 :         auto it = find(kNodesToAdd.begin(), kNodesToAdd.end(), node);
     222           0 :         if (sm->getId() != node && it == kNodesToAdd.end()) {
     223           0 :             kNodesToAdd.push_back(node);
     224           0 :             knownNodesSwarmManager.at(sm).push_back(node);
     225           0 :             counter++;
     226             :         }
     227             :     }
     228             : 
     229           0 :     sm->setKnownNodes(kNodesToAdd);
     230           0 : }
     231             : 
     232             : void
     233          62 : RoutingTableTest::needSocketCallBack(const std::shared_ptr<SwarmManager>& sm)
     234             : {
     235          62 :     sm->needSocketCb_ = [this, wsm = std::weak_ptr<SwarmManager>(sm)](const std::string& nodeId,
     236         301 :                                                                       auto&& onSocket) {
     237         303 :         Manager::instance().ioContext()->post([this, wsm, nodeId, onSocket = std::move(onSocket)] {
     238         303 :             auto sm = wsm.lock();
     239         303 :             if (!sm || sm->isShutdown())
     240          10 :                 return;
     241         293 :             NodeId node = dhtnet::DeviceId(nodeId);
     242         293 :             std::lock_guard lk(channelSocketsMtx_);
     243         563 :             if (auto smRemote = getManager(node)) {
     244         270 :                 if (sm->isShutdown()) {
     245           0 :                     std::cout << "SWARMMANAGER " << sm->getId() << " IS SHUTDOWN" << std::endl;
     246           0 :                     return;
     247             :                 }
     248         270 :                 auto myId = sm->getId();
     249         270 :                 auto& cstRemote = channelSockets_[node][myId];
     250         270 :                 auto& cstMe = channelSockets_[myId][node];
     251         270 :                 if (!cstRemote) {
     252         210 :                     cstRemote = std::make_shared<dhtnet::ChannelSocketTest>(Manager::instance().ioContext(), myId, "test1", 0);
     253             :                 }
     254         270 :                 if (!cstMe) {
     255         210 :                     cstMe = std::make_shared<dhtnet::ChannelSocketTest>(Manager::instance().ioContext(), node, "test1", 0);
     256             :                 }
     257         270 :                 dhtnet::ChannelSocketTest::link(cstMe, cstRemote);
     258         270 :                 onSocket(cstMe);
     259         270 :                 smRemote->addChannel(cstRemote);
     260             :             }
     261         303 :         });
     262         427 :     };
     263          62 : }
     264             : 
     265             : void
     266           0 : RoutingTableTest::distribution()
     267             : {
     268           0 :     std::vector<unsigned> dist(8);
     269           0 :     for (const auto& sm : swarmManagers) {
     270           0 :         auto val = sm.second->getRoutingTable().getRoutingTableNodeCount();
     271           0 :         if (dist.size() <= val)
     272           0 :             dist.resize(val + 1);
     273           0 :         dist[val]++;
     274             :     }
     275             : 
     276           0 :     for (size_t i = 0; i < dist.size(); i++) {
     277           0 :         std::cout << "Swarm Managers with " << i << " nodes: " << dist[i] << std::endl;
     278             :     }
     279           0 : }
     280             : 
     281             : void
     282           1 : RoutingTableTest::testBucketMainFunctions()
     283             : {
     284           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     285             : 
     286           1 :     NodeId node0 = nodeTestIds1.at(0);
     287           1 :     NodeId node1 = nodeTestIds1.at(1);
     288           1 :     NodeId node2 = nodeTestIds1.at(2);
     289           1 :     NodeId node3 = nodeTestIds1.at(3);
     290             : 
     291           1 :     auto sNode1 = nodeTestChannels1.at(1);
     292           1 :     auto sNode2 = nodeTestChannels1.at(2);
     293           1 :     auto sNode3 = nodeTestChannels1.at(3);
     294             : 
     295           1 :     NodeInfo InfoNode1(true, sNode2);
     296             : 
     297           4 :     std::set<std::shared_ptr<dhtnet::ChannelSocketInterface>> socketsCheck {sNode1, sNode2};
     298           1 :     std::set<NodeId> nodesCheck {node1, node2};
     299             : 
     300           1 :     Bucket bucket(node0);
     301             : 
     302           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Lower limit error", node0, bucket.getLowerLimit());
     303             : 
     304           1 :     bucket.addNode(sNode1);
     305           1 :     bucket.addNode(std::move(InfoNode1));
     306             : 
     307             :     //bucket.printBucket(0);
     308             : 
     309           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have node", true, bucket.hasNode(sNode1->deviceId()));
     310           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have node", true, bucket.hasNode(sNode2->deviceId()));
     311             : 
     312           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have nodes",
     313             :                                  true,
     314             :                                  socketsCheck == bucket.getNodeSockets());
     315           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have nodes", true, nodesCheck == bucket.getNodeIds());
     316           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have nodes", true, bucket.isFull());
     317           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known node",
     318             :                                  false,
     319             :                                  bucket.hasKnownNode(node1));
     320           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known node",
     321             :                                  false,
     322             :                                  bucket.hasKnownNode(node2));
     323           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     324             :                                  false,
     325             :                                  bucket.hasConnectingNode(node1));
     326           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     327             :                                  false,
     328             :                                  bucket.hasConnectingNode(node2));
     329             : 
     330           2 :     CPPUNIT_ASSERT_THROW_MESSAGE("Supposed to be out of range",
     331             :                                  bucket.getKnownNode(5),
     332             :                                  std::out_of_range);
     333             : 
     334           1 :     bucket.removeNode(sNode1->deviceId());
     335           1 :     bucket.shutdownNode(sNode2->deviceId());
     336             : 
     337           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node", false, bucket.hasNode(node1));
     338           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node", false, bucket.hasNode(node2));
     339           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have known node", true, bucket.hasKnownNode(node1));
     340           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have known node", false, bucket.hasKnownNode(node2));
     341           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have known node", false, bucket.hasMobileNode(node1));
     342           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have known node", true, bucket.hasMobileNode(node2));
     343           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     344             :                                  false,
     345             :                                  bucket.hasConnectingNode(node1));
     346           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     347             :                                  false,
     348             :                                  bucket.hasConnectingNode(node2));
     349             : 
     350           1 :     auto nodeTest = bucket.randomId(rd);
     351             : 
     352           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("One of the two nodes",
     353             :                                  true,
     354             :                                  nodeTest == node1 || nodeTest == node2);
     355             : 
     356           1 :     bucket.addNode(sNode1);
     357           1 :     bucket.addNode(sNode2);
     358             : 
     359           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be 2", 2u, bucket.getNodesSize());
     360           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to return zero, node already added",
     361             :                                  false,
     362             :                                  bucket.addNode(sNode2));
     363             : 
     364           1 :     bucket.removeNode(node1);
     365           1 :     bucket.removeNode(node2);
     366             : 
     367           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node", false, bucket.hasNode(node1));
     368           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node", false, bucket.hasNode(node2));
     369             : 
     370           1 :     bucket.addKnownNode(node3);
     371             : 
     372           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have known node", true, bucket.hasKnownNode(node3));
     373           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     374             :                                  false,
     375             :                                  bucket.hasConnectingNode(node3));
     376           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be 3", 3u, bucket.getKnownNodesSize());
     377           1 :     bucket.removeKnownNode(node3);
     378             : 
     379           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known node",
     380             :                                  false,
     381             :                                  bucket.hasKnownNode(node3));
     382           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have connecting node",
     383             :                                  false,
     384             :                                  bucket.hasConnectingNode(node3));
     385             : 
     386           1 :     bucket.addConnectingNode(node1);
     387           1 :     bucket.addConnectingNode(node2);
     388             : 
     389           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have connecting node",
     390             :                                  true,
     391             :                                  bucket.hasConnectingNode(node1));
     392             : 
     393           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have nodes",
     394             :                                  true,
     395             :                                  nodesCheck == bucket.getConnectingNodes());
     396             : 
     397           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be 2", 2u, bucket.getConnectingNodesSize());
     398             : 
     399           1 :     bucket.removeConnectingNode(node2);
     400             : 
     401           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not upposed to have connecting node",
     402             :                                  false,
     403             :                                  bucket.hasConnectingNode(node2));
     404           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be 1", 1u, bucket.getConnectingNodesSize());
     405           1 : }
     406             : 
     407             : void
     408           1 : RoutingTableTest::testBucketKnownNodes()
     409             : {
     410           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     411             : 
     412           1 :     Bucket bucket(randomNodeIds.at(0));
     413             : 
     414          10 :     for (size_t i = 0; i < randomNodeIds.size(); i++) {
     415           9 :         bucket.addKnownNode(randomNodeIds.at(i));
     416             :     }
     417             : 
     418           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have the known node",
     419             :                                  true,
     420             :                                  bucket.hasKnownNode(randomNodeIds.at(randomNodeIds.size() - 1)));
     421           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Error with bucket size",
     422             :                                  true,
     423             :                                  bucket.getKnownNodesSize() == randomNodeIds.size());
     424           1 : }
     425             : 
     426             : void
     427           1 : RoutingTableTest::testRoutingTableMainFunctions()
     428             : {
     429           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     430             : 
     431           1 :     RoutingTable rt;
     432           1 :     NodeId node1 = nodeTestIds1.at(0);
     433           1 :     NodeId node2 = nodeTestIds1.at(1);
     434           1 :     NodeId node3 = nodeTestIds1.at(2);
     435             : 
     436           1 :     rt.setId(node1);
     437             : 
     438           1 :     rt.addKnownNode(node1);
     439           1 :     rt.addKnownNode(node2);
     440           1 :     rt.addKnownNode(node3);
     441             : 
     442           1 :     CPPUNIT_ASSERT(!rt.hasKnownNode(node1));
     443           1 :     CPPUNIT_ASSERT(rt.hasKnownNode(node2));
     444             : 
     445           1 :     auto knownNodes = rt.getKnownNodes();
     446             : 
     447           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have 2 nodes", true, knownNodes.size() == 2);
     448             : 
     449           1 :     auto bucket1 = rt.findBucket(node1);
     450           1 :     auto bucket2 = rt.findBucket(node2);
     451           1 :     auto bucket3 = rt.findBucket(node3);
     452             : 
     453           1 :     rt.addNode(nodeTestChannels1.at(0), bucket1);
     454           1 :     rt.addNode(nodeTestChannels1.at(1), bucket2);
     455           1 :     rt.addNode(nodeTestChannels1.at(2), bucket3);
     456             : 
     457           1 :     CPPUNIT_ASSERT(!rt.hasNode(node1));
     458           1 :     CPPUNIT_ASSERT(rt.hasNode(node2));
     459           1 :     CPPUNIT_ASSERT(rt.hasNode(node3));
     460             : 
     461           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist 0", false, rt.removeNode(node1));
     462           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist 1", true, rt.removeNode(node2));
     463             : 
     464           1 :     rt.removeNode(node1);
     465           1 :     rt.removeNode(node2);
     466           1 :     rt.removeNode(node3);
     467             : 
     468           1 :     rt.addConnectingNode(node1);
     469           1 :     rt.addConnectingNode(node2);
     470           1 :     rt.addConnectingNode(node3);
     471             : 
     472           1 :     std::vector<NodeId> nodesCheck({node2, node3});
     473           1 :     const auto& nodes = rt.getConnectingNodes();
     474             : 
     475           1 :     std::vector<NodeId> connectingNode;
     476           1 :     connectingNode.insert(connectingNode.end(), nodes.begin(), nodes.end());
     477             : 
     478           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist 3", false, rt.hasNode(node3));
     479           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist 1", false, rt.hasConnectingNode(node1));
     480           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist 3", true, rt.hasConnectingNode(node3));
     481             : 
     482           1 :     std::vector<NodeId> diff;
     483           1 :     std::set_difference(connectingNode.begin(),
     484             :                         connectingNode.end(),
     485             :                         nodes.begin(),
     486             :                         nodes.end(),
     487             :                         std::inserter(diff, diff.begin()));
     488             : 
     489           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be equal", true, diff.size() == 0);
     490             : 
     491           1 :     rt.shutdownNode(node2);
     492           1 :     rt.shutdownNode(node3);
     493             : 
     494           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist", true, rt.hasConnectingNode(node2));
     495           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to exist", true, rt.hasConnectingNode(node3));
     496           1 : }
     497             : 
     498             : void
     499           1 : RoutingTableTest::testSwarmManagerConnectingNodes_1b()
     500             : {
     501           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     502             : 
     503           1 :     std::vector<NodeId> tryConnect;
     504           1 :     std::vector<std::string> needSocketNodes;
     505           1 :     std::condition_variable cv;
     506           1 :     std::mutex mutex;
     507           1 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds1.at(0), rd, std::move([&](auto n) {
     508           1 :         std::lock_guard<std::mutex> lk(mutex);
     509           1 :         tryConnect.emplace_back(n);
     510           1 :         cv.notify_one();
     511           1 :         return false;
     512           2 :     }));
     513           2 :     sm1->needSocketCb_ = [&](const auto& n, auto) {
     514           1 :         std::lock_guard<std::mutex> lk(mutex);
     515           1 :         needSocketNodes.emplace_back(n);
     516           1 :         cv.notify_one();
     517           2 :     };
     518           1 :     auto& rt1 = sm1->getRoutingTable();
     519             : 
     520             :     std::vector<NodeId> toTest(
     521           1 :         {NodeId("053927d831827a9f7e606d4c9c9fe833922c0d35b3960dd2250085f46c0e4f41"),
     522           2 :          NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")});
     523             : 
     524           1 :     std::unique_lock lk(mutex);
     525           1 :     sm1->setKnownNodes(toTest);
     526           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&](){return tryConnect.size() != 0 && needSocketNodes.size() != 0;}));
     527             : 
     528           1 :     CPPUNIT_ASSERT(!rt1.hasConnectingNode(nodeTestIds1.at(0)));
     529           1 :     CPPUNIT_ASSERT(rt1.hasConnectingNode(nodeTestIds1.at(1)));
     530           1 :     CPPUNIT_ASSERT(!rt1.hasKnownNode(nodeTestIds1.at(0)));
     531           1 :     CPPUNIT_ASSERT(!rt1.hasKnownNode(nodeTestIds1.at(1)));
     532           1 : }
     533             : 
     534             : void
     535           1 : RoutingTableTest::testClosestNodes_1b()
     536             : {
     537           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     538             : 
     539           1 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds1.at(0), rd, std::move([](auto) {return false;}));
     540           1 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds2.at(0), rd, std::move([](auto) {return false;}));
     541             : 
     542           1 :     auto& rt1 = sm1->getRoutingTable();
     543           1 :     auto& rt2 = sm2->getRoutingTable();
     544             : 
     545           1 :     auto bucket1 = rt1.findBucket(nodeTestIds1.at(0));
     546           1 :     auto bucket2 = rt2.findBucket(nodeTestIds2.at(0));
     547             : 
     548          11 :     for (size_t i = 0; i < nodeTestIds2.size(); i++) {
     549          10 :         bucket1->addNode(nodeTestChannels1.at(i));
     550          10 :         bucket2->addNode(nodeTestChannels2.at(i));
     551             :     }
     552             : 
     553             :     std::vector<NodeId>
     554           1 :         closestNodes1 {NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8"),
     555           1 :                        NodeId("28f4c7e34eb4310b2e1ea3b139ee6993e6b021770ee98895a54cdd1e372bd78e"),
     556           1 :                        NodeId("2dd1dd976c7dc234ca737c85e4ea48ad09423067a77405254424c4cdd845720d"),
     557           1 :                        NodeId("33f280d8208f42ac34321e6e6871aecd100c2bfd4f1848482e7a7ed8ae895414")
     558             : 
     559           4 :         };
     560             : 
     561             :     std::vector<NodeId>
     562           1 :         closestNodes2 {NodeId("053927d831827a9f7e606d4c9c9fe833922c0d35b3960dd2250085f46c0e4f41"),
     563           1 :                        NodeId("4f76e769061f343b2caf9eea35632d28cde8d7a67e5e0f59857733cabc538997"),
     564           1 :                        NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8"),
     565           1 :                        NodeId("77a9fba2c5a65812d9290c567897131b20a723e0ca2f65ef5c6b421585e4da2b")
     566             : 
     567           4 :         };
     568             : 
     569           1 :     auto closestNodes1_ = rt1.closestNodes(nodeTestIds2.at(4), 4);
     570           1 :     auto closestNodes2_ = rt2.closestNodes(nodeTestIds1.at(4), 4);
     571           1 :     auto sameIdTest = rt2.closestNodes(nodeTestIds2.at(0), 1);
     572             : 
     573           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", true, closestNodes1 == closestNodes1_);
     574           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", true, closestNodes2 == closestNodes2_);
     575           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", false, nodeTestIds1.at(0) == sameIdTest.at(0));
     576           1 : }
     577             : 
     578             : void
     579           1 : RoutingTableTest::testClosestNodes_multipleb()
     580             : {
     581           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     582             : 
     583           1 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds1.at(2), rd, std::move([](auto) {return false;}));
     584           1 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds1.at(6), rd, std::move([](auto) {return false;}));
     585             : 
     586          11 :     for (size_t i = 0; i < nodeTestChannels1.size(); i++) {
     587          10 :         sm1->addChannel(nodeTestChannels1.at(i));
     588          10 :         sm2->addChannel(nodeTestChannels1.at(i));
     589             :     }
     590             : 
     591             :     std::vector<NodeId>
     592           1 :         closestNodes1 {NodeId("2dd1dd976c7dc234ca737c85e4ea48ad09423067a77405254424c4cdd845720d"),
     593           1 :                        NodeId("30e177a56bd1a7969e1973ad8b210a556f6a2b15debc972661a8f555d52edbe2"),
     594           2 :                        NodeId("312226d8fa653704758a681c8c21ec81cec914d0b8aa19e1142d3cf900e3f3b4")};
     595             : 
     596             :     std::vector<NodeId>
     597           1 :         closestNodes2 {NodeId("30e177a56bd1a7969e1973ad8b210a556f6a2b15debc972661a8f555d52edbe2"),
     598           1 :                        NodeId("312226d8fa653704758a681c8c21ec81cec914d0b8aa19e1142d3cf900e3f3b4"),
     599           2 :                        NodeId("33f280d8208f42ac34321e6e6871aecd100c2bfd4f1848482e7a7ed8ae895414")};
     600             : 
     601           1 :     auto closestNodes1_ = sm1->getRoutingTable().closestNodes(nodeTestIds1.at(5), 3);
     602           1 :     auto closestNodes2_ = sm2->getRoutingTable().closestNodes(nodeTestIds1.at(5), 3);
     603             : 
     604           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", true, closestNodes1 == closestNodes1_);
     605           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", true, closestNodes2 == closestNodes2_);
     606           1 : }
     607             : 
     608             : void
     609           1 : RoutingTableTest::testBucketSplit_1n()
     610             : {
     611           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     612             : 
     613           1 :     SwarmManager sm1(nodeTestIds2.at(0), rd, std::move([](auto) {return false;}));
     614           1 :     SwarmManager sm2(nodeTestIds2.at(nodeTestIds2.size() - 1), rd, std::move([](auto) {return false;}));
     615           1 :     SwarmManager sm3(nodeTestIds2.at(nodeTestIds2.size() / 2), rd, std::move([](auto) {return false;}));
     616             : 
     617           1 :     auto& rt1 = sm1.getRoutingTable();
     618           1 :     auto& rt2 = sm2.getRoutingTable();
     619           1 :     auto& rt3 = sm3.getRoutingTable();
     620             : 
     621           1 :     auto& b1 = rt1.getBuckets();
     622           1 :     auto& b2 = rt2.getBuckets();
     623           1 :     auto& b3 = rt3.getBuckets();
     624             : 
     625          11 :     for (size_t i = 0; i < nodeTestIds2.size(); i++) {
     626          10 :         auto bucket1 = rt1.findBucket(nodeTestIds2.at(i));
     627          10 :         auto bucket2 = rt2.findBucket(nodeTestIds2.at(i));
     628          10 :         auto bucket3 = rt3.findBucket(nodeTestIds2.at(i));
     629             : 
     630          10 :         rt1.addNode(nodeTestChannels2.at(i), bucket1);
     631          10 :         rt2.addNode(nodeTestChannels2.at(i), bucket2);
     632          10 :         rt3.addNode(nodeTestChannels2.at(i), bucket3);
     633             :     }
     634             : 
     635             :     // SM1
     636           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node ntc2 0",
     637             :                                  false,
     638             :                                  rt1.hasNode(nodeTestChannels2.at(0)->deviceId()));
     639             : 
     640           1 :     int sm1BucketCounter = 1;
     641           4 :     for (const auto& buckIt : b1) {
     642           3 :         switch (sm1BucketCounter) {
     643           1 :         case 1:
     644           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Size error", 0u, buckIt.getNodesSize());
     645           1 :             break;
     646             : 
     647           1 :         case 2: {
     648           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(1),
     649           2 :                                          nodeTestIds2.at(2),
     650           2 :                                          nodeTestIds2.at(3),
     651           2 :                                          nodeTestIds2.at(4),
     652           1 :                                          nodeTestIds2.at(8)};
     653             : 
     654           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     655             :                                          true,
     656             :                                          nodesCheck == buckIt.getNodeIds());
     657           1 :         }
     658             : 
     659           1 :         break;
     660             : 
     661           1 :         case 3: {
     662           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(5),
     663           2 :                                          nodeTestIds2.at(6),
     664           2 :                                          nodeTestIds2.at(7),
     665           1 :                                          nodeTestIds2.at(9)};
     666           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     667             :                                          true,
     668             :                                          nodesCheck == buckIt.getNodeIds());
     669           1 :         }
     670             : 
     671           1 :         break;
     672             :         }
     673             : 
     674           3 :         sm1BucketCounter++;
     675             :     }
     676             : 
     677           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", 3, sm1BucketCounter - 1);
     678             : 
     679             :     // SM2
     680           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node ntc2 9",
     681             :                                  false,
     682             :                                  rt2.hasNode(nodeTestChannels2.at(9)->deviceId()));
     683             : 
     684           1 :     int sm2BucketCounter = 1;
     685           4 :     for (const auto& buckIt : b2) {
     686           3 :         switch (sm2BucketCounter) {
     687           1 :         case 1: {
     688           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(0),
     689           2 :                                          nodeTestIds2.at(1),
     690           2 :                                          nodeTestIds2.at(2),
     691           2 :                                          nodeTestIds2.at(3),
     692           2 :                                          nodeTestIds2.at(4),
     693           1 :                                          nodeTestIds2.at(8)};
     694           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     695             :                                          true,
     696             :                                          nodesCheck == buckIt.getNodeIds());
     697           1 :         }
     698             : 
     699           1 :         break;
     700             : 
     701           1 :         case 2: {
     702           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(6), nodeTestIds2.at(7)};
     703           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     704             :                                          true,
     705             :                                          nodesCheck == buckIt.getNodeIds());
     706           1 :         }
     707             : 
     708           1 :         break;
     709             : 
     710           1 :         case 3:
     711           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have node ntc2 5",
     712             :                                          true,
     713             :                                          buckIt.hasNode(nodeTestChannels2.at(5)->deviceId()));
     714           1 :             break;
     715             :         }
     716             : 
     717           3 :         sm2BucketCounter++;
     718             :     }
     719             : 
     720           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", 3, sm2BucketCounter - 1);
     721             : 
     722             :     // SM3
     723           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have node ntc2 5",
     724             :                                  false,
     725             :                                  rt3.hasNode(nodeTestChannels2.at(5)->deviceId()));
     726             : 
     727           1 :     int sm3BucketCounter = 1;
     728           4 :     for (const auto& buckIt : b3) {
     729           3 :         switch (sm3BucketCounter) {
     730           1 :         case 1: {
     731           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(0),
     732           2 :                                          nodeTestIds2.at(1),
     733           2 :                                          nodeTestIds2.at(2),
     734           2 :                                          nodeTestIds2.at(3),
     735           2 :                                          nodeTestIds2.at(4),
     736           1 :                                          nodeTestIds2.at(8)};
     737           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     738             :                                          true,
     739             :                                          nodesCheck == buckIt.getNodeIds());
     740           1 :         }
     741             : 
     742           1 :         break;
     743             : 
     744           1 :         case 2: {
     745           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(6), nodeTestIds2.at(7)};
     746           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     747             :                                          true,
     748             :                                          nodesCheck == buckIt.getNodeIds());
     749           1 :         } break;
     750             : 
     751           1 :         case 3:
     752           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have node ntc2 9",
     753             :                                          true,
     754             :                                          buckIt.hasNode(nodeTestChannels2.at(9)->deviceId()));
     755           1 :             break;
     756             :         }
     757             : 
     758           3 :         sm3BucketCounter++;
     759             :     }
     760           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("ERROR", 3, sm3BucketCounter - 1);
     761           1 : }
     762             : 
     763             : void
     764           1 : RoutingTableTest::testSendKnownNodes_1b()
     765             : {
     766           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     767             : 
     768           4 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds2.at(0), rd, std::move([](auto) {return false;}));
     769           1 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds3.at(0), rd, std::move([](auto) {return false;}));
     770             : 
     771           1 :     swarmManagers.insert({sm1->getId(), sm1});
     772           1 :     swarmManagers.insert({sm2->getId(), sm2});
     773             : 
     774           1 :     auto& rt1 = sm1->getRoutingTable();
     775           1 :     auto& rt2 = sm2->getRoutingTable();
     776             : 
     777           1 :     auto bucket1 = rt1.findBucket(nodeTestIds2.at(0));
     778           1 :     auto bucket2 = rt2.findBucket(nodeTestIds3.at(0));
     779             : 
     780          11 :     for (size_t i = 0; i < nodeTestChannels3.size(); i++) {
     781          10 :         auto node = nodeTestChannels3.at(i)->deviceId();
     782          10 :         if (node != sm1->getId() && node != sm2->getId()) {
     783           8 :             bucket2->addNode(nodeTestChannels3.at(i));
     784             :         }
     785             :     }
     786             : 
     787             :     std::vector<NodeId> node2Co = {
     788           1 :         NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")};
     789           1 :     needSocketCallBack(sm1);
     790             : 
     791           1 :     sm1->setKnownNodes(node2Co);
     792             : 
     793           1 :     auto start = std::chrono::steady_clock::now();
     794           1 :     bool cn1 {false}, cn2 {false};
     795             : 
     796           2 :     auto isGood = [&] {
     797           2 :         return (cn1 and cn2);
     798           1 :     };
     799             :     do {
     800           1 :         std::this_thread::sleep_for(1s);
     801           1 :         cn1 = bucket1->hasConnectingNode(nodeTestIds3.at(2));
     802           1 :         cn2 = bucket1->hasConnectingNode(nodeTestIds3.at(3));
     803             : 
     804           1 :         if (isGood())
     805           1 :             break;
     806           0 :     } while (std::chrono::steady_clock::now() - start < 10s);
     807             : 
     808           1 :     CPPUNIT_ASSERT(isGood());
     809           1 : }
     810             : 
     811             : void
     812           1 : RoutingTableTest::testSendKnownNodes_multipleb()
     813             : {
     814           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     815             : 
     816           4 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds2.at(8), rd, std::move([](auto) {return false;}));
     817           3 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds3.at(0), rd, std::move([](auto) {return false;}));
     818             : 
     819           1 :     swarmManagers.insert({sm1->getId(), sm1});
     820           1 :     swarmManagers.insert({sm2->getId(), sm2});
     821             : 
     822           1 :     auto& rt1 = sm1->getRoutingTable();
     823           1 :     auto& rt2 = sm2->getRoutingTable();
     824             : 
     825          11 :     for (size_t i = 0; i < nodeTestIds2.size(); i++) {
     826          10 :         if (i != 1 && i != 0) {
     827           8 :             auto bucket1 = rt1.findBucket(nodeTestIds2.at(i));
     828           8 :             rt1.addNode(nodeTestChannels2.at(i), bucket1);
     829             :         }
     830             : 
     831          10 :         auto bucket2 = rt2.findBucket(nodeTestIds3.at(i));
     832          10 :         rt2.addNode(nodeTestChannels3.at(i), bucket2);
     833             :     }
     834             : 
     835             :     std::vector<NodeId> node2Co = {
     836           1 :         NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")};
     837           1 :     needSocketCallBack(sm1);
     838             : 
     839           1 :     sm1->setKnownNodes(node2Co);
     840             : 
     841           1 :     auto bucket1 = rt1.findBucket(nodeTestIds3.at(1));
     842           1 :     auto bucket2 = rt1.findBucket(nodeTestIds3.at(3));
     843             : 
     844           1 :     auto start = std::chrono::steady_clock::now();
     845           1 :     bool cn1 {false}, cn2 {false};
     846           2 :     auto isGood = [&] {
     847           2 :         return (cn1 or cn2);
     848           1 :     };
     849             :     do {
     850           1 :         std::this_thread::sleep_for(1s);
     851           1 :         cn1 = bucket1->hasConnectingNode(nodeTestIds3.at(1));
     852           1 :         cn2 = bucket2->hasConnectingNode(nodeTestIds3.at(3));
     853             : 
     854           1 :     } while (not isGood() and std::chrono::steady_clock::now() - start < 10s);
     855             : 
     856           1 :     CPPUNIT_ASSERT(isGood());
     857           1 : }
     858             : 
     859             : void
     860           1 : RoutingTableTest::testMobileNodeFunctions()
     861             : {
     862           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     863             : 
     864           1 :     RoutingTable rt;
     865           1 :     NodeId node1 = nodeTestIds1.at(0);
     866           1 :     NodeId node2 = nodeTestIds1.at(1);
     867           1 :     NodeId node3 = nodeTestIds1.at(2);
     868             : 
     869           1 :     rt.setId(node1);
     870           1 :     rt.addMobileNode(node1);
     871           1 :     rt.addMobileNode(node2);
     872           1 :     rt.addMobileNode(node3);
     873             : 
     874           1 :     CPPUNIT_ASSERT(!rt.hasMobileNode(node1));
     875           1 :     CPPUNIT_ASSERT(rt.hasMobileNode(node2));
     876           1 :     CPPUNIT_ASSERT(rt.hasMobileNode(node3));
     877             : 
     878           1 :     auto mobileNodes = rt.getMobileNodes();
     879           1 :     CPPUNIT_ASSERT(mobileNodes.size() == 2);
     880             : 
     881           1 :     rt.removeMobileNode(node2);
     882           1 :     rt.removeMobileNode(node3);
     883             : 
     884           1 :     CPPUNIT_ASSERT(!rt.hasMobileNode(node2));
     885           1 :     CPPUNIT_ASSERT(!rt.hasMobileNode(node3));
     886           1 : }
     887             : 
     888             : void
     889           1 : RoutingTableTest::testMobileNodeAnnouncement()
     890             : {
     891           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     892             : 
     893           2 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds1.at(0), rd, std::move([](auto) {return false;}));
     894           1 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds2.at(1), rd, std::move([](auto) {return false;}));
     895             : 
     896           1 :     swarmManagers.insert({sm1->getId(), sm1});
     897           1 :     swarmManagers.insert({sm2->getId(), sm2});
     898           1 :     sm2->setMobility(true);
     899             : 
     900             :     std::vector<NodeId> node2Co = {
     901           1 :         NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")};
     902             : 
     903           1 :     needSocketCallBack(sm1);
     904             : 
     905           1 :     sm1->setKnownNodes(node2Co);
     906           1 :     sleep(1);
     907           1 :     auto& rt1 = sm1->getRoutingTable();
     908             : 
     909           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE(
     910             :         "Supposed to have",
     911             :         true,
     912             :         rt1.hasNode(NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")));
     913             : 
     914           1 :     sm2->shutdown();
     915           1 :     sleep(5);
     916             : 
     917           1 :     auto mb1 = rt1.getMobileNodes();
     918             : 
     919             :     std::vector<NodeId> node2Test = {
     920           1 :         NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")};
     921             : 
     922           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be identical", true, node2Test == mb1);
     923           1 : }
     924             : 
     925             : void
     926           1 : RoutingTableTest::testMobileNodeSplit()
     927             : {
     928           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     929             : 
     930           1 :     SwarmManager sm1(nodeTestIds1.at(0), rd, std::move([](auto) {return false;}));
     931             : 
     932           1 :     auto& rt1 = sm1.getRoutingTable();
     933             : 
     934          11 :     for (size_t i = 0; i < nodeTestIds1.size(); i++) {
     935          10 :         rt1.addNode(nodeTestChannels1.at(i));
     936             :     }
     937             : 
     938           1 :     sm1.setMobileNodes(nodeTestIds2);
     939             : 
     940           1 :     auto& buckets = rt1.getBuckets();
     941             : 
     942           1 :     unsigned counter = 1;
     943             : 
     944           6 :     for (auto& buckIt : buckets) {
     945           5 :         switch (counter) {
     946           1 :         case 1:
     947           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have",
     948             :                                          false,
     949             :                                          buckIt.hasMobileNode(nodeTestIds2.at(0)));
     950           1 :             break;
     951             : 
     952           1 :         case 4: {
     953           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(2),
     954           2 :                                          nodeTestIds2.at(3),
     955           2 :                                          nodeTestIds2.at(4),
     956           1 :                                          nodeTestIds2.at(8)};
     957           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     958             :                                          true,
     959             :                                          nodesCheck == buckIt.getMobileNodes());
     960           1 :         }
     961             : 
     962           1 :         break;
     963             : 
     964           1 :         case 5: {
     965           1 :             std::set<NodeId> nodesCheck {nodeTestIds2.at(5),
     966           2 :                                          nodeTestIds2.at(6),
     967           2 :                                          nodeTestIds2.at(7),
     968           1 :                                          nodeTestIds2.at(9)};
     969           1 :             CPPUNIT_ASSERT_EQUAL_MESSAGE("Not supposed to have known nodes",
     970             :                                          true,
     971             :                                          nodesCheck == buckIt.getMobileNodes());
     972           1 :         }
     973             : 
     974           1 :         break;
     975             :         }
     976             : 
     977           5 :         counter++;
     978             :     }
     979           1 : }
     980             : 
     981             : void
     982           1 : RoutingTableTest::testSendMobileNodes()
     983             : {
     984           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
     985             : 
     986           4 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds2.at(8), rd, std::move([](auto) {return false;}));
     987           3 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds3.at(0), rd, std::move([](auto) {return false;}));
     988             : 
     989           1 :     std::cout << sm1->getId() << std::endl;
     990             : 
     991           1 :     swarmManagers.insert({sm1->getId(), sm1});
     992           1 :     swarmManagers.insert({sm2->getId(), sm2});
     993             : 
     994           1 :     auto& rt1 = sm1->getRoutingTable();
     995           1 :     auto& rt2 = sm2->getRoutingTable();
     996             : 
     997          11 :     for (size_t i = 0; i < nodeTestIds2.size(); i++) {
     998          10 :         if (i != 1 && i != 0) {
     999           8 :             auto bucket1 = rt1.findBucket(nodeTestIds2.at(i));
    1000           8 :             rt1.addNode(nodeTestChannels2.at(i), bucket1);
    1001             :         }
    1002             : 
    1003          10 :         auto bucket2 = rt2.findBucket(nodeTestIds3.at(i));
    1004          10 :         rt2.addNode(nodeTestChannels3.at(i), bucket2);
    1005             :     }
    1006             : 
    1007             :     std::vector<NodeId> mobileNodes
    1008           1 :         = {NodeId("4000000000000000000000000000000000000000000000000000000000000000"),
    1009           1 :            NodeId("8000000000000000000000000000000000000000000000000000000000000000")};
    1010           1 :     sm2->setMobileNodes(mobileNodes);
    1011             : 
    1012             :     std::vector<NodeId> node2Co = {
    1013           1 :         NodeId("41a05179e4b3e42c3409b10280bb448d5bbd5ef64784b997d2d1663457bb6ba8")};
    1014           1 :     needSocketCallBack(sm1);
    1015             : 
    1016           1 :     sm1->setKnownNodes(node2Co);
    1017             : 
    1018           1 :     sleep(4);
    1019             : 
    1020           1 :     auto bucket1 = rt1.findBucket(sm1->getId());
    1021           1 :     auto bucket2 = rt2.findBucket(sm2->getId());
    1022             : 
    1023           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have",
    1024             :                                  true,
    1025             :                                  bucket1->hasMobileNode(mobileNodes.at(0)));
    1026           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have",
    1027             :                                  false,
    1028             :                                  bucket1->hasMobileNode(mobileNodes.at(1)));
    1029           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have", false, rt1.hasMobileNode(mobileNodes.at(1)));
    1030             : 
    1031           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have",
    1032             :                                  true,
    1033             :                                  bucket2->hasMobileNode(mobileNodes.at(0)));
    1034           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to have", true, rt2.hasMobileNode(mobileNodes.at(1)));
    1035           1 : }
    1036             : 
    1037             : void
    1038           8 : RoutingTableTest::crossNodes(NodeId nodeId)
    1039             : {
    1040           8 :     std::list<NodeId> pendingNodes {nodeId};
    1041           8 :     discoveredNodes.clear();
    1042             : 
    1043         558 :     for (const auto& curNode : pendingNodes) {
    1044         550 :         if (std::find(discoveredNodes.begin(), discoveredNodes.end(), curNode)
    1045        1100 :             == discoveredNodes.end()) {
    1046          82 :             if (discoveredNodes.emplace_back(curNode)) {
    1047          82 :                 if (auto sm = getManager(curNode))
    1048         624 :                     for (auto const& node : sm->getRoutingTable().getNodes()) {
    1049         542 :                         pendingNodes.emplace_back(node);
    1050         164 :                     }
    1051             :             }
    1052             :         }
    1053             :     }
    1054           8 : }
    1055             : 
    1056             : void
    1057           1 : RoutingTableTest::testSwarmManagersSmallBootstrapList()
    1058             : {
    1059           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
    1060             : 
    1061          10 :     for (const auto& sm : swarmManagers) {
    1062           9 :         needSocketCallBack(sm.second);
    1063             :     }
    1064             : 
    1065           1 :     Counter counter(swarmManagers.size());
    1066          10 :     for (const auto& sm : swarmManagers) {
    1067           9 :         dht::ThreadPool::computation().run([&] {
    1068           9 :             std::vector<NodeId> randIds(BOOTSTRAP_SIZE);
    1069           9 :             std::uniform_int_distribution<size_t> distribution(0, randomNodeIds.size() - 1);
    1070           9 :             std::generate(randIds.begin(), randIds.end(), [&] {
    1071          18 :                 return randomNodeIds[distribution(rd)];
    1072             :             });
    1073           9 :             sm.second->setKnownNodes(randIds);
    1074           9 :             counter.count();
    1075           9 :         });
    1076             :     }
    1077             : 
    1078           1 :     counter.wait();
    1079             : 
    1080           1 :     sleep(time * 2);
    1081             : 
    1082           1 :     crossNodes(swarmManagers.begin()->first);
    1083             :     // distribution();
    1084             : 
    1085           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1086           1 : }
    1087             : 
    1088             : void
    1089           1 : RoutingTableTest::testRoutingTableForConnectingNode()
    1090             : {
    1091           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
    1092             : 
    1093          10 :     for (const auto& sm : swarmManagers) {
    1094           9 :         needSocketCallBack(sm.second);
    1095             :     }
    1096             : 
    1097           1 :     Counter counter(swarmManagers.size());
    1098          10 :     for (const auto& sm : swarmManagers) {
    1099           9 :         dht::ThreadPool::computation().run([&] {
    1100           9 :             std::vector<NodeId> randIds(BOOTSTRAP_SIZE);
    1101           8 :             std::uniform_int_distribution<size_t> distribution(0, randomNodeIds.size() - 1);
    1102           8 :             std::generate(randIds.begin(), randIds.end(), [&] {
    1103          17 :                 return randomNodeIds[distribution(rd)];
    1104             :             });
    1105           9 :             sm.second->setKnownNodes(randIds);
    1106           9 :             counter.count();
    1107           9 :         });
    1108             :     }
    1109           1 :     counter.wait();
    1110             : 
    1111           9 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds3.at(0), rd, std::move([](auto) {return false;}));
    1112          10 :     auto sm2 = std::make_shared<SwarmManager>(nodeTestIds3.at(1), rd, std::move([](auto) {return false;}));
    1113             : 
    1114           1 :     swarmManagers.insert({sm1->getId(), sm1});
    1115           1 :     swarmManagers.insert({sm2->getId(), sm2});
    1116             : 
    1117           1 :     needSocketCallBack(sm1);
    1118           1 :     needSocketCallBack(sm2);
    1119             : 
    1120           1 :     std::vector<NodeId> knownNodesSm1({randomNodeIds.at(2), randomNodeIds.at(3)});
    1121           1 :     std::vector<NodeId> knownNodesSm2({randomNodeIds.at(4), randomNodeIds.at(5)});
    1122             : 
    1123           1 :     sm1->setKnownNodes(knownNodesSm1);
    1124           1 :     sm2->setKnownNodes(knownNodesSm2);
    1125             : 
    1126           1 :     sleep(10);
    1127             : 
    1128           1 :     crossNodes(swarmManagers.begin()->first);
    1129           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1130           1 : }
    1131             : 
    1132             : void
    1133           1 : RoutingTableTest::testRoutingTableForShuttingNode()
    1134             : {
    1135           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
    1136             : 
    1137          10 :     for (const auto& sm : swarmManagers) {
    1138           9 :         needSocketCallBack(sm.second);
    1139             :     }
    1140             : 
    1141           1 :     Counter counter(swarmManagers.size());
    1142          10 :     for (const auto& sm : swarmManagers) {
    1143           9 :         dht::ThreadPool::computation().run([&] {
    1144           9 :             std::vector<NodeId> randIds(BOOTSTRAP_SIZE);
    1145           9 :             std::uniform_int_distribution<size_t> distribution(0, randomNodeIds.size() - 1);
    1146           8 :             std::generate(randIds.begin(), randIds.end(), [&] {
    1147          18 :                 return randomNodeIds[distribution(rd)];
    1148             :             });
    1149           8 :             sm.second->setKnownNodes(randIds);
    1150           9 :             counter.count();
    1151           9 :         });
    1152             :     }
    1153             : 
    1154           1 :     counter.wait();
    1155             : 
    1156           8 :     auto sm1 = std::make_shared<SwarmManager>(nodeTestIds3.at(0), rd, std::move([](auto) {return false;}));
    1157           1 :     auto sm1Id = sm1->getId();
    1158             : 
    1159           1 :     swarmManagers.emplace(sm1->getId(), sm1);
    1160           1 :     needSocketCallBack(sm1);
    1161             : 
    1162           1 :     std::vector<NodeId> knownNodesSm1({randomNodeIds.at(2), randomNodeIds.at(3)});
    1163           1 :     sm1->setKnownNodes(knownNodesSm1);
    1164             : 
    1165           1 :     sleep(10);
    1166             : 
    1167           1 :     crossNodes(swarmManagers.begin()->first);
    1168           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1169             : 
    1170          11 :     for (const auto& sm : swarmManagers) {
    1171          10 :         if (sm.first != nodeTestIds3.at(0)) {
    1172           9 :             swarmManagersTest_.emplace(sm);
    1173             :         }
    1174             :     }
    1175             : 
    1176           1 :     auto it1 = swarmManagers.find(sm1Id);
    1177           1 :     swarmManagers.erase(it1);
    1178             : 
    1179           1 :     auto it2 = channelSockets_.find(sm1Id);
    1180           1 :     channelSockets_.erase(it2);
    1181             : 
    1182           1 :     sm1 = {};
    1183           1 :     sleep(5);
    1184          10 :     for (const auto& sm : swarmManagersTest_) {
    1185           9 :         auto& a = sm.second->getRoutingTable();
    1186           9 :         CPPUNIT_ASSERT(!a.hasNode(sm1Id));
    1187             :     }
    1188           1 : }
    1189             : 
    1190             : void
    1191           1 : RoutingTableTest::testRoutingTableForMassShuttingsNodes()
    1192             : {
    1193           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
    1194             : 
    1195           1 :     std::vector<NodeId> swarmToCompare;
    1196             : 
    1197          10 :     for (const auto& sm : swarmManagers) {
    1198           9 :         needSocketCallBack(sm.second);
    1199           9 :         swarmManagersTest_.emplace(sm);
    1200           9 :         swarmToCompare.emplace_back(sm.first);
    1201             :     }
    1202             : 
    1203           1 :     Counter counter(swarmManagers.size());
    1204          10 :     for (const auto& sm : swarmManagers) {
    1205           9 :         dht::ThreadPool::computation().run([&] {
    1206           9 :             std::vector<NodeId> randIds(BOOTSTRAP_SIZE);
    1207           8 :             std::uniform_int_distribution<size_t> distribution(0, randomNodeIds.size() - 1);
    1208           7 :             std::generate(randIds.begin(), randIds.end(), [&] {
    1209          15 :                 return randomNodeIds[distribution(rd)];
    1210             :             });
    1211           8 :             sm.second->setKnownNodes(randIds);
    1212             : 
    1213           9 :             counter.count();
    1214           9 :         });
    1215             :     }
    1216           1 :     counter.wait();
    1217             : 
    1218           1 :     sleep(time * 2);
    1219             : 
    1220           1 :     crossNodes(swarmManagers.begin()->first);
    1221             : 
    1222           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1223             : 
    1224             :     // ADDING NEW NODES TO NETWORK
    1225          11 :     for (size_t i = 0; i < nodeTestIds1.size(); i++) {
    1226          71 :         auto sm = std::make_shared<SwarmManager>(nodeTestIds1.at(i), rd, std::move([](auto) {return false;}));
    1227          10 :         auto smId = sm->getId();
    1228          10 :         swarmManagers.emplace(smId, sm);
    1229          10 :         needSocketCallBack(sm);
    1230          10 :         std::vector<NodeId> knownNodesSm({randomNodeIds.at(2), randomNodeIds.at(3)});
    1231          10 :         sm->setKnownNodes(knownNodesSm);
    1232          10 :     }
    1233             : 
    1234           1 :     sleep(time * 3);
    1235           1 :     crossNodes(swarmManagers.begin()->first);
    1236             : 
    1237           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1238             : 
    1239             :     // SHUTTING DOWN ADDED NODES
    1240           1 :     std::lock_guard lk(channelSocketsMtx_);
    1241          11 :     for (auto& nodes : nodeTestIds1) {
    1242          10 :         auto it = swarmManagers.find(nodes);
    1243          10 :         if (it != swarmManagers.end()) {
    1244          10 :             it->second->shutdown();
    1245          10 :             channelSockets_.erase(it->second->getId());
    1246          10 :             swarmManagers.erase(it);
    1247             :         }
    1248             :     }
    1249             : 
    1250           1 :     sleep(time * 2);
    1251             : 
    1252           1 :     crossNodes(swarmManagers.begin()->first);
    1253             : 
    1254           1 :     CPPUNIT_ASSERT_EQUAL(swarmManagers.size(), discoveredNodes.size());
    1255             : 
    1256          10 :     for (const auto& sm : swarmManagersTest_) {
    1257          99 :         for (size_t i = 0; i < nodeTestIds1.size(); i++) {
    1258          90 :             auto& a = sm.second->getRoutingTable();
    1259          90 :             if (!a.hasNode(nodeTestIds1.at(i))) {
    1260          90 :                 CPPUNIT_ASSERT(true);
    1261             :             } else {
    1262           0 :                 CPPUNIT_ASSERT(false);
    1263             :             }
    1264             :         }
    1265             :     }
    1266           1 : }
    1267             : 
    1268             : void
    1269           1 : RoutingTableTest::testSwarmManagersWMobileModes()
    1270             : {
    1271           1 :     std::cout << "\nRunning test: " << __func__ << std::endl;
    1272             : 
    1273          10 :     for (const auto& sm : swarmManagers) {
    1274           9 :         needSocketCallBack(sm.second);
    1275             :     }
    1276             : 
    1277           1 :     Counter counter(swarmManagers.size());
    1278          10 :     for (const auto& sm : swarmManagers) {
    1279           9 :         dht::ThreadPool::computation().run([&] {
    1280           9 :             std::vector<NodeId> randIds(BOOTSTRAP_SIZE);
    1281           9 :             std::uniform_int_distribution<size_t> distribution(0, randomNodeIds.size() - 1);
    1282           9 :             std::generate(randIds.begin(), randIds.end(), [&] {
    1283          18 :                 return randomNodeIds[distribution(rd)];
    1284             :             });
    1285           9 :             sm.second->setKnownNodes(randIds);
    1286           9 :             counter.count();
    1287           9 :         });
    1288             :     }
    1289             : 
    1290           1 :     counter.wait();
    1291             : 
    1292           1 :     sleep(time);
    1293             : 
    1294             :     // distribution();
    1295             : 
    1296           1 :     crossNodes(swarmManagers.begin()->first);
    1297           1 :     sleep(2);
    1298           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be equal with mobile nodes",
    1299             :                                  swarmManagers.size(),
    1300             :                                  discoveredNodes.size());
    1301             : 
    1302             :     // Shutting down Mobile Nodes
    1303             :     {
    1304           1 :         std::lock_guard lk(channelSocketsMtx_);
    1305          10 :         for (auto it = swarmManagers.begin(); it != swarmManagers.end();) {
    1306           9 :             if (it->second->isMobile()) {
    1307           3 :                 it->second->shutdown();
    1308           3 :                 channelSockets_.erase(it->second->getId());
    1309           3 :                 it = swarmManagers.erase(it);
    1310             : 
    1311             :             } else {
    1312           6 :                 ++it;
    1313             :             }
    1314             :         }
    1315           1 :     }
    1316             : 
    1317           1 :     sleep(20);
    1318             : 
    1319             :     {
    1320           1 :         if (!swarmManagers.empty()) {
    1321           1 :             crossNodes(swarmManagers.begin()->first);
    1322             :             // distribution();
    1323             :         }
    1324             :     }
    1325             : 
    1326           1 :     sleep(10);
    1327             : 
    1328           1 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("Supposed to be equal without mobile nodes",
    1329             :                                  swarmManagers.size(),
    1330             :                                  discoveredNodes.size());
    1331           1 : }
    1332             : 
    1333             : }; // namespace test
    1334             : } // namespace jami
    1335           1 : RING_TEST_RUNNER(jami::test::RoutingTableTest::name())

Generated by: LCOV version 1.14