LCOV - code coverage report
Current view: top level - test/unitTest/conversationRepository - conversationRepository.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 261 280 93.2 %
Date: 2024-12-21 08:56:24 Functions: 19 19 100.0 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 Savoir-faire Linux Inc.
       3             :  *
       4             :  *  This program is free software: you can redistribute it and/or modify
       5             :  *  it under the terms of the GNU General Public License as published by
       6             :  *  the Free Software Foundation, either version 3 of the License, or
       7             :  *  (at your option) any later version.
       8             :  *
       9             :  *  This program is distributed in the hope that it will be useful,
      10             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12             :  *  GNU General Public License for more details.
      13             :  *
      14             :  *  You should have received a copy of the GNU General Public License
      15             :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "manager.h"
      19             : #include "jamidht/conversationrepository.h"
      20             : #include "jamidht/gitserver.h"
      21             : #include "jamidht/jamiaccount.h"
      22             : #include "../../test_runner.h"
      23             : #include "jami.h"
      24             : #include "base64.h"
      25             : #include "fileutils.h"
      26             : #include "account_const.h"
      27             : #include "common.h"
      28             : 
      29             : #include <git2.h>
      30             : 
      31             : #include <dhtnet/connectionmanager.h>
      32             : 
      33             : #include <cppunit/TestAssert.h>
      34             : #include <cppunit/TestFixture.h>
      35             : #include <cppunit/extensions/HelperMacros.h>
      36             : 
      37             : #include <condition_variable>
      38             : #include <string>
      39             : #include <fstream>
      40             : #include <streambuf>
      41             : #include <filesystem>
      42             : 
      43             : using namespace std::string_literals;
      44             : using namespace libjami::Account;
      45             : 
      46             : namespace jami {
      47             : namespace test {
      48             : 
      49             : class ConversationRepositoryTest : public CppUnit::TestFixture
      50             : {
      51             : public:
      52           7 :     ConversationRepositoryTest()
      53           7 :     {
      54             :         // Init daemon
      55           7 :         libjami::init(
      56             :             libjami::InitFlag(libjami::LIBJAMI_FLAG_DEBUG | libjami::LIBJAMI_FLAG_CONSOLE_LOG));
      57           7 :         if (not Manager::instance().initialized)
      58           1 :             CPPUNIT_ASSERT(libjami::start("jami-sample.yml"));
      59           7 :     }
      60          14 :     ~ConversationRepositoryTest() { libjami::fini(); }
      61           2 :     static std::string name() { return "ConversationRepository"; }
      62             :     void setUp();
      63             :     void tearDown();
      64             : 
      65             :     std::string aliceId;
      66             :     std::string bobId;
      67             : 
      68             : private:
      69             :     void testCreateRepository();
      70             :     void testAddSomeMessages();
      71             :     void testLogMessages();
      72             :     void testMerge();
      73             :     void testFFMerge();
      74             :     void testDiff();
      75             : 
      76             :     void testMergeProfileWithConflict();
      77             : 
      78             :     std::string addCommit(git_repository* repo,
      79             :                           const std::shared_ptr<JamiAccount> account,
      80             :                           const std::string& branch,
      81             :                           const std::string& commit_msg);
      82             :     void addAll(git_repository* repo);
      83             :     bool merge_in_main(const std::shared_ptr<JamiAccount> account,
      84             :                        git_repository* repo,
      85             :                        const std::string& commit_ref);
      86             : 
      87           2 :     CPPUNIT_TEST_SUITE(ConversationRepositoryTest);
      88           1 :     CPPUNIT_TEST(testCreateRepository);
      89           1 :     CPPUNIT_TEST(testAddSomeMessages);
      90           1 :     CPPUNIT_TEST(testLogMessages);
      91           1 :     CPPUNIT_TEST(testMerge);
      92           1 :     CPPUNIT_TEST(testFFMerge);
      93           1 :     CPPUNIT_TEST(testDiff);
      94           1 :     CPPUNIT_TEST(testMergeProfileWithConflict);
      95             : 
      96           4 :     CPPUNIT_TEST_SUITE_END();
      97             : };
      98             : 
      99             : CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ConversationRepositoryTest,
     100             :                                       ConversationRepositoryTest::name());
     101             : 
     102             : void
     103           7 : ConversationRepositoryTest::setUp()
     104             : {
     105          14 :     auto actors = load_actors_and_wait_for_announcement("actors/alice-bob.yml");
     106           7 :     aliceId = actors["alice"];
     107           7 :     bobId = actors["bob"];
     108           7 : }
     109             : 
     110             : void
     111           7 : ConversationRepositoryTest::tearDown()
     112             : {
     113          21 :     wait_for_removal_of({aliceId, bobId});
     114           7 : }
     115             : 
     116             : void
     117           1 : ConversationRepositoryTest::testCreateRepository()
     118             : {
     119           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     120           1 :     auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     121           1 :     auto uri = aliceAccount->getUsername();
     122             : 
     123           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     124             : 
     125             :     // Assert that repository exists
     126           1 :     CPPUNIT_ASSERT(repository != nullptr);
     127           2 :     auto repoPath = fileutils::get_data_dir() / aliceAccount->getAccountID()
     128           4 :                     / "conversations" / repository->id();
     129           1 :     CPPUNIT_ASSERT(std::filesystem::is_directory(repoPath));
     130             : 
     131             :     // Assert that first commit is signed by alice
     132             :     git_repository* repo;
     133           1 :     CPPUNIT_ASSERT(git_repository_open(&repo, repoPath.c_str()) == 0);
     134             : 
     135             :     // 1. Verify that last commit is correctly signed by alice
     136             :     git_oid commit_id;
     137           1 :     CPPUNIT_ASSERT(git_reference_name_to_id(&commit_id, repo, "HEAD") == 0);
     138             : 
     139           1 :     git_buf signature = {}, signed_data = {};
     140           1 :     git_commit_extract_signature(&signature, &signed_data, repo, &commit_id, "signature");
     141           2 :     auto pk = base64::decode(std::string(signature.ptr, signature.ptr + signature.size));
     142           1 :     auto data = std::vector<uint8_t>(signed_data.ptr, signed_data.ptr + signed_data.size);
     143           1 :     git_repository_free(repo);
     144             : 
     145           1 :     CPPUNIT_ASSERT(aliceAccount->identity().second->getPublicKey().checkSignature(data, pk));
     146             : 
     147             :     // 2. Check created files
     148           2 :     auto CRLsPath = repoPath / "CRLs" / aliceDeviceId.toString();
     149           1 :     CPPUNIT_ASSERT(std::filesystem::is_directory(repoPath));
     150             : 
     151           2 :     auto adminCrt = repoPath / "admins" / (uri + ".crt");
     152           1 :     CPPUNIT_ASSERT(std::filesystem::is_regular_file(adminCrt));
     153             : 
     154           1 :     auto crt = std::ifstream(adminCrt);
     155           1 :     std::string adminCrtStr((std::istreambuf_iterator<char>(crt)), std::istreambuf_iterator<char>());
     156             : 
     157           1 :     auto cert = aliceAccount->identity().second;
     158           1 :     auto deviceCert = cert->toString(false);
     159           1 :     auto parentCert = cert->issuer->toString(true);
     160             : 
     161           1 :     CPPUNIT_ASSERT(adminCrtStr == parentCert);
     162             : 
     163           2 :     auto deviceCrt = repoPath / "devices" / (aliceDeviceId.toString() + ".crt");
     164           1 :     CPPUNIT_ASSERT(std::filesystem::is_regular_file(deviceCrt));
     165             : 
     166           1 :     crt = std::ifstream(deviceCrt);
     167             :     std::string deviceCrtStr((std::istreambuf_iterator<char>(crt)),
     168           1 :                              std::istreambuf_iterator<char>());
     169             : 
     170           1 :     CPPUNIT_ASSERT(deviceCrtStr == deviceCert);
     171           1 : }
     172             : 
     173             : void
     174           1 : ConversationRepositoryTest::testAddSomeMessages()
     175             : {
     176           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     177           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     178             : 
     179           2 :     auto id1 = repository->commitMessage("Commit 1");
     180           2 :     auto id2 = repository->commitMessage("Commit 2");
     181           2 :     auto id3 = repository->commitMessage("Commit 3");
     182             : 
     183           1 :     auto messages = repository->log();
     184           1 :     CPPUNIT_ASSERT(messages.size() == 4 /* 3 + initial */);
     185           1 :     CPPUNIT_ASSERT(messages[0].id == id3);
     186           1 :     CPPUNIT_ASSERT(messages[0].parents.front() == id2);
     187           1 :     CPPUNIT_ASSERT(messages[0].commit_msg == "Commit 3");
     188           1 :     CPPUNIT_ASSERT(messages[0].author.name == messages[3].author.name);
     189           1 :     CPPUNIT_ASSERT(messages[0].author.email == messages[3].author.email);
     190           1 :     CPPUNIT_ASSERT(messages[1].id == id2);
     191           1 :     CPPUNIT_ASSERT(messages[1].parents.front() == id1);
     192           1 :     CPPUNIT_ASSERT(messages[1].commit_msg == "Commit 2");
     193           1 :     CPPUNIT_ASSERT(messages[1].author.name == messages[3].author.name);
     194           1 :     CPPUNIT_ASSERT(messages[1].author.email == messages[3].author.email);
     195           1 :     CPPUNIT_ASSERT(messages[2].id == id1);
     196           1 :     CPPUNIT_ASSERT(messages[2].commit_msg == "Commit 1");
     197           1 :     CPPUNIT_ASSERT(messages[2].author.name == messages[3].author.name);
     198           1 :     CPPUNIT_ASSERT(messages[2].author.email == messages[3].author.email);
     199           1 :     CPPUNIT_ASSERT(messages[2].parents.front() == repository->id());
     200             :     // Check sig
     201           1 :     CPPUNIT_ASSERT(
     202             :         aliceAccount->identity().second->getPublicKey().checkSignature(messages[0].signed_content,
     203             :                                                                        messages[0].signature));
     204           1 :     CPPUNIT_ASSERT(
     205             :         aliceAccount->identity().second->getPublicKey().checkSignature(messages[1].signed_content,
     206             :                                                                        messages[1].signature));
     207           1 :     CPPUNIT_ASSERT(
     208             :         aliceAccount->identity().second->getPublicKey().checkSignature(messages[2].signed_content,
     209             :                                                                        messages[2].signature));
     210           1 : }
     211             : 
     212             : void
     213           1 : ConversationRepositoryTest::testLogMessages()
     214             : {
     215           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     216           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     217             : 
     218           2 :     auto id1 = repository->commitMessage("Commit 1");
     219           2 :     auto id2 = repository->commitMessage("Commit 2");
     220           2 :     auto id3 = repository->commitMessage("Commit 3");
     221             : 
     222           1 :     LogOptions options;
     223           1 :     options.from = repository->id();
     224           1 :     options.nbOfCommits = 1;
     225           1 :     auto messages = repository->log(options);
     226           1 :     CPPUNIT_ASSERT(messages.size() == 1);
     227           1 :     CPPUNIT_ASSERT(messages[0].id == repository->id());
     228           1 :     options.from = id2;
     229           1 :     options.nbOfCommits = 2;
     230           1 :     messages = repository->log(options);
     231           1 :     CPPUNIT_ASSERT(messages.size() == 2);
     232           1 :     CPPUNIT_ASSERT(messages[0].id == id2);
     233           1 :     CPPUNIT_ASSERT(messages[1].id == id1);
     234           1 :     options.from = repository->id();
     235           1 :     options.nbOfCommits = 3;
     236           1 :     messages = repository->log(options);
     237           1 :     CPPUNIT_ASSERT(messages.size() == 1);
     238           1 :     CPPUNIT_ASSERT(messages[0].id == repository->id());
     239           1 : }
     240             : 
     241             : std::string
     242           7 : ConversationRepositoryTest::addCommit(git_repository* repo,
     243             :                                       const std::shared_ptr<JamiAccount> account,
     244             :                                       const std::string& branch,
     245             :                                       const std::string& commit_msg)
     246             : {
     247           7 :     auto deviceId = DeviceId(std::string(account->currentDeviceId()));
     248           7 :     auto name = account->getDisplayName();
     249           7 :     if (name.empty())
     250           0 :         name = deviceId.toString();
     251             : 
     252           7 :     git_signature* sig_ptr = nullptr;
     253             :     // Sign commit's buffer
     254           7 :     if (git_signature_new(&sig_ptr, name.c_str(), deviceId.to_c_str(), std::time(nullptr), 0) < 0) {
     255           0 :         JAMI_ERR("Unable to create a commit signature.");
     256           0 :         return {};
     257             :     }
     258           7 :     GitSignature sig {sig_ptr, git_signature_free};
     259             : 
     260             :     // Retrieve current HEAD
     261             :     git_oid commit_id;
     262           7 :     if (git_reference_name_to_id(&commit_id, repo, "HEAD") < 0) {
     263           0 :         JAMI_ERR("Unable to get reference for HEAD");
     264           0 :         return {};
     265             :     }
     266             : 
     267           7 :     git_commit* head_ptr = nullptr;
     268           7 :     if (git_commit_lookup(&head_ptr, repo, &commit_id) < 0) {
     269           0 :         JAMI_ERR("Unable to look up HEAD commit");
     270           0 :         return {};
     271             :     }
     272           7 :     GitCommit head_commit {head_ptr, git_commit_free};
     273             : 
     274             :     // Retrieve current index
     275           7 :     git_index* index_ptr = nullptr;
     276           7 :     if (git_repository_index(&index_ptr, repo) < 0) {
     277           0 :         JAMI_ERR("Unable to open repository index");
     278           0 :         return {};
     279             :     }
     280           7 :     GitIndex index {index_ptr, git_index_free};
     281             : 
     282             :     git_oid tree_id;
     283           7 :     if (git_index_write_tree(&tree_id, index.get()) < 0) {
     284           0 :         JAMI_ERR("Unable to write initial tree from index");
     285           0 :         return {};
     286             :     }
     287             : 
     288           7 :     git_tree* tree_ptr = nullptr;
     289           7 :     if (git_tree_lookup(&tree_ptr, repo, &tree_id) < 0) {
     290           0 :         JAMI_ERR("Unable to look up initial tree");
     291           0 :         return {};
     292             :     }
     293           7 :     GitTree tree = {tree_ptr, git_tree_free};
     294             : 
     295           7 :     git_buf to_sign = {};
     296             : #if( LIBGIT2_VER_MAJOR > 1 ) || ( LIBGIT2_VER_MAJOR == 1 && LIBGIT2_VER_MINOR >= 8 )
     297             :     // For libgit2 version 1.8.0 and above
     298           7 :     git_commit* const head_ref[1] = {head_commit.get()};
     299             : #else
     300             :     const git_commit* head_ref[1] = {head_commit.get()};
     301             : #endif
     302          14 :     if (git_commit_create_buffer(&to_sign,
     303             :                                  repo,
     304           7 :                                  sig.get(),
     305           7 :                                  sig.get(),
     306             :                                  nullptr,
     307             :                                  commit_msg.c_str(),
     308           7 :                                  tree.get(),
     309             :                                  1,
     310             :                                  &head_ref[0])
     311           7 :         < 0) {
     312           0 :         JAMI_ERR("Unable to create commit buffer");
     313           0 :         return {};
     314             :     }
     315             : 
     316             :     // git commit -S
     317           7 :     auto to_sign_vec = std::vector<uint8_t>(to_sign.ptr, to_sign.ptr + to_sign.size);
     318           7 :     auto signed_buf = account->identity().first->sign(to_sign_vec);
     319           7 :     std::string signed_str = base64::encode(signed_buf);
     320           7 :     if (git_commit_create_with_signature(&commit_id,
     321             :                                          repo,
     322           7 :                                          to_sign.ptr,
     323             :                                          signed_str.c_str(),
     324             :                                          "signature")
     325           7 :         < 0) {
     326           0 :         JAMI_ERR("Unable to sign commit");
     327           0 :         return {};
     328             :     }
     329             : 
     330           7 :     auto commit_str = git_oid_tostr_s(&commit_id);
     331           7 :     if (commit_str) {
     332           7 :         JAMI_INFO("New commit added with id: %s", commit_str);
     333             :         // Move commit to main branch
     334           7 :         git_reference* ref_ptr = nullptr;
     335           7 :         std::string branch_name = "refs/heads/" + branch;
     336           7 :         if (git_reference_create(&ref_ptr, repo, branch_name.c_str(), &commit_id, true, nullptr)
     337           7 :             < 0) {
     338           0 :             JAMI_WARN("Unable to move commit to main");
     339             :         }
     340           7 :         git_reference_free(ref_ptr);
     341           7 :     }
     342           7 :     return commit_str ? commit_str : "";
     343           7 : }
     344             : 
     345             : void
     346           3 : ConversationRepositoryTest::addAll(git_repository* repo)
     347             : {
     348             :     // git add -A
     349           3 :     git_index* index_ptr = nullptr;
     350           3 :     if (git_repository_index(&index_ptr, repo) < 0)
     351           0 :         return;
     352           3 :     GitIndex index {index_ptr, git_index_free};
     353           3 :     git_strarray array = {nullptr, 0};
     354           3 :     git_index_add_all(index.get(), &array, 0, nullptr, nullptr);
     355           3 :     git_index_write(index.get());
     356           3 :     git_strarray_free(&array);
     357           3 : }
     358             : 
     359             : void
     360           1 : ConversationRepositoryTest::testMerge()
     361             : {
     362           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     363           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     364             : 
     365             :     // Assert that repository exists
     366           1 :     CPPUNIT_ASSERT(repository != nullptr);
     367           2 :     auto repoPath = fileutils::get_data_dir() / aliceAccount->getAccountID()
     368           4 :                     / "conversations" / repository->id();
     369           1 :     CPPUNIT_ASSERT(std::filesystem::is_directory(repoPath));
     370             : 
     371             :     // Assert that first commit is signed by alice
     372             :     git_repository* repo;
     373           1 :     CPPUNIT_ASSERT(git_repository_open(&repo, repoPath.c_str()) == 0);
     374           2 :     auto id1 = addCommit(repo, aliceAccount, "main", "Commit 1");
     375             : 
     376           1 :     git_reference* ref = nullptr;
     377           1 :     git_commit* commit = nullptr;
     378             :     git_oid commit_id;
     379           1 :     git_oid_fromstr(&commit_id, repository->id().c_str());
     380           1 :     git_commit_lookup(&commit, repo, &commit_id);
     381           1 :     git_branch_create(&ref, repo, "to_merge", commit, false);
     382           1 :     git_reference_free(ref);
     383           1 :     git_repository_set_head(repo, "refs/heads/to_merge");
     384             : 
     385           2 :     auto id2 = addCommit(repo, aliceAccount, "to_merge", "Commit 2");
     386           1 :     git_repository_free(repo);
     387             : 
     388             :     // This will create a merge commit
     389           1 :     repository->merge(id2);
     390             : 
     391           1 :     CPPUNIT_ASSERT(repository->log().size() == 4 /* Initial, commit 1, 2, merge */);
     392           1 : }
     393             : 
     394             : void
     395           1 : ConversationRepositoryTest::testFFMerge()
     396             : {
     397           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     398           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     399             : 
     400             :     // Assert that repository exists
     401           1 :     CPPUNIT_ASSERT(repository != nullptr);
     402           2 :     auto repoPath = fileutils::get_data_dir() / aliceAccount->getAccountID()
     403           4 :                     / "conversations" / repository->id();
     404           1 :     CPPUNIT_ASSERT(std::filesystem::is_directory(repoPath));
     405             : 
     406             :     // Assert that first commit is signed by alice
     407             :     git_repository* repo;
     408           1 :     CPPUNIT_ASSERT(git_repository_open(&repo, repoPath.c_str()) == 0);
     409           2 :     auto id1 = addCommit(repo, aliceAccount, "main", "Commit 1");
     410             : 
     411           1 :     git_reference* ref = nullptr;
     412           1 :     git_commit* commit = nullptr;
     413             :     git_oid commit_id;
     414           1 :     git_oid_fromstr(&commit_id, id1.c_str());
     415           1 :     git_commit_lookup(&commit, repo, &commit_id);
     416           1 :     git_branch_create(&ref, repo, "to_merge", commit, false);
     417           1 :     git_reference_free(ref);
     418           1 :     git_repository_set_head(repo, "refs/heads/to_merge");
     419             : 
     420           2 :     auto id2 = addCommit(repo, aliceAccount, "to_merge", "Commit 2");
     421           1 :     git_repository_free(repo);
     422             : 
     423             :     // This will use a fast forward merge
     424           1 :     repository->merge(id2);
     425             : 
     426           1 :     CPPUNIT_ASSERT(repository->log().size() == 3 /* Initial, commit 1, 2 */);
     427           1 : }
     428             : 
     429             : void
     430           1 : ConversationRepositoryTest::testDiff()
     431             : {
     432           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     433           1 :     auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     434           1 :     auto uri = aliceAccount->getUsername();
     435           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     436             : 
     437           2 :     auto id1 = repository->commitMessage("Commit 1");
     438           2 :     auto id2 = repository->commitMessage("Commit 2");
     439           2 :     auto id3 = repository->commitMessage("Commit 3");
     440             : 
     441           1 :     auto diff = repository->diffStats(id2, id1);
     442           1 :     CPPUNIT_ASSERT(ConversationRepository::changedFiles(diff).empty());
     443           1 :     diff = repository->diffStats(id1);
     444           1 :     auto changedFiles = ConversationRepository::changedFiles(diff);
     445           1 :     CPPUNIT_ASSERT(!changedFiles.empty());
     446           1 :     CPPUNIT_ASSERT(changedFiles[0] == "admins/" + uri + ".crt");
     447           1 :     CPPUNIT_ASSERT(changedFiles[1] == "devices/" + aliceDeviceId.toString() + ".crt");
     448           1 : }
     449             : 
     450             : void
     451           1 : ConversationRepositoryTest::testMergeProfileWithConflict()
     452             : {
     453           1 :     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     454           2 :     auto repository = ConversationRepository::createConversation(aliceAccount);
     455             : 
     456             :     // Assert that repository exists
     457           1 :     CPPUNIT_ASSERT(repository != nullptr);
     458           2 :     auto repoPath = fileutils::get_data_dir() / aliceAccount->getAccountID()
     459           4 :                     / "conversations" / repository->id();
     460           1 :     CPPUNIT_ASSERT(std::filesystem::is_directory(repoPath));
     461             : 
     462             :     // Assert that first commit is signed by alice
     463             :     git_repository* repo;
     464           1 :     CPPUNIT_ASSERT(git_repository_open(&repo, repoPath.c_str()) == 0);
     465             : 
     466           2 :     auto profile = std::ofstream(repoPath / "profile.vcf");
     467           1 :     if (profile.is_open()) {
     468           1 :         profile << "TITLE: SWARM\n";
     469           1 :         profile << "SUBTITLE: Some description\n";
     470           1 :         profile << "AVATAR: BASE64\n";
     471           1 :         profile.close();
     472             :     }
     473           1 :     addAll(repo);
     474           2 :     auto id1 = addCommit(repo, aliceAccount, "main", "add profile");
     475           1 :     profile = std::ofstream(repoPath / "profile.vcf");
     476           1 :     if (profile.is_open()) {
     477           1 :         profile << "TITLE: SWARM\n";
     478           1 :         profile << "SUBTITLE: New description\n";
     479           1 :         profile << "AVATAR: BASE64\n";
     480           1 :         profile.close();
     481             :     }
     482           1 :     addAll(repo);
     483           2 :     auto id2 = addCommit(repo, aliceAccount, "main", "modify profile");
     484             : 
     485           1 :     git_reference* ref = nullptr;
     486           1 :     git_commit* commit = nullptr;
     487             :     git_oid commit_id;
     488           1 :     git_oid_fromstr(&commit_id, id1.c_str());
     489           1 :     git_commit_lookup(&commit, repo, &commit_id);
     490           1 :     git_branch_create(&ref, repo, "to_merge", commit, false);
     491           1 :     git_reference_free(ref);
     492           1 :     git_repository_set_head(repo, "refs/heads/to_merge");
     493             : 
     494           1 :     profile = std::ofstream(repoPath / "profile.vcf");
     495           1 :     if (profile.is_open()) {
     496           1 :         profile << "TITLE: SWARM\n";
     497           1 :         profile << "SUBTITLE: Another description\n";
     498           1 :         profile << "AVATAR: BASE64\n";
     499           1 :         profile.close();
     500             :     }
     501           1 :     addAll(repo);
     502           2 :     auto id3 = addCommit(repo, aliceAccount, "to_merge", "modify profile merge");
     503             : 
     504             :     // This will create a merge commit
     505           1 :     repository->merge(id3);
     506           1 :     CPPUNIT_ASSERT(repository->log().size() == 5 /* Initial, add, modify 1, modify 2, merge */);
     507           1 : }
     508             : 
     509             : } // namespace test
     510             : } // namespace jami
     511             : 
     512           1 : RING_TEST_RUNNER(jami::test::ConversationRepositoryTest::name())

Generated by: LCOV version 1.14