LCOV - code coverage report
Current view: top level - test/unitTest - common.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 98 103 95.1 %
Date: 2024-11-15 09:04:49 Functions: 10 10 100.0 %

          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 <yaml-cpp/yaml.h>
      23             : 
      24             : #include "common.h"
      25             : 
      26             : /* Jami */
      27             : #include "account_const.h"
      28             : #include "jami.h"
      29             : #include "fileutils.h"
      30             : #include "manager.h"
      31             : 
      32             : /* Make GCC quiet about unused functions */
      33             : #pragma GCC diagnostic push
      34             : #pragma GCC diagnostic ignored "-Wunused-function"
      35             : 
      36             : void
      37         265 : wait_for_announcement_of(const std::vector<std::string> accountIDs,
      38             :                          std::chrono::seconds timeout)
      39             : {
      40         265 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
      41         265 :     std::mutex mtx;
      42         265 :     std::unique_lock lk {mtx};
      43         265 :     std::condition_variable cv;
      44         265 :     std::vector<std::atomic_bool> accountsReady(accountIDs.size());
      45             : 
      46         265 :     size_t to_be_announced = accountIDs.size();
      47             : 
      48         265 :     confHandlers.insert(
      49         530 :         libjami::exportable_callback<libjami::ConfigurationSignal::VolatileDetailsChanged>(
      50        2554 :             [&,
      51         265 :              accountIDs = std::move(accountIDs)](const std::string& accountID,
      52             :                                                  const std::map<std::string, std::string>& details) {
      53       11077 :                 for (size_t i = 0; i < accountIDs.size(); ++i) {
      54        8523 :                     if (accountIDs[i] != accountID) {
      55        6111 :                         continue;
      56             :                     }
      57             : 
      58        2412 :                     if (jami::Manager::instance().getAccount(accountID)->getAccountType() == "SIP") {
      59           4 :                         auto daemonStatus = details.at(libjami::Account::ConfProperties::Registration::STATUS);
      60           2 :                         if (daemonStatus != "REGISTERED") {
      61           0 :                             continue;
      62             :                         }
      63           2 :                     } else {
      64             :                         try {
      65        4217 :                             if ("true"
      66        2410 :                                 != details.at(libjami::Account::VolatileProperties::DEVICE_ANNOUNCED)) {
      67        1807 :                                 continue;
      68             :                             }
      69           0 :                         } catch (const std::out_of_range&) {
      70           0 :                             continue;
      71           0 :                         }
      72             :                     }
      73             : 
      74         605 :                     accountsReady[i] = true;
      75         605 :                     cv.notify_one();
      76             :                 }
      77        2554 :             }));
      78             : 
      79         265 :     JAMI_DBG("Waiting for %zu account to be announced...", to_be_announced);
      80             : 
      81         265 :     libjami::registerSignalHandlers(confHandlers);
      82             : 
      83        1991 :     CPPUNIT_ASSERT(cv.wait_for(lk, timeout, [&] {
      84             :         for (const auto& rdy : accountsReady) {
      85             :             if (not rdy) {
      86             :                 return false;
      87             :             }
      88             :         }
      89             : 
      90             :         return true;
      91             :     }));
      92             : 
      93         265 :     libjami::unregisterSignalHandlers();
      94             : 
      95         265 :     JAMI_DBG("%zu account announced!", to_be_announced);
      96         265 : }
      97             : 
      98             : void
      99           8 : wait_for_announcement_of(const std::string& accountId,
     100             :                          std::chrono::seconds timeout)
     101             : {
     102          16 :     wait_for_announcement_of(std::vector<std::string> {accountId}, timeout);
     103           8 : }
     104             : 
     105             : void
     106         267 : wait_for_removal_of(const std::vector<std::string> accounts,
     107             :                     std::chrono::seconds timeout)
     108             : {
     109         267 :     JAMI_INFO("Removing %zu accounts...", accounts.size());
     110             : 
     111         267 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     112         267 :     std::mutex mtx;
     113         267 :     std::unique_lock lk {mtx};
     114         267 :     std::condition_variable cv;
     115         267 :     std::atomic_bool accountsRemoved {false};
     116             : 
     117         267 :     size_t current = jami::Manager::instance().getAccountList().size();
     118             : 
     119             :     /* Prevent overflow */
     120         267 :     CPPUNIT_ASSERT(current >= accounts.size());
     121             : 
     122         267 :     size_t target = current - accounts.size();
     123             : 
     124         267 :     confHandlers.insert(
     125         534 :         libjami::exportable_callback<libjami::ConfigurationSignal::AccountsChanged>([&]() {
     126         784 :             if (jami::Manager::instance().getAccountList().size() <= target) {
     127         267 :                 accountsRemoved = true;
     128         267 :                 cv.notify_one();
     129             :             }
     130         784 :         }));
     131             : 
     132         267 :     libjami::unregisterSignalHandlers();
     133         267 :     libjami::registerSignalHandlers(confHandlers);
     134             : 
     135        1051 :     for (const auto& account : accounts) {
     136         784 :         jami::Manager::instance().removeAccount(account, true);
     137             :     }
     138             : 
     139         534 :     CPPUNIT_ASSERT(cv.wait_for(lk, timeout, [&] { return accountsRemoved.load(); }));
     140             : 
     141         267 :     libjami::unregisterSignalHandlers();
     142         267 : }
     143             : 
     144             : void
     145          14 : wait_for_removal_of(const std::string& account,
     146             :                     std::chrono::seconds timeout)
     147             : {
     148          28 :     wait_for_removal_of(std::vector<std::string>{account}, timeout);
     149          14 : }
     150             : 
     151             : std::map<std::string, std::string>
     152         258 : load_actors(const std::filesystem::path& from_yaml)
     153             : {
     154         258 :     std::map<std::string, std::string> actors {};
     155             : 
     156         258 :     std::ifstream file(from_yaml);
     157             : 
     158         258 :     CPPUNIT_ASSERT(file.is_open());
     159             : 
     160         258 :     YAML::Node node = YAML::Load(file);
     161             : 
     162         258 :     CPPUNIT_ASSERT(node.IsMap());
     163             : 
     164         258 :     auto default_account = node["default-account"];
     165             : 
     166         516 :     std::map<std::string, std::string> default_details = libjami::getAccountTemplate(default_account["type"].as<std::string>());
     167         258 :     if (default_account.IsMap()) {
     168        1546 :         for (const auto& kv : default_account) {
     169        1288 :             auto key = kv.first.as<std::string>();
     170        1288 :             if (default_details.find(key) != default_details.end()) {
     171           1 :                 default_details[key] = kv.second.as<std::string>();
     172             :             } else {
     173        1287 :                 default_details["Account." + key] = kv.second.as<std::string>();
     174             :             }
     175        1546 :         }
     176             :     }
     177             : 
     178         258 :     auto accounts = node["accounts"];
     179             : 
     180         258 :     CPPUNIT_ASSERT(accounts.IsMap());
     181             : 
     182         998 :     for (const auto& kv : accounts) {
     183         740 :         auto account_name = kv.first.as<std::string>();
     184         740 :         auto account = kv.second.as<YAML::Node>();
     185         740 :         auto details = std::map<std::string, std::string>(default_details);
     186             : 
     187        2236 :         for (const auto& detail : account) {
     188        1496 :             auto key = detail.first.as<std::string>();
     189        1496 :             if (details.find(key) != details.end()) {
     190           0 :                 details[key] = detail.second.as<std::string>();
     191             :             } else {
     192        1496 :                 details["Account." + key] = detail.second.as<std::string>();
     193             :             }
     194        2236 :         }
     195             : 
     196         740 :         actors[account_name] = jami::Manager::instance().addAccount(details);
     197         998 :     }
     198             : 
     199         516 :     return actors;
     200         258 : }
     201             : 
     202             : std::map<std::string, std::string>
     203          97 : load_actors_and_wait_for_announcement(const std::string& from_yaml)
     204             : {
     205          97 :     auto actors = load_actors(from_yaml);
     206             : 
     207          97 :     std::vector<std::string> wait_for;
     208             : 
     209          97 :     wait_for.reserve(actors.size());
     210             : 
     211         350 :     for (auto it = actors.cbegin(); it != actors.cend(); ++it) {
     212         253 :         wait_for.emplace_back(it->second);
     213             :     }
     214             : 
     215          97 :     wait_for_announcement_of(wait_for);
     216             : 
     217         194 :     return actors;
     218          97 : }
     219             : 
     220             : #pragma GCC diagnostic pop

Generated by: LCOV version 1.14