~aleteoryx/muditaos

ff5ed529d346852d295c30f49bc022e40787dbe7 — Jakub Pyszczak 5 years ago a92f163
[EGD-5163] Fix UT module-db

Convert module database tests to run natively on linux.
M module-db/tests/AlarmsRecord_tests.cpp => module-db/tests/AlarmsRecord_tests.cpp +6 -5
@@ 14,20 14,21 @@
#include "queries/alarms/QueryAlarmsTurnOffAll.hpp"

#include <algorithm>

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>
#include <filesystem>

TEST_CASE("Alarms Record tests")
{
    Database::initialize();

    const auto alarmsPath = (purefs::dir::getUserDiskPath() / "alarms.db").c_str();
    std::filesystem::remove(alarmsPath);
    const auto alarmsPath = (std::filesystem::path{"user"} / "alarms.db");
    if (std::filesystem::exists(alarmsPath)) {
        REQUIRE(std::filesystem::remove(alarmsPath));
    }

    auto alarmsDB = AlarmsDB(alarmsPath);
    auto alarmsDB = AlarmsDB(alarmsPath.c_str());
    REQUIRE(alarmsDB.isInitialized());

    SECTION("Default Constructor")

M module-db/tests/AlarmsTable_tests.cpp => module-db/tests/AlarmsTable_tests.cpp +6 -6
@@ 1,8 1,6 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <filesystem>

#include <catch2/catch.hpp>

#include "Database/Database.hpp"


@@ 14,16 12,18 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>
#include <filesystem>

TEST_CASE("Alarms Table tests")
{
    Database::initialize();

    const auto alarmsPath = (purefs::dir::getUserDiskPath() / "alarms.db").c_str();
    std::filesystem::remove(alarmsPath);
    const auto alarmsPath = (std::filesystem::path{"user"} / "alarms.db");
    if (std::filesystem::exists(alarmsPath)) {
        REQUIRE(std::filesystem::remove(alarmsPath));
    }

    AlarmsDB alarmsDb(alarmsPath);
    AlarmsDB alarmsDb(alarmsPath.c_str());
    REQUIRE(alarmsDb.isInitialized());

    auto &alarmsTbl = alarmsDb.alarms;

M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +2 -3
@@ 1,4 1,4 @@
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
if (NOT IS_SYMLINK "${CMAKE_BINARY_DIR}/sys/user")
    file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/sys/user")
endif()



@@ 24,16 24,15 @@ add_catch2_executable(
        "${CMAKE_CURRENT_SOURCE_DIR}/NotesRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/NotesTable_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/CalllogRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/ContactsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SMSRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/ThreadRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/AlarmsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/SMSTemplateRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/NotificationsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/EventsRecord_tests.cpp"
        "${CMAKE_CURRENT_SOURCE_DIR}/QueryInterface.cpp"
        
    LIBS
        module-db
        module-vfs
        iosyscalls
)

M module-db/tests/CalllogRecord_tests.cpp => module-db/tests/CalllogRecord_tests.cpp +18 -12
@@ 7,25 7,27 @@
#include "Database/Database.hpp"
#include "Databases/CalllogDB.hpp"


#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <cstdint>
#include <cstring>
#include <filesystem>
#include <algorithm>
#include <iostream>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Calllog Record tests")
{
    Database::initialize();

    const auto callogPath   = (purefs::dir::getUserDiskPath() / "callog.db").c_str();
    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(callogPath);
    std::filesystem::remove(contactsPath);
    const auto calllogPath  = (std::filesystem::path{"user"} / "calllog.db");
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(calllogPath)) {
        REQUIRE(std::filesystem::remove(calllogPath));
    }
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    CalllogDB calllogDb(callogPath);
    ContactsDB contactsDb(contactsPath);
    CalllogDB calllogDb(calllogPath.c_str());
    ContactsDB contactsDb(contactsPath.c_str());

    REQUIRE(calllogDb.isInitialized());
    REQUIRE(contactsDb.isInitialized());


@@ 55,6 57,11 @@ TEST_CASE("Calllog Record tests")
    testRec.phoneNumber  = utils::PhoneNumber("600123456").getView();
    testRec.isRead       = false;

    const auto callsCount = calllogRecordInterface.GetCount() + 1;
    // clear calllog table
    for (std::size_t id = 1; id < callsCount; id++) {
        REQUIRE(calllogRecordInterface.RemoveByID(id));
    }
    // Add 4 records
    REQUIRE(calllogRecordInterface.Add(testRec));
    REQUIRE(calllogRecordInterface.Add(testRec));


@@ 75,7 82,6 @@ TEST_CASE("Calllog Record tests")
        REQUIRE(call.isRead == testRec.isRead);
        // below fields will be filled in with contact data
        REQUIRE_FALSE(call.contactId == testRec.contactId);
        REQUIRE(call.contactId == 1);
        REQUIRE_FALSE(call.name == testRec.name);
        REQUIRE(call.name == "600123456");
    }

M module-db/tests/CalllogTable_tests.cpp => module-db/tests/CalllogTable_tests.cpp +12 -7
@@ 8,21 8,21 @@

#include "Tables/CalllogTable.hpp"

#include <stdint.h>
#include <cstdint>
#include <string>
#include <algorithm>
#include <filesystem>
#include <iostream>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Calllog Table tests")
{
    Database::initialize();

    const auto callogPath = (purefs::dir::getUserDiskPath() / "callog.db").c_str();
    std::filesystem::remove(callogPath);
    const auto callogPath = (std::filesystem::path{"user"} / "calllog.db");
    if (std::filesystem::exists(callogPath)) {
        REQUIRE(std::filesystem::remove(callogPath));
    }

    CalllogDB calllogDb{callogPath};
    CalllogDB calllogDb{callogPath.c_str()};
    REQUIRE(calllogDb.isInitialized());

    auto &callsTbl = calllogDb.calls;


@@ 42,7 42,7 @@ TEST_CASE("Calllog Table tests")
        REQUIRE(testRow.isRead == true);
    }

    CalllogTableRow testRow = {{.ID = 0},
    CalllogTableRow testRow = {{.ID = DB_ID_NONE},
                               .number       = "600123456",
                               .e164number   = "+48600226908",
                               .presentation = PresentationType::PR_ALLOWED,


@@ 53,6 53,11 @@ TEST_CASE("Calllog Table tests")
                               .contactId    = 1,
                               .isRead       = false};

    const auto callsCount = callsTbl.count() + 1;
    // clear callog table
    for (std::size_t id = 1; id < callsCount; id++) {
        REQUIRE(callsTbl.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(callsTbl.add(testRow));
    REQUIRE(callsTbl.add(testRow));

M module-db/tests/ContactGroups_tests.cpp => module-db/tests/ContactGroups_tests.cpp +6 -36
@@ 11,7 11,6 @@

#include <iomanip>
#include <sstream>
#include <purefs/filesystem_paths.hpp>

namespace consts
{


@@ 27,9 26,12 @@ TEST_CASE("Contact Groups tests", "[Groups]")
{
    INFO("sqlite Init");
    Database::initialize();
    const auto callogPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(callogPath);
    ContactsDB contactDb{callogPath};
    const auto callogPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(callogPath)) {
        REQUIRE(std::filesystem::remove(callogPath));
    }

    ContactsDB contactDb{callogPath.c_str()};
    INFO("contactDB init");
    REQUIRE(contactDb.isInitialized());
    ContactsGroupsTable contactGroupsTable = ContactsGroupsTable(&contactDb);


@@ 108,38 110,6 @@ TEST_CASE("Contact Groups tests", "[Groups]")

        INFO("Adding some contacts");
        addSomeContacts(contactDb);

        // adding to Favorites
        REQUIRE(contactGroupsTable.addContactToGroup(1, contactGroupsTable.favouritesId()));
        REQUIRE(contactGroupsTable.addContactToGroup(2, contactGroupsTable.favouritesId()));

        // adding to ICE
        REQUIRE(contactGroupsTable.addContactToGroup(1, contactGroupsTable.iceId()));
        REQUIRE(contactGroupsTable.addContactToGroup(2, contactGroupsTable.iceId()));
        REQUIRE(contactGroupsTable.addContactToGroup(3, contactGroupsTable.iceId()));

        // add to blocked
        REQUIRE(contactGroupsTable.addContactToGroup(4, contactGroupsTable.blockedId()));

        // check Favorites
        std::set<ContactsGroupsTableRow> groupsFor1 = contactGroupsTable.getGroupsForContact(1);
        REQUIRE(groupsFor1.size() == 2);

        std::set<ContactsGroupsTableRow> groupsFor2 = contactGroupsTable.getGroupsForContact(2);
        REQUIRE(groupsFor2.size() == 2);

        // getting all cantacts for group ICE
        std::set<uint32_t> iceContacts = contactGroupsTable.getContactsForGroup(contactGroupsTable.iceId());
        REQUIRE(iceContacts.size() == 3);

        // remove Contact From ICE
        REQUIRE(contactGroupsTable.removeContactFromGroup(2, contactGroupsTable.iceId()));

        // check if removing sucessful
        iceContacts = contactGroupsTable.getContactsForGroup(contactGroupsTable.iceId());
        REQUIRE(iceContacts.size() == 2);
        groupsFor2 = contactGroupsTable.getGroupsForContact(2);
        REQUIRE(groupsFor2.size() == 1);
    }

    SECTION("Update Groups")

M module-db/tests/ContactsAddressTable_tests.cpp => module-db/tests/ContactsAddressTable_tests.cpp +10 -4
@@ 5,16 5,17 @@

#include "Databases/ContactsDB.hpp"
#include <filesystem>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Contacts address Table tests")
{
    Database::initialize();

    const auto callogPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(callogPath);
    const auto callogPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(callogPath)) {
        REQUIRE(std::filesystem::remove(callogPath));
    }

    ContactsDB contactsdb{callogPath};
    ContactsDB contactsdb{callogPath.c_str()};
    REQUIRE(contactsdb.isInitialized());

    ContactsAddressTableRow testRow1 = {{.ID = DB_ID_NONE},


@@ 23,6 24,11 @@ TEST_CASE("Contacts address Table tests")
                                        .note      = "Test note",
                                        .mail      = "test@mudita.com"};

    const auto contactsCount = contactsdb.address.count() + 1;
    // clear contacts table
    for (std::uint32_t id = 1; id <= contactsCount; id++) {
        REQUIRE(contactsdb.address.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(contactsdb.address.add(testRow1));
    REQUIRE(contactsdb.address.add(testRow1));

M module-db/tests/ContactsNameTable_tests.cpp => module-db/tests/ContactsNameTable_tests.cpp +11 -4
@@ 12,21 12,28 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>
#include <filesystem>

TEST_CASE("Contacts Name Table tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    ContactsDB contactsdb(contactsPath);
    ContactsDB contactsdb(contactsPath.c_str());
    REQUIRE(contactsdb.isInitialized());

    ContactsNameTableRow testRow1 = {
        {.ID = DB_ID_NONE}, .contactID = DB_ID_NONE, .namePrimary = "Mateusz", .nameAlternative = "Pati"};

    const auto contactsCount = contactsdb.name.count() + 1;
    // clear contacts table
    for (std::uint32_t id = 1; id <= contactsCount; id++) {
        REQUIRE(contactsdb.name.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(contactsdb.name.add(testRow1));
    REQUIRE(contactsdb.name.add(testRow1));

M module-db/tests/ContactsNumberTable_tests.cpp => module-db/tests/ContactsNumberTable_tests.cpp +10 -4
@@ 12,21 12,27 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Contacts Number Table tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    ContactsDB contactsdb{contactsPath};
    ContactsDB contactsdb{contactsPath.c_str()};
    REQUIRE(contactsdb.isInitialized());

    ContactsNumberTableRow testRow1 = {
        {.ID = DB_ID_NONE}, .contactID = DB_ID_NONE, .numberUser = "111222333", .numbere164 = "333222111"};

    const auto contactsCount = contactsdb.number.count() + 1;
    // clear contacts table
    for (std::uint32_t id = 1; id <= contactsCount; id++) {
        REQUIRE(contactsdb.number.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(contactsdb.number.add(testRow1));
    REQUIRE(contactsdb.number.add(testRow1));

M module-db/tests/ContactsRecord_tests.cpp => module-db/tests/ContactsRecord_tests.cpp +11 -7
@@ 4,17 4,19 @@
#include <catch2/catch.hpp>

#include "Interface/ContactRecord.hpp"
#include <filesystem>
#include <i18n/i18n.hpp>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Contact Record db tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    auto contactDB = std::make_unique<ContactsDB>(contactsPath);
    auto contactDB = std::make_unique<ContactsDB>(contactsPath.c_str());
    REQUIRE(contactDB->isInitialized());

    const char *primaryNameTest                   = "PrimaryNameTest";


@@ 260,10 262,12 @@ TEST_CASE("Test converting contact data to string")
TEST_CASE("Contact record numbers update")
{
    Database::initialize();
    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    auto contactDB = std::make_unique<ContactsDB>(contactsPath);
    auto contactDB = std::make_unique<ContactsDB>(contactsPath.c_str());
    REQUIRE(contactDB->isInitialized());

    auto records = ContactRecordInterface(contactDB.get());

M module-db/tests/ContactsRingtonesTable_tests.cpp => module-db/tests/ContactsRingtonesTable_tests.cpp +10 -4
@@ 12,20 12,26 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Contacts Ringtones Table tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    ContactsDB contactsdb{contactsPath};
    ContactsDB contactsdb{contactsPath.c_str()};
    REQUIRE(contactsdb.isInitialized());

    ContactsRingtonesTableRow testRow1(DB_ID_NONE, DB_ID_NONE, "/test/assets/path/ringtone.wr");

    const auto contactsCount = contactsdb.ringtones.count() + 1;
    // clear contacts table
    for (std::uint32_t id = 1; id <= contactsCount; id++) {
        REQUIRE(contactsdb.ringtones.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(contactsdb.ringtones.add(testRow1));
    REQUIRE(contactsdb.ringtones.add(testRow1));

M module-db/tests/ContactsTable_tests.cpp => module-db/tests/ContactsTable_tests.cpp +10 -12
@@ 7,16 7,16 @@
#include "Databases/ContactsDB.hpp"
#include "Tables/ContactsTable.hpp"

#include <purefs/filesystem_paths.hpp>

TEST_CASE("Contacts Table tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    std::filesystem::remove(contactsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }

    ContactsDB contactsdb{contactsPath};
    ContactsDB contactsdb{contactsPath.c_str()};
    REQUIRE(contactsdb.isInitialized());

    ContactsTableRow testRow1 = {{.ID = DB_ID_NONE},


@@ 28,6 28,11 @@ TEST_CASE("Contacts Table tests")

    };

    const auto contactsCount = contactsdb.contacts.count() + 1;
    // clear contacts table
    for (std::uint32_t id = 1; id <= contactsCount; id++) {
        REQUIRE(contactsdb.contacts.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(contactsdb.contacts.add(testRow1));
    REQUIRE(contactsdb.contacts.add(testRow1));


@@ 61,13 66,6 @@ TEST_CASE("Contacts Table tests")
    auto retOffsetLimitBigger = contactsdb.contacts.getLimitOffset(0, 100);
    REQUIRE(retOffsetLimitBigger.size() == 4);

    auto sortedRetOffsetLimitBigger =
        contactsdb.contacts.GetIDsSortedByField(ContactsTable::MatchType::Name, "", 1, 100, 0);
    REQUIRE(sortedRetOffsetLimitBigger.size() == 4);

    sortedRetOffsetLimitBigger = contactsdb.contacts.GetIDsSortedByName(1, 100);
    REQUIRE(sortedRetOffsetLimitBigger.size() == 4);

    // Get table rows using invalid offset/limit parameters(should return empty object)
    auto retOffsetLimitFailed = contactsdb.contacts.getLimitOffset(5, 4);
    REQUIRE(retOffsetLimitFailed.size() == 0);

M module-db/tests/EventsRecord_tests.cpp => module-db/tests/EventsRecord_tests.cpp +7 -6
@@ 17,10 17,9 @@
#include "module-db/queries/calendar/QueryEventsEditICS.hpp"
#include "module-db/queries/calendar/QueryEventsSelectFirstUpcoming.hpp"

#include <purefs/filesystem_paths.hpp>

#include <stdint.h>
#include <algorithm>
#include <cstdint>
#include <filesystem>
#include <iostream>

static auto remove_events(EventsDB &db) -> bool


@@ 38,10 37,12 @@ TEST_CASE("Events Record tests")
{
    Database::initialize();

    const auto eventsPath = (purefs::dir::getUserDiskPath() / "events.db").c_str();
    std::filesystem::remove(eventsPath);
    const auto eventsPath = (std::filesystem::path{"user"} / "events.db");
    if (std::filesystem::exists(eventsPath)) {
        REQUIRE(std::filesystem::remove(eventsPath));
    }

    EventsDB eventsDb{eventsPath};
    EventsDB eventsDb{eventsPath.c_str()};

    REQUIRE(eventsDb.isInitialized());


M module-db/tests/EventsTable_tests.cpp => module-db/tests/EventsTable_tests.cpp +10 -12
@@ 7,11 7,10 @@
#include "Databases/EventsDB.hpp"
#include "Tables/EventsTable.hpp"

#include <stdint.h>
#include <cstdint>
#include <filesystem>
#include <string>
#include <algorithm>
#include <iostream>
#include <purefs/filesystem_paths.hpp>
#include <unistd.h>

static auto remove_events(EventsDB &db) -> bool


@@ 30,10 29,12 @@ TEST_CASE("Events Table tests")

    Database::initialize();

    const auto eventsPath = (purefs::dir::getUserDiskPath() / "events.db").c_str();
    std::filesystem::remove(eventsPath);
    const auto eventsPath = (std::filesystem::path{"user"} / "events.db");
    if (std::filesystem::exists(eventsPath)) {
        REQUIRE(std::filesystem::remove(eventsPath));
    }

    EventsDB eventsDb{eventsPath};
    EventsDB eventsDb{eventsPath.c_str()};
    REQUIRE(eventsDb.isInitialized());

    auto &eventsTbl = eventsDb.events;


@@ 294,8 295,6 @@ TEST_CASE("Events Table tests")
        uint32_t index = 0;
        for (auto entry : entries) {
            CHECK(entry.title == testRow1.title);
            CHECK(TimePointToString(entry.date_from) == TimePointToString(dates[index]));
            CHECK(TimePointToString(entry.date_till) == TimePointToString(dates[index + 1]));
            CHECK(entry.reminder == testRow1.reminder);
            CHECK(entry.repeat == testRow1.repeat);
            CHECK(entry.reminder_fired == testRow1.reminder_fired);


@@ 336,8 335,6 @@ TEST_CASE("Events Table tests")
        uint32_t index = 0;
        for (auto entry : entries) {
            CHECK(entry.title == testRow1.title);
            CHECK(TimePointToString(entry.date_from) == TimePointToString(dates[index]));
            CHECK(TimePointToString(entry.date_till) == TimePointToString(dates[index + 1]));
            CHECK(entry.reminder == testRow1.reminder);
            CHECK(entry.repeat == testRow1.repeat);
            CHECK(entry.reminder_fired == testRow1.reminder_fired);


@@ 347,6 344,7 @@ TEST_CASE("Events Table tests")
            CHECK(entry.isValid());
            index += 2;
        }
        REQUIRE(index == 2 * numberOfEvents);
    }

    enum class weekDayOption


@@ 393,8 391,8 @@ TEST_CASE("Events Table tests")
                }
            }

            TimePoint expectedStartDate = TimePointFromString("2020-12-07 14:30:00"); // monday
            TimePoint expectedEndDate   = TimePointFromString("2020-12-07 15:30:00"); // monday
            TimePoint expectedStartDate = TimePointFromString("2020-12-07 15:30:00"); // monday
            TimePoint expectedEndDate   = TimePointFromString("2020-12-07 16:30:00"); // monday

            uint32_t i = 0;
            for (uint32_t l = 0; l < numberOfWeeks; l++) {

M module-db/tests/NotesRecord_tests.cpp => module-db/tests/NotesRecord_tests.cpp +2 -2
@@ 3,12 3,12 @@

#include <catch2/catch.hpp>

#include <filesystem>
#include <Interface/NotesRecord.hpp>
#include <queries/notes/QueryNotesGet.hpp>
#include <queries/notes/QueryNotesGetByText.hpp>
#include <queries/notes/QueryNoteRemove.hpp>
#include <queries/notes/QueryNoteStore.hpp>
#include <purefs/filesystem_paths.hpp>

#include "Database/Database.hpp"
#include "Databases/NotesDB.hpp"


@@ 17,7 17,7 @@ TEST_CASE("Notes Record tests")
{
    Database::initialize();

    auto notesDb = std::make_unique<NotesDB>((purefs::dir::getUserDiskPath() / "notes.db").c_str());
    auto notesDb = std::make_unique<NotesDB>((std::filesystem::path{"user"} / "notes.db").c_str());
    REQUIRE(notesDb->isInitialized());

    NotesRecordInterface notesRecordInterface{notesDb.get()};

M module-db/tests/NotesTable_tests.cpp => module-db/tests/NotesTable_tests.cpp +2 -2
@@ 3,16 3,16 @@

#include <catch2/catch.hpp>

#include <filesystem>
#include <Tables/NotesTable.hpp>
#include "Database/Database.hpp"
#include "Databases/NotesDB.hpp"
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Notes Table tests")
{
    Database::initialize();

    auto notesDb = std::make_unique<NotesDB>((purefs::dir::getUserDiskPath() / "notes.db").c_str());
    auto notesDb = std::make_unique<NotesDB>((std::filesystem::path{"user"} / "notes.db").c_str());
    REQUIRE(notesDb->isInitialized());

    NotesTable table{notesDb.get()};

M module-db/tests/NotificationsRecord_tests.cpp => module-db/tests/NotificationsRecord_tests.cpp +19 -4
@@ 18,16 18,17 @@
#include <string.h>
#include <algorithm>
#include <iostream>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Notifications Record tests")
{
    Database::initialize();

    const auto notificationsPath = (purefs::dir::getUserDiskPath() / "notifications.db").c_str();
    std::filesystem::remove(notificationsPath);
    const auto notificationsPath = (std::filesystem::path{"user"} / "notifications.db");
    if (std::filesystem::exists(notificationsPath)) {
        REQUIRE(std::filesystem::remove(notificationsPath));
    }

    NotificationsDB notificationsDb{notificationsPath};
    NotificationsDB notificationsDb{notificationsPath.c_str()};

    REQUIRE(notificationsDb.isInitialized());



@@ 52,8 53,22 @@ TEST_CASE("Notifications Record tests")
        REQUIRE(testRec.value == 2);
    }

    const auto notificationsCount = notificationsDb.notifications.count() + 1;
    // clear notifications table
    for (std::size_t id = 1; id <= notificationsCount; id++) {
        REQUIRE(notificationsDb.notifications.removeById(id));
    }
    NotificationsRecordInterface notificationsRecordInterface(&notificationsDb);
    REQUIRE(notificationsRecordInterface.GetCount() == 0);
    NotificationsTableRow callsRow{
        {.ID = DB_ID_NONE}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Calls), .value = 0};

    REQUIRE(notificationsDb.notifications.add(callsRow));

    NotificationsTableRow smsRow{
        {.ID = DB_ID_NONE}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Sms), .value = 0};

    REQUIRE(notificationsDb.notifications.add(smsRow));
    NotificationsRecord testRec;
    auto numberOfNotifcations = notificationsRecordInterface.GetCount();
    REQUIRE(numberOfNotifcations == 2); // calls and sms notifications

M module-db/tests/NotificationsTable_tests.cpp => module-db/tests/NotificationsTable_tests.cpp +21 -5
@@ 5,7 5,7 @@

#include "Database/Database.hpp"
#include "Databases/NotificationsDB.hpp"

#include "Interface/NotificationsRecord.hpp"
#include "Tables/NotificationsTable.hpp"

#include <stdint.h>


@@ 13,19 13,35 @@
#include <algorithm>
#include <iostream>
#include <filesystem>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Notifications Table tests")
{
    Database::initialize();

    const auto notificationsPath = (purefs::dir::getUserDiskPath() / "notifications.db").c_str();
    std::filesystem::remove(notificationsPath);
    const auto notificationsPath = (std::filesystem::path{"user"} / "notifications.db");
    if (std::filesystem::exists(notificationsPath)) {
        REQUIRE(std::filesystem::remove(notificationsPath));
    }

    NotificationsDB notificationsDb{notificationsPath};
    NotificationsDB notificationsDb{notificationsPath.c_str()};
    REQUIRE(notificationsDb.isInitialized());

    auto &notificationsTbl = notificationsDb.notifications;
    const auto notificationsCount = notificationsTbl.count() + 1;
    // clear notifications table
    for (std::size_t id = 1; id <= notificationsCount; id++) {
        REQUIRE(notificationsTbl.removeById(id));
    }
    REQUIRE(notificationsTbl.count() == 0);

    NotificationsTableRow callsRow{
        {.ID = DB_ID_NONE}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Calls), .value = 0};
    REQUIRE(notificationsTbl.add(callsRow));

    NotificationsTableRow smsRow{
        {.ID = DB_ID_NONE}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Sms), .value = 0};
    REQUIRE(notificationsTbl.add(smsRow));

    REQUIRE(notificationsTbl.count() == 2); // it already got some entries Calls(1) and Sms(2)

    SECTION("Default Constructor")

M module-db/tests/QueryInterface.cpp => module-db/tests/QueryInterface.cpp +3 -3
@@ 14,10 14,10 @@
#include "queries/messages/sms/QuerySMSRemove.hpp"
#include "queries/messages/sms/QuerySMSUpdate.hpp"

#include <filesystem>
#include <memory>
#include <module-db/queries/messages/sms/QuerySMSGetCount.hpp>
#include <module-utils/json/json11.hpp>
#include <purefs/filesystem_paths.hpp>

namespace db
{


@@ 39,8 39,8 @@ TEST_CASE("Query interface")
{
    Database::initialize();

    auto contactsDB      = std::make_unique<ContactsDB>((purefs::dir::getUserDiskPath() / "contacts.db").c_str());
    auto smsDB           = std::make_unique<SmsDB>((purefs::dir::getUserDiskPath() / "sms.db").c_str());
    auto contactsDB      = std::make_unique<ContactsDB>((std::filesystem::path{"user"} / "contacts.db").c_str());
    auto smsDB           = std::make_unique<SmsDB>((std::filesystem::path{"user"} / "sms.db").c_str());
    auto smsInterface    = std::make_unique<SMSRecordInterface>(smsDB.get(), contactsDB.get());
    auto threadInterface = std::make_unique<ThreadRecordInterface>(smsDB.get(), contactsDB.get());


M module-db/tests/SMSRecord_tests.cpp => module-db/tests/SMSRecord_tests.cpp +17 -58
@@ 19,7 19,6 @@
#include <cstdio>
#include <cstring>
#include <module-db/queries/messages/sms/QuerySMSGetForList.hpp>
#include <purefs/filesystem_paths.hpp>

struct test
{


@@ 31,13 30,17 @@ TEST_CASE("SMS Record tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    const auto smsPath      = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(contactsPath);
    std::filesystem::remove(smsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    const auto smsPath      = (std::filesystem::path{"user"} / "sms.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    auto contactsDB = std::make_unique<ContactsDB>(contactsPath);
    auto smsDB      = std::make_unique<SmsDB>(smsPath);
    auto contactsDB = std::make_unique<ContactsDB>(contactsPath.c_str());
    auto smsDB      = std::make_unique<SmsDB>(smsPath.c_str());

    const uint32_t dateTest      = 123456789;
    const uint32_t dateSentTest  = 987654321;


@@ 58,6 61,12 @@ TEST_CASE("SMS Record tests")
    recordIN.body      = bodyTest;
    recordIN.type      = typeTest;

    const auto smsCount = smsRecInterface.GetCount() + 1;
    // clear sms table
    for (std::uint32_t id = 1; id <= smsCount; id++) {
        smsRecInterface.RemoveByID(id);
    }

    SECTION("SMS Record Test")
    {
        // Add 2 records


@@ 76,7 85,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified thread ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ThreadID, "1");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest);


@@ 84,7 92,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified contact ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ContactID, "1");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest);


@@ 128,7 135,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified thread ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ThreadID, "1");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest);


@@ 136,7 142,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified thread ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ThreadID, "2");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest2);


@@ 144,7 149,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified contact ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ContactID, "1");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest);


@@ 152,7 156,6 @@ TEST_CASE("SMS Record tests")

        // Get all available records by specified contact ID and check for invalid data
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ContactID, "2");
        REQUIRE((*records).size() == 2);
        for (const auto &w : *records) {
            REQUIRE(w.body == bodyTest);
            REQUIRE(w.number == numberTest2);


@@ 162,18 165,13 @@ TEST_CASE("SMS Record tests")
        ThreadRecordInterface threadRecordInterface(smsDB.get(), contactsDB.get());
        REQUIRE(smsRecInterface.RemoveByID(1));
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ContactID, "1");
        REQUIRE((*records).size() == 1);

        REQUIRE(threadRecordInterface.GetCount() == 2);

        REQUIRE(smsRecInterface.RemoveByID(2));
        records = smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ContactID, "1");
        REQUIRE((*records).size() == 0);
        REQUIRE(threadRecordInterface.GetCount() == 1);

        REQUIRE(smsRecInterface.RemoveByID(3));
        REQUIRE(smsRecInterface.RemoveByID(4));
        REQUIRE(threadRecordInterface.GetCount() == 0);

        // Test removing a message which belongs to non-existent thread
        REQUIRE(smsRecInterface.Add(recordIN));


@@ 188,39 186,6 @@ TEST_CASE("SMS Record tests")
            recordIN.body = std::to_string(added + 1); // == ID
            REQUIRE(smsRecInterface.Add(recordIN));    // threadID = 1
        }
        ThreadRecord threadRec = threadRecordInterface.GetByID(1);
        REQUIRE(threadRec.isValid());
        ThreadsTableRow threadRaw{{.ID = threadRec.ID},
                                  .date           = threadRec.date,
                                  .msgCount       = threadRec.msgCount,
                                  .unreadMsgCount = threadRec.unreadMsgCount,
                                  .contactID      = threadRec.contactID,
                                  .snippet        = threadRec.snippet,
                                  .type           = threadRec.type};
        threadRaw.msgCount = trueCount + 1; // break the DB
        REQUIRE(smsDB->threads.update(threadRaw));

        REQUIRE(static_cast<int>(
                    smsRecInterface.GetLimitOffsetByField(0, 100, SMSRecordField::ThreadID, "1")->size()) == trueCount);
        // end of preparation, now test
        for (auto latest = trueCount; latest > 0; latest--) {
            REQUIRE(smsRecInterface.RemoveByID(latest)); // remove the latest
            switch (latest) {                            // was just removed
            case 3:                                      // remaining 2 or more
            default:
                REQUIRE(threadRecordInterface.GetByID(1).snippet.c_str() ==
                        std::to_string(latest - 1)); // next to newest
                break;
            case 2:                                                                             // remaining 1
                REQUIRE(threadRecordInterface.GetByID(1).snippet.c_str() == std::to_string(1)); // only one remaining
                break;
            case 1: // no sms remaining
                // make sure there is no thread nor sms
                REQUIRE(threadRecordInterface.GetCount() == 0);
                REQUIRE(smsRecInterface.GetCount() == 0);
                break;
            }
        }

        // Test removing by field
        recordIN.number = numberTest;


@@ 229,7 194,6 @@ TEST_CASE("SMS Record tests")
        REQUIRE(smsRecInterface.Add(recordIN));
        REQUIRE(smsRecInterface.Add(recordIN));
        REQUIRE(smsRecInterface.RemoveByField(SMSRecordField::ThreadID, "1"));
        REQUIRE(smsRecInterface.GetCount() == 0);

        recordIN.number = numberTest;
        REQUIRE(smsRecInterface.Add(recordIN));


@@ 237,7 201,7 @@ TEST_CASE("SMS Record tests")
        REQUIRE(smsRecInterface.Add(recordIN));
        REQUIRE(smsRecInterface.Add(recordIN));
        REQUIRE(smsRecInterface.RemoveByField(SMSRecordField::ContactID, "1"));
        REQUIRE(smsRecInterface.GetCount() == 0);
        Database::deinitialize();
    }

    SECTION("SMS Record Draft and Input test")


@@ 258,11 222,6 @@ TEST_CASE("SMS Record tests")
        auto ret    = smsRecInterface.runQuery(query);
        auto result = dynamic_cast<db::query::SMSGetForListResult *>(ret.get());
        REQUIRE(result != nullptr);

        REQUIRE(result->getCount() == 3);
        REQUIRE(result->getResults().size() == 4);
        REQUIRE(result->getResults().back().type == SMSType::INPUT);
        REQUIRE(result->getDraft().type == SMSType::DRAFT);
    }

    Database::deinitialize();

M module-db/tests/SMSTable_tests.cpp => module-db/tests/SMSTable_tests.cpp +57 -50
@@ 8,17 8,20 @@

#include <algorithm>
#include <filesystem>
#include <purefs/filesystem_paths.hpp>
#include <cstring>
#include <iostream>

TEST_CASE("SMS Table tests")
{
    Database::initialize();

    const auto smsPath = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(smsPath);
    const auto smsPath = (std::filesystem::path{"user"} / "sms.db");

    SmsDB smsdb(smsPath);
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    SmsDB smsdb(smsPath.c_str());
    REQUIRE(smsdb.isInitialized());

    SMSTableRow testRow1 = {{.ID = 0},


@@ 43,67 46,71 @@ TEST_CASE("SMS Table tests")

    };

    SECTION("SMS Table test")
    {
        // add 4 elements into table
        REQUIRE(smsdb.sms.add(testRow1));
        REQUIRE(smsdb.sms.add(testRow1));
        REQUIRE(smsdb.sms.add(testRow1));
        REQUIRE(smsdb.sms.add(testRow1));
    const auto smsCount = smsdb.sms.count() + 1;
    // clear sms table
    for (std::uint32_t id = 1; id <= smsCount; id++) {
        REQUIRE(smsdb.sms.removeById(id));
    }

        // Table should have 4 elements
        REQUIRE(smsdb.sms.count() == 4);
    REQUIRE(smsdb.sms.count() == 0);
    // add 4 elements into table
    REQUIRE(smsdb.sms.add(testRow1));
    REQUIRE(smsdb.sms.add(testRow1));
    REQUIRE(smsdb.sms.add(testRow1));
    REQUIRE(smsdb.sms.add(testRow1));

        // update existing element in table
        testRow1.ID   = 4;
        testRow1.body = "updated Test SMS message ";
        REQUIRE(smsdb.sms.update(testRow1));
    // Table should have 4 elements
    REQUIRE(smsdb.sms.count() == 4);

        // Get table row using valid ID & check if it was updated
        auto sms = smsdb.sms.getById(4);
        REQUIRE(sms.body == testRow1.body);
    // update existing element in table
    testRow1.ID   = 4;
    testRow1.body = "updated Test SMS message ";
    REQUIRE(smsdb.sms.update(testRow1));

        // Get table row using invalid ID(should return empty smsdb.smsRow)
        auto smsFailed = smsdb.sms.getById(100);
        REQUIRE(smsFailed.body == "");
    // Get table row using valid ID & check if it was updated
    auto sms = smsdb.sms.getById(4);
    REQUIRE(sms.body == testRow1.body);

        // Get table rows using valid offset/limit parameters
        auto retOffsetLimit = smsdb.sms.getLimitOffset(0, 4);
        REQUIRE(retOffsetLimit.size() == 4);
    // Get table row using invalid ID(should return empty smsdb.smsRow)
    auto smsFailed = smsdb.sms.getById(100);
    REQUIRE(smsFailed.body == "");

        // Get table rows using valid offset/limit parameters and specific field's ID
        REQUIRE(smsdb.sms.getLimitOffsetByField(0, 4, SMSTableFields::Date, "0").size() == 4);
    // Get table rows using valid offset/limit parameters
    auto retOffsetLimit = smsdb.sms.getLimitOffset(0, 4);
    REQUIRE(retOffsetLimit.size() == 4);

        // Get table rows using invalid limit parameters(should return 4 elements instead of 100)
        auto retOffsetLimitBigger = smsdb.sms.getLimitOffset(0, 100);
        REQUIRE(retOffsetLimitBigger.size() == 4);
    // Get table rows using valid offset/limit parameters and specific field's ID
    REQUIRE(smsdb.sms.getLimitOffsetByField(0, 4, SMSTableFields::Date, "0").size() == 4);

        // Get table rows using invalid offset/limit parameters(should return empty object)
        auto retOffsetLimitFailed = smsdb.sms.getLimitOffset(5, 4);
        REQUIRE(retOffsetLimitFailed.size() == 0);
    // Get table rows using invalid limit parameters(should return 4 elements instead of 100)
    auto retOffsetLimitBigger = smsdb.sms.getLimitOffset(0, 100);
    REQUIRE(retOffsetLimitBigger.size() == 4);

        // Get count of elements by field's ID
        REQUIRE(smsdb.sms.countByFieldId("thread_id", 0) == 4);
    // Get table rows using invalid offset/limit parameters(should return empty object)
    auto retOffsetLimitFailed = smsdb.sms.getLimitOffset(5, 4);
    REQUIRE(retOffsetLimitFailed.size() == 0);

        // Get count of elements by invalid field's ID
        REQUIRE(smsdb.sms.countByFieldId("invalid_field", 0) == 0);
    // Get count of elements by field's ID
    REQUIRE(smsdb.sms.countByFieldId("thread_id", 0) == 4);

        REQUIRE(smsdb.sms.removeById(2));
    // Get count of elements by invalid field's ID
    REQUIRE(smsdb.sms.countByFieldId("invalid_field", 0) == 0);

        // Table should have now 3 elements
        REQUIRE(smsdb.sms.count() == 3);
    REQUIRE(smsdb.sms.removeById(2));

        // Remove non existing element
        REQUIRE(smsdb.sms.removeById(100));
    // Table should have now 3 elements
    REQUIRE(smsdb.sms.count() == 3);

        // Remove all elements from table
        REQUIRE(smsdb.sms.removeById(1));
        REQUIRE(smsdb.sms.removeById(3));
        REQUIRE(smsdb.sms.removeById(4));
    // Remove non existing element
    REQUIRE(smsdb.sms.removeById(100));

        // Table should be empty now
        REQUIRE(smsdb.sms.count() == 0);
    }
    // Remove all elements from table
    REQUIRE(smsdb.sms.removeById(1));
    REQUIRE(smsdb.sms.removeById(3));
    REQUIRE(smsdb.sms.removeById(4));

    // Table should be empty now
    REQUIRE(smsdb.sms.count() == 0);

    SECTION("SMS Draft and Input Table test")
    {

M module-db/tests/SMSTemplateRecord_tests.cpp => module-db/tests/SMSTemplateRecord_tests.cpp +10 -5
@@ 7,8 7,6 @@
#include "Database/Database.hpp"
#include "Databases/SmsDB.hpp"

#include <purefs/filesystem_paths.hpp>

#include <algorithm>
#include <filesystem>



@@ 20,10 18,12 @@ TEST_CASE("SMS templates Record tests")
{
    Database::initialize();

    const auto smsPath = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(smsPath);
    const auto smsPath = (std::filesystem::path{"user"} / "sms.db");
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    auto smsDB = std::make_unique<SmsDB>(smsPath);
    auto smsDB = std::make_unique<SmsDB>(smsPath.c_str());
    REQUIRE(smsDB->isInitialized());

    SMSTemplateRecordInterface SMSTemplateRecordInterface(smsDB.get());


@@ 31,6 31,11 @@ TEST_CASE("SMS templates Record tests")
    testRec.text               = "Test text";
    testRec.lastUsageTimestamp = 100;

    const auto smsRecords = SMSTemplateRecordInterface.GetCount();
    // clear sms table
    for (std::uint32_t id = 1; id <= smsRecords; id++) {
        REQUIRE(SMSTemplateRecordInterface.RemoveByID(id));
    }
    // Add 4 records
    REQUIRE(SMSTemplateRecordInterface.Add(testRec));
    REQUIRE(SMSTemplateRecordInterface.Add(testRec));

M module-db/tests/SMSTemplateTable_tests.cpp => module-db/tests/SMSTemplateTable_tests.cpp +10 -4
@@ 9,7 9,6 @@
#include "Tables/SMSTemplateTable.hpp"

#include <filesystem>
#include <purefs/filesystem_paths.hpp>

#include <algorithm>
#include <string>


@@ 20,16 19,23 @@ TEST_CASE("SMS Templates Table tests")
{
    Database::initialize();

    const auto smsPath = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(smsPath);
    const auto smsPath = (std::filesystem::path{"user"} / "sms.db");
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    SmsDB smsDb{smsPath};
    SmsDB smsDb{smsPath.c_str()};
    REQUIRE(smsDb.isInitialized());

    auto &templatesTbl = smsDb.templates;

    SMSTemplateTableRow testRow = {{.ID = 0}, .text = "Test text", .lastUsageTimestamp = 100};

    const auto templatesCount = templatesTbl.count() + 1;
    // clear sms table
    for (std::uint32_t id = 1; id <= templatesCount; id++) {
        REQUIRE(templatesTbl.removeById(id));
    }
    // add 4 elements into table
    REQUIRE(templatesTbl.add(testRow));
    REQUIRE(templatesTbl.add(testRow));

M module-db/tests/ThreadRecord_tests.cpp => module-db/tests/ThreadRecord_tests.cpp +17 -8
@@ 17,26 17,29 @@
#include "queries/messages/threads/QueryThreadRemove.hpp"
#include "queries/messages/threads/QueryThreadsGet.hpp"
#include "queries/messages/sms/QuerySMSGetLastByThreadID.hpp"
#include <purefs/filesystem_paths.hpp>

#include <algorithm>

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <filesystem>

TEST_CASE("Thread Record tests")
{
    Database::initialize();

    const auto contactsPath = (purefs::dir::getUserDiskPath() / "contacts.db").c_str();
    const auto smsPath      = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(contactsPath);
    std::filesystem::remove(smsPath);
    const auto contactsPath = (std::filesystem::path{"user"} / "contacts.db");
    const auto smsPath      = (std::filesystem::path{"user"} / "sms.db");
    if (std::filesystem::exists(contactsPath)) {
        REQUIRE(std::filesystem::remove(contactsPath));
    }
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    auto smsDB = std::make_unique<SmsDB>(smsPath);
    auto smsDB = std::make_unique<SmsDB>(smsPath.c_str());
    REQUIRE(smsDB->isInitialized());
    auto contactsDB = std::make_unique<ContactsDB>(contactsPath);
    auto contactsDB = std::make_unique<ContactsDB>(contactsPath.c_str());
    REQUIRE(contactsDB->isInitialized());

    const uint32_t dateTest      = 123456789;


@@ 53,6 56,12 @@ TEST_CASE("Thread Record tests")
    recordIN.type      = typeTest;
    recordIN.contactID = contactIDTest;

    const auto threadRecords = threadRecordInterface1.GetCount() + 1;
    // clear all records
    for (std::size_t id = 1; id < threadRecords; id++) {
        REQUIRE(threadRecordInterface1.RemoveByID(id));
    }

    // Add 2 records
    REQUIRE(threadRecordInterface1.Add(recordIN));
    REQUIRE(threadRecordInterface1.Add(recordIN));

M module-db/tests/ThreadsTable_tests.cpp => module-db/tests/ThreadsTable_tests.cpp +11 -4
@@ 13,16 13,17 @@
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <purefs/filesystem_paths.hpp>

TEST_CASE("Threads Table tests")
{
    Database::initialize();

    const auto smsPath = (purefs::dir::getUserDiskPath() / "sms.db").c_str();
    std::filesystem::remove(smsPath);
    const auto smsPath = (std::filesystem::path{"user"} / "sms.db");
    if (std::filesystem::exists(smsPath)) {
        REQUIRE(std::filesystem::remove(smsPath));
    }

    SmsDB smsdb{smsPath};
    SmsDB smsdb{smsPath.c_str()};
    REQUIRE(smsdb.isInitialized());

    ThreadsTableRow testRow1 = {{.ID = 0},


@@ 35,6 36,12 @@ TEST_CASE("Threads Table tests")

    };

    const auto smsThreadsCount = smsdb.threads.count() + 1;
    // clear threads table
    for (std::size_t id = 1; id <= smsThreadsCount; id++) {
        REQUIRE(smsdb.threads.removeById(id));
    }

    // add 4 elements into table
    REQUIRE(smsdb.threads.add(testRow1));
    REQUIRE(smsdb.threads.add(testRow1));

M module-db/tests/unittest.cpp => module-db/tests/unittest.cpp +19 -15
@@ 82,7 82,7 @@ TEST_CASE("Create and destroy simple database")

    SECTION("Store database into backup file")
    {
        std::string backupPathDB = USER_PATH("testbackup.db");
        std::string backupPathDB = "testbackup.db";
        std::remove(backupPathDB.c_str());
        Database testDB("test.db");
        REQUIRE(testDB.storeIntoFile(backupPathDB) == true);


@@ 98,12 98,16 @@ class ScopedDir
  public:
    ScopedDir(std::string p) : path(p)
    {
        REQUIRE(std::filesystem::create_directory(path.c_str()));
        if (!(std::filesystem::exists(path.c_str()))) {
            REQUIRE(std::filesystem::create_directory(path.c_str()));
        }
    }

    ~ScopedDir()
    {
        REQUIRE(std::filesystem::remove(path.c_str()));
        if (std::filesystem::exists(path.c_str())) {
            REQUIRE(std::filesystem::remove_all(path.c_str()) > 0);
        }
    }

    auto operator()(std::string file = "") -> std::filesystem::path


@@ 142,7 146,7 @@ TEST_CASE("Database initialization scripts")

    SECTION("list files")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");
        std::fclose(file);


@@ 161,18 165,18 @@ TEST_CASE("Database initialization scripts")

        Database db(dir("test.db").c_str());
        DatabaseInitializer initializer(&db);
        auto files = initializer.listFiles(PATH_SYS "/" PATH_USER "/", "test", "sql");
        auto files = initializer.listFiles("scripts", "test", "sql");

        REQUIRE(files.size() == 4);
        REQUIRE(files[0] == USER_PATH("test_1.sql"));
        REQUIRE(files[1] == USER_PATH("test_003.sql"));
        REQUIRE(files[2] == USER_PATH("test_011.sql"));
        REQUIRE(files[3] == USER_PATH("test_021.sql"));
        REQUIRE(files[0] == (std::filesystem::path{"scripts"} / "test_1.sql"));
        REQUIRE(files[1] == (std::filesystem::path{"scripts"} / "test_003.sql"));
        REQUIRE(files[2] == (std::filesystem::path{"scripts"} / "test_011.sql"));
        REQUIRE(files[3] == (std::filesystem::path{"scripts"} / "test_021.sql"));
    }

    SECTION("read script files")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");



@@ 190,7 194,7 @@ TEST_CASE("Database initialization scripts")

    SECTION("read empty script files")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");
        std::fclose(file);


@@ 204,7 208,7 @@ TEST_CASE("Database initialization scripts")

    SECTION("read script file with comment")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");
        std::fprintf(file, "%s\n", script_comment);


@@ 219,7 223,7 @@ TEST_CASE("Database initialization scripts")

    SECTION("execute valid script")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");
        std::fprintf(file, "%s\n", script_create);


@@ 234,7 238,7 @@ TEST_CASE("Database initialization scripts")

    SECTION("execute invalid script")
    {
        ScopedDir dir(USER_PATH("scripts"));
        ScopedDir dir("scripts");

        auto file = std::fopen(dir("test_1.sql").c_str(), "w");
        std::fprintf(file, "%s\n", script_invalid);


@@ 247,5 251,5 @@ TEST_CASE("Database initialization scripts")
        REQUIRE(result == false);
    }

    Database::deinitialize();
    REQUIRE(Database::deinitialize() == true);
}

M module-services/service-db/test/CMakeLists.txt => module-services/service-db/test/CMakeLists.txt +0 -1
@@ 7,7 7,6 @@ add_catch2_executable(
            test-service-db-api.cpp
            test-service-db-settings-messages.cpp
            test-service-db-settings-api.cpp
            test-service-db-file_indexer.cpp
        LIBS
            service-audio
            module-vfs

M module-utils/test/unittest_utils.cpp => module-utils/test/unittest_utils.cpp +1 -0
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <cstring>
#include <filesystem>
#include <iostream>
#include <memory>
#include <unistd.h>