From 31df1ce788ec1fec020880441fc0b62ed0920280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ta=C5=84ski?= Date: Wed, 23 Dec 2020 10:17:52 +0100 Subject: [PATCH] [EGD-4921] Add next harness test cases Test harness extended with additional tests: - Making a call to a specific phone number. - Calling back to the last number from the call log. - Searching for SMSes with a phone number filter. --- changelog.md | 1 + module-db/Interface/SMSRecord.cpp | 26 +++++- module-db/Interface/SMSRecord.hpp | 5 ++ module-db/Tables/SMSTable.cpp | 24 ++++++ module-db/Tables/SMSTable.hpp | 1 + .../messages/sms/QuerySMSGetByText.cpp | 16 ++++ .../messages/sms/QuerySMSGetByText.hpp | 11 ++- module-services/service-db/ServiceDB.cpp | 2 +- .../endpoints/messages/MessageHelper.cpp | 5 ++ test/harness/utils.py | 2 +- test/pytest/test_call_back.py | 38 +++++++++ test/pytest/test_search_sms.py | 13 +++ test/pytest/test_send_message.py | 10 +-- test/search_sms.py | 52 ++++++++++++ test/send_message.py | 83 ------------------- 15 files changed, 196 insertions(+), 93 deletions(-) create mode 100644 test/pytest/test_call_back.py create mode 100644 test/pytest/test_search_sms.py create mode 100644 test/search_sms.py delete mode 100755 test/send_message.py diff --git a/changelog.md b/changelog.md index ea47c92d0c739ca9ea1f2dd3984a4cd7e2e30ea7..19c0d57ab01866dc22ce16f1bbf510a8e4cee7fa 100644 --- a/changelog.md +++ b/changelog.md @@ -11,6 +11,7 @@ * Add Bluetooth virtual audio device. * Add custom repeat window for the alarm application * `[PowerManagement]` Add CPU frequency shift mechanism. +* `[tests]` Extended the automated tests with new test cases: making a call, answering a call. ### Fixed diff --git a/module-db/Interface/SMSRecord.cpp b/module-db/Interface/SMSRecord.cpp index afc33bce5a7f7bccda611c12a790d1d5273e217c..11028ac1f14a8fc7fc7bee17ae1d619b7c19b317 100644 --- a/module-db/Interface/SMSRecord.cpp +++ b/module-db/Interface/SMSRecord.cpp @@ -380,13 +380,37 @@ std::unique_ptr SMSRecordInterface::getByContactIDQuery(const s std::unique_ptr SMSRecordInterface::getByTextQuery(const std::shared_ptr &query) { const auto localQuery = static_cast(query.get()); - auto smsVector = smsDB->sms.getByText(localQuery->text); + auto smsVector = getByText(localQuery->getText(), localQuery->getPhoneNumber()); auto recordVector = std::vector(smsVector.begin(), smsVector.end()); auto response = std::make_unique(recordVector); response->setRequestQuery(query); return response; } + +std::vector SMSRecordInterface::getByText(const std::string &text, + const std::optional &phoneNumberFilter) +{ + if (phoneNumberFilter.has_value()) { + return getByTextAndPhoneNumber(text, phoneNumberFilter.value()); + } + const auto &records = smsDB->sms.getByText(text); + return std::vector(records.begin(), records.end()); +} + +std::vector SMSRecordInterface::getByTextAndPhoneNumber(const std::string &text, + const utils::PhoneNumber::View &phoneNumber) +{ + ThreadRecordInterface threadsInterface{smsDB, contactsDB}; + const auto &thread = threadsInterface.GetByNumber(phoneNumber); + if (!thread.isValid()) { + return {}; + } + + const auto &smsRecords = smsDB->sms.getByText(text, thread.ID); + return std::vector(smsRecords.begin(), smsRecords.end()); +} + std::unique_ptr SMSRecordInterface::getCountQuery(const std::shared_ptr &query) { auto response = std::make_unique(smsDB->sms.count()); diff --git a/module-db/Interface/SMSRecord.hpp b/module-db/Interface/SMSRecord.hpp index 6e00ce0b8f517fa901ff33ebd4b67cf75f6dec0f..72e9d368c0b27ad3c340046283a583742e6a0d35 100644 --- a/module-db/Interface/SMSRecord.hpp +++ b/module-db/Interface/SMSRecord.hpp @@ -77,6 +77,11 @@ class SMSRecordInterface : public RecordInterface SmsDB *smsDB = nullptr; ContactsDB *contactsDB = nullptr; + std::vector getByText(const std::string &text, + const std::optional &phoneNumberFilter); + std::vector getByTextAndPhoneNumber(const std::string &text, + const utils::PhoneNumber::View &phoneNumber); + static void UpdateThreadSummary(ThreadRecord &threadToUpdate, const SMSRecord &rec); std::unique_ptr runQueryImpl(const db::query::SMSSearchByType *query); std::unique_ptr getByIDQuery(const std::shared_ptr &query); diff --git a/module-db/Tables/SMSTable.cpp b/module-db/Tables/SMSTable.cpp index d9d5adcc59e9776b85de7ac684e998b7bf301676..0ba02fc4404a363d4f11e6b829162189709eb917 100644 --- a/module-db/Tables/SMSTable.cpp +++ b/module-db/Tables/SMSTable.cpp @@ -234,6 +234,30 @@ std::vector SMSTable::getByText(std::string text) return ret; } +std::vector SMSTable::getByText(std::string text, uint32_t threadId) +{ + auto retQuery = + db->query("SELECT *, INSTR(body,'%s') pos FROM sms WHERE pos > 0 AND thread_id=%u;", text.c_str(), threadId); + if ((retQuery == nullptr) || (retQuery->getRowCount() == 0)) { + return {}; + } + + std::vector ret; + do { + ret.push_back(SMSTableRow{ + (*retQuery)[0].getUInt32(), // ID + (*retQuery)[1].getUInt32(), // threadID + (*retQuery)[2].getUInt32(), // contactID + (*retQuery)[3].getUInt32(), // date + (*retQuery)[4].getUInt32(), // dateSent + (*retQuery)[5].getUInt32(), // errorCode + (*retQuery)[6].getString(), // body + static_cast((*retQuery)[7].getUInt32()), // type + }); + } while (retQuery->nextRow()); + return ret; +} + std::vector SMSTable::getLimitOffset(uint32_t offset, uint32_t limit) { auto retQuery = db->query("SELECT * from sms ORDER BY date DESC LIMIT %lu OFFSET %lu;", limit, offset); diff --git a/module-db/Tables/SMSTable.hpp b/module-db/Tables/SMSTable.hpp index b78b8e82845bfb83c294ff18a805b971ca3d8d28..85f7117551ee8eefa126260a9f161236c6b84062 100644 --- a/module-db/Tables/SMSTable.hpp +++ b/module-db/Tables/SMSTable.hpp @@ -49,6 +49,7 @@ class SMSTable : public Table uint32_t countByFieldId(const char *field, uint32_t id) override final; std::vector getByContactId(uint32_t contactId); std::vector getByText(std::string text); + std::vector getByText(std::string text, uint32_t threadId); std::vector getByThreadId(uint32_t threadId, uint32_t offset, uint32_t limit); std::vector getByThreadIdWithoutDraftWithEmptyInput(uint32_t threadId, uint32_t offset, diff --git a/module-db/queries/messages/sms/QuerySMSGetByText.cpp b/module-db/queries/messages/sms/QuerySMSGetByText.cpp index b7719db1954b39222181a51b92e3490d60704363..f918808644696e8c935f1c1d224a4ae1568db772 100644 --- a/module-db/queries/messages/sms/QuerySMSGetByText.cpp +++ b/module-db/queries/messages/sms/QuerySMSGetByText.cpp @@ -8,6 +8,21 @@ namespace db::query SMSGetByText::SMSGetByText(std::string text) : Query(Query::Type::Read), text(std::move(text)) {} + void SMSGetByText::filterByPhoneNumber(const utils::PhoneNumber::View &number) noexcept + { + phoneNumber = number; + } + + auto SMSGetByText::getPhoneNumber() const noexcept -> const std::optional & + { + return phoneNumber; + } + + auto SMSGetByText::getText() const noexcept -> const std::string & + { + return text; + } + auto SMSGetByText::debugInfo() const -> std::string { return "SMSGetByText"; @@ -15,6 +30,7 @@ namespace db::query SMSGetByTextResult::SMSGetByTextResult(std::vector result) : result(std::move(result)) {} + auto SMSGetByTextResult::getResults() const -> std::vector { return result; diff --git a/module-db/queries/messages/sms/QuerySMSGetByText.hpp b/module-db/queries/messages/sms/QuerySMSGetByText.hpp index 8fe7f2010107f4670bca1e9cd6fc1d6916b992fb..255569195224cd717ed3929f8dfb9f87b5b0e1ce 100644 --- a/module-db/queries/messages/sms/QuerySMSGetByText.hpp +++ b/module-db/queries/messages/sms/QuerySMSGetByText.hpp @@ -14,9 +14,16 @@ namespace db::query class SMSGetByText : public Query { public: - SMSGetByText(std::string text); - std::string text; + explicit SMSGetByText(std::string text); + + void filterByPhoneNumber(const utils::PhoneNumber::View &number) noexcept; + [[nodiscard]] auto getPhoneNumber() const noexcept -> const std::optional &; + [[nodiscard]] auto getText() const noexcept -> const std::string &; [[nodiscard]] auto debugInfo() const -> std::string override; + + private: + std::string text; + std::optional phoneNumber; }; class SMSGetByTextResult : public QueryResult diff --git a/module-services/service-db/ServiceDB.cpp b/module-services/service-db/ServiceDB.cpp index 042ecd8a17d9b99343050ffe51252a208e420b28..6752a1019e14ace1273eea44f84bb7f9a91da720 100644 --- a/module-services/service-db/ServiceDB.cpp +++ b/module-services/service-db/ServiceDB.cpp @@ -541,7 +541,7 @@ sys::ReturnCodes ServiceDB::InitHandler() smsDB = std::make_unique((purefs::dir::getUserDiskPath() / "sms.db").c_str()); alarmsDB = std::make_unique((purefs::dir::getUserDiskPath() / "alarms.db").c_str()); notesDB = std::make_unique((purefs::dir::getUserDiskPath() / "notes.db").c_str()); - calllogDB = std::make_unique((purefs::dir::getUserDiskPath() / "callog.db").c_str()); + calllogDB = std::make_unique((purefs::dir::getUserDiskPath() / "calllog.db").c_str()); countryCodesDB = std::make_unique("country-codes.db"); notificationsDB = std::make_unique((purefs::dir::getUserDiskPath() / "notifications.db").c_str()); eventsDB = std::make_unique((purefs::dir::getUserDiskPath() / "events.db").c_str()); diff --git a/module-services/service-desktop/endpoints/messages/MessageHelper.cpp b/module-services/service-desktop/endpoints/messages/MessageHelper.cpp index c16cb344c25ddb8a6e20ee1f7a46931630e976a8..6b55c14d6225e356bcc92509928ec6c44e6e8949 100644 --- a/module-services/service-desktop/endpoints/messages/MessageHelper.cpp +++ b/module-services/service-desktop/endpoints/messages/MessageHelper.cpp @@ -198,6 +198,11 @@ auto MessageHelper::requestSMS(Context &context) -> sys::ReturnCodes else if (context.getBody()[json::messages::messageBody].string_value().empty() == false) { auto query = std::make_unique(context.getBody()[json::messages::messageBody].string_value()); + if (const auto filterByNumber = !context.getBody()[json::messages::phoneNumber].string_value().empty(); + filterByNumber) { + utils::PhoneNumber number{context.getBody()[json::messages::phoneNumber].string_value()}; + query->filterByPhoneNumber(number.getView()); + } auto listener = std::make_unique( [=](db::QueryResult *result, Context context) { diff --git a/test/harness/utils.py b/test/harness/utils.py index 9bbd1ef6ca6157ef7612ca107fa8130692bd299d..2f65ec74b0ac5ba692483aadfdbcb0d0a729ef6c 100644 --- a/test/harness/utils.py +++ b/test/harness/utils.py @@ -10,7 +10,7 @@ from harness.interface.defs import key_codes # assuming that the harness is actually in the menu application_keypath = { - "phone": [ + "calllog": [ "enter" ], "contacts": [ diff --git a/test/pytest/test_call_back.py b/test/pytest/test_call_back.py new file mode 100644 index 0000000000000000000000000000000000000000..606b1e9ef7f264cb0de9799d96e9eef1a1410db9 --- /dev/null +++ b/test/pytest/test_call_back.py @@ -0,0 +1,38 @@ +# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +import time +import pytest + +from harness.interface.defs import key_codes + + +def get_calllog_count(harness): + body = {"count": True} + return harness.endpoint_request("calllog", "get", body)["body"]["count"] + + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("phone_unlocked") +def test_call(harness, call_duration): + count_before = get_calllog_count(harness) + + # enter menu + harness.connection.send_key(key_codes["enter"]) + harness.open_application("calllog") + if harness.connection.get_window_name() != "ApplicationCallLog": + time.sleep(2) + assert harness.connection.get_window_name() == "ApplicationCallLog" + + # call + harness.connection.send_key(key_codes["fnLeft"]) + time.sleep(call_duration) + # hang up + harness.connection.send_key(key_codes["fnRight"]) + count_after = get_calllog_count(harness) + + for _ in range(3): + harness.connection.send_key(key_codes["fnRight"]) + time.sleep(1) + + assert count_before + 1 == count_after + time.sleep(2) # needed to restore after call diff --git a/test/pytest/test_search_sms.py b/test/pytest/test_search_sms.py new file mode 100644 index 0000000000000000000000000000000000000000..f21a05536ecbfa481fbe9539150860b832ac37f1 --- /dev/null +++ b/test/pytest/test_search_sms.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md +import time +import pytest + +from harness.interface.defs import key_codes + +@pytest.mark.rt1051 +@pytest.mark.usefixtures("phone_unlocked") +def test_search_sms(harness, sms_text, phone_number): + body = {"messageBody": sms_text, "phoneNumber": str(phone_number)} + messages = harness.endpoint_request("messages", "get", body)["body"] + assert len(messages) != 0 diff --git a/test/pytest/test_send_message.py b/test/pytest/test_send_message.py index 3540f74d244b9612090f4977b2b39ac12e9bb38b..17cd05dbc1d4664db9ed7cc9895087707e12b878 100644 --- a/test/pytest/test_send_message.py +++ b/test/pytest/test_send_message.py @@ -6,15 +6,15 @@ import pytest from harness.interface.defs import key_codes -def get_message_by_text(harness, message: str): - body = {"messageBody": message} +def get_message_by_text(harness, message: str, phone_number: str): + body = {"messageBody": message, "phoneNumber": phone_number} return harness.endpoint_request("messages", "get", body)["body"] @pytest.mark.rt1051 @pytest.mark.usefixtures("phone_unlocked") def test_send_message(harness, phone_number, sms_text): - messages = get_message_by_text(harness, sms_text.upper()) + messages = get_message_by_text(harness, sms_text.upper(), str(phone_number)) # enter menu harness.connection.send_key(key_codes["enter"]) @@ -35,11 +35,11 @@ def test_send_message(harness, phone_number, sms_text): harness.connection.send_key(key_codes["enter"]) # go back to main screen - for i in range(3): + for _ in range(3): harness.connection.send_key(key_codes["fnRight"]) time.sleep(2) - new_messages = get_message_by_text(harness, sms_text.upper()) + new_messages = get_message_by_text(harness, sms_text.upper(), str(phone_number)) diff = [i for i in messages + new_messages if i not in messages or i not in new_messages] assert len(diff) == 1 diff --git a/test/search_sms.py b/test/search_sms.py new file mode 100644 index 0000000000000000000000000000000000000000..bdad6f11f682b2f10d24718096412f5342ef13f5 --- /dev/null +++ b/test/search_sms.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +import sys +import time + +from harness import log +from harness.harness import Harness +from harness.interface.defs import key_codes, endpoint, method +from harness.interface.error import TestError, Error + + +def search_sms(harness, message: str, phone_number: str): + @harness.with_phone_unlocked + def do_it(connection): + body = {"messageBody": message, "phoneNumber": phone_number} + messages = harness.endpoint_request("messages", "get", body)["body"] + print(f'Found {len(messages)} messages') + + +def main(): + if len(sys.argv) == 1 or "/dev" not in sys.argv[1]: + log.warning("Port name not passed, trying port name filename from simulator...") + try: + file = open("/tmp/purephone_pts_name", "r") + except FileNotFoundError: + raise TestError(Error.PORT_FILE_NOT_FOUND) + + port_name = file.readline() + if port_name.isascii(): + log.debug("found {} entry!".format(port_name)) + else: + print(f'Please pass port name as the parameter: python {sys.argv[0]} /dev/ttyACM0 number text ') + raise TestError(Error.PORT_NOT_FOUND) + else: + port_name = sys.argv[1] + + harness = Harness(port_name) + message = str(sys.argv[2]) + phone_number = str(sys.argv[3]) + + search_sms(harness, message, phone_number) + + +if __name__ == "__main__": + try: + main() + except TestError as err: + log.error(err) + exit(err.get_error_code()) + diff --git a/test/send_message.py b/test/send_message.py deleted file mode 100755 index 32bac93b4601d0ee4297dbc185be0eafb9b85a4b..0000000000000000000000000000000000000000 --- a/test/send_message.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. -# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md - -import sys -import time - -from harness import log -from harness.harness import Harness -from harness.interface.defs import key_codes, endpoint, method -from harness.interface.error import TestError, Error - - -def send_message(harness, phone_number: str, message: str): - @harness.with_phone_unlocked - def send(connection): - # enter menu - connection.send_key(key_codes["enter"]) - harness.open_application("messages") - if harness.connection.get_window_name() != "ApplicationMessages": - time.sleep(2) - if harness.connection.get_window_name() != "ApplicationMessages": - print("Application didn't switch, exiting...") - exit(1) - - # create new message - connection.send_key(key_codes["left"]) - # enter phone number - harness.send_number(phone_number) - # move down to message body - connection.send_key(key_codes["down"]) - # write a message - harness.send_text(message) - # send - connection.send_key(key_codes["enter"]) - - -def get_message_by_text(harness, message: str): - body = {"messageBody": message} - return harness.endpoint_request("messages", "get", body)["body"] - - -def main(): - if len(sys.argv) == 1 or "/dev" not in sys.argv[1]: - log.warning("Port name not passed, trying port name filename from simulator...") - try: - file = open("/tmp/purephone_pts_name", "r") - except FileNotFoundError as err: - raise TestError(Error.PORT_FILE_NOT_FOUND) - - - port_name = file.readline() - if port_name.isascii(): - log.debug("found {} entry!".format(port_name)) - else: - print(f'Please pass port name as the parameter: python {sys.argv[0]} /dev/ttyACM0 number text ') - raise TestError(Error.PORT_NOT_FOUND) - else: - port_name = sys.argv[1] - - harness = Harness(port_name) - message = str(sys.argv[3]) - messages = get_message_by_text(harness, message.upper()) - - send_message(harness, str(sys.argv[2]), message) - time.sleep(2) - new_messages = get_message_by_text(harness, message.upper()) - - diff = [i for i in messages + new_messages if i not in messages or i not in new_messages] - if len(diff) != 1 or diff[0]["type"] != 0x08: # 0x08 - SMSType::OUTBOX - log.error("sending error!") - raise TestError(Error.TEST_FAILED) - else: - log.info("sending success!") - - -if __name__ == "__main__": - try: - main() - except TestError as err: - log.error(err) - exit(err.get_error_code()) -