LCOV - code coverage report
Current view: top level - test/unitTest/namedirectory - namedirectory.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 174 179 97.2 %
Date: 2024-12-21 08:56:24 Functions: 36 38 94.7 %

          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             : 
      18             : #include <cppunit/TestAssert.h>
      19             : #include <cppunit/TestFixture.h>
      20             : #include <cppunit/extensions/HelperMacros.h>
      21             : 
      22             : #include <condition_variable>
      23             : #include <string>
      24             : #include <thread>
      25             : #include <restinio/all.hpp>
      26             : 
      27             : #include "manager.h"
      28             : #include "jamidht/jamiaccount.h"
      29             : #include "../../test_runner.h"
      30             : #include "account_const.h"
      31             : #include "common.h"
      32             : 
      33             : using namespace libjami::Account;
      34             : using namespace restinio;
      35             : using namespace std::literals::chrono_literals;
      36             : 
      37             : namespace jami {
      38             : namespace test {
      39             : 
      40             : 
      41             : using RestRouter = restinio::router::express_router_t<>;
      42             : struct RestRouterTraits : public restinio::default_traits_t
      43             : {
      44             :     using request_handler_t = RestRouter;
      45             : };
      46             : 
      47             : class NameDirectoryTest : public CppUnit::TestFixture
      48             : {
      49             : public:
      50           7 :     NameDirectoryTest()
      51           7 :     {
      52             :         // Init daemon
      53           7 :         libjami::init(
      54             :             libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
      55           7 :         if (not Manager::instance().initialized) {
      56           1 :             CPPUNIT_ASSERT(libjami::start("jami-sample.yml"));
      57             : 
      58             :             // Create express router for our service.
      59           1 :             auto router = std::make_unique<router::express_router_t<>>();
      60           1 :             router->http_post(
      61             :                     R"(/name/:name)",
      62           1 :                     [](auto req, auto params) {
      63           1 :                         const auto qp = parse_query(req->header().query());
      64             :                         return req->create_response()
      65           3 :                                 .set_body(
      66             :                                         fmt::format("{{\"success\":true}}")
      67             :                                 )
      68           2 :                                 .done();
      69           1 :                     });
      70           1 :             router->http_get(
      71             :                     R"(/name/:name)",
      72           2 :                     [](auto req, auto params) {
      73           2 :                         const auto qp = parse_query(req->header().query());
      74           2 :                         if (params["name"] == "taken") {
      75             :                             return req->create_response()
      76           3 :                                     .set_body(
      77             :                                             fmt::format("{{\"name\":\"taken\",\"addr\":\"c0dec0dec0dec0dec0dec0dec0dec0dec0dec0de\"}}")
      78             :                                     )
      79           1 :                                     .done();
      80             :                         }
      81             :                         return req->create_response(restinio::status_not_found())
      82           3 :                                 .set_body(
      83             :                                         fmt::format("{{\"error\":\"name not registered\"}}")
      84             :                                 )
      85           1 :                                 .done();
      86           2 :                     });
      87           1 :             router->http_get(
      88             :                     R"(/addr/:addr)",
      89           8 :                     [](auto req, auto params) {
      90           8 :                         const auto qp = parse_query(req->header().query());
      91           8 :                         if (params["addr"] == "c0dec0dec0dec0dec0dec0dec0dec0dec0dec0de") {
      92             :                             return req->create_response()
      93           0 :                                     .set_body(
      94             :                                             fmt::format("{{\"name\":\"taken\",\"addr\":\"c0dec0dec0dec0dec0dec0dec0dec0dec0dec0de\"}}")
      95             :                                     )
      96           0 :                                     .done();
      97             :                         }
      98             :                         return req->create_response(restinio::status_not_found())
      99          24 :                                 .set_body(
     100             :                                         fmt::format("{{\"error\":\"address not registered\"}}")
     101             :                                 )
     102           8 :                                 .done();
     103           8 :                     });
     104             : 
     105           1 :             router->non_matched_request_handler(
     106           0 :                     [](auto req){
     107           0 :                         return req->create_response(restinio::status_not_found()).connection_close().done();
     108             :                     });
     109             : 
     110             : 
     111           1 :             auto settings = restinio::run_on_this_thread_settings_t<RestRouterTraits>();
     112           1 :             settings.address("localhost");
     113           1 :             settings.port(1412);
     114           1 :             settings.request_handler(std::move(router));
     115           3 :             httpServer_ = std::make_unique<restinio::http_server_t<RestRouterTraits>>(
     116           2 :                 Manager::instance().ioContext(),
     117           1 :                 std::forward<restinio::run_on_this_thread_settings_t<RestRouterTraits>>(std::move(settings))
     118           1 :             );
     119             :             // run http server
     120           2 :             serverThread_ = std::thread([this](){
     121           2 :                 httpServer_->open_async([]{/*ok*/}, [](std::exception_ptr ex){
     122           0 :                     std::rethrow_exception(ex);
     123             :                 });
     124           1 :                 httpServer_->io_context().run();
     125           1 :             });
     126           1 :         }
     127             : 
     128           7 :     }
     129          14 :     ~NameDirectoryTest() {
     130           7 :         libjami::fini();
     131           7 :         if (serverThread_.joinable())
     132           1 :             serverThread_.join();
     133          14 :     }
     134           2 :     static std::string name() { return "NameDirectory"; }
     135             :     void setUp();
     136             :     void tearDown();
     137             : 
     138             :     std::string aliceId;
     139             : 
     140             :     // http server
     141             :     std::thread serverThread_;
     142             :     std::unique_ptr<restinio::http_server_t<RestRouterTraits>> httpServer_;
     143             : 
     144             : private:
     145             :     void testRegisterName();
     146             :     void testLookupName();
     147             :     void testLookupNameInvalid();
     148             :     void testLookupNameNotFound();
     149             :     void testLookupAddr();
     150             :     void testLookupAddrInvalid();
     151             :     void testLookupAddrNotFound();
     152             : 
     153           2 :     CPPUNIT_TEST_SUITE(NameDirectoryTest);
     154           1 :     CPPUNIT_TEST(testRegisterName);
     155           1 :     CPPUNIT_TEST(testLookupName);
     156           1 :     CPPUNIT_TEST(testLookupNameInvalid);
     157           1 :     CPPUNIT_TEST(testLookupNameNotFound);
     158           1 :     CPPUNIT_TEST(testLookupAddr);
     159           1 :     CPPUNIT_TEST(testLookupAddrInvalid);
     160           1 :     CPPUNIT_TEST(testLookupAddrNotFound);
     161           4 :     CPPUNIT_TEST_SUITE_END();
     162             : };
     163             : 
     164             : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(NameDirectoryTest, NameDirectoryTest::name());
     165             : 
     166             : void
     167           7 : NameDirectoryTest::setUp()
     168             : {
     169          14 :     auto actors = load_actors_and_wait_for_announcement("actors/alice.yml");
     170           7 :     aliceId = actors["alice"];
     171           7 :     std::map<std::string, std::string> details;
     172           7 :     details[ConfProperties::RingNS::URI] = "http://localhost:1412";
     173           7 :     libjami::setAccountDetails(aliceId, details);
     174           7 : }
     175             : 
     176             : void
     177           7 : NameDirectoryTest::tearDown()
     178             : {
     179           7 :     wait_for_removal_of({aliceId});
     180           7 : }
     181             : 
     182             : void
     183           1 : NameDirectoryTest::testRegisterName()
     184             : {
     185           1 :     std::mutex mtx;
     186           1 :     std::unique_lock lk {mtx};
     187           1 :     std::condition_variable cv;
     188           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     189           1 :     bool nameRegistered {false};
     190             :     // Watch signals
     191           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::NameRegistrationEnded>(
     192           1 :         [&](const std::string&,
     193             :             int status,
     194             :             const std::string&) {
     195           1 :             nameRegistered = status == 0;
     196           1 :             cv.notify_one();
     197           1 :         }));
     198           1 :     libjami::registerSignalHandlers(confHandlers);
     199           1 :     CPPUNIT_ASSERT(libjami::registerName(aliceId, "foo"));
     200           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return nameRegistered; }));
     201           1 : }
     202             : 
     203             : void
     204           1 : NameDirectoryTest::testLookupName()
     205             : {
     206           1 :     std::mutex mtx;
     207           1 :     std::unique_lock lk {mtx};
     208           1 :     std::condition_variable cv;
     209           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     210           1 :     bool nameFound {false};
     211             :     // Watch signals
     212           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     213           1 :         [&](const std::string&,
     214             :             int status,
     215             :             const std::string&,
     216             :             const std::string&) {
     217           1 :             nameFound = status == 0;
     218           1 :             cv.notify_one();
     219           1 :         }));
     220           1 :     libjami::registerSignalHandlers(confHandlers);
     221           1 :     CPPUNIT_ASSERT(libjami::lookupName(aliceId, "", "taken"));
     222           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return nameFound; }));
     223           1 : }
     224             : 
     225             : void
     226           1 : NameDirectoryTest::testLookupNameInvalid()
     227             : {
     228           1 :     std::mutex mtx;
     229           1 :     std::unique_lock lk {mtx};
     230           1 :     std::condition_variable cv;
     231           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     232           1 :     bool nameInvalid {false};
     233             :     // Watch signals
     234           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     235           1 :         [&](const std::string&,
     236             :             int status,
     237             :             const std::string&,
     238             :             const std::string&) {
     239           1 :             nameInvalid = status == 1;
     240           1 :             cv.notify_one();
     241           1 :         }));
     242           1 :     libjami::registerSignalHandlers(confHandlers);
     243           1 :     CPPUNIT_ASSERT(libjami::lookupName(aliceId, "", "===="));
     244           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return nameInvalid; }));
     245           1 : }
     246             : 
     247             : void
     248           1 : NameDirectoryTest::testLookupNameNotFound()
     249             : {
     250           1 :     std::mutex mtx;
     251           1 :     std::unique_lock lk {mtx};
     252           1 :     std::condition_variable cv;
     253           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     254           1 :     bool nameNotFound {false};
     255             :     // Watch signals
     256           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     257           1 :         [&](const std::string&,
     258             :             int status,
     259             :             const std::string&,
     260             :             const std::string&) {
     261           1 :             nameNotFound = status == 2;
     262           1 :             cv.notify_one();
     263           1 :         }));
     264           1 :     libjami::registerSignalHandlers(confHandlers);
     265           1 :     CPPUNIT_ASSERT(libjami::lookupName(aliceId, "", "nottaken"));
     266           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return nameNotFound; }));
     267           1 : }
     268             : 
     269             : void
     270           1 : NameDirectoryTest::testLookupAddr()
     271             : {
     272           1 :     std::mutex mtx;
     273           1 :     std::unique_lock lk {mtx};
     274           1 :     std::condition_variable cv;
     275           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     276           1 :     bool addrFound {false};
     277             :     // Watch signals
     278           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     279           1 :         [&](const std::string&,
     280             :             int status,
     281             :             const std::string&,
     282             :             const std::string&) {
     283           1 :             addrFound = status == 0;
     284           1 :             cv.notify_one();
     285           1 :         }));
     286           1 :     libjami::registerSignalHandlers(confHandlers);
     287           1 :     CPPUNIT_ASSERT(libjami::lookupAddress(aliceId, "", "c0dec0dec0dec0dec0dec0dec0dec0dec0dec0de"));
     288           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return addrFound; }));
     289           1 : }
     290             : 
     291             : void
     292           1 : NameDirectoryTest::testLookupAddrInvalid()
     293             : {
     294           1 :     std::mutex mtx;
     295           1 :     std::unique_lock lk {mtx};
     296           1 :     std::condition_variable cv;
     297           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     298           1 :     bool addrInvalid {false};
     299             :     // Watch signals
     300           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     301           1 :         [&](const std::string&,
     302             :             int status,
     303             :             const std::string&,
     304             :             const std::string&) {
     305           1 :             addrInvalid = status == 1;
     306           1 :             cv.notify_one();
     307           1 :         }));
     308           1 :     libjami::registerSignalHandlers(confHandlers);
     309           1 :     CPPUNIT_ASSERT(libjami::lookupName(aliceId, "", "===="));
     310           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return addrInvalid; }));
     311           1 : }
     312             : 
     313             : void
     314           1 : NameDirectoryTest::testLookupAddrNotFound()
     315             : {
     316           1 :     std::mutex mtx;
     317           1 :     std::unique_lock lk {mtx};
     318           1 :     std::condition_variable cv;
     319           1 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     320           1 :     bool addrNotFound {false};
     321             :     // Watch signals
     322           1 :     confHandlers.insert(libjami::exportable_callback<libjami::ConfigurationSignal::RegisteredNameFound>(
     323           1 :         [&](const std::string&,
     324             :             int status,
     325             :             const std::string&,
     326             :             const std::string&) {
     327           1 :             addrNotFound = status == 2;
     328           1 :             cv.notify_one();
     329           1 :         }));
     330           1 :     libjami::registerSignalHandlers(confHandlers);
     331           1 :     CPPUNIT_ASSERT(libjami::lookupAddress(aliceId, "", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"));
     332           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return addrNotFound; }));
     333           1 : }
     334             : 
     335             : } // namespace test
     336             : } // namespace jami
     337             : 
     338           1 : RING_TEST_RUNNER(jami::test::NameDirectoryTest::name())

Generated by: LCOV version 1.14