diff --git a/CMakeLists.txt b/CMakeLists.txt
index 227118f..21d7b69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,9 +3,11 @@
 
 set(CMAKE_CXX_STANDARD 17)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
+include(CTest)
 
 find_package (PkgConfig REQUIRED)
 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 (pjproject REQUIRED IMPORTED_TARGET libpjproject)
 
@@ -30,8 +32,25 @@
 )
 
 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_compile_definitions(dhtnet PRIVATE
-    PJ_AUTOCONF=1
-)
+add_compile_definitions(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
diff --git a/tests/certstore.cpp b/tests/certstore.cpp
new file mode 100644
index 0000000..7d6b75f
--- /dev/null
+++ b/tests/certstore.cpp
@@ -0,0 +1,209 @@
+/*
+ *  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());
diff --git a/tests/connectionManager.cpp b/tests/connectionManager.cpp
new file mode 100644
index 0000000..504f49f
--- /dev/null
+++ b/tests/connectionManager.cpp
@@ -0,0 +1,1277 @@
+/*
+ *  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())
diff --git a/tests/testFileutils.cpp b/tests/testFileutils.cpp
new file mode 100644
index 0000000..ba95e33
--- /dev/null
+++ b/tests/testFileutils.cpp
@@ -0,0 +1,156 @@
+/*
+ *  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());
+
diff --git a/tests/testString_utils.cpp b/tests/testString_utils.cpp
new file mode 100644
index 0000000..ba4b163
--- /dev/null
+++ b/tests/testString_utils.cpp
@@ -0,0 +1,125 @@
+/*
+ *  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());
diff --git a/tests/test_runner.h b/tests/test_runner.h
new file mode 100644
index 0000000..ecd5081
--- /dev/null
+++ b/tests/test_runner.h
@@ -0,0 +1,31 @@
+#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; \
+    }
