mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-01-25 06:18:18 -05:00
The dangling ptrs derefencing freed memory has been fixed. They caused the tests to trigger the ASan. Additonally, in some tests where DB objects were allocated dynamically, they are now allocated automatically on the stack to simplify the code.
264 lines
9.7 KiB
C++
264 lines
9.7 KiB
C++
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
|
|
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
|
|
|
|
#include <catch2/catch.hpp>
|
|
|
|
#include "Database/Database.hpp"
|
|
#include "Databases/ContactsDB.hpp"
|
|
#include "Databases/SmsDB.hpp"
|
|
#include "Interface/ContactRecord.hpp"
|
|
#include "Interface/SMSRecord.hpp"
|
|
#include "Interface/ThreadRecord.hpp"
|
|
#include "queries/messages/threads/QueryThreadMarkAsRead.hpp"
|
|
#include "queries/messages/threads/QueryThreadsSearchForList.hpp"
|
|
#include "queries/messages/threads/QueryThreadGetByID.hpp"
|
|
#include "queries/messages/threads/QueryThreadGetByContactID.hpp"
|
|
#include "queries/messages/threads/QueryThreadGetByNumber.hpp"
|
|
#include "queries/messages/threads/QueryThreadRemove.hpp"
|
|
#include "queries/messages/threads/QueryThreadsGet.hpp"
|
|
#include "queries/messages/sms/QuerySMSGetLastByThreadID.hpp"
|
|
#include <vfs.hpp>
|
|
#include <purefs/filesystem_paths.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
|
|
TEST_CASE("Thread Record tests")
|
|
{
|
|
Database::initialize();
|
|
|
|
const auto contactsPath = purefs::dir::getUserDiskPath() / "contacts.db";
|
|
const auto smsPath = purefs::dir::getUserDiskPath() / "sms.db";
|
|
std::filesystem::remove(contactsPath);
|
|
std::filesystem::remove(smsPath);
|
|
|
|
SmsDB smsDB(smsPath.c_str());
|
|
REQUIRE(smsDB.isInitialized());
|
|
ContactsDB contactsDB(contactsPath.c_str());
|
|
REQUIRE(contactsDB.isInitialized());
|
|
|
|
const uint32_t dateTest = 123456789;
|
|
const char *snippetTest = "Test snippet";
|
|
const char *snippetTest2 = "Test snippet2";
|
|
const SMSType typeTest = SMSType ::UNKNOWN;
|
|
const uint32_t contactIDTest = 100;
|
|
|
|
ThreadRecordInterface threadRecordInterface1(&smsDB, &contactsDB);
|
|
|
|
ThreadRecord recordIN;
|
|
recordIN.date = dateTest;
|
|
recordIN.snippet = snippetTest;
|
|
recordIN.type = typeTest;
|
|
recordIN.contactID = contactIDTest;
|
|
|
|
// Add 2 records
|
|
REQUIRE(threadRecordInterface1.Add(recordIN));
|
|
REQUIRE(threadRecordInterface1.Add(recordIN));
|
|
|
|
SECTION("isUnread")
|
|
{
|
|
REQUIRE_FALSE(recordIN.isUnread());
|
|
recordIN.unreadMsgCount = 10;
|
|
REQUIRE(recordIN.isUnread());
|
|
}
|
|
|
|
SECTION("Get Count")
|
|
{
|
|
recordIN.unreadMsgCount = 10;
|
|
REQUIRE(threadRecordInterface1.Add(recordIN));
|
|
REQUIRE(threadRecordInterface1.GetCount() == 3);
|
|
REQUIRE(threadRecordInterface1.GetCount(EntryState::ALL) == 3);
|
|
REQUIRE(threadRecordInterface1.GetCount(EntryState::READ) == 2);
|
|
REQUIRE(threadRecordInterface1.GetCount(EntryState::UNREAD) == 1);
|
|
}
|
|
|
|
SECTION("Get all available records")
|
|
{
|
|
auto records = threadRecordInterface1.GetLimitOffset(0, 100);
|
|
REQUIRE((*records).size() == 2);
|
|
|
|
// Check if fetched records contain valid data
|
|
for (const auto &w : *records) {
|
|
REQUIRE(w.date == dateTest);
|
|
REQUIRE(w.snippet == snippetTest);
|
|
REQUIRE(w.type == typeTest);
|
|
REQUIRE(w.contactID == contactIDTest);
|
|
}
|
|
}
|
|
SECTION("Get all available records with query")
|
|
{
|
|
auto query = std::make_shared<db::query::ThreadsGet>(0, 100);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::ThreadsGetResults *>(ret.get());
|
|
REQUIRE(result != nullptr);
|
|
auto results = result->getResults();
|
|
REQUIRE(results.size() == 2);
|
|
|
|
// Check if fetched records contain valid data
|
|
for (const auto &w : results) {
|
|
REQUIRE(w.date == dateTest);
|
|
REQUIRE(w.snippet == snippetTest);
|
|
REQUIRE(w.type == typeTest);
|
|
REQUIRE(w.contactID == contactIDTest);
|
|
}
|
|
}
|
|
|
|
SECTION("Get all available records by specified thread ID and check for invalid data")
|
|
{
|
|
auto records = threadRecordInterface1.GetLimitOffsetByField(
|
|
0, 100, ThreadRecordField ::ContactID, std::to_string(contactIDTest).c_str());
|
|
REQUIRE((*records).size() == 2);
|
|
for (const auto &w : *records) {
|
|
REQUIRE(w.date == dateTest);
|
|
REQUIRE(w.snippet == snippetTest);
|
|
REQUIRE(w.type == typeTest);
|
|
REQUIRE(w.contactID == contactIDTest);
|
|
}
|
|
}
|
|
|
|
SECTION("Get record by id with query")
|
|
{
|
|
auto query = std::make_shared<db::query::ThreadGetByID>(1);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::ThreadGetByIDResult *>(ret.get());
|
|
|
|
REQUIRE(result->getRecord().has_value());
|
|
}
|
|
|
|
SECTION("Get record by contact id")
|
|
{
|
|
auto query = std::make_shared<db::query::ThreadGetByContactID>(contactIDTest);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::ThreadGetByContactIDResult *>(ret.get());
|
|
|
|
REQUIRE(result->getRecord().has_value());
|
|
REQUIRE(result->getRecord()->contactID == contactIDTest);
|
|
}
|
|
|
|
SECTION("Remove records one by one")
|
|
{
|
|
REQUIRE(threadRecordInterface1.RemoveByID(1));
|
|
REQUIRE(threadRecordInterface1.RemoveByID(2));
|
|
|
|
// SMS database should not contain any records
|
|
REQUIRE(threadRecordInterface1.GetCount() == 0);
|
|
}
|
|
|
|
SECTION("Remove records with query")
|
|
{
|
|
auto query1 = std::make_shared<db::query::ThreadRemove>(1);
|
|
auto ret1 = threadRecordInterface1.runQuery(query1);
|
|
auto result1 = dynamic_cast<db::query::ThreadRemoveResult *>(ret1.get());
|
|
REQUIRE(result1->success());
|
|
|
|
auto query2 = std::make_shared<db::query::ThreadRemove>(2);
|
|
auto ret2 = threadRecordInterface1.runQuery(query2);
|
|
auto result2 = dynamic_cast<db::query::ThreadRemoveResult *>(ret2.get());
|
|
REQUIRE(result2->success());
|
|
|
|
// SMS database should not contain any records
|
|
REQUIRE(threadRecordInterface1.GetCount() == 0);
|
|
}
|
|
|
|
SECTION("Test updating record")
|
|
{
|
|
// REQUIRE(threadRecordInterface1.Add(recordIN));
|
|
recordIN.ID = 1;
|
|
recordIN.snippet = snippetTest2;
|
|
REQUIRE(threadRecordInterface1.Update(recordIN));
|
|
|
|
auto record = threadRecordInterface1.GetByID(1);
|
|
REQUIRE(record.isValid());
|
|
REQUIRE(record.snippet == snippetTest2);
|
|
}
|
|
|
|
SECTION("Mark as read / unread")
|
|
{
|
|
recordIN.unreadMsgCount = 10;
|
|
REQUIRE(threadRecordInterface1.Add(recordIN));
|
|
auto rec = threadRecordInterface1.GetByID(3);
|
|
REQUIRE(rec.isUnread());
|
|
|
|
{
|
|
auto query = std::make_shared<db::query::MarkAsRead>(3, db::query::MarkAsRead::Read::True);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::MarkAsReadResult *>(ret.get());
|
|
REQUIRE(result != nullptr);
|
|
REQUIRE(result->getResult());
|
|
rec = threadRecordInterface1.GetByID(3);
|
|
REQUIRE_FALSE(rec.isUnread());
|
|
}
|
|
|
|
{
|
|
auto query = std::make_shared<db::query::MarkAsRead>(3, db::query::MarkAsRead::Read::False);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::MarkAsReadResult *>(ret.get());
|
|
REQUIRE(result != nullptr);
|
|
REQUIRE(result->getResult());
|
|
rec = threadRecordInterface1.GetByID(3);
|
|
REQUIRE(rec.isUnread());
|
|
}
|
|
}
|
|
|
|
SECTION("SMS search")
|
|
{
|
|
const utils::PhoneNumber phoneNumber("+48600123456", utils::country::Id::UNKNOWN);
|
|
const std::string lastSmsBody = "Ola";
|
|
|
|
SMSRecordInterface smsRecInterface(&smsDB, &contactsDB);
|
|
SMSRecord recordIN;
|
|
recordIN.date = 123456789;
|
|
recordIN.dateSent = 987654321;
|
|
recordIN.errorCode = 0;
|
|
recordIN.number = phoneNumber.getView();
|
|
recordIN.body = "Ala";
|
|
recordIN.type = SMSType ::DRAFT;
|
|
|
|
REQUIRE(smsRecInterface.Add(recordIN));
|
|
|
|
recordIN.body = lastSmsBody;
|
|
REQUIRE(smsRecInterface.Add(recordIN));
|
|
|
|
{
|
|
auto query = std::make_shared<db::query::ThreadsSearchForList>("A", 0, 10);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::ThreadsSearchResultForList *>(ret.get());
|
|
REQUIRE(result != nullptr);
|
|
auto results = result->getResults();
|
|
REQUIRE(results.size() == 2);
|
|
}
|
|
|
|
{
|
|
auto query = std::make_shared<db::query::ThreadsSearchForList>("O", 0, 10);
|
|
auto ret = threadRecordInterface1.runQuery(query);
|
|
auto result = dynamic_cast<db::query::ThreadsSearchResultForList *>(ret.get());
|
|
REQUIRE(result != nullptr);
|
|
auto results = result->getResults();
|
|
REQUIRE(results.size() == 1);
|
|
}
|
|
|
|
SECTION("Get last SMS by thread id")
|
|
{
|
|
auto getThreadQuery = std::make_shared<db::query::ThreadGetByNumber>(phoneNumber.getView());
|
|
auto getThreadRet = threadRecordInterface1.runQuery(getThreadQuery);
|
|
auto getThreatResult = dynamic_cast<db::query::ThreadGetByNumberResult *>(getThreadRet.get());
|
|
REQUIRE(getThreatResult != nullptr);
|
|
auto threadRec = getThreatResult->getThread();
|
|
REQUIRE(threadRec.isValid());
|
|
|
|
auto getLastQuery = std::make_shared<db::query::SMSGetLastByThreadID>(threadRec.ID);
|
|
auto getLastRet = smsRecInterface.runQuery(getLastQuery);
|
|
auto getLastResult = dynamic_cast<db::query::SMSGetLastByThreadIDResult *>(getLastRet.get());
|
|
REQUIRE(getLastResult != nullptr);
|
|
auto smsRec = getLastResult->record;
|
|
REQUIRE(smsRec.has_value());
|
|
REQUIRE(smsRec->body == lastSmsBody);
|
|
}
|
|
}
|
|
|
|
Database::deinitialize();
|
|
}
|