M enabled_unittests => enabled_unittests +4 -0
@@ 215,6 215,10 @@ TESTS_LIST["catch2-service-desktop"]="
Endpoint Factory test;
"
#---------
+TESTS_LIST["catch2-service-desktop-endpoint-contacts"]="
+ Endpoint Contacts Test;
+"
+#---------
TESTS_LIST["catch2-service-evtmgr"]="
ScreenLightControlFunctions;
"
M module-db/Common/Query.cpp => module-db/Common/Query.cpp +20 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Query.hpp"
@@ 22,7 22,12 @@ bool QueryCallback::handleQueryResponse(QueryResult *response)
}
EndpointListener::EndpointListener(EndpointQueryCallbackFunction &&_callback, parserFSM::Context &_context)
- : callback{std::move(_callback)}, context{_context}
+ : callback{std::move(_callback)}, context(_context)
+{}
+
+EndpointListenerWithPages::EndpointListenerWithPages(EndpointQueryCallbackFunctionWithPages &&_callback,
+ const parserFSM::PagedContext &_context)
+ : callback{std::move(_callback)}, context(_context)
{}
bool EndpointListener::handleQueryResponse(db::QueryResult *response)
@@ 38,6 43,19 @@ bool EndpointListener::handleQueryResponse(db::QueryResult *response)
return false;
}
+bool EndpointListenerWithPages::handleQueryResponse(db::QueryResult *response)
+{
+ if (callback) {
+ LOG_DEBUG("Executing callback...");
+ const auto ret = callback(response, context);
+ LOG_DEBUG("Callback finished");
+ return ret;
+ }
+
+ LOG_ERROR("callback is nullptr!");
+ return false;
+}
+
Query::Query(Type type) : type(type)
{}
M module-db/Common/Query.hpp => module-db/Common/Query.hpp +16 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 14,7 14,7 @@ namespace db
class QueryResult; // Forward declaration
using QueryCallbackFunction = std::function<bool(db::QueryResult *)>;
using EndpointQueryCallbackFunction = std::function<bool(db::QueryResult *, parserFSM::Context &)>;
-
+ using EndpointQueryCallbackFunctionWithPages = std::function<bool(db::QueryResult *, parserFSM::PagedContext &)>;
class QueryListener
{
public:
@@ 49,6 49,20 @@ namespace db
parserFSM::Context context;
};
+ class EndpointListenerWithPages : public EndpointListener
+ {
+ public:
+ EndpointListenerWithPages() = default;
+ EndpointListenerWithPages(EndpointQueryCallbackFunctionWithPages &&_callback,
+ const parserFSM::PagedContext &_context);
+
+ bool handleQueryResponse(db::QueryResult *result) override;
+
+ private:
+ EndpointQueryCallbackFunctionWithPages callback;
+ parserFSM::PagedContext context;
+ };
+
/// virtual query input interface
class Query
{
M module-db/Interface/ContactRecord.cpp => module-db/Interface/ContactRecord.cpp +32 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ContactRecord.hpp"
@@ 135,6 135,9 @@ auto ContactRecordInterface::runQuery(std::shared_ptr<db::Query> query) -> std::
if (typeid(*query) == typeid(db::query::ContactGet)) {
return getQuery(query);
}
+ else if (typeid(*query) == typeid(db::query::ContactGetWithTotalCount)) {
+ return getQueryWithTotalCount(query);
+ }
else if (typeid(*query) == typeid(db::query::ContactGetLetterMap)) {
return getLetterMapQuery(query);
}
@@ 162,7 165,7 @@ auto ContactRecordInterface::runQuery(std::shared_ptr<db::Query> query) -> std::
}
}
-auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+auto ContactRecordInterface::getQueryRecords(std::shared_ptr<db::Query> query) -> std::vector<ContactRecord>
{
auto textFilter = dynamic_cast<const db::query::TextFilter *>(query.get());
assert(query != nullptr);
@@ 203,11 206,31 @@ auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::
for (uint32_t idx = 0; idx < static_cast<uint32_t>(ids.size()); idx++) {
result[idx].contactPosOnList = offset + idx;
}
- auto response = std::make_unique<db::query::ContactGetResult>(result);
+ return result;
+}
+
+auto ContactRecordInterface::getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+{
+ auto response = std::make_unique<db::query::ContactGetResult>(getQueryRecords(query));
response->setRequestQuery(query);
return response;
}
+auto ContactRecordInterface::getQueryWithTotalCount(std::shared_ptr<db::Query> query)
+ -> std::unique_ptr<db::QueryResult>
+{
+ if (auto queryContacts = dynamic_cast<db::query::ContactGet *>(query.get())) {
+ auto querySize = std::make_shared<db::query::ContactGetSize>(queryContacts->getFilterData(),
+ queryContacts->getGroupFilterData(),
+ queryContacts->getContactDisplayMode());
+ auto response = std::make_unique<db::query::ContactGetResultWithTotalCount>(getQueryRecords(query),
+ getContactsSize(querySize));
+ response->setRequestQuery(query);
+ return response;
+ }
+ return nullptr;
+}
+
auto ContactRecordInterface::getLetterMapQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
{
ContactsMapData result = contactDB->contacts.GetPosOfFirstLetters();
@@ 233,7 256,7 @@ auto ContactRecordInterface::getByIDQuery(std::shared_ptr<db::Query> query) -> s
return response;
}
-auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+auto ContactRecordInterface::getContactsSize(std::shared_ptr<db::Query> query) -> std::size_t
{
auto textFilter = dynamic_cast<const db::query::TextFilter *>(query.get());
assert(query != nullptr);
@@ 280,7 303,12 @@ auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> s
else {
count = contactDB->name.GetCountByName(countQuery->getFilterData());
}
+ return count;
+}
+auto ContactRecordInterface::getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
+{
+ auto count = getContactsSize(query);
debug_db_data("Contact count query result: %lu", static_cast<unsigned long>(count));
auto response = std::make_unique<db::query::RecordsSizeQueryResult>(count);
M module-db/Interface/ContactRecord.hpp => module-db/Interface/ContactRecord.hpp +4 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 236,10 236,13 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
const std::uint32_t favouritesGroupId;
auto getQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
+ auto getQueryRecords(std::shared_ptr<db::Query> query) -> std::vector<ContactRecord>;
+ auto getQueryWithTotalCount(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getForListQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getLetterMapQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto getByIDQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
+ auto getContactsSize(std::shared_ptr<db::Query> query) -> std::size_t;
auto getSizeQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto addQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
auto updateQuery(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
M module-db/queries/Filter.hpp => module-db/queries/Filter.hpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 95,7 95,7 @@ namespace db::query
*
* @param groupText group filter text
*/
- ContactGroupFilter(const std::uint32_t &groupId) : filterData(std::move(groupId))
+ ContactGroupFilter(std::uint32_t groupId) : filterData(groupId)
{}
[[nodiscard]] const std::uint32_t &getGroupFilterData() const noexcept
@@ 121,7 121,7 @@ namespace db::query
*
* @param mode contact display mode
*/
- ContactDisplayMode(const std::uint32_t &mode) : displayMode(std::move(mode))
+ ContactDisplayMode(std::uint32_t mode) : displayMode(mode)
{}
[[nodiscard]] const std::uint32_t &getContactDisplayMode() const noexcept
M module-db/queries/RecordQuery.cpp => module-db/queries/RecordQuery.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "RecordQuery.hpp"
@@ 13,7 13,7 @@ using namespace db::query;
RecordQuery::RecordQuery() noexcept : Query(Query::Type::Read)
{}
-RecordQuery::RecordQuery(std::size_t offset, std::size_t limit) noexcept
+RecordQuery::RecordQuery(std::size_t limit, std::size_t offset) noexcept
: Query(Query::Type::Read), limit(limit), offset(offset)
{}
M module-db/queries/phonebook/QueryContactGet.cpp => module-db/queries/phonebook/QueryContactGet.cpp +31 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "QueryContactGet.hpp"
@@ 14,14 14,32 @@ ContactGet::ContactGet(const std::string &filter, const std::uint32_t &groupFilt
ContactGet::ContactGet(std::size_t limit,
std::size_t offset,
const std::string &filter,
- const std::uint32_t &groupFilter,
- const std::uint32_t &displayMode)
+ std::uint32_t groupFilter,
+ std::uint32_t displayMode)
: RecordQuery(limit, offset), TextFilter(filter), ContactGroupFilter(groupFilter), ContactDisplayMode(displayMode)
{}
+ContactGetWithTotalCount::ContactGetWithTotalCount(std::size_t limit,
+ std::size_t offset,
+ const std::string &filter,
+ std::uint32_t groupFilter,
+ std::uint32_t displayMode)
+ : ContactGet(limit, offset, filter, groupFilter, displayMode)
+{}
+
ContactGetResult::ContactGetResult(const std::vector<ContactRecord> &records) : RecordQueryResult(records)
{}
+ContactGetResultWithTotalCount::ContactGetResultWithTotalCount(const std::vector<ContactRecord> &records,
+ std::size_t allLength)
+ : ContactGetResult(records), allLength(allLength)
+{}
+
+auto ContactGetResultWithTotalCount::getAllLength() const -> std::size_t
+{
+ return allLength;
+}
+
ContactGetSize::ContactGetSize(const std::string &filter,
const std::uint32_t &groupFilter,
const std::uint32_t &displayMode)
@@ 50,11 68,21 @@ ContactGetLetterMapResult ::ContactGetLetterMapResult(ContactsMapData &LetterMap
return "ContactGet";
}
+[[nodiscard]] auto ContactGetWithTotalCount::debugInfo() const -> std::string
+{
+ return "ContactGetWithTotalCount";
+}
+
[[nodiscard]] auto ContactGetResult::debugInfo() const -> std::string
{
return "ContactGetResult";
}
+[[nodiscard]] auto ContactGetResultWithTotalCount::debugInfo() const -> std::string
+{
+ return "ContactGetResultWithTotalCount";
+}
+
[[nodiscard]] auto ContactGetSize::debugInfo() const -> std::string
{
return "ContactGetSize";
M module-db/queries/phonebook/QueryContactGet.hpp => module-db/queries/phonebook/QueryContactGet.hpp +26 -4
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 37,9 37,9 @@ namespace db::query
*/
ContactGet(std::size_t limit,
std::size_t offset,
- const std::string &filter = "",
- const std::uint32_t &groupFilter = 0,
- const std::uint32_t &displayMode = 0);
+ const std::string &filter = "",
+ std::uint32_t groupFilter = 0,
+ std::uint32_t displayMode = 0);
/**
* @brief debug info
@@ 72,6 72,17 @@ namespace db::query
[[nodiscard]] auto debugInfo() const -> std::string override;
};
+ class ContactGetResultWithTotalCount : public ContactGetResult
+ {
+ public:
+ ContactGetResultWithTotalCount(const std::vector<ContactRecord> &records, std::size_t allLength);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ auto getAllLength() const -> std::size_t;
+
+ private:
+ std::size_t allLength;
+ };
+
/**
* @brief A query to get a number of contacts filtered with a text
*
@@ 99,6 110,17 @@ namespace db::query
[[nodiscard]] auto debugInfo() const -> std::string override;
};
+ class ContactGetWithTotalCount : public ContactGet
+ {
+ public:
+ ContactGetWithTotalCount(std::size_t limit,
+ std::size_t offset,
+ const std::string &filter = "",
+ std::uint32_t groupFilter = 0,
+ std::uint32_t displayMode = 0);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
class ContactGetLetterMap : public RecordQuery,
public TextFilter,
public ContactGroupFilter,
M module-services/service-desktop/endpoints/Context.hpp => module-services/service-desktop/endpoints/Context.hpp +84 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 15,7 15,12 @@ namespace parserFSM
inline constexpr auto endpoint = "endpoint";
inline constexpr auto uuid = "uuid";
inline constexpr auto status = "status";
+ inline constexpr auto totalCount = "totalCount";
inline constexpr auto body = "body";
+ inline constexpr auto offset = "offset";
+ inline constexpr auto limit = "limit";
+ inline constexpr auto nextPage = "nextPage";
+ inline constexpr auto entries = "entries";
} // namespace json
struct endpointResponseContext
@@ 28,7 33,7 @@ namespace parserFSM
class Context
{
- private:
+ protected:
json11::Json body;
EndpointType endpoint;
uint32_t uuid;
@@ 84,8 89,9 @@ namespace parserFSM
uuid = invalidUuid;
method = http::Method::get;
}
+ virtual ~Context() noexcept = default;
- auto createSimpleResponse() -> std::string
+ virtual auto createSimpleResponse() -> std::string
{
json11::Json responseJson = json11::Json::object{{json::endpoint, static_cast<int>(getEndpoint())},
{json::status, static_cast<int>(responseContext.status)},
@@ 123,4 129,79 @@ namespace parserFSM
}
};
+ class PagedContext : public Context
+ {
+ private:
+ // from request
+ std::size_t requestedLimit, requestedOffset;
+ // set by query (during helper run)
+ std::size_t totalCount;
+ // set it before calling handle on helper
+ std::size_t pageSize;
+
+ public:
+ explicit PagedContext(json11::Json &js, size_t pageSize) : Context(js), pageSize(pageSize)
+ {}
+ PagedContext() = default;
+ void setRequestedLimit(std::size_t limit)
+ {
+ requestedLimit = limit;
+ }
+ void setRequestedOffset(std::size_t offset)
+ {
+ requestedOffset = offset;
+ }
+ void setTotalCount(std::size_t count)
+ {
+ totalCount = count;
+ }
+ std::size_t getPageSize() const
+ {
+ return pageSize;
+ }
+
+ auto createSimpleResponse() -> std::string override
+ {
+ auto elemsCount = responseContext.body.array_items().size();
+ auto newBody = json11::Json::object{{json::entries, responseContext.body},
+ {json::totalCount, static_cast<int>(totalCount)}};
+ if (requestedLimit > elemsCount) {
+ std::size_t offset = requestedOffset + elemsCount;
+ if (offset < totalCount) {
+ auto lastTableIndex = std::min(totalCount, offset + requestedLimit - elemsCount);
+ std::size_t limit = std::min(pageSize, lastTableIndex - offset);
+ auto nextPageParams = json11::Json::object{{json::offset, static_cast<int>(offset)},
+ {json::limit, static_cast<int>(limit)}};
+ newBody.insert({json::nextPage, nextPageParams});
+ }
+ }
+
+ setResponseBody(newBody);
+ return Context::createSimpleResponse();
+ }
+ };
+
+ namespace endpoint_pageing
+ {
+ inline constexpr std::size_t contactsPageSize = 10;
+ }
+
+ class ContextFactory
+ {
+ public:
+ static auto create(json11::Json &js) -> std::unique_ptr<parserFSM::Context>
+ {
+ switch (static_cast<EndpointType>(js[json::endpoint].int_value())) {
+ // enable for pagination in other endpoints
+ // case EndpointType::calendarEvents:
+ // case EndpointType::calllog:
+ case EndpointType::contacts:
+ // case EndpointType::messages:
+ return std::make_unique<PagedContext>(js, endpoint_pageing::contactsPageSize);
+ default:
+ return std::make_unique<Context>(js);
+ }
+ }
+ };
+
} // namespace parserFSM
M module-services/service-desktop/endpoints/Endpoint.hpp => module-services/service-desktop/endpoints/Endpoint.hpp +3 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 10,6 10,7 @@
#include <Common/Query.hpp>
#include <Service/Service.hpp>
#include <string>
+#include <memory>
namespace parserFSM
{
@@ 20,7 21,7 @@ namespace parserFSM
public:
Endpoint(sys::Service *_ownerServicePtr) : ownerServicePtr(_ownerServicePtr){};
virtual ~Endpoint() = default;
- virtual auto handle(Context &context) -> void = 0;
+ virtual auto handle(parserFSM::Context &context) -> void = 0;
auto c_str() -> const char *
{
return debugName.c_str();
M module-services/service-desktop/endpoints/contacts/ContactHelper.cpp => module-services/service-desktop/endpoints/contacts/ContactHelper.cpp +39 -30
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ContactHelper.hpp"
@@ 27,6 27,7 @@
#include <memory>
#include <utility>
#include <vector>
+#include <algorithm>
using namespace parserFSM;
@@ 72,38 73,46 @@ auto ContactHelper::requestDataFromDB(Context &context) -> sys::ReturnCodes
if (context.getBody()[json::contacts::id].int_value() != 0) {
return requestContactByID(context);
}
- else if (context.getBody()[json::contacts::count].bool_value()) {
+ else if (context.getBody()[json::contacts::limit].bool_value()) {
return requestCount(context);
}
- auto limit = context.getBody()[json::contacts::count].int_value();
- auto offset = context.getBody()[json::contacts::offset].int_value();
- auto query = std::make_unique<db::query::ContactGet>(offset, limit, "");
-
- auto listener = std::make_unique<db::EndpointListener>(
- [](db::QueryResult *result, Context context) {
- if (auto contactResult = dynamic_cast<db::query::ContactGetResult *>(result)) {
-
- auto recordsPtr = std::make_unique<std::vector<ContactRecord>>(contactResult->getRecords());
- json11::Json::array contactsArray;
-
- for (auto record : *recordsPtr.get()) {
- contactsArray.emplace_back(ContactHelper::to_json(record));
+ try {
+ auto &ctx = dynamic_cast<PagedContext &>(context);
+ std::size_t limit = ctx.getBody()[json::contacts::limit].int_value();
+ std::size_t offset = ctx.getBody()[json::contacts::offset].int_value();
+ ctx.setRequestedLimit(limit);
+ ctx.setRequestedOffset(offset);
+ auto query = std::make_unique<db::query::ContactGetWithTotalCount>(std::min(ctx.getPageSize(), limit), offset);
+ auto listener = std::make_unique<db::EndpointListenerWithPages>(
+ [](db::QueryResult *result, PagedContext &context) {
+ if (auto contactResult = dynamic_cast<db::query::ContactGetResultWithTotalCount *>(result)) {
+
+ auto recordsPtr = std::make_unique<std::vector<ContactRecord>>(contactResult->getRecords());
+ context.setTotalCount(contactResult->getAllLength());
+ json11::Json::array contactsArray;
+
+ for (const auto &record : *recordsPtr.get()) {
+ contactsArray.emplace_back(ContactHelper::to_json(record));
+ }
+
+ context.setResponseBody(contactsArray);
+
+ MessageHandler::putToSendQueue(context.createSimpleResponse());
+ return true;
}
-
- context.setResponseBody(contactsArray);
- MessageHandler::putToSendQueue(context.createSimpleResponse());
- return true;
- }
- else {
- return false;
- }
- },
- context);
-
- query->setQueryListener(std::move(listener));
-
- DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::Contact, std::move(query));
+ else {
+ return false;
+ }
+ },
+ ctx);
+ query->setQueryListener(std::move(listener));
+ DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::Contact, std::move(query));
+ }
+ catch (const std::exception &e) {
+ LOG_ERROR("%s", e.what());
+ return sys::ReturnCodes::Failure;
+ }
return sys::ReturnCodes::Success;
}
@@ 118,7 127,7 @@ sys::ReturnCodes ContactHelper::requestCount(Context &context)
auto count = contactResult->getSize();
- context.setResponseBody(json11::Json::object({{json::contacts::count, static_cast<int>(count)}}));
+ context.setResponseBody(json11::Json::object({{json::contacts::limit, static_cast<int>(count)}}));
MessageHandler::putToSendQueue(context.createSimpleResponse());
return true;
}
M module-services/service-desktop/endpoints/contacts/ContactHelper.hpp => module-services/service-desktop/endpoints/contacts/ContactHelper.hpp +5 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 26,8 26,10 @@ namespace parserFSM
class ContactHelper : public DBHelper
{
+
public:
- ContactHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr){};
+ ContactHelper(sys::Service *_ownerServicePtr) : DBHelper(_ownerServicePtr)
+ {}
auto createDBEntry(Context &context) -> sys::ReturnCodes override;
auto requestDataFromDB(Context &context) -> sys::ReturnCodes override;
@@ 42,7 44,7 @@ namespace parserFSM
namespace json::contacts
{
- inline constexpr auto count = "count";
+ inline constexpr auto limit = "limit";
inline constexpr auto offset = "offset";
inline constexpr auto primaryName = "priName";
inline constexpr auto alternativeName = "altName";
M module-services/service-desktop/endpoints/contacts/ContactsEndpoint.cpp => module-services/service-desktop/endpoints/contacts/ContactsEndpoint.cpp +1 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ContactHelper.hpp"
@@ 9,7 9,6 @@
#include <memory>
using namespace parserFSM;
-
auto ContactsEndpoint::handle(Context &context) -> void
{
switch (context.getMethod()) {
M module-services/service-desktop/endpoints/contacts/ContactsEndpoint.hpp => module-services/service-desktop/endpoints/contacts/ContactsEndpoint.hpp +1 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
M module-services/service-desktop/parser/MessageHandler.cpp => module-services/service-desktop/parser/MessageHandler.cpp +8 -8
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "MessageHandler.hpp"
@@ 35,18 35,18 @@ MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerSe
void MessageHandler::processMessage()
{
- Context context(messageJson);
+ auto context = ContextFactory::create(messageJson);
LOG_DEBUG("[MsgHandler]\nmethod: %d\nendpoint: %d\nuuid: %" PRIu32 "\nbody: %s\n",
- static_cast<int>(context.getMethod()),
- static_cast<int>(context.getEndpoint()),
- context.getUuid(),
- context.getBody().dump().c_str());
+ static_cast<int>(context->getMethod()),
+ static_cast<int>(context->getEndpoint()),
+ context->getUuid(),
+ context->getBody().dump().c_str());
- auto handler = EndpointFactory::create(context, OwnerServicePtr);
+ auto handler = EndpointFactory::create(*context, OwnerServicePtr);
if (handler != nullptr) {
- handler->handle(context);
+ handler->handle(*context);
}
else {
LOG_ERROR("No way to handle!");
M module-services/service-desktop/tests/CMakeLists.txt => module-services/service-desktop/tests/CMakeLists.txt +14 -0
@@ 15,3 15,17 @@ add_catch2_executable(
DEPS
PurePhone.img-target
)
+
+add_catch2_executable(
+ NAME
+ service-desktop-endpoint-contacts
+ SRCS
+ tests-main.cpp
+ test-contacts.cpp
+ LIBS
+ service-desktop
+ module-utils
+ module-apps
+ module-vfs
+ iosyscalls
+)
A module-services/service-desktop/tests/test-contacts.cpp => module-services/service-desktop/tests/test-contacts.cpp +204 -0
@@ 0,0 1,204 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <endpoints/Endpoint.hpp>
+#include <endpoints/EndpointFactory.hpp>
+
+#include <catch2/catch.hpp>
+#include <json/json11.hpp>
+#include <purefs/filesystem_paths.hpp>
+#include <utf8/UTF8.hpp>
+#include <vfs.hpp>
+
+#include <memory>
+#include <filesystem>
+#include <string>
+#include <vector>
+
+#include <module-db/Interface/ContactRecord.hpp>
+#include <module-db/Databases/ContactsDB.hpp>
+
+class vfs vfs;
+std::unique_ptr<ContactsDB> contactsDb = nullptr;
+std::vector<std::string> messageStrings;
+
+// stubs
+std::pair<bool, std::uint64_t> DBServiceAPI::GetQuery(sys::Service *serv,
+ db::Interface::Name database,
+ std::unique_ptr<db::Query> query)
+{
+ auto queryType = query->type;
+ LOG_DEBUG("query is: %d", static_cast<uint32_t>(queryType));
+
+ ContactRecordInterface cri(contactsDb.get());
+ auto result = cri.runQuery(std::move(query));
+ auto queryListener = result->getRequestQuery()->getQueryListener();
+ queryListener->handleQueryResponse(result.get());
+
+ return std::make_pair(true, 0);
+}
+auto DBServiceAPI::ThreadGetByNumber(sys::Service *serv,
+ const utils::PhoneNumber::View &phoneNumber,
+ std::uint32_t timeout) -> std::unique_ptr<ThreadRecord>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ThreadGetCount(sys::Service *serv, EntryState state) -> uint32_t
+{
+ return 0;
+}
+
+auto DBServiceAPI::GetQueryWithReply(sys::Service *serv,
+ db::Interface::Name database,
+ std::unique_ptr<db::Query> query,
+ std::uint32_t timeout) -> sys::SendResult
+{
+ return {};
+}
+
+auto DBServiceAPI::verifyContact(sys::Service *serv, const ContactRecord &rec) -> ContactVerificationResult
+{
+ return {};
+}
+auto DBServiceAPI::ContactGetByID(sys::Service *serv, uint32_t contactID) -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByIDWithTemporary(sys::Service *serv, uint32_t contactID)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByIDCommon(sys::Service *serv, std::shared_ptr<DBContactMessage> contactMsg)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetBySpeeddial(sys::Service *serv, UTF8 speeddial)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactGetByPhoneNumber(sys::Service *serv, UTF8 phoneNumber)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::MatchContactByPhoneNumber(sys::Service *serv, const utils::PhoneNumber::View &numberView)
+ -> std::unique_ptr<ContactRecord>
+{
+ return nullptr;
+}
+auto DBServiceAPI::ContactAdd(sys::Service *serv, const ContactRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactRemove(sys::Service *serv, uint32_t id) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactUpdate(sys::Service *serv, const ContactRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::ContactSearch(sys::Service *serv, UTF8 primaryName, UTF8 alternativeName, UTF8 number)
+ -> std::unique_ptr<std::vector<ContactRecord>>
+{
+ return nullptr;
+}
+auto DBServiceAPI::CalllogAdd(sys::Service *serv, const CalllogRecord &rec) -> CalllogRecord
+{
+ return {};
+}
+auto DBServiceAPI::CalllogRemove(sys::Service *serv, uint32_t id) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::CalllogUpdate(sys::Service *serv, const CalllogRecord &rec) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::CalllogGetCount(sys::Service *serv, EntryState state) -> uint32_t
+{
+ return 0;
+}
+auto DBServiceAPI::CalllogGetLimitOffset(sys::Service *serv, uint32_t offset, uint32_t limit) -> bool
+{
+ return false;
+}
+auto DBServiceAPI::GetCountryCodeByMCC(sys::Service *serv, uint32_t mcc) -> uint32_t
+{
+ return 0;
+}
+auto DBServiceAPI::DBBackup(sys::Service *serv, std::string backupPath) -> bool
+{
+ return false;
+}
+bool DBServiceAPI::AddSMS(sys::Service *serv, const SMSRecord &record, std::unique_ptr<db::QueryListener> &&listener)
+{
+ return false;
+}
+
+xQueueHandle parserFSM::MessageHandler::sendQueue;
+parserFSM::MessageHandler::MessageHandler(const std::string &message, sys::Service *OwnerService)
+ : OwnerServicePtr(OwnerService)
+{}
+void parserFSM::MessageHandler::processMessage()
+{}
+void parserFSM::MessageHandler::putToSendQueue(const std::string &msg)
+{
+ messageStrings.push_back(msg);
+ LOG_DEBUG("response is: %s", msg.c_str());
+}
+//~stubs
+
+TEST_CASE("Endpoint Contacts Test")
+{
+ vfs.Init();
+ Database::initialize();
+
+ const auto contactsPath = purefs::dir::getUserDiskPath() / "contacts.db";
+ std::filesystem::remove(contactsPath);
+
+ contactsDb = std::make_unique<ContactsDB>(contactsPath.c_str());
+ REQUIRE(contactsDb->isInitialized());
+ messageStrings.clear();
+
+ SECTION("Request with pages")
+ {
+ auto count = 29; // requested number of record to return
+ auto endpoint = 7;
+ auto uuid = "1103";
+ auto totalCount = contactsDb->contacts.count();
+ auto testMessage = "{\"endpoint\":" + std::to_string(endpoint) + ", \"method\":1, \"uuid\":" + uuid +
+ ", \"body\":{\"limit\":" + std::to_string(count) + ", \"offset\":20}}";
+ std::string err;
+ auto msgJson = json11::Json::parse(testMessage, err);
+ REQUIRE(err.empty());
+
+ parserFSM::PagedContext context(msgJson, 10);
+ auto handler = EndpointFactory::create(context, nullptr);
+ handler->handle(context);
+ auto pageSize = context.getPageSize();
+ REQUIRE(10 == pageSize);
+ REQUIRE(1 == messageStrings.size());
+ auto msg = messageStrings[0];
+ REQUIRE(msg.size() > 10);
+ auto retJson = json11::Json::parse(msg.substr(10), err); // string length and go to real data
+
+ REQUIRE(err.empty());
+ REQUIRE(uuid == retJson[parserFSM::json::uuid].string_value());
+ REQUIRE(endpoint == retJson[parserFSM::json::endpoint].int_value());
+
+ auto body = retJson[parserFSM::json::body];
+ REQUIRE(totalCount == static_cast<uint32_t>(body[parserFSM::json::totalCount].int_value()));
+
+ auto nextPage = body[parserFSM::json::nextPage];
+ REQUIRE(static_cast<int>(pageSize) == nextPage[parserFSM::json::limit].int_value());
+ // base offset + pageSize cause asked for 29
+ REQUIRE(30 == nextPage[parserFSM::json::offset].int_value());
+
+ auto entries = body[parserFSM::json::entries];
+ REQUIRE(pageSize == entries.array_items().size());
+ }
+}
R test/pytest/service-desktop/test_calllog.py => test/pytest/service-desktop/disabled_test_calllog.py +0 -0
R test/pytest/service-desktop/test_messages.py => test/pytest/service-desktop/disabled_test_messages.py +0 -0
M test/pytest/service-desktop/test_contacts.py => test/pytest/service-desktop/test_contacts.py +16 -16
@@ 7,49 7,49 @@ from harness.interface.defs import status
@pytest.mark.service_desktop_test
def test_contacts(harness):
# getting the contacts count
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- count = ret["body"]["count"]
+ count = ret["body"]["limit"]
if count == 0:
pytest.skip("No contacts entries, skipping")
# getting all contacts
- batch_size = 30
+ batch_size = 10
divider = int(count / batch_size)
reminder = count % batch_size
contacts = []
for i in range(divider):
- body = {"count": batch_size, "offset": batch_size*i}
+ body = {"limit": batch_size, "offset": batch_size*i}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
- body = {"count": reminder, "offset": count-reminder}
+ body = {"limit": reminder, "offset": count-reminder}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
contacts_length = len(contacts)
assert contacts_length
assert contacts_length == count
# try to get more than available
- batch_size = 30
+ batch_size = 10
divider = int((count+10) / batch_size)
reminder = (count+10) % batch_size
contacts = []
for i in range(divider):
- body = {"count": batch_size, "offset": batch_size * i}
+ body = {"limit": batch_size, "offset": batch_size * i}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
- body = {"count": reminder, "offset": (count+10)-reminder}
+ body = {"limit": reminder, "offset": (count+10)-reminder}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- contacts = contacts + ret["body"]
+ contacts = contacts + ret["body"]["entries"]
contacts_length = len(contacts)
assert contacts_length
@@ 78,10 78,10 @@ def test_contacts(harness):
assert ret["status"] == status["NotAcceptable"]
# checking count after adding
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- assert ret["body"]["count"] == count + 1
+ assert ret["body"]["limit"] == count + 1
# updating existing contact
body = {"address": "6 Czeczota St.\n02600 Warsaw",
@@ 112,8 112,8 @@ def test_contacts(harness):
assert ret["status"] == status["OK"]
# verifying count
- body = {"count": True}
+ body = {"limit": True}
ret = harness.endpoint_request("contacts", "get", body)
assert ret["status"] == status["OK"]
- assert ret["body"]["count"] == count
+ assert ret["body"]["limit"] == count