LCOV - code coverage report
Current view: top level - test/unitTest/fileTransfer - fileTransfer.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 371 394 94.2 %
Date: 2024-03-28 08:00:27 Functions: 70 72 97.2 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2020-2024 Savoir-faire Linux Inc.
       3             :  *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
       4             :  *
       5             :  *  This program is free software; you can redistribute it and/or modify
       6             :  *  it under the terms of the GNU General Public License as published by
       7             :  *  the Free Software Foundation; either version 3 of the License, or
       8             :  *  (at your option) any later version.
       9             :  *
      10             :  *  This program is distributed in the hope that it will be useful,
      11             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  *  GNU General Public License for more details.
      14             :  *
      15             :  *  You should have received a copy of the GNU General Public License
      16             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : #include "fileutils.h"
      20             : #include "manager.h"
      21             : 
      22             : #include "jamidht/jamiaccount.h"
      23             : #include "../../test_runner.h"
      24             : #include "jami.h"
      25             : #include "data_transfer.h"
      26             : #include "jami/datatransfer_interface.h"
      27             : #include "account_const.h"
      28             : #include "common.h"
      29             : 
      30             : #include <dhtnet/connectionmanager.h>
      31             : 
      32             : #include <cppunit/TestAssert.h>
      33             : #include <cppunit/TestFixture.h>
      34             : #include <cppunit/extensions/HelperMacros.h>
      35             : 
      36             : #include <condition_variable>
      37             : #include <string>
      38             : #include <filesystem>
      39             : 
      40             : using namespace std::literals::chrono_literals;
      41             : using namespace libjami::Account;
      42             : using namespace std::literals::chrono_literals;
      43             : 
      44             : namespace jami {
      45             : namespace test {
      46             : 
      47             : struct UserData {
      48             :     std::string conversationId;
      49             :     bool removed {false};
      50             :     bool requestReceived {false};
      51             :     bool registered {false};
      52             :     bool stopped {false};
      53             :     bool deviceAnnounced {false};
      54             :     int code {0};
      55             :     std::vector<libjami::SwarmMessage> messages;
      56             :     std::vector<libjami::SwarmMessage> messagesUpdated;
      57             : };
      58             : 
      59             : class FileTransferTest : public CppUnit::TestFixture
      60             : {
      61             : public:
      62          10 :     FileTransferTest()
      63          10 :     {
      64             :         // Init daemon
      65          10 :         libjami::init(
      66             :             libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
      67          10 :         if (not Manager::instance().initialized)
      68           1 :             CPPUNIT_ASSERT(libjami::start("jami-sample.yml"));
      69          10 :     }
      70          20 :     ~FileTransferTest() { libjami::fini(); }
      71           2 :     static std::string name() { return "Call"; }
      72             :     bool compare(const std::string& fileA, const std::string& fileB) const;
      73             :     void setUp();
      74             :     void tearDown();
      75             : 
      76             :     std::string aliceId;
      77             :     UserData aliceData;
      78             :     std::string bobId;
      79             :     UserData bobData;
      80             :     std::string carlaId;
      81             :     UserData carlaData;
      82             : 
      83             :     std::filesystem::path sendPath {std::filesystem::current_path() / "SEND"};
      84             :     std::filesystem::path recvPath {std::filesystem::current_path() / "RECV"};
      85             :     std::filesystem::path recv2Path {std::filesystem::current_path() / "RECV2"};
      86             : 
      87             :     std::mutex mtx;
      88             :     std::unique_lock<std::mutex> lk {mtx};
      89             :     std::condition_variable cv;
      90             : 
      91             :     void connectSignals();
      92             : 
      93             : private:
      94             :     void testConversationFileTransfer();
      95             :     void testFileTransferInConversation();
      96             :     void testVcfFileTransferInConversation();
      97             :     void testBadSha3sumOut();
      98             :     void testBadSha3sumIn();
      99             :     void testAskToMultipleParticipants();
     100             :     void testCancelInTransfer();
     101             :     void testCancelOutTransfer();
     102             :     void testTransferInfo();
     103             :     void testRemoveHardLink();
     104             :     void testTooLarge();
     105             : 
     106           2 :     CPPUNIT_TEST_SUITE(FileTransferTest);
     107           1 :     CPPUNIT_TEST(testConversationFileTransfer);
     108           1 :     CPPUNIT_TEST(testFileTransferInConversation);
     109           1 :     CPPUNIT_TEST(testVcfFileTransferInConversation);
     110           1 :     CPPUNIT_TEST(testBadSha3sumOut);
     111           1 :     CPPUNIT_TEST(testBadSha3sumIn);
     112           1 :     CPPUNIT_TEST(testAskToMultipleParticipants);
     113           1 :     CPPUNIT_TEST(testCancelInTransfer);
     114           1 :     CPPUNIT_TEST(testTransferInfo);
     115           1 :     CPPUNIT_TEST(testRemoveHardLink);
     116           1 :     CPPUNIT_TEST(testTooLarge);
     117           4 :     CPPUNIT_TEST_SUITE_END();
     118             : };
     119             : 
     120             : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(FileTransferTest, FileTransferTest::name());
     121             : 
     122             : bool
     123           0 : FileTransferTest::compare(const std::string& fileA, const std::string& fileB) const
     124             : {
     125           0 :     std::ifstream f1(fileA, std::ifstream::binary | std::ifstream::ate);
     126           0 :     std::ifstream f2(fileB, std::ifstream::binary | std::ifstream::ate);
     127             : 
     128           0 :     if (f1.fail() || f2.fail() || f1.tellg() != f2.tellg()) {
     129           0 :         return false;
     130             :     }
     131             : 
     132           0 :     f1.seekg(0, std::ifstream::beg);
     133           0 :     f2.seekg(0, std::ifstream::beg);
     134           0 :     return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
     135             :                       std::istreambuf_iterator<char>(),
     136           0 :                       std::istreambuf_iterator<char>(f2.rdbuf()));
     137           0 : }
     138             : 
     139             : void
     140          10 : FileTransferTest::setUp()
     141             : {
     142          20 :     auto actors = load_actors_and_wait_for_announcement("actors/alice-bob-carla.yml");
     143          10 :     aliceId = actors["alice"];
     144          10 :     bobId = actors["bob"];
     145          10 :     carlaId = actors["carla"];
     146          10 :     aliceData = {};
     147          10 :     bobData = {};
     148          10 :     carlaData = {};
     149          10 : }
     150             : 
     151             : void
     152          10 : FileTransferTest::tearDown()
     153             : {
     154          10 :     std::filesystem::remove(sendPath);
     155          10 :     std::filesystem::remove(recvPath);
     156          10 :     std::filesystem::remove(recv2Path);
     157          40 :     wait_for_removal_of({aliceId, bobId, carlaId});
     158          10 : }
     159             : 
     160             : void
     161          10 : FileTransferTest::connectSignals()
     162             : {
     163          10 :     std::map<std::string, std::shared_ptr<libjami::CallbackWrapperBase>> confHandlers;
     164          10 :     confHandlers.insert(libjami::exportable_callback<libjami::ConversationSignal::ConversationReady>(
     165          21 :         [&](const std::string& accountId, const std::string& conversationId) {
     166          21 :             if (accountId == aliceId) {
     167          10 :                 aliceData.conversationId = conversationId;
     168          11 :             } else if (accountId == bobId) {
     169           9 :                 bobData.conversationId = conversationId;
     170           2 :             } else if (accountId == carlaId) {
     171           2 :                 carlaData.conversationId = conversationId;
     172             :             }
     173          21 :             cv.notify_one();
     174          21 :         }));
     175          10 :     confHandlers.insert(
     176          20 :         libjami::exportable_callback<libjami::ConversationSignal::ConversationRequestReceived>(
     177          11 :             [&](const std::string& accountId,
     178             :                 const std::string& /* conversationId */,
     179             :                 std::map<std::string, std::string> /*metadatas*/) {
     180          11 :                 if (accountId == aliceId) {
     181           0 :                     aliceData.requestReceived = true;
     182          11 :                 } else if (accountId == bobId) {
     183           9 :                     bobData.requestReceived = true;
     184           2 :                 } else if (accountId == carlaId) {
     185           2 :                     carlaData.requestReceived = true;
     186             :                 }
     187          11 :                 cv.notify_one();
     188          11 :             }));
     189          10 :     confHandlers.insert(libjami::exportable_callback<libjami::ConversationSignal::SwarmMessageReceived>(
     190          45 :         [&](const std::string& accountId,
     191             :             const std::string& /* conversationId */,
     192             :             libjami::SwarmMessage message) {
     193          45 :             if (accountId == aliceId) {
     194          32 :                 aliceData.messages.emplace_back(message);
     195          13 :             } else if (accountId == bobId) {
     196          11 :                 bobData.messages.emplace_back(message);
     197           2 :             } else if (accountId == carlaId) {
     198           2 :                 carlaData.messages.emplace_back(message);
     199             :             }
     200          45 :             cv.notify_one();
     201          45 :         }));
     202          10 :     confHandlers.insert(libjami::exportable_callback<libjami::ConversationSignal::SwarmMessageUpdated>(
     203           0 :         [&](const std::string& accountId,
     204             :             const std::string& /* conversationId */,
     205             :             libjami::SwarmMessage message) {
     206           0 :             if (accountId == aliceId) {
     207           0 :                 aliceData.messagesUpdated.emplace_back(message);
     208           0 :             } else if (accountId == bobId) {
     209           0 :                 bobData.messagesUpdated.emplace_back(message);
     210           0 :             } else if (accountId == carlaId) {
     211           0 :                 carlaData.messagesUpdated.emplace_back(message);
     212             :             }
     213           0 :             cv.notify_one();
     214           0 :         }));
     215          10 :     confHandlers.insert(
     216          20 :         libjami::exportable_callback<libjami::ConversationSignal::ConversationRemoved>(
     217           1 :             [&](const std::string& accountId, const std::string&) {
     218           1 :                 if (accountId == aliceId)
     219           1 :                     aliceData.removed = true;
     220           0 :                 else if (accountId == bobId)
     221           0 :                     bobData.removed = true;
     222           1 :                 cv.notify_one();
     223           1 :             }));
     224          10 :     confHandlers.insert(libjami::exportable_callback<libjami::DataTransferSignal::DataTransferEvent>(
     225          29 :         [&](const std::string& accountId,
     226             :             const std::string& conversationId,
     227             :             const std::string&,
     228             :             const std::string& fileId,
     229             :             int code) {
     230          29 :             if (conversationId.empty())
     231           0 :                 return;
     232          29 :             if (accountId == aliceId)
     233           9 :                 aliceData.code = code;
     234          20 :             else if (accountId == bobId)
     235          16 :                 bobData.code = code;
     236           4 :             else if (accountId == carlaId)
     237           4 :                 carlaData.code = code;
     238          29 :             cv.notify_one();
     239             :         }));
     240          10 :     libjami::registerSignalHandlers(confHandlers);
     241          10 : }
     242             : 
     243             : void
     244           1 : FileTransferTest::testConversationFileTransfer()
     245             : {
     246           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     247           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     248           1 :     auto bobUri = bobAccount->getUsername();
     249           1 :     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     250           1 :     auto carlaUri = carlaAccount->getUsername();
     251           1 :     aliceAccount->trackBuddyPresence(carlaUri, true);
     252             : 
     253             :     // Enable carla
     254           1 :     Manager::instance().sendRegister(carlaId, true);
     255           1 :     wait_for_announcement_of(carlaId);
     256             : 
     257           1 :     connectSignals();
     258             : 
     259           1 :     auto convId = libjami::startConversation(aliceId);
     260             : 
     261           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     262           1 :     libjami::addConversationMember(aliceId, convId, carlaUri);
     263           6 :     CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&]() { return bobData.requestReceived && carlaData.requestReceived; }));
     264             : 
     265           1 :     auto aliceMsgSize = aliceData.messages.size();
     266           1 :     libjami::acceptConversationRequest(bobId, convId);
     267           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     268           1 :     aliceMsgSize = aliceData.messages.size();
     269           1 :     auto bobMsgSize = bobData.messages.size();
     270           1 :     libjami::acceptConversationRequest(carlaId, convId);
     271           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size() && bobMsgSize + 1 == bobData.messages.size(); }));
     272             : 
     273             :     // Send file
     274           1 :     std::ofstream sendFile(sendPath);
     275           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     276           1 :     sendFile << std::string(64000, 'A');
     277           1 :     sendFile.close();
     278             : 
     279           1 :     bobMsgSize = bobData.messages.size();
     280           1 :     auto carlaMsgSize = carlaData.messages.size();
     281           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     282             : 
     283           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return bobData.messages.size() == bobMsgSize + 1 && carlaData.messages.size() == carlaMsgSize + 1; }));
     284           1 :     auto id = bobData.messages.rbegin()->id;
     285           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     286             : 
     287           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     288           1 :     libjami::downloadFile(carlaId, convId, id, fileId, recv2Path);
     289             : 
     290           8 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return carlaData.code == static_cast<int>(libjami::DataTransferEventCode::finished) && bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     291           1 : }
     292             : 
     293             : void
     294           1 : FileTransferTest::testFileTransferInConversation()
     295             : {
     296           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     297           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     298           1 :     auto bobUri = bobAccount->getUsername();
     299           1 :     auto aliceUri = aliceAccount->getUsername();
     300           1 :     connectSignals();
     301             : 
     302           1 :     auto convId = libjami::startConversation(aliceId);
     303             : 
     304           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     305           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     306             : 
     307           1 :     auto aliceMsgSize = aliceData.messages.size();
     308           1 :     libjami::acceptConversationRequest(bobId, convId);
     309           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     310             : 
     311             :     // Create file to send
     312           1 :     std::ofstream sendFile(sendPath);
     313           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     314           1 :     sendFile << std::string(64000, 'A');
     315           1 :     sendFile.close();
     316             : 
     317           1 :     auto bobMsgSize = bobData.messages.size();
     318           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     319           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize  + 1== bobData.messages.size(); }));
     320             : 
     321           1 :     auto id = bobData.messages.rbegin()->id;
     322           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     323           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     324             : 
     325           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return aliceData.code == static_cast<int>(libjami::DataTransferEventCode::finished) && bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     326           1 : }
     327             : 
     328             : void
     329           1 : FileTransferTest::testVcfFileTransferInConversation()
     330             : {
     331           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     332           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     333           1 :     auto bobUri = bobAccount->getUsername();
     334           1 :     auto aliceUri = aliceAccount->getUsername();
     335           1 :     connectSignals();
     336           1 :     auto convId = libjami::startConversation(aliceId);
     337             : 
     338           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     339           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     340             : 
     341           1 :     auto aliceMsgSize = aliceData.messages.size();
     342           1 :     libjami::acceptConversationRequest(bobId, convId);
     343           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     344             : 
     345             :     // Create file to send
     346           1 :     std::ofstream sendFile(sendPath);
     347           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     348           1 :     sendFile << std::string(64000, 'A');
     349           1 :     sendFile.close();
     350             : 
     351           1 :     auto bobMsgSize = bobData.messages.size();
     352           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     353           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     354             : 
     355           1 :     auto id = bobData.messages.rbegin()->id;
     356           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     357           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     358             : 
     359           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return aliceData.code == static_cast<int>(libjami::DataTransferEventCode::finished) && bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     360           1 : }
     361             : 
     362             : void
     363           1 : FileTransferTest::testBadSha3sumOut()
     364             : {
     365           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     366           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     367           1 :     auto bobUri = bobAccount->getUsername();
     368           1 :     auto aliceUri = aliceAccount->getUsername();
     369           1 :     connectSignals();
     370           1 :     auto convId = libjami::startConversation(aliceId);
     371             : 
     372           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     373           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     374             : 
     375           1 :     auto aliceMsgSize = aliceData.messages.size();
     376           1 :     libjami::acceptConversationRequest(bobId, convId);
     377           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     378             : 
     379             :     // Create file to send
     380           1 :     std::ofstream sendFile(sendPath);
     381           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     382           1 :     sendFile << std::string(64000, 'A');
     383           1 :     sendFile.close();
     384             : 
     385           1 :     auto bobMsgSize = bobData.messages.size();
     386           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     387           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     388             : 
     389             :     // modifiy file
     390           1 :     sendFile = std::ofstream(sendPath);
     391           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     392           1 :     sendFile << std::string(64000, 'B');
     393           1 :     sendFile.close();
     394             : 
     395           1 :     auto id = bobData.messages.rbegin()->id;
     396           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     397           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     398             : 
     399           3 :     CPPUNIT_ASSERT(!cv.wait_for(lk, 45s, [&]() { return aliceData.code == static_cast<int>(libjami::DataTransferEventCode::finished) || bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     400           1 : }
     401             : 
     402             : void
     403           1 : FileTransferTest::testBadSha3sumIn()
     404             : {
     405           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     406           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     407           1 :     auto bobUri = bobAccount->getUsername();
     408           1 :     auto aliceUri = aliceAccount->getUsername();
     409           1 :     connectSignals();
     410           1 :     auto convId = libjami::startConversation(aliceId);
     411             : 
     412           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     413           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     414             : 
     415           1 :     auto aliceMsgSize = aliceData.messages.size();
     416           1 :     libjami::acceptConversationRequest(bobId, convId);
     417           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     418             : 
     419             :     // Create file to send
     420           1 :     std::ofstream sendFile(sendPath);
     421           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     422           1 :     sendFile << std::string(64000, 'A');
     423           1 :     sendFile.close();
     424             : 
     425           1 :     aliceAccount->noSha3sumVerification(true);
     426           1 :     auto bobMsgSize = bobData.messages.size();
     427           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     428           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     429             : 
     430             :     // modifiy file
     431           1 :     sendFile = std::ofstream(sendPath);
     432           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     433             :     // Avoid ASAN error on big alloc   sendFile << std::string("B", 64000);
     434           1 :     sendFile << std::string(64000, 'B');
     435           1 :     sendFile.close();
     436             : 
     437           1 :     auto id = bobData.messages.rbegin()->id;
     438           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     439           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     440             : 
     441             :     // The file transfer will be sent but refused by bob
     442           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     443           4 :     CPPUNIT_ASSERT(!cv.wait_for(lk, 30s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     444             : 
     445           1 :     std::filesystem::remove(sendPath);
     446           1 : }
     447             : 
     448             : void
     449           1 : FileTransferTest::testAskToMultipleParticipants()
     450             : {
     451           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     452           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     453           1 :     auto carlaAccount = Manager::instance().getAccount<JamiAccount>(carlaId);
     454           1 :     auto aliceUri = aliceAccount->getUsername();
     455           1 :     auto bobUri = bobAccount->getUsername();
     456           1 :     auto carlaUri = carlaAccount->getUsername();
     457           1 :     connectSignals();
     458           1 :     auto convId = libjami::startConversation(aliceId);
     459             : 
     460           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     461           1 :     libjami::addConversationMember(aliceId, convId, carlaUri);
     462           6 :     CPPUNIT_ASSERT(cv.wait_for(lk, 60s, [&]() { return bobData.requestReceived && carlaData.requestReceived; }));
     463             : 
     464           1 :     auto aliceMsgSize = aliceData.messages.size();
     465           1 :     libjami::acceptConversationRequest(bobId, convId);
     466           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     467           1 :     aliceMsgSize = aliceData.messages.size();
     468           1 :     auto bobMsgSize = bobData.messages.size();
     469           1 :     libjami::acceptConversationRequest(carlaId, convId);
     470           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size() && bobMsgSize + 1 == bobData.messages.size(); }));
     471             : 
     472             :     // Create file to send
     473           1 :     std::ofstream sendFile(sendPath);
     474           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     475           1 :     sendFile << std::string(64000, 'A');
     476           1 :     sendFile.close();
     477             : 
     478           1 :     bobMsgSize = bobData.messages.size();
     479           1 :     auto carlaMsgSize = carlaData.messages.size();
     480           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     481             : 
     482           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return bobData.messages.size() == bobMsgSize + 1 && carlaData.messages.size() == carlaMsgSize + 1; }));
     483           1 :     auto id = bobData.messages.rbegin()->id;
     484           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     485             : 
     486           1 :     libjami::downloadFile(carlaId, convId, id, fileId, recv2Path);
     487           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return carlaData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     488           1 :     CPPUNIT_ASSERT(dhtnet::fileutils::isFile(recv2Path));
     489             : 
     490           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     491           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     492           1 :     CPPUNIT_ASSERT(dhtnet::fileutils::isFile(recvPath));
     493           1 : }
     494             : 
     495             : void
     496           1 : FileTransferTest::testCancelInTransfer()
     497             : {
     498           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     499           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     500           1 :     auto bobUri = bobAccount->getUsername();
     501           1 :     auto aliceUri = aliceAccount->getUsername();
     502           1 :     connectSignals();
     503           1 :     auto convId = libjami::startConversation(aliceId);
     504             : 
     505           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     506           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     507             : 
     508           1 :     auto aliceMsgSize = aliceData.messages.size();
     509           1 :     libjami::acceptConversationRequest(bobId, convId);
     510           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     511             : 
     512             :     // Create file to send
     513           1 :     std::ofstream sendFile(sendPath);
     514           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     515           1 :     sendFile << std::string(640000, 'A');
     516           1 :     sendFile.close();
     517             : 
     518           1 :     auto bobMsgSize = bobData.messages.size();
     519           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     520           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     521           1 :     auto id = bobData.messages.rbegin()->id;
     522           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     523             : 
     524           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     525           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::ongoing); }));
     526             : 
     527           1 :     libjami::cancelDataTransfer(bobId, convId, fileId);
     528           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::closed_by_peer); }));
     529           1 :     CPPUNIT_ASSERT(!dhtnet::fileutils::isFile(recvPath));
     530           1 :     CPPUNIT_ASSERT(!bobAccount->dataTransfer(convId)->isWaiting(fileId));
     531           1 : }
     532             : 
     533             : void
     534           1 : FileTransferTest::testTransferInfo()
     535             : {
     536           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     537           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     538           1 :     auto bobUri = bobAccount->getUsername();
     539           1 :     auto aliceUri = aliceAccount->getUsername();
     540           1 :     connectSignals();
     541           1 :     auto convId = libjami::startConversation(aliceId);
     542             : 
     543           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     544           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     545             : 
     546           1 :     auto aliceMsgSize = aliceData.messages.size();
     547           1 :     libjami::acceptConversationRequest(bobId, convId);
     548           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     549             : 
     550             :     // Create file to send
     551           1 :     std::ofstream sendFile(sendPath);
     552           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     553           1 :     sendFile << std::string(640000, 'A');
     554           1 :     sendFile.close();
     555             : 
     556           1 :     auto bobMsgSize = bobData.messages.size();
     557           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     558           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     559           1 :     auto id = bobData.messages.rbegin()->id;
     560           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     561             : 
     562             :     int64_t totalSize, bytesProgress;
     563           1 :     std::string path;
     564           1 :     CPPUNIT_ASSERT(libjami::fileTransferInfo(bobId, convId, fileId, path, totalSize, bytesProgress)
     565             :                    == libjami::DataTransferError::invalid_argument);
     566           1 :     CPPUNIT_ASSERT(bytesProgress == 0);
     567           1 :     CPPUNIT_ASSERT(!std::filesystem::is_regular_file(path));
     568             :     // No check for total as not started
     569             : 
     570           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     571           5 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::finished); }));
     572           1 :     CPPUNIT_ASSERT(libjami::fileTransferInfo(bobId, convId, fileId, path, totalSize, bytesProgress)
     573             :                    == libjami::DataTransferError::success);
     574           1 :     CPPUNIT_ASSERT(bytesProgress == 640000);
     575           1 :     CPPUNIT_ASSERT(totalSize == 640000);
     576           1 :     CPPUNIT_ASSERT(dhtnet::fileutils::isFile(path));
     577           1 : }
     578             : 
     579             : void
     580           1 : FileTransferTest::testRemoveHardLink()
     581             : {
     582           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     583           1 :     connectSignals();
     584           1 :     auto convId = libjami::startConversation(aliceId);
     585             : 
     586           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return !aliceData.conversationId.empty(); }));
     587             : 
     588             :     // Send file
     589           1 :     std::ofstream sendFile(sendPath);
     590           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     591           1 :     sendFile << std::string(64000, 'A');
     592           1 :     sendFile.close();
     593             : 
     594           1 :     libjami::sendFile(aliceId, convId, sendPath, std::filesystem::absolute("SEND"), "");
     595             : 
     596           1 :     auto aliceMsgSize = aliceData.messages.size();
     597           3 :     CPPUNIT_ASSERT(cv.wait_for(lk, 45s, [&]() { return aliceMsgSize + 1 == aliceData.messages.size(); }));
     598             : 
     599           1 :     CPPUNIT_ASSERT(libjami::removeConversation(aliceId, convId));
     600           2 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceData.removed; }));
     601             : 
     602           1 :     auto content = fileutils::loadTextFile(sendPath);
     603           1 :     CPPUNIT_ASSERT(content.find("AAA") != std::string::npos);
     604           1 : }
     605             : 
     606             : void
     607           1 : FileTransferTest::testTooLarge()
     608             : {
     609           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     610           1 :     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
     611           1 :     auto bobUri = bobAccount->getUsername();
     612           1 :     connectSignals();
     613           1 :     auto convId = libjami::startConversation(aliceId);
     614             : 
     615           1 :     libjami::addConversationMember(aliceId, convId, bobUri);
     616           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobData.requestReceived; }));
     617             : 
     618           1 :     auto aliceMsgSize = aliceData.messages.size();
     619           1 :     libjami::acceptConversationRequest(bobId, convId);
     620           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() {
     621             :         return aliceMsgSize + 1 == aliceData.messages.size(); }));
     622             : 
     623             :     // Send file
     624           1 :     std::ofstream sendFile(sendPath);
     625           1 :     CPPUNIT_ASSERT(sendFile.is_open());
     626           1 :     sendFile << std::string(64000, 'A');
     627           1 :     sendFile.close();
     628             : 
     629           1 :     auto bobMsgSize = bobData.messages.size();
     630           1 :     libjami::sendFile(aliceId, convId, sendPath, "SEND", "");
     631           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return bobMsgSize + 1 == bobData.messages.size(); }));
     632           1 :     auto id = bobData.messages.rbegin()->id;
     633           2 :     auto fileId = bobData.messages.rbegin()->body["fileId"];
     634             : 
     635             :     // Add some data for the reception. This will break the final shasum
     636           1 :     std::ofstream recvFile(recvPath);
     637           1 :     CPPUNIT_ASSERT(recvFile.is_open());
     638           1 :     recvFile << std::string(1000, 'B');
     639           1 :     recvFile.close();
     640           1 :     libjami::downloadFile(bobId, convId, id, fileId, recvPath);
     641             : 
     642           4 :     CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return bobData.code == static_cast<int>(libjami::DataTransferEventCode::closed_by_host); }));
     643           1 :     CPPUNIT_ASSERT(!dhtnet::fileutils::isFile(recvPath));
     644           1 : }
     645             : 
     646             : } // namespace test
     647             : } // namespace jami
     648             : 
     649           1 : RING_TEST_RUNNER(jami::test::FileTransferTest::name())

Generated by: LCOV version 1.14