# Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. # For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md import time import pytest import sys import os.path sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir))) from harness import log from harness.harness import Harness from harness import utils from harness.interface.error import TestError, Error from harness.interface.CDCSerial import Keytype, CDCSerial as serial from harness.api.security import SetPhoneLockOff, GetPhoneLockStatus from harness.interface.defs import key_codes simulator_port = 'simulator' def pytest_addoption(parser): parser.addoption("--port", type=str, action="store", required=False) parser.addoption("--timeout", type=int, action="store", default=15) parser.addoption("--phone_number", type=int, action="store") parser.addoption("--call_duration", type=int, action="store", default=30) parser.addoption("--sms_text", type=str, action="store", default='') parser.addoption("--bt_device", type=str, action="store", default='') parser.addoption("--passcode", type=str, action="store", default='') parser.addoption("--update_file_path", type=str, action="store", default='') @pytest.fixture(scope='session') def phone_number(request): phone_number = request.config.option.phone_number assert phone_number return phone_number @pytest.fixture(scope='session') def passcode(request): passcode = request.config.option.passcode assert passcode return passcode @pytest.fixture(scope='session') def update_file_path(request): update_file_path = request.config.option.update_file_path assert update_file_path return update_file_path @pytest.fixture(scope='session') def call_duration(request): call_duration = request.config.option.call_duration assert call_duration return call_duration @pytest.fixture(scope='session') def sms_text(request): sms_text = request.config.option.sms_text assert sms_text != '' return sms_text @pytest.fixture(scope='session') def bt_device(request): bt_device = request.config.option.bt_device return bt_device @pytest.fixture(scope='session') def harness(request): ''' Try to init one Pure phone with serial port path or automatically ''' port_name = request.config.option.port TIMEOUT = request.config.option.timeout timeout_started = time.time() RETRY_EVERY_SECONDS = 1.0 try: if port_name is None: log.warning("no port provided! trying automatic detection") harness = None with utils.Timeout.limit(seconds=TIMEOUT): while not harness: try: harness = Harness.from_detect() except TestError as e: if e.get_error_code() == Error.PORT_NOT_FOUND: log.info(f"waiting for a serial port… ({TIMEOUT- int(time.time() - timeout_started)})") time.sleep(RETRY_EVERY_SECONDS) else: assert '/dev' in port_name or simulator_port in port_name if simulator_port in port_name: file = None with utils.Timeout.limit(seconds=TIMEOUT): while not file: try: file = open("/tmp/purephone_pts_name", "r") except FileNotFoundError as err: log.info( f"waiting for a simulator port… ({TIMEOUT- int(time.time() - timeout_started)})") time.sleep(RETRY_EVERY_SECONDS) port_name = file.readline() if port_name.isascii(): log.debug("found {} entry!".format(port_name)) else: pytest.exit("not a valid sim pts entry!") harness = Harness(port_name) ''' Wait for endpoints to initialize ''' testbody = {"ui": True, "getWindow": True} result = None with utils.Timeout.limit(seconds=305): while not result: try: result = harness.endpoint_request("developerMode", "get", testbody) except ValueError: log.info("Endpoints not ready..") except utils.Timeout: pytest.exit("couldn't find any viable port. exiting") else: return harness @pytest.fixture(scope='session') def harnesses(): ''' Automatically init at least two Pure phones ''' connected_devices = serial.find_Devices() harnesses = [Harness(device) for device in connected_devices] if not len(harnesses) >= 2: pytest.skip("At least two phones are needed for this test") assert len(harnesses) >= 2 return harnesses @pytest.fixture(scope='session') def phone_unlocked(harness): harness.unlock_phone() assert not harness.is_phone_locked() @pytest.fixture(scope='session') def phone_locked(harness): harness.lock_phone() assert harness.is_phone_locked() @pytest.fixture(scope='session') def phones_unlocked(harnesses): for harness in harnesses: harness.unlock_phone() assert not harness.is_phone_locked() @pytest.fixture(scope='session') def phone_in_desktop(harness): # go to desktop if harness.get_application_name() != "ApplicationDesktop": harness.connection.send_key_code(key_codes["fnRight"], Keytype.long_press) # in some cases we have to do it twice if harness.get_application_name() != "ApplicationDesktop": harness.connection.send_key_code(key_codes["fnRight"], Keytype.long_press) # assert that we are in ApplicationDesktop assert harness.get_application_name() == "ApplicationDesktop" @pytest.fixture(scope='function') def phone_ends_test_in_desktop(harness): yield target_application = "ApplicationDesktop" target_window = "MainWindow" log.info(f"returning to {target_window} of {target_application} ...") time.sleep(1) if harness.get_application_name() != target_application : body = {"switchApplication" : {"applicationName": target_application, "windowName" : target_window }} harness.endpoint_request("developerMode", "put", body) time.sleep(1) max_retry_counter = 5 while harness.get_application_name() != target_application: max_retry_counter -= 1 if max_retry_counter == 0: break log.info(f"Not in {target_application}, {max_retry_counter} attempts left...") time.sleep(1) else : # switching window in case ApplicationDesktop is not on MainWindow: body = {"switchWindow" : {"applicationName": target_application, "windowName" : target_window }} harness.endpoint_request("developerMode", "put", body) time.sleep(1) # assert that we are in ApplicationDesktop assert harness.get_application_name() == target_application time.sleep(1) @pytest.fixture(scope='session') def phone_security_unlocked(harness,passcode): for _ in range(2): try: GetPhoneLockStatus().run(harness) except TransactionError as e: log.info(f"transaction code: {e}") log.info("Phone security locked, unlocking") SetPhoneLockOff(passcode=passcode).run(harness) def pytest_configure(config): config.addinivalue_line("markers", "service_desktop_test: mark test if it's related to service-desktop API") config.addinivalue_line("markers", "rt1051: mark test if it's target only (eg. calls, messages)") config.addinivalue_line("markers", "usb_cdc_echo: mark test if it's intended for usb-cdc echo mode") config.addinivalue_line("markers", "two_sim_cards: mark test in case when two sim cards are required") config.addinivalue_line("markers", "backup: subset of backup user data tests") config.addinivalue_line("markers", "restore: subset of restore user data tests")