~aleteoryx/muditaos

d86d3aed09ca50c40218abd5cb18bbc17a305f49 — Pawel Paprocki 5 years ago f693845
[EGD-4182] Create UT for File Indexer DB (#1050)

M changelog.md => changelog.md +1 -0
@@ 3,6 3,7 @@
### Added

* `[cellular]` Integration with basic flow for SIM card (cellular<>GUI)
* `[file indexer db]` Added UT fot File Indexer DB

### Fixed


M module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp => module-services/service-db/agents/file_indexer/FileIndexerAgent.cpp +43 -19
@@ 19,6 19,19 @@ void FileIndexerAgent::initDb()
{
    LOG_INFO("[ServiceDB][File Indexer] Initialized");
    database->execute(getDbInitString().c_str());

    auto notifications = database->query(FileIndexer::Statements::getAllNotifications);
    if (nullptr == notifications || FileIndexer::ONE_ROW_FOUND == notifications->getRowCount()) {
        return;
    }
    if (notifications->getFieldCount() == FileIndexer::NOTIFICATION_RECORD_COLUMN_COUNT) {
        fileChangeRecipents.clear();
        do {
            std::string directory = (*notifications)[1].getString();
            std::string service   = (*notifications)[2].getString();
            fileChangeRecipents[directory].insert(service);
        } while (notifications->nextRow());
    }
}

void FileIndexerAgent::deinitDb()


@@ 91,30 104,40 @@ auto FileIndexerAgent::dbUnregisterFileChange(std::string dir, std::string servi

auto FileIndexerAgent::handleRegisterOnFileChange(sys::Message *req) -> sys::MessagePointer
{
    std::string directory;
    if (auto msg = dynamic_cast<FileIndexer::Messages::RegisterOnFileChange *>(req)) {
        if (dbRegisterFileChange(msg->directory, msg->sender)) {
            auto it = fileChangeRecipents.find(msg->directory);
            if (fileChangeRecipents.end() == it) {
                fileChangeRecipents[msg->directory] = {msg->sender};
            }
            else {
                it->second.insert(msg->sender);
        if (msg->directory != nullptr) {
            directory = *(msg->directory);
            if (dbRegisterFileChange(directory, msg->sender)) {
                auto it = fileChangeRecipents.find(directory);
                if (fileChangeRecipents.end() == it) {
                    fileChangeRecipents[directory] = {msg->sender};
                }
                else {
                    it->second.insert(msg->sender);
                }
            }
        }
    }
    LOG_INFO("RegisterOnFileChange from %s", req->sender.c_str());
    return std::make_shared<sys::ResponseMessage>();
}

auto FileIndexerAgent::handleUnregisterOnFileChange(sys::Message *req) -> sys::MessagePointer
{
    std::string directory;
    if (auto msg = dynamic_cast<FileIndexer::Messages::UnregisterOnFileChange *>(req)) {
        if (dbUnregisterFileChange(msg->directory, msg->sender)) {
            auto it = fileChangeRecipents.find(msg->directory);
            if (fileChangeRecipents.end() != it) {
                it->second.erase(msg->sender);
        if (msg->directory != nullptr) {
            directory = *(msg->directory);
            if (dbUnregisterFileChange(directory, msg->sender)) {
                auto it = fileChangeRecipents.find(directory);
                if (fileChangeRecipents.end() != it) {
                    it->second.erase(msg->sender);
                }
            }
        }
    }
    LOG_INFO("UnRegisterOnFileChange from %s", req->sender.c_str());
    return std::make_shared<sys::ResponseMessage>();
}



@@ 200,7 223,6 @@ auto FileIndexerAgent::dbGetRecord(std::unique_ptr<FileIndexer::FileRecord> reco

auto FileIndexerAgent::dbSetRecord(std::unique_ptr<FileIndexer::FileRecord> record) -> bool
{

    auto retQuery = database->query(FileIndexer::Statements::getFileInfoByPath, record->path.c_str());
    FileIndexer::FileRecord retRecord(retQuery.get());



@@ 262,11 284,12 @@ auto FileIndexerAgent::handleSetRecord(sys::Message *req) -> sys::MessagePointer

            sys::Bus::SendUnicast(std::move(updateMsg), msg->sender, parentService);
            dbSetRecord(std::make_unique<FileIndexer::FileRecord>(record));
        }

        for (auto recipient : fileChangeRecipents[record.directory]) {
            auto notifeMsg = std::make_shared<FileIndexer::Messages::FileChanged>(record.directory);
            sys::Bus::SendUnicast(std::move(notifeMsg), recipient, parentService);
            for (auto recipient : fileChangeRecipents[record.directory]) {
                auto notifeMsg = std::make_shared<FileIndexer::Messages::FileChanged>(
                    std::make_unique<std::string>(record.directory));
                sys::Bus::SendUnicast(std::move(notifeMsg), recipient, parentService);
            }
        }
    }
    return std::make_shared<sys::ResponseMessage>();


@@ 402,7 425,7 @@ auto FileIndexerAgent::handleGetProperty(sys::Message *req) -> sys::MessagePoint

auto FileIndexerAgent::handleGetAllProperties(sys::Message *req) -> sys::MessagePointer
{
    if (auto msg = dynamic_cast<FileIndexer::Messages::GetPropertyMessage *>(req)) {
    if (auto msg = dynamic_cast<FileIndexer::Messages::GetAllPropertiesMessage *>(req)) {
        auto metaDataPtr                   = std::move(msg->metaData);
        FileIndexer::FileMetadata metaData = *metaDataPtr;
        msg->dbMetaData                    = dbGetAllProperties(std::make_unique<FileIndexer::FileMetadata>(metaData));


@@ 437,7 460,7 @@ auto FileIndexerAgent::handleSetProperty(sys::Message *req) -> sys::MessagePoint

auto FileIndexerAgent::handleSetProperties(sys::Message *req) -> sys::MessagePointer
{
    if (auto msg = dynamic_cast<FileIndexer::Messages::SetPropertyMessage *>(req)) {
    if (auto msg = dynamic_cast<FileIndexer::Messages::SetPropertiesMessage *>(req)) {
        auto metaDataPtr                   = std::move(msg->metaData);
        FileIndexer::FileMetadata metaData = *metaDataPtr;
        msg->dbMetaData                    = dbGetAllProperties(std::make_unique<FileIndexer::FileMetadata>(metaData));


@@ 447,7 470,8 @@ auto FileIndexerAgent::handleSetProperties(sys::Message *req) -> sys::MessagePoi
        dbSetProperties(std::make_unique<FileIndexer::FileMetadata>(metaData));

        for (auto recipient : fileChangeRecipents[metaData.directory]) {
            auto notifyMsg = std::make_shared<FileIndexer::Messages::FileChanged>(metaData.directory);
            auto notifyMsg =
                std::make_shared<FileIndexer::Messages::FileChanged>(std::make_unique<std::string>(metaData.directory));
            sys::Bus::SendUnicast(std::move(notifyMsg), recipient, parentService);
        }
    }

M module-services/service-db/agents/file_indexer/FileIndexerAgent.hpp => module-services/service-db/agents/file_indexer/FileIndexerAgent.hpp +15 -11
@@ 16,13 16,24 @@ class FileIndexerAgent : public DatabaseAgent
    void deinitDb() override;
    void registerMessages() override;
    auto getAgentName() -> const std::string override;
    void dbTest();

  private:
    using MapOfRecipentsToBeNotified = std::map<std::string, std::set<std::string>>;
    MapOfRecipentsToBeNotified fileChangeRecipents;
  protected:
    // msg handlers
    auto handleRegisterOnFileChange(sys::Message *req) -> sys::MessagePointer;
    auto handleUnregisterOnFileChange(sys::Message *req) -> sys::MessagePointer;
    auto handleListDir(sys::Message *req) -> sys::MessagePointer;
    auto handleGetProperty(sys::Message *req) -> sys::MessagePointer;
    auto handleGetAllProperties(sys::Message *req) -> sys::MessagePointer;
    auto handleSetProperty(sys::Message *req) -> sys::MessagePointer;
    auto handleSetProperties(sys::Message *req) -> sys::MessagePointer;
    auto handleGetRecord(sys::Message *req) -> sys::MessagePointer;
    auto handleSetRecord(sys::Message *req) -> sys::MessagePointer;

    using MapOfRecipentsToBeNotified = std::map<std::string, std::set<std::string>>;
    MapOfRecipentsToBeNotified fileChangeRecipents;

  private:
    // db operations
    auto dbRegisterFileChange(std::string dir, std::string service) -> bool;
    auto dbUnregisterFileChange(std::string dir, std::string service) -> bool;
    auto dbListDir(std::unique_ptr<FileIndexer::ListDirData> listDir) -> std::unique_ptr<FileIndexer::ListDirData>;


@@ 37,11 48,4 @@ class FileIndexerAgent : public DatabaseAgent
    auto getDbInitString() -> const std::string override;
    auto getDbFilePath() -> const std::string override;
    auto dbGetFilesCount() -> unsigned int;
    auto handleListDir(sys::Message *req) -> sys::MessagePointer;
    auto handleGetProperty(sys::Message *req) -> sys::MessagePointer;
    auto handleGetAllProperties(sys::Message *req) -> sys::MessagePointer;
    auto handleSetProperty(sys::Message *req) -> sys::MessagePointer;
    auto handleSetProperties(sys::Message *req) -> sys::MessagePointer;
    auto handleGetRecord(sys::Message *req) -> sys::MessagePointer;
    auto handleSetRecord(sys::Message *req) -> sys::MessagePointer;
};

M module-services/service-db/service-db/FileIndexerMessages.hpp => module-services/service-db/service-db/FileIndexerMessages.hpp +7 -6
@@ 15,6 15,7 @@ namespace FileIndexer
{
    constexpr unsigned int FILE_ID_NOT_EXISTS       = 0;
    constexpr unsigned int FILE_RECORD_COLUMN_COUNT = 7;
    constexpr unsigned int NOTIFICATION_RECORD_COLUMN_COUNT = 3;
    constexpr unsigned int ONE_ROW_FOUND            = 1;
    constexpr unsigned int ZERO_ROWS_FOUND          = 0;



@@ 94,28 95,28 @@ namespace FileIndexer
        {
          public:
            RegisterOnFileChange() = default;
            explicit RegisterOnFileChange(std::string dir) : directory(std::move(dir))
            explicit RegisterOnFileChange(std::unique_ptr<std::string> dir) : directory(std::move(dir))
            {}
            std::string directory;
            std::unique_ptr<std::string> directory;
        };

        class UnregisterOnFileChange : public FileIndexerMessage
        {
          public:
            UnregisterOnFileChange() = default;
            explicit UnregisterOnFileChange(std::string dir) : directory(std::move(dir))
            explicit UnregisterOnFileChange(std::unique_ptr<std::string> dir) : directory(std::move(dir))
            {}
            std::string directory;
            std::unique_ptr<std::string> directory;
        };

        class FileChanged : public FileIndexerMessage
        {
          public:
            FileChanged() = default;
            explicit FileChanged(std::string dir) : directory(dir)
            explicit FileChanged(std::unique_ptr<std::string> dir) : directory(std::move(dir))
            {}

            std::string directory;
            std::unique_ptr<std::string> directory;
        };

        class GetListDirMessage : public FileIndexerMessage

M module-services/service-db/test/CMakeLists.txt => module-services/service-db/test/CMakeLists.txt +1 -0
@@ 7,6 7,7 @@ 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

A module-services/service-db/test/test-service-db-file_indexer.cpp => module-services/service-db/test/test-service-db-file_indexer.cpp +226 -0
@@ 0,0 1,226 @@
// 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 <Service/Service.hpp>
#include <functional>
#include <thread> // for Message_t, ResponseMessage, DataMessage, Message
#include <service-db/ServiceDB.hpp>

#include <module-services/service-db/test/test-service-db-file_indexer.hpp>
#include <service-db/FileIndexerMessages.hpp>

class ClientService : public sys::Service
{
  public:
    using sys::Service::Service;

    explicit ClientService(std::string name) : Service(name)
    {}

    sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp)
    {
        return std::make_shared<sys::ResponseMessage>();
    }

    sys::ReturnCodes InitHandler()
    {
        return sys::ReturnCodes::Success;
    }

    sys::ReturnCodes DeinitHandler()
    {
        return sys::ReturnCodes::Success;
    }

    sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode)
    {
        return sys::ReturnCodes::Success;
    }
};

TEST_CASE("FileIndexer")
{
    std::string serviceName = "file_indexer_client";
    ClientService file_indexer_client_service(serviceName);
    file_indexer_client_service.InitHandler();

    SECTION("init db, register /unregister on file change")
    {
        std::cout << "Init File Indexer DB" << std::endl << std::flush;
        std::unique_ptr<FileIndexerTest> fiAgentTest{new FileIndexerTest(&file_indexer_client_service)};
        fiAgentTest->initDb();
        fiAgentTest->registerMessages();

        std::cout << "Register on file change" << std::endl << std::flush;
        std::string inputDirReg = "mp3";
        auto recordPtr          = std::make_unique<std::string>(inputDirReg);
        auto regMsg             = std::make_shared<FileIndexer::Messages::RegisterOnFileChange>(std::move(recordPtr));
        regMsg->sender          = serviceName;
        sys::MessagePointer recMsg = fiAgentTest->handleRegisterOnFileChangeTest(regMsg.get());
        fiAgentTest->getNumberOfRecipients(inputDirReg);

        regMsg->sender        = "serv1";
        recMsg                = fiAgentTest->handleRegisterOnFileChangeTest(regMsg.get());
        auto recipientsCount1 = fiAgentTest->getNumberOfRecipients(inputDirReg);

        std::cout << "Unregister on file change" << std::endl << std::flush;
        std::string inputDirUnReg = "mp3";
        auto strPtr               = std::make_unique<std::string>(inputDirUnReg);
        auto unregMsg             = std::make_shared<FileIndexer::Messages::UnregisterOnFileChange>(std::move(strPtr));
        unregMsg->sender          = serviceName;
        recMsg                    = fiAgentTest->handleUnregisterOnFileChangeTest(unregMsg.get());
        auto recipientsCount2     = fiAgentTest->getNumberOfRecipients(inputDirUnReg);

        REQUIRE(recipientsCount2 == recipientsCount1 - 1);
        REQUIRE(fiAgentTest->getAgentName() == "fileIndexerAgent");
    }

    SECTION("SetRecord & GetRecord")
    {
        FileIndexer::FileRecord record{};
        std::cout << "Test File indexer Get/Set/Get Record sequence:" << std::endl << std::flush;

        // GetRecord
        record.file_id = 1;
        auto recordPtr = std::make_unique<FileIndexer::FileRecord>(record);
        auto getMsg    = std::make_shared<FileIndexer::Messages::GetRecordMessage>(std::move(recordPtr));
        std::unique_ptr<FileIndexerTest> fiAgentTest{new FileIndexerTest(&file_indexer_client_service)};
        sys::MessagePointer recMsg = fiAgentTest->handleGetRecordTest(getMsg.get());
        auto msg                   = dynamic_cast<FileIndexer::Messages::GetRecordResponseMessage *>(recMsg.get());
        auto fileRec               = msg->record.get();

        LOG_INFO("file id= %d file path= %s  size = %d  mime= %d  mtime = %d directory= %s ftype= %d",
                 fileRec->file_id,
                 fileRec->path.c_str(),
                 fileRec->size,
                 fileRec->mime_type,
                 fileRec->mtime,
                 fileRec->directory.c_str(),
                 fileRec->file_type);

        REQUIRE(fileRec->file_id == record.file_id);

        record = *fileRec; // fill record by data recived from db

        // SetRecord - modify mime_type
        record.mime_type = 2;
        recordPtr        = std::make_unique<FileIndexer::FileRecord>(record);
        auto setMsg      = std::make_shared<FileIndexer::Messages::SetRecordMessage>(std::move(recordPtr));
        setMsg->sender   = serviceName;
        recMsg           = fiAgentTest->handleSetRecordTest(setMsg.get());

        // GetRecord to confirm changes in mime_type
        recordPtr = std::make_unique<FileIndexer::FileRecord>(record);
        getMsg    = std::make_shared<FileIndexer::Messages::GetRecordMessage>(std::move(recordPtr));
        recMsg    = fiAgentTest->handleGetRecordTest(getMsg.get());
        msg       = dynamic_cast<FileIndexer::Messages::GetRecordResponseMessage *>(recMsg.get());
        fileRec   = msg->record.get();

        LOG_INFO("file id= %d file path= %s  size = %d  mime= %d  mtime = %d directory= %s ftype= %d",
                 fileRec->file_id,
                 fileRec->path.c_str(),
                 fileRec->size,
                 fileRec->mime_type,
                 fileRec->mtime,
                 fileRec->directory.c_str(),
                 fileRec->file_type);
        // check if new value was set
        REQUIRE(fileRec->mime_type == record.mime_type);
        // check if the rest of the record did not change
        REQUIRE(fileRec->file_id == record.file_id);
        REQUIRE(fileRec->path == record.path);
        REQUIRE(fileRec->size == record.size);
        REQUIRE(fileRec->mtime == record.mtime);
        REQUIRE(fileRec->directory == record.directory);
        REQUIRE(fileRec->file_type == record.file_type);
    }

    SECTION("List dir - support for listview")
    {
        FileIndexer::ListDirData inputData{};
        std::cout << "List dir - support for listview" << std::endl << std::flush;

        // GetListDir
        inputData.directory   = "mp3";
        inputData.list_offset = 1;
        inputData.list_limit  = 2;

        auto recordPtr = std::make_unique<FileIndexer::ListDirData>(inputData);
        auto getMsg    = std::make_shared<FileIndexer::Messages::GetListDirMessage>(std::move(recordPtr));
        std::unique_ptr<FileIndexerTest> fiAgentTest{new FileIndexerTest(&file_indexer_client_service)};
        sys::MessagePointer recMsg = fiAgentTest->handleListDirTest(getMsg.get());
        auto msg                   = dynamic_cast<FileIndexer::Messages::GetListDirResponseMessage *>(recMsg.get());
        auto fileCount             = msg->getCount();
        auto fileList              = msg->getResults();
        LOG_INFO("Total number of files in %s = %d", inputData.directory.c_str(), fileCount);
        LOG_INFO("Limit= %d Offset= %d", inputData.list_limit, inputData.list_offset);
        for (auto fileRec : fileList) {
            LOG_INFO("file id= %d file path= %s  size = %d  mime= %d  mtime = %d directory= %s ftype= %d",
                     fileRec.file_id,
                     fileRec.path.c_str(),
                     fileRec.size,
                     fileRec.mime_type,
                     fileRec.mtime,
                     fileRec.directory.c_str(),
                     fileRec.file_type);
        }
        REQUIRE(fileList.size() == inputData.list_limit);
        REQUIRE(fileList[0].directory == inputData.directory);
    }

    SECTION("get/set Properties")
    {
        FileIndexer::FileMetadata inputMetaData{};
        std::cout << "get/set Properties" << std::endl << std::flush;

        // Get Properties
        inputMetaData.path = "mp3/track3.mp3";
        LOG_INFO("File path= %s", inputMetaData.path.c_str());

        auto recordPtr = std::make_unique<FileIndexer::FileMetadata>(inputMetaData);
        auto getMsg    = std::make_shared<FileIndexer::Messages::GetAllPropertiesMessage>(std::move(recordPtr));
        std::unique_ptr<FileIndexerTest> fiAgentTest{new FileIndexerTest(&file_indexer_client_service)};
        sys::MessagePointer recMsg = fiAgentTest->handleGetAllPropertiesTest(getMsg.get());
        auto msg                   = dynamic_cast<FileIndexer::Messages::GetPropertyResponseMessage *>(recMsg.get());
        for (auto prop : msg->metaData->properties) {
            LOG_INFO("file id= %d property= %s  value = %s",
                     msg->metaData->file_id,
                     prop.first.c_str(),
                     prop.second.c_str());
        }
        REQUIRE(msg->metaData->properties.size() > 0);

        // set Properties
        inputMetaData.properties.clear();
        inputMetaData.properties.emplace("year", "2015");

        std::string newProperty      = "time";
        std::string newPropertyValue = "5min";
        inputMetaData.properties.emplace(newProperty, newPropertyValue);
        recordPtr      = std::make_unique<FileIndexer::FileMetadata>(inputMetaData);
        auto setMsg    = std::make_shared<FileIndexer::Messages::SetPropertiesMessage>(std::move(recordPtr));
        setMsg->sender = serviceName;
        recMsg         = fiAgentTest->handleSetPropertiesTest(setMsg.get());

        // Get Properties
        recordPtr = std::make_unique<FileIndexer::FileMetadata>(inputMetaData);
        getMsg    = std::make_shared<FileIndexer::Messages::GetAllPropertiesMessage>(std::move(recordPtr));
        recMsg    = fiAgentTest->handleGetAllPropertiesTest(getMsg.get());
        msg       = dynamic_cast<FileIndexer::Messages::GetPropertyResponseMessage *>(recMsg.get());
        for (auto prop : msg->metaData->properties) {
            LOG_INFO("file id= %d property= %s  value = %s",
                     msg->metaData->file_id,
                     prop.first.c_str(),
                     prop.second.c_str());
        }
        //  serch if a new property was set correctly
        std::string newPropertyValueFound;
        auto it = msg->metaData->properties.find(newProperty);
        if (msg->metaData->properties.end() != it) {
            newPropertyValueFound = it->second;
        }
        REQUIRE(newPropertyValueFound == newPropertyValue);
    }
}

A module-services/service-db/test/test-service-db-file_indexer.hpp => module-services/service-db/test/test-service-db-file_indexer.hpp +60 -0
@@ 0,0 1,60 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <service-db/DatabaseAgent.hpp>
#include <service-db/FileIndexerMessages.hpp>
#include <module-services/service-db/agents/file_indexer/FileIndexerAgent.hpp>

class FileIndexerTest : public FileIndexerAgent
{
  public:
    FileIndexerTest(sys::Service *parentService) : FileIndexerAgent(parentService){};
    ~FileIndexerTest() = default;

    auto handleGetRecordTest(FileIndexer::Messages::GetRecordMessage *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleGetRecord(req);
    }

    auto handleSetRecordTest(FileIndexer::Messages::SetRecordMessage *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleSetRecord(req);
    }

    auto handleListDirTest(FileIndexer::Messages::GetListDirMessage *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleListDir(req);
    }

    auto handleGetAllPropertiesTest(FileIndexer::Messages::GetAllPropertiesMessage *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleGetAllProperties(req);
    }

    auto handleSetPropertiesTest(FileIndexer::Messages::SetPropertiesMessage *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleSetProperties(req);
    }

    auto handleRegisterOnFileChangeTest(FileIndexer::Messages::RegisterOnFileChange *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleRegisterOnFileChange(req);
    }

    auto handleUnregisterOnFileChangeTest(FileIndexer::Messages::UnregisterOnFileChange *req) -> sys::MessagePointer
    {
        return FileIndexerAgent::handleUnregisterOnFileChange(req);
    }

    unsigned int getNumberOfRecipients(std::string directory)
    {
        unsigned int recipientCount = 0;
        for (auto recipient : fileChangeRecipents[directory]) {
            LOG_INFO("Notifications:  directory= %s service= %s", directory.c_str(), recipient.c_str());
            recipientCount++;
        }
        return recipientCount++;
    }
};