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-05-11 09:31:29 Functions: 64 76 84.2 %

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

Generated by: LCOV version 1.14