~aleteoryx/muditaos

aedd6a7a3697af9836c71d9c34f5109cdafba641 — Bartosz Cichocki 5 years ago b96313b
[EGD-4319] Added test harness API (#993)

[EGD-4319] added phone lock checking and opening application from harness

Co-authored-by: SP2FET <bartosz.cichocki@mudita.com>
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +16 -0
@@ 54,6 54,11 @@ namespace app
        else if (auto msg = dynamic_cast<cellular::StateChange *>(msgl)) {
            handled = handle(msg);
        }
        else if (auto msg = dynamic_cast<sdesktop::developerMode::DeveloperModeRequest *>(msgl)) {
            if (auto event = dynamic_cast<sdesktop::developerMode::ScreenlockCheckEvent *>(msg->event.get())) {
                handled = handle(event);
            }
        }

        else if (auto msg = dynamic_cast<sdesktop::UpdateOsMessage *>(msgl)) {
            handled = handle(msg);


@@ 92,6 97,17 @@ namespace app
        return true;
    }

    auto ApplicationDesktop::handle(sdesktop::developerMode::ScreenlockCheckEvent *event) -> bool
    {
        if (event != nullptr) {
            auto event = std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>(lockHandler.lock.isLocked());
            auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
            sys::Bus::SendUnicast(std::move(msg), service::name::service_desktop, this);
        }

        return true;
    }

    auto ApplicationDesktop::handle(db::query::notifications::GetAllResult *msg) -> bool
    {
        assert(msg);

M module-apps/application-desktop/ApplicationDesktop.hpp => module-apps/application-desktop/ApplicationDesktop.hpp +1 -1
@@ 66,7 66,7 @@ namespace app
        bool handle(cellular::StateChange *msg);
        auto handle(db::query::notifications::GetAllResult *msg) -> bool;
        auto handle(sdesktop::UpdateOsMessage *msg) -> bool;

        auto handle(sdesktop::developerMode::ScreenlockCheckEvent *event) -> bool;
        /**
         * This static method will be used to lock the phone
         */

M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +7 -2
@@ 29,12 29,17 @@ auto DeveloperModeHelper::processPutRequest(Context &context) -> sys::ReturnCode
        auto msg     = std::make_shared<cellular::RawCommand>();
        msg->command = body[json::developerMode::AT].string_value();
        msg->timeout = 3000;
        sys::Bus::SendUnicast(msg, ServiceCellular::serviceName, ownerServicePtr);
        sys::Bus::SendUnicast(std::move(msg), ServiceCellular::serviceName, ownerServicePtr);
    }
    else if (body[json::developerMode::focus].bool_value()) {
        auto event = std::make_unique<sdesktop::developerMode::AppFocusChangeEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        sys::Bus::SendUnicast(msg, service::name::evt_manager, ownerServicePtr);
        sys::Bus::SendUnicast(std::move(msg), service::name::evt_manager, ownerServicePtr);
    }
    else if (body[json::developerMode::isLocked].bool_value()) {
        auto event = std::make_unique<sdesktop::developerMode::ScreenlockCheckEvent>();
        auto msg   = std::make_shared<sdesktop::developerMode::DeveloperModeRequest>(std::move(event));
        sys::Bus::SendUnicast(std::move(msg), "ApplicationDesktop", ownerServicePtr);
    }
    else {
        context.setResponseStatus(http::Code::BadRequest);

M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.hpp +1 -0
@@ 36,5 36,6 @@ namespace parserFSM
        inline constexpr auto ATResponse    = "ATResponse";
        inline constexpr auto AT            = "AT";
        inline constexpr auto focus         = "focus";
        inline constexpr auto isLocked      = "isLocked";
    }
} // namespace parserFSM

M module-services/service-desktop/messages/DesktopMessages.cpp => module-services/service-desktop/messages/DesktopMessages.cpp +7 -0
@@ 24,6 24,13 @@ namespace sdesktop::developerMode
        context.setResponseBody(json11::Json::object{{json::developerMode::focus, appName}});
    }

    ScreenlockCheckEvent::ScreenlockCheckEvent(bool isLocked)
    {
        context.setResponseStatus(http::Code::OK);
        context.setEndpoint(EndpointType::developerMode);
        context.setResponseBody(json11::Json::object{{json::developerMode::isLocked, isLocked}});
    }

    DeveloperModeRequest::DeveloperModeRequest(std::unique_ptr<Event> event)
        : sys::DataMessage(MessageType::DeveloperModeRequest), event(std::move(event))
    {}

M module-services/service-desktop/messages/DesktopMessages.hpp => module-services/service-desktop/messages/DesktopMessages.hpp +8 -0
@@ 75,6 75,7 @@ namespace sdesktop

          public:
            void send();
            virtual ~Event() = default;
        };

        class ATResponseEvent : public Event


@@ 90,6 91,13 @@ namespace sdesktop
            explicit AppFocusChangeEvent(std::string appName);
        };

        class ScreenlockCheckEvent : public Event
        {
          public:
            ScreenlockCheckEvent() = default;
            explicit ScreenlockCheckEvent(bool isLocked);
        };

        class DeveloperModeRequest : public sys::DataMessage
        {
          public:

M test/harness/__init__.py => test/harness/__init__.py +2 -0
@@ 2,5 2,7 @@
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import logging
import harness.interface
# logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
log = logging.getLogger(__name__)


A test/harness/harness.py => test/harness/harness.py +39 -0
@@ 0,0 1,39 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

from harness.interface import CDCSerial as serial
from harness.interface.defs import key_codes
from harness.utils import send_keystoke, application_keypath


class Harness:
    connection = None
    is_phone_unlocked = False

    def __init__(self, port='/dev/ttyACM2'):
        self.connection = serial.CDCSerial(port)

    def get_connection(self):
        return self.connection

    def unlock_phone(self):
        if self.connection.is_phone_locked():
            self.connection.send_key(key_codes["enter"])
            self.connection.send_key(key_codes["#"])
            self.connection.send_key(3)
            self.connection.send_key(3)
            self.connection.send_key(3)
            self.connection.send_key(3)
            print("Phone unlocked")
        else:
            print("Phone already unlocked")

    def with_phone_unlocked(self, func):
        if not self.is_phone_unlocked:
            self.unlock_phone()
            self.is_phone_unlocked = True
            
        func(self.connection)

    def open_application(self, app):
        send_keystoke(application_keypath[app], self.connection)

R test/interface/CDCSerial.py => test/harness/interface/CDCSerial.py +11 -2
@@ 6,13 6,14 @@ import serial
import json
import random
import logging
from interface.defs import *

from harness.interface.defs import endpoint, method, status

log = logging.getLogger(__name__)


class CDCSerial:
    def __init__(self, port_name='/dev/ttyACM2'):
    def __init__(self, port_name):
        self.body = ""
        try:
            self.serial = serial.Serial(port_name, baudrate=115200, timeout=10)


@@ 73,3 74,11 @@ class CDCSerial:

        ret = self.write(self.__wrap_message(body))
        return ret["body"]["focus"]

    def is_phone_locked(self):
        body = {
            "isLocked": True
        }

        ret = self.write(self.__wrap_message(body))
        return ret["body"]["isLocked"]

A test/harness/interface/__init__.py => test/harness/interface/__init__.py +3 -0
@@ 0,0 1,3 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md


R test/interface/defs.py => test/harness/interface/defs.py +0 -0
D test/harness/uart.py => test/harness/uart.py +0 -10
@@ 1,10 0,0 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import logging

from interface.CDCSerial import CDCSerial

logging.basicConfig(format='%(asctime)s %(message)s', level=logging.DEBUG)
log = logging.getLogger(__name__)
connection = CDCSerial()

A test/harness/utils.py => test/harness/utils.py +59 -0
@@ 0,0 1,59 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import time

from harness.interface.defs import key_codes

# assuming that the harness is actually in the menu
application_keypath = {
    "phone": [
        "enter"
    ],
    "contacts": [
        "right",
        "enter"
    ],
    "messages": [
        "right",
        "right",
        "enter"
    ],
    "music": [
        "down",
        "enter"
    ],
    "meditation": [
        "down",
        "right",
        "enter"
    ],
    "settings": [
        "down",
        "right",
        "right",
        "enter"
    ],
    "tools": [
        "up",
        "enter"
    ],
    "alarm": [
        "up",
        "right",
        "enter"
    ],
    "calendar": [
        "up",
        "left",
        "left",
        "enter"
    ]
}


def send_keystoke(keypath, connection):
    for i in keypath:
        print(i)
        connection.send_key(key_codes[i])
        time.sleep(0.3)

M test/service-desktop-test/main.py => test/service-desktop-test/main.py +11 -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

import interface.CDCSerial

import sys
from tests.messages import *
from tests.templates import *
from tests.contacts import *


@@ 13,14 11,21 @@ from tests.backup import *
from tests.calllog import *
from termcolor import colored

from harness.harness import Harness


def main(port_name='/dev/ttyACM2'):
def main():
    if len(sys.argv) == 1 or sys.argv[1] is None:
        print('Please pass port name as the parameter: python main.py /dev/ttyACM0 ')
        exit(1)

    serial = interface.CDCSerial.CDCSerial(port_name)
    test_harness = Harness(sys.argv[1])
    serial = test_harness.get_connection()
    final_result = True
    failed_tests = []
    for test_instance in (DeviceInfoTest(serial), UpdateTest(serial), BackupTest(serial), MessageTest(serial),
                          MessageTemplateTest(serial), ContactTest(serial), CalllogTest(serial), FactoryResetTest(serial)):
                          MessageTemplateTest(serial), ContactTest(serial), CalllogTest(serial),
                          FactoryResetTest(serial)):
        test_name = type(test_instance).__name__
        result = test_instance.run()
        if result == False:

R test/service-desktop-test/test.py => test/service-desktop-test/test_api.py +0 -0
A test/service-desktop-test/tests/__init__.py => test/service-desktop-test/tests/__init__.py +9 -0
@@ 0,0 1,9 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

import sys, os, inspect
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
parent2dir = os.path.dirname(parentdir)
sys.path.insert(0, parentdir)
sys.path.insert(0, parent2dir)

M test/service-desktop-test/tests/backup.py => test/service-desktop-test/tests/backup.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class BackupTest:

M test/service-desktop-test/tests/calllog.py => test/service-desktop-test/tests/calllog.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class CalllogTest:

M test/service-desktop-test/tests/contacts.py => test/service-desktop-test/tests/contacts.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class ContactTest:

M test/service-desktop-test/tests/developerMode.py => test/service-desktop-test/tests/developerMode.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *
import time



M test/service-desktop-test/tests/deviceinfo.py => test/service-desktop-test/tests/deviceinfo.py +3 -2
@@ 1,8 1,9 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

from interface.defs import *
from test import *
from harness.interface.defs import endpoint, method, status

from test_api import *


class DeviceInfoTest:

M test/service-desktop-test/tests/factoryReset.py => test/service-desktop-test/tests/factoryReset.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class FactoryResetTest:

M test/service-desktop-test/tests/messages.py => test/service-desktop-test/tests/messages.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

from interface.defs import *
from test import *
from harness.interface.defs import endpoint, method, status
from test_api import *


class MessageTest:

M test/service-desktop-test/tests/templates.py => test/service-desktop-test/tests/templates.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class MessageTemplateTest:

M test/service-desktop-test/tests/update.py => test/service-desktop-test/tests/update.py +2 -2
@@ 1,8 1,8 @@
# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
from harness.interface.defs import endpoint, method, status

from interface.defs import *
from test import *
from test_api import *


class UpdateTest:

A test/test.py => test/test.py +31 -0
@@ 0,0 1,31 @@
#!/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
from harness.harness import Harness
from harness.interface.defs import key_codes


def main():
    if len(sys.argv) == 1 or sys.argv[1] is None:
        print('Please pass port name as the parameter: python test.py /dev/ttyACM0 ')
        exit(1)

    test = Harness(sys.argv[1])

    print(test.connection.get_window())

    @test.with_phone_unlocked
    def decorator_test(connection):
        # enter menu
        connection.send_key(key_codes["enter"])

    print(test.connection.get_window())

    test.open_application("settings")
    print(test.connection.get_window())


if __name__ == "__main__":
    main()