Skip to content
Snippets Groups Projects
Commit efe27372 authored by Adrien Béraud's avatar Adrien Béraud
Browse files

add tests

Change-Id: I0782b614c3028b8e846d995cb5dbb81f04eb563b
parent 612b55b1
Branches
No related tags found
No related merge requests found
...@@ -3,9 +3,11 @@ project(dhtnet) ...@@ -3,9 +3,11 @@ project(dhtnet)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(CTest)
find_package (PkgConfig REQUIRED) find_package (PkgConfig REQUIRED)
find_package(msgpack REQUIRED QUIET CONFIG NAMES msgpack msgpack-cxx) find_package(msgpack REQUIRED QUIET CONFIG NAMES msgpack msgpack-cxx)
find_package(fmt)
pkg_check_modules (opendht REQUIRED IMPORTED_TARGET opendht>=2.6.0) pkg_check_modules (opendht REQUIRED IMPORTED_TARGET opendht>=2.6.0)
pkg_check_modules (pjproject REQUIRED IMPORTED_TARGET libpjproject) pkg_check_modules (pjproject REQUIRED IMPORTED_TARGET libpjproject)
...@@ -30,8 +32,25 @@ list (APPEND dhtnet_HEADERS ...@@ -30,8 +32,25 @@ list (APPEND dhtnet_HEADERS
) )
add_library(dhtnet ${dhtnet_SOURCES}) add_library(dhtnet ${dhtnet_SOURCES})
target_link_libraries(dhtnet PUBLIC PkgConfig::opendht msgpack-cxx) target_link_libraries(dhtnet PUBLIC PkgConfig::opendht fmt::fmt msgpack-cxx)
target_include_directories(dhtnet PUBLIC include) target_include_directories(dhtnet PUBLIC include)
target_compile_definitions(dhtnet PRIVATE add_compile_definitions(PJ_AUTOCONF=1)
PJ_AUTOCONF=1
) if (BUILD_TESTING AND NOT MSVC)
pkg_search_module(Cppunit REQUIRED IMPORTED_TARGET cppunit)
add_executable(tests_certstore tests/certstore.cpp)
target_link_libraries(tests_certstore PRIVATE dhtnet fmt::fmt PkgConfig::Cppunit)
add_test(NAME tests_certstore COMMAND tests_certstore)
add_executable(tests_connectionManager tests/connectionManager.cpp)
target_link_libraries(tests_connectionManager PRIVATE dhtnet fmt::fmt PkgConfig::Cppunit)
add_test(NAME tests_connectionManager COMMAND tests_connectionManager)
#add_executable(tests_fileutils tests/testFileutils.cpp)
#target_link_libraries(tests_fileutils PRIVATE dhtnet fmt::fmt PkgConfig::Cppunit)
#add_test(NAME tests_fileutils COMMAND tests_fileutils)
#add_executable(tests_stringutils tests/testString_utils.cpp)
#target_link_libraries(tests_stringutils PRIVATE dhtnet fmt::fmt PkgConfig::Cppunit)
#add_test(NAME tests_stringutils COMMAND tests_stringutils)
endif()
\ No newline at end of file
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
*
* Author: florian Wiesweg <florian.wiesweg@campus.tu-berlin.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include "test_runner.h"
#include "certstore.h"
namespace jami {
namespace test {
class CertStoreTest : public CppUnit::TestFixture
{
public:
CertStoreTest()
{
}
~CertStoreTest() { }
static std::string name() { return "certstore"; }
void setUp();
void tearDown();
std::string aliceId;
std::string bobId;
private:
void trustStoreTest();
void getCertificateWithSplitted();
CPPUNIT_TEST_SUITE(CertStoreTest);
CPPUNIT_TEST(trustStoreTest);
CPPUNIT_TEST(getCertificateWithSplitted);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(CertStoreTest, CertStoreTest::name());
void
CertStoreTest::setUp()
{
/*auto actors = load_actors_and_wait_for_announcement("actors/alice-bob.yml");
aliceId = actors["alice"];
bobId = actors["bob"];*/
}
void
CertStoreTest::tearDown()
{
//wait_for_removal_of({aliceId, bobId});
}
void
CertStoreTest::trustStoreTest()
{
//auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto ca = dht::crypto::generateIdentity("test CA");
auto account = dht::crypto::generateIdentity("test account", ca, 4096, true);
auto device = dht::crypto::generateIdentity("test device", account);
auto device2 = dht::crypto::generateIdentity("test device 2", account);
/*auto storeSize = aliceAccount->certStore().getPinnedCertificates().size();
auto id = ca.second->getId().toString();
auto pinned = aliceAccount->certStore().getPinnedCertificates();
CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; })
== pinned.end());
// Test certificate status
auto certAllowed = aliceAccount->accountManager()->getCertificatesByStatus(
jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(
std::find_if(certAllowed.begin(), certAllowed.end(), [&](auto v) { return v == id; })
== certAllowed.end());
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id)
== jami::tls::TrustStore::PermissionStatus::UNDEFINED);
aliceAccount->setCertificateStatus(ca.second, jami::tls::TrustStore::PermissionStatus::ALLOWED);
certAllowed = aliceAccount->accountManager()->getCertificatesByStatus(
jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(
std::find_if(certAllowed.begin(), certAllowed.end(), [&](auto v) { return v == id; })
!= certAllowed.end());
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id)
== jami::tls::TrustStore::PermissionStatus::ALLOWED);
aliceAccount->setCertificateStatus(ca.second, jami::tls::TrustStore::PermissionStatus::UNDEFINED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id)
== jami::tls::TrustStore::PermissionStatus::UNDEFINED);
aliceAccount->setCertificateStatus(ca.second, jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id)
== jami::tls::TrustStore::PermissionStatus::ALLOWED);
// Test getPinnedCertificates
pinned = aliceAccount->certStore().getPinnedCertificates();
CPPUNIT_ASSERT(pinned.size() == storeSize + 2);
CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; })
!= pinned.end());
// Test findCertificateByUID & findIssuer
CPPUNIT_ASSERT(!aliceAccount->certStore().findCertificateByUID("NON_EXISTING_ID"));
auto cert = aliceAccount->certStore().findCertificateByUID(id);
CPPUNIT_ASSERT(cert);
auto issuer = aliceAccount->certStore().findIssuer(cert);
CPPUNIT_ASSERT(issuer);
CPPUNIT_ASSERT(issuer->getId().toString() == id);
// Test is allowed
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second));
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second));
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*device.second));
// Ban device
aliceAccount->setCertificateStatus(device.second, jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(device.second->getId().toString())
== jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(id)
== jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second));
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second));
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device.second));
// Ban account
aliceAccount->setCertificateStatus(account.second, jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(account.second->getId().toString())
== jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second));
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*account.second));
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device2.second));
// Unban account
aliceAccount->setCertificateStatus(account.second,
jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(account.second->getId().toString())
== jami::tls::TrustStore::PermissionStatus::ALLOWED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*ca.second));
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*account.second));
CPPUNIT_ASSERT(aliceAccount->accountManager()->isAllowed(*device2.second));
// Ban CA
aliceAccount->setCertificateStatus(ca.second, jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(ca.second->getId().toString())
== jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*ca.second));
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*account.second));
CPPUNIT_ASSERT(not aliceAccount->accountManager()->isAllowed(*device2.second));
aliceAccount->setCertificateStatus(ca.second, jami::tls::TrustStore::PermissionStatus::BANNED);
CPPUNIT_ASSERT(aliceAccount->accountManager()->getCertificateStatus(ca.second->getId().toString())
== jami::tls::TrustStore::PermissionStatus::BANNED);
// Test unpin
aliceAccount->certStore().unpinCertificate(id);
pinned = aliceAccount->certStore().getPinnedCertificates();
CPPUNIT_ASSERT(std::find_if(pinned.begin(), pinned.end(), [&](auto v) { return v == id; })
== pinned.end());
// Test statusToStr
CPPUNIT_ASSERT(strcmp(jami::tls::statusToStr(jami::tls::TrustStatus::TRUSTED),
libjami::Certificate::TrustStatus::TRUSTED)
== 0);
CPPUNIT_ASSERT(strcmp(jami::tls::statusToStr(jami::tls::TrustStatus::UNTRUSTED),
libjami::Certificate::TrustStatus::UNTRUSTED)
== 0);*/
}
void
CertStoreTest::getCertificateWithSplitted()
{
//auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto ca = dht::crypto::generateIdentity("test CA");
auto account = dht::crypto::generateIdentity("test account", ca, 4096, true);
auto device = dht::crypto::generateIdentity("test device", account);
auto caCert = std::make_shared<dht::crypto::Certificate>(ca.second->toString(false));
auto accountCert = std::make_shared<dht::crypto::Certificate>(account.second->toString(false));
auto devicePartialCert = std::make_shared<dht::crypto::Certificate>(
device.second->toString(false));
/*aliceAccount->certStore().pinCertificate(caCert);
aliceAccount->certStore().pinCertificate(accountCert);
aliceAccount->certStore().pinCertificate(devicePartialCert);
auto fullCert = aliceAccount->certStore().getCertificate(device.second->getId().toString());
CPPUNIT_ASSERT(fullCert->issuer && fullCert->issuer->getUID() == accountCert->getUID());
CPPUNIT_ASSERT(fullCert->issuer->issuer
&& fullCert->issuer->issuer->getUID() == caCert->getUID());*/
}
} // namespace test
} // namespace jami
JAMI_TEST_RUNNER(jami::test::CertStoreTest::name());
/*
* Copyright (C) 2017-2023 Savoir-faire Linux Inc.
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include <condition_variable>
#include "connectionmanager.h"
#include "multiplexed_socket.h"
#include "test_runner.h"
using namespace std::literals::chrono_literals;
namespace jami {
namespace test {
class ConnectionManagerTest : public CppUnit::TestFixture
{
public:
ConnectionManagerTest() {}
~ConnectionManagerTest() { }
static std::string name() { return "ConnectionManager"; }
void setUp();
void tearDown();
std::string aliceId;
std::string bobId;
private:
void testConnectDevice();
void testAcceptConnection();
void testMultipleChannels();
void testMultipleChannelsOneDeclined();
void testMultipleChannelsSameName();
void testDeclineConnection();
void testSendReceiveData();
void testAcceptsICERequest();
void testDeclineICERequest();
void testChannelRcvShutdown();
void testChannelSenderShutdown();
void testCloseConnectionWith();
void testShutdownCallbacks();
void testFloodSocket();
void testDestroyWhileSending();
void testIsConnecting();
void testCanSendBeacon();
void testCannotSendBeacon();
void testConnectivityChangeTriggerBeacon();
void testOnNoBeaconTriggersShutdown();
void testShutdownWhileNegotiating();
CPPUNIT_TEST_SUITE(ConnectionManagerTest);
CPPUNIT_TEST(testConnectDevice);
CPPUNIT_TEST(testAcceptConnection);
CPPUNIT_TEST(testMultipleChannels);
CPPUNIT_TEST(testMultipleChannelsOneDeclined);
CPPUNIT_TEST(testMultipleChannelsSameName);
CPPUNIT_TEST(testDeclineConnection);
CPPUNIT_TEST(testSendReceiveData);
CPPUNIT_TEST(testAcceptsICERequest);
CPPUNIT_TEST(testDeclineICERequest);
CPPUNIT_TEST(testChannelRcvShutdown);
CPPUNIT_TEST(testChannelSenderShutdown);
CPPUNIT_TEST(testCloseConnectionWith);
CPPUNIT_TEST(testShutdownCallbacks);
CPPUNIT_TEST(testFloodSocket);
CPPUNIT_TEST(testDestroyWhileSending);
CPPUNIT_TEST(testIsConnecting);
CPPUNIT_TEST(testCanSendBeacon);
CPPUNIT_TEST(testCannotSendBeacon);
CPPUNIT_TEST(testConnectivityChangeTriggerBeacon);
CPPUNIT_TEST(testOnNoBeaconTriggersShutdown);
CPPUNIT_TEST(testShutdownWhileNegotiating);
CPPUNIT_TEST_SUITE_END();
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ConnectionManagerTest, ConnectionManagerTest::name());
void
ConnectionManagerTest::setUp()
{
/*auto actors = load_actors_and_wait_for_announcement("actors/alice-bob.yml");
aliceId = actors["alice"];
bobId = actors["bob"];
// Pin certificate from one to another certstore (because we do not perform any DHT operation in this test)
auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
bobAccount->certStore().pinCertificate(aliceAccount->identity().second);
aliceAccount->certStore().pinCertificate(bobAccount->identity().second);*/
}
void
ConnectionManagerTest::tearDown()
{
//wait_for_removal_of({aliceId, bobId});
}
void
ConnectionManagerTest::testConnectDevice()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv, cvReceive;
bool successfullyConnected = false;
bool successfullyReceive = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive, &cvReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "git://*";
cvReceive.notify_one();
return true;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cvReceive.wait_for(lk, 60s, [&] { return successfullyReceive; }));
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyConnected; }));*/
}
void
ConnectionManagerTest::testAcceptConnection()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "git://*";
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string& name,
std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket && (name == "git://*");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return successfullyReceive && successfullyConnected && receiverConnected;
}));*/
}
void
ConnectionManagerTest::testMultipleChannels()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyConnected2 = false;
int receiverConnected = 0;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string&,
std::shared_ptr<ChannelSocket> socket) {
if (socket)
receiverConnected += 1;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected2 = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
}));
CPPUNIT_ASSERT(aliceAccount->connectionManager().activeSockets() == 1);*/
}
void
ConnectionManagerTest::testMultipleChannelsOneDeclined()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyNotConnected = false;
bool successfullyConnected2 = false;
int receiverConnected = 0;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string& name) {
if (name == "git://*")
return false;
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
if (socket)
receiverConnected += 1;
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (!socket)
successfullyNotConnected = true;
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket)
successfullyConnected2 = true;
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return successfullyNotConnected && successfullyConnected2 && receiverConnected == 1;
}));
CPPUNIT_ASSERT(aliceAccount->connectionManager().activeSockets() == 1);*/
}
void
ConnectionManagerTest::testMultipleChannelsSameName()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyConnected2 = false;
int receiverConnected = 0;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string&,
std::shared_ptr<ChannelSocket> socket) {
if (socket)
receiverConnected += 1;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
// We can open two sockets with the same name, it will be two different channel
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected2 = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return successfullyConnected && successfullyConnected2 && receiverConnected == 2;
}));*/
}
void
ConnectionManagerTest::testSendReceiveData()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
std::atomic_int events(0);
bool successfullyConnected = false, successfullyConnected2 = false, successfullyReceive = false,
receiverConnected = false;
const uint8_t buf_other[] = {0x64, 0x65, 0x66, 0x67};
const uint8_t buf_test[] = {0x68, 0x69, 0x70, 0x71};
bool dataOk = false, dataOk2 = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string&) {
successfullyReceive = true;
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
if (socket && (name == "test" || name == "other")) {
receiverConnected = true;
std::error_code ec;
auto res = socket->waitForData(std::chrono::milliseconds(5000), ec);
if (res == 4) {
uint8_t buf[4];
socket->read(&buf[0], 4, ec);
if (name == "test")
dataOk = std::equal(std::begin(buf), std::end(buf), std::begin(buf_test));
else
dataOk2 = std::equal(std::begin(buf), std::end(buf), std::begin(buf_other));
events++;
cv.notify_one();
}
}
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"test",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
std::error_code ec;
socket->write(&buf_test[0], 4, ec);
}
events++;
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"other",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected2 = true;
std::error_code ec;
socket->write(&buf_other[0], 4, ec);
}
events++;
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return events == 4 && successfullyReceive && successfullyConnected && successfullyConnected2
&& dataOk && dataOk2;
}));*/
}
void
ConnectionManagerTest::testDeclineConnection()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string&) {
successfullyReceive = true;
return false;
});
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string&,
std::shared_ptr<ChannelSocket> socket) {
if (socket)
receiverConnected = true;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
cv.wait_for(lk, 30s);
CPPUNIT_ASSERT(successfullyReceive);
CPPUNIT_ASSERT(!successfullyConnected);
CPPUNIT_ASSERT(!receiverConnected);*/
}
void
ConnectionManagerTest::testAcceptsICERequest()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onICERequest([&](const DeviceId&) {
successfullyReceive = true;
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string& name,
std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket && (name == "git://*");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
return successfullyReceive && successfullyConnected && receiverConnected;
}));*/
}
void
ConnectionManagerTest::testDeclineICERequest()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onICERequest([&](const DeviceId&) {
successfullyReceive = true;
return false;
});
bobAccount->connectionManager().onConnectionReady(
[&receiverConnected](const DeviceId&,
const std::string& name,
std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket && (name == "git://*");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
cv.wait_for(lk, 30s);
CPPUNIT_ASSERT(successfullyReceive);
CPPUNIT_ASSERT(!receiverConnected);
CPPUNIT_ASSERT(!successfullyConnected);*/
}
void
ConnectionManagerTest::testChannelRcvShutdown()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool shutdownReceived = false;
std::shared_ptr<ChannelSocket> bobSock;
bobAccount->connectionManager().onChannelRequest(
[](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId& did, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
if (socket && name == "git://*" && did != bobDeviceId) {
bobSock = socket;
cv.notify_one();
}
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
socket->onShutdown([&] {
shutdownReceived = true;
cv.notify_one();
});
successfullyConnected = true;
cv.notify_one();
}
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return bobSock && successfullyConnected; }));
bobSock->shutdown();
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return shutdownReceived; }));*/
}
void
ConnectionManagerTest::testChannelSenderShutdown()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable rcv, scv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bool shutdownReceived = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "git://*";
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
if (socket) {
socket->onShutdown([&] {
shutdownReceived = true;
scv.notify_one();
});
}
receiverConnected = socket && (name == "git://*");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
rcv.notify_one();
socket->shutdown();
}
});
rcv.wait_for(lk, 30s);
scv.wait_for(lk, 30s);
CPPUNIT_ASSERT(shutdownReceived);
CPPUNIT_ASSERT(successfullyReceive);
CPPUNIT_ASSERT(successfullyConnected);
CPPUNIT_ASSERT(receiverConnected);*/
}
void
ConnectionManagerTest::testCloseConnectionWith()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
auto bobUri = bobAccount->getUsername();
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable rcv, scv;
std::atomic_int events(0);
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "git://*";
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
if (socket) {
socket->onShutdown([&] {
events += 1;
scv.notify_one();
});
}
receiverConnected = socket && (name == "git://*");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
socket->onShutdown([&] {
events += 1;
scv.notify_one();
});
successfullyConnected = true;
rcv.notify_one();
}
});
rcv.wait_for(lk, 30s);
// This should trigger onShutdown
aliceAccount->connectionManager().closeConnectionsWith(bobUri);
CPPUNIT_ASSERT(scv.wait_for(lk, 60s, [&] {
return events == 2 && successfullyReceive && successfullyConnected && receiverConnected;
}));*/
}
void
ConnectionManagerTest::testShutdownCallbacks()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
auto aliceUri = aliceAccount->getUsername();
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable rcv, chan2cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive, &chan2cv](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
if (name == "1") {
successfullyReceive = true;
} else {
chan2cv.notify_one();
// Do not return directly. Let the connection be closed
std::this_thread::sleep_for(10s);
}
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket && (name == "1");
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"1",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
rcv.notify_one();
}
});
// Connect first channel. This will initiate a mx sock
CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] {
return successfullyReceive && successfullyConnected && receiverConnected;
}));
// Connect another channel, but close the connection
bool channel2NotConnected = false;
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"2",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
channel2NotConnected = !socket;
rcv.notify_one();
});
chan2cv.wait_for(lk, 30s);
// This should trigger onShutdown for second callback
bobAccount->connectionManager().closeConnectionsWith(aliceUri);
CPPUNIT_ASSERT(rcv.wait_for(lk, 30s, [&] { return channel2NotConnected; }));*/
}
void
ConnectionManagerTest::testFloodSocket()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
std::shared_ptr<ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2, sendSock3;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "1";
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket != nullptr;
if (name == "1")
rcvSock1 = socket;
else if (name == "2")
rcvSock2 = socket;
else if (name == "3")
rcvSock3 = socket;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"1",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
return successfullyReceive && successfullyConnected && receiverConnected;
}));
CPPUNIT_ASSERT(receiverConnected);
successfullyConnected = false;
receiverConnected = false;
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"2",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock2 = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
successfullyConnected = false;
receiverConnected = false;
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"3",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock3 = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
std::mutex mtxRcv {};
std::string alphabet, shouldRcv, rcv1, rcv2, rcv3;
for (int i = 0; i < 100; ++i)
alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
rcvSock1->setOnRecv([&](const uint8_t* buf, size_t len) {
rcv1 += std::string(buf, buf + len);
return len;
});
rcvSock2->setOnRecv([&](const uint8_t* buf, size_t len) {
rcv2 += std::string(buf, buf + len);
return len;
});
rcvSock3->setOnRecv([&](const uint8_t* buf, size_t len) {
rcv3 += std::string(buf, buf + len);
return len;
});
for (uint64_t i = 0; i < alphabet.size(); ++i) {
auto send = std::string(8000, alphabet[i]);
shouldRcv += send;
std::error_code ec;
sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
CPPUNIT_ASSERT(!ec);
}
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] {
return shouldRcv == rcv1 && shouldRcv == rcv2 && shouldRcv == rcv3;
}));*/
}
void
ConnectionManagerTest::testDestroyWhileSending()
{
// Same as test before, but destroy the accounts while sending.
// This test if a segfault occurs
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
bool successfullyReceive = false;
bool receiverConnected = false;
std::shared_ptr<ChannelSocket> rcvSock1, rcvSock2, rcvSock3, sendSock, sendSock2, sendSock3;
bobAccount->connectionManager().onChannelRequest(
[&successfullyReceive](const std::shared_ptr<dht::crypto::Certificate>&,
const std::string& name) {
successfullyReceive = name == "1";
return true;
});
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string& name, std::shared_ptr<ChannelSocket> socket) {
receiverConnected = socket != nullptr;
if (name == "1")
rcvSock1 = socket;
else if (name == "2")
rcvSock2 = socket;
else if (name == "3")
rcvSock3 = socket;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"1",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] {
return successfullyReceive && successfullyConnected && receiverConnected;
}));
successfullyConnected = false;
receiverConnected = false;
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"2",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock2 = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
successfullyConnected = false;
receiverConnected = false;
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"3",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
sendSock3 = socket;
successfullyConnected = true;
}
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyConnected && receiverConnected; }));
std::mutex mtxRcv {};
std::string alphabet;
for (int i = 0; i < 100; ++i)
alphabet += "QWERTYUIOPASDFGHJKLZXCVBNM";
rcvSock1->setOnRecv([&](const uint8_t*, size_t len) { return len; });
rcvSock2->setOnRecv([&](const uint8_t*, size_t len) { return len; });
rcvSock3->setOnRecv([&](const uint8_t*, size_t len) { return len; });
for (uint64_t i = 0; i < alphabet.size(); ++i) {
auto send = std::string(8000, alphabet[i]);
std::error_code ec;
sendSock->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
sendSock2->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
sendSock3->write(reinterpret_cast<unsigned char*>(send.data()), send.size(), ec);
CPPUNIT_ASSERT(!ec);
}*/
// No need to wait, immediately destroy, no segfault must occurs
}
void
ConnectionManagerTest::testIsConnecting()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false, successfullyReceive = false;
bobAccount->connectionManager().onChannelRequest(
[&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) {
successfullyReceive = true;
cv.notify_one();
std::this_thread::sleep_for(2s);
return true;
});
CPPUNIT_ASSERT(!aliceAccount->connectionManager().isConnecting(bobDeviceId, "sip"));
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
successfullyConnected = true;
}
cv.notify_one();
});
// connectDevice is full async, so isConnecting will be true after a few ms.
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyReceive; }));
CPPUNIT_ASSERT(aliceAccount->connectionManager().isConnecting(bobDeviceId, "sip"));
CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&] { return successfullyConnected; }));
std::this_thread::sleep_for(
std::chrono::milliseconds(100)); // Just to wait for the callback to finish
CPPUNIT_ASSERT(!aliceAccount->connectionManager().isConnecting(bobDeviceId, "sip"));*/
}
void
ConnectionManagerTest::testCanSendBeacon()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
bobAccount->connectionManager().onChannelRequest(
[&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
if (socket && socket->name() == "sip")
bobSocket = socket->underlyingSocket();
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
aliceSocket = socket->underlyingSocket();
successfullyConnected = true;
}
cv.notify_one();
});
// connectDevice is full async, so isConnecting will be true after a few ms.
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket && successfullyConnected; }));
CPPUNIT_ASSERT(aliceSocket->canSendBeacon());
// Because onConnectionReady is true before version is sent, we can wait a bit
// before canSendBeacon is true.
auto start = std::chrono::steady_clock::now();
auto aliceCanSendBeacon = false;
auto bobCanSendBeacon = false;
do {
aliceCanSendBeacon = aliceSocket->canSendBeacon();
bobCanSendBeacon = bobSocket->canSendBeacon();
if (!bobCanSendBeacon || !aliceCanSendBeacon)
std::this_thread::sleep_for(1s);
} while ((not bobCanSendBeacon or not aliceCanSendBeacon)
and std::chrono::steady_clock::now() - start < 5s);
CPPUNIT_ASSERT(bobCanSendBeacon && aliceCanSendBeacon);*/
}
void
ConnectionManagerTest::testCannotSendBeacon()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
bobAccount->connectionManager().onChannelRequest(
[&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
if (socket && socket->name() == "sip")
bobSocket = socket->underlyingSocket();
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
aliceSocket = socket->underlyingSocket();
successfullyConnected = true;
}
cv.notify_one();
});
// connectDevice is full async, so isConnecting will be true after a few ms.
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
int version = 1412;
bobSocket->setOnVersionCb([&](auto v) {
version = v;
cv.notify_one();
});
aliceSocket->setVersion(0);
aliceSocket->sendVersion();
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return version == 0; }));
CPPUNIT_ASSERT(!bobSocket->canSendBeacon());*/
}
void
ConnectionManagerTest::testConnectivityChangeTriggerBeacon()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
bobAccount->connectionManager().onChannelRequest(
[&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
if (socket && socket->name() == "sip")
bobSocket = socket->underlyingSocket();
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
aliceSocket = socket->underlyingSocket();
successfullyConnected = true;
}
cv.notify_one();
});
// connectDevice is full async, so isConnecting will be true after a few ms.
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
bool hasRequest = false;
bobSocket->setOnBeaconCb([&](auto p) {
if (p)
hasRequest = true;
cv.notify_one();
});
aliceAccount->connectionManager().connectivityChanged();
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return hasRequest; }));*/
}
void
ConnectionManagerTest::testOnNoBeaconTriggersShutdown()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyConnected = false;
std::shared_ptr<MultiplexedSocket> aliceSocket, bobSocket;
bobAccount->connectionManager().onChannelRequest(
[&](const std::shared_ptr<dht::crypto::Certificate>&, const std::string&) { return true; });
bobAccount->connectionManager().onConnectionReady(
[&](const DeviceId&, const std::string&, std::shared_ptr<ChannelSocket> socket) {
if (socket && socket->name() == "sip")
bobSocket = socket->underlyingSocket();
cv.notify_one();
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"sip",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
if (socket) {
aliceSocket = socket->underlyingSocket();
successfullyConnected = true;
}
cv.notify_one();
});
// connectDevice is full async, so isConnecting will be true after a few ms.
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return aliceSocket && bobSocket; }));
bool isClosed = false;
aliceSocket->onShutdown([&] {
isClosed = true;
cv.notify_one();
});
bobSocket->answerToBeacon(false);
aliceAccount->connectionManager().connectivityChanged();
CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&] { return isClosed; }));*/
}
void
ConnectionManagerTest::testShutdownWhileNegotiating()
{
/*auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
bool successfullyReceive = false;
bool notConnected = false;
bobAccount->connectionManager().onICERequest([&](const DeviceId&) {
successfullyReceive = true;
cv.notify_one();
return true;
});
aliceAccount->connectionManager().connectDevice(bobDeviceId,
"git://*",
[&](std::shared_ptr<ChannelSocket> socket,
const DeviceId&) {
notConnected = !socket;
cv.notify_one();
});
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return successfullyReceive; }));
Manager::instance().setAccountActive(aliceId, false, true);
CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&] { return notConnected; }));*/
}
} // namespace test
} // namespace jami
JAMI_TEST_RUNNER(jami::test::ConnectionManagerTest::name())
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Author: Olivier Gregoire <olivier.gregoire@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include "test_runner.h"
#include "fileutils.h"
#include <string>
#include <iostream>
#include <cstdlib>
#include <unistd.h>
namespace jami { namespace fileutils { namespace test {
class FileutilsTest : public CppUnit::TestFixture {
public:
static std::string name() { return "fileutils"; }
void setUp();
void tearDown();
private:
void testCheckDir();
void testPath();
void testReadDirectory();
void testLoadFile();
void testIsDirectoryWritable();
CPPUNIT_TEST_SUITE(FileutilsTest);
CPPUNIT_TEST(testCheckDir);
CPPUNIT_TEST(testPath);
CPPUNIT_TEST(testReadDirectory);
CPPUNIT_TEST(testLoadFile);
CPPUNIT_TEST(testIsDirectoryWritable);
CPPUNIT_TEST_SUITE_END();
static constexpr auto tmpFileName = "temp_file";
std::string TEST_PATH;
std::string NON_EXISTANT_PATH_BASE;
std::string NON_EXISTANT_PATH;
std::string EXISTANT_FILE;
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FileutilsTest, FileutilsTest::name());
void
FileutilsTest::setUp()
{
char template_name[] = {"ring_unit_tests_XXXXXX"};
// Generate a temporary directory with a file inside
auto directory = mkdtemp(template_name);
CPPUNIT_ASSERT(directory);
TEST_PATH = directory;
EXISTANT_FILE = TEST_PATH + DIR_SEPARATOR_STR + tmpFileName;
NON_EXISTANT_PATH_BASE = TEST_PATH + DIR_SEPARATOR_STR + "not_existing_path";
NON_EXISTANT_PATH = NON_EXISTANT_PATH_BASE + DIR_SEPARATOR_STR + "test";
auto* fd = fopen(EXISTANT_FILE.c_str(), "w");
fwrite("RING", 1, 4, fd);
fclose(fd);
}
void
FileutilsTest::tearDown()
{
unlink(EXISTANT_FILE.c_str());
rmdir(TEST_PATH.c_str());
}
void
FileutilsTest::testCheckDir()
{
// check existed directory
CPPUNIT_ASSERT(check_dir(TEST_PATH.c_str()));
CPPUNIT_ASSERT(isDirectory(TEST_PATH.c_str()));
// check non-existent directory
CPPUNIT_ASSERT(!isDirectory(NON_EXISTANT_PATH));
CPPUNIT_ASSERT(check_dir(NON_EXISTANT_PATH.c_str()));
CPPUNIT_ASSERT(isDirectory(NON_EXISTANT_PATH));
CPPUNIT_ASSERT(removeAll(NON_EXISTANT_PATH_BASE) == 0);
CPPUNIT_ASSERT(!isDirectory(NON_EXISTANT_PATH_BASE));
//remove an non existent directory
CPPUNIT_ASSERT(removeAll(NON_EXISTANT_PATH_BASE) == -1);
}
void
FileutilsTest::testPath()
{
CPPUNIT_ASSERT(isPathRelative("relativePath"));
CPPUNIT_ASSERT(isFile(EXISTANT_FILE));
CPPUNIT_ASSERT(!isDirectory(EXISTANT_FILE));
CPPUNIT_ASSERT(isDirectory(TEST_PATH));
}
void
FileutilsTest::testReadDirectory()
{
CPPUNIT_ASSERT(recursive_mkdir(TEST_PATH + DIR_SEPARATOR_STR + "readDirectory" + DIR_SEPARATOR_STR + "test1"));
CPPUNIT_ASSERT(recursive_mkdir(TEST_PATH + DIR_SEPARATOR_STR + "readDirectory" + DIR_SEPARATOR_STR + "test2"));
auto dirs = readDirectory(TEST_PATH + DIR_SEPARATOR_STR + "readDirectory");
CPPUNIT_ASSERT(dirs.size() == 2);
CPPUNIT_ASSERT(
(dirs.at(0).compare("test1") == 0 && dirs.at(1).compare("test2") == 0)
|| (dirs.at(1).compare("test1") == 0 && dirs.at(0).compare("test2") == 0));
CPPUNIT_ASSERT(removeAll(TEST_PATH + DIR_SEPARATOR_STR + "readDirectory") == 0);
}
void
FileutilsTest::testLoadFile()
{
auto file = loadFile(EXISTANT_FILE);
CPPUNIT_ASSERT(file.size() == 4);
CPPUNIT_ASSERT(file.at(0) == 'R');
CPPUNIT_ASSERT(file.at(1) == 'I');
CPPUNIT_ASSERT(file.at(2) == 'N');
CPPUNIT_ASSERT(file.at(3) == 'G');
}
void
FileutilsTest::testIsDirectoryWritable()
{
CPPUNIT_ASSERT(recursive_mkdir(NON_EXISTANT_PATH_BASE));
CPPUNIT_ASSERT(isDirectoryWritable(NON_EXISTANT_PATH_BASE));
CPPUNIT_ASSERT(removeAll(NON_EXISTANT_PATH_BASE) == 0);
// Create directory with permission: read by owner
CPPUNIT_ASSERT(recursive_mkdir(NON_EXISTANT_PATH_BASE, 0400));
CPPUNIT_ASSERT(!isDirectoryWritable(NON_EXISTANT_PATH_BASE));
CPPUNIT_ASSERT(removeAll(NON_EXISTANT_PATH_BASE) == 0);
}
}}} // namespace jami::test::fileutils
JAMI_TEST_RUNNER(jami::fileutils::test::FileutilsTest::name());
/*
* Copyright (C) 2004-2023 Savoir-faire Linux Inc.
* Author: Olivier Gregoire <olivier.gregoire@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <cppunit/TestAssert.h>
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include "string_utils.h"
#include "test_runner.h"
#include <string>
#include <string_view>
using namespace std::literals;
namespace jami {
namespace test {
class StringUtilsTest : public CppUnit::TestFixture
{
public:
static std::string name() { return "string_utils"; }
private:
void bool_to_str_test();
void to_string_test();
void to_number_test();
void split_string_test();
CPPUNIT_TEST_SUITE(StringUtilsTest);
CPPUNIT_TEST(bool_to_str_test);
CPPUNIT_TEST(to_string_test);
CPPUNIT_TEST(to_number_test);
CPPUNIT_TEST(split_string_test);
CPPUNIT_TEST_SUITE_END();
const double DOUBLE = 3.14159265359;
const int INT = 42;
const std::string PI_DOUBLE = "3.14159265359";
const std::string PI_FLOAT = "3.14159265359";
const std::string PI_42 = "42";
};
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(StringUtilsTest, StringUtilsTest::name());
void
StringUtilsTest::bool_to_str_test()
{
CPPUNIT_ASSERT(bool_to_str(true) == TRUE_STR);
CPPUNIT_ASSERT(bool_to_str(false) == FALSE_STR);
}
void
StringUtilsTest::to_string_test()
{
// test with double
CPPUNIT_ASSERT(to_string(DOUBLE) == PI_DOUBLE);
// test with float
float varFloat = 3.14;
std::string sVarFloat = to_string(varFloat);
CPPUNIT_ASSERT(sVarFloat.at(0) == '3' && sVarFloat.at(1) == '.' && sVarFloat.at(2) == '1'
&& sVarFloat.at(3) == '4');
// test with int
CPPUNIT_ASSERT(std::to_string(INT).compare(PI_42) == 0);
CPPUNIT_ASSERT_EQUAL("0000000000000010"s, to_hex_string(16));
CPPUNIT_ASSERT_EQUAL((uint64_t)16, from_hex_string("0000000000000010"s));
}
void
StringUtilsTest::to_number_test()
{
// test with int
CPPUNIT_ASSERT(jami::stoi(PI_42) == INT);
// test with double
CPPUNIT_ASSERT(jami::stod(PI_DOUBLE) == DOUBLE);
}
void
StringUtilsTest::split_string_test()
{
auto data = "*fdg454()**{&xcx*"sv;
auto split_string_result = split_string(data, '*');
CPPUNIT_ASSERT(split_string_result.size() == 2);
CPPUNIT_ASSERT(split_string_result.at(0) == "fdg454()"sv
&& split_string_result.at(1) == "{&xcx"sv);
auto split_string_to_unsigned_result = split_string_to_unsigned("/4545497//45454/", '/');
CPPUNIT_ASSERT(split_string_to_unsigned_result.size() == 2);
CPPUNIT_ASSERT(split_string_to_unsigned_result.at(0) == 4545497
&& split_string_to_unsigned_result.at(1) == 45454);
std::string_view line;
split_string_result.clear();
while (jami::getline(data, line, '*')) {
split_string_result.emplace_back(line);
}
CPPUNIT_ASSERT(split_string_result.size() == 2);
CPPUNIT_ASSERT(split_string_result.at(0) == "fdg454()"sv
&& split_string_result.at(1) == "{&xcx"sv);
}
} // namespace test
} // namespace jami
JAMI_TEST_RUNNER(jami::test::StringUtilsTest::name());
#include <iostream>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/CompilerOutputter.h>
// This version of the test runner is similar to RING_TEST_RUNNER but
// can take multiple unit tests.
// It's practical to run a test for diffrent configs, for instance when
// running the same test for both Jami and SIP accounts.
// The test will abort if a test fails.
#define JAMI_TEST_RUNNER(...) \
int main() \
{ \
std::vector<std::string> suite_names {__VA_ARGS__}; \
for (const std::string& name : suite_names) { \
CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry( \
name); \
CppUnit::Test* suite = registry.makeTest(); \
if (suite->countTestCases() == 0) { \
std::cout << "No test cases specified for suite \"" << name << "\"\n"; \
continue; \
} \
CppUnit::TextUi::TestRunner runner; \
runner.addTest(suite); \
if (not runner.run()) \
return 1; \
} \
return 0; \
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment