1# Copyright (c) 2023 Nordic Semiconductor ASA 2# 3# SPDX-License-Identifier: Apache-2.0 4 5import logging 6from pathlib import Path 7from typing import Generator, Type 8 9import pytest 10import time 11 12from twister_harness.device.device_adapter import DeviceAdapter 13from twister_harness.device.factory import DeviceFactory 14from twister_harness.twister_harness_config import DeviceConfig, TwisterHarnessConfig 15from twister_harness.helpers.shell import Shell 16from twister_harness.helpers.mcumgr import MCUmgr 17from twister_harness.helpers.utils import find_in_config 18 19logger = logging.getLogger(__name__) 20 21 22@pytest.fixture(scope='session') 23def twister_harness_config(request: pytest.FixtureRequest) -> TwisterHarnessConfig: 24 """Return twister_harness_config object.""" 25 twister_harness_config: TwisterHarnessConfig = request.config.twister_harness_config # type: ignore 26 return twister_harness_config 27 28 29@pytest.fixture(scope='session') 30def device_object(twister_harness_config: TwisterHarnessConfig) -> Generator[DeviceAdapter, None, None]: 31 """Return device object - without run application.""" 32 device_config: DeviceConfig = twister_harness_config.devices[0] 33 device_type = device_config.type 34 device_class: Type[DeviceAdapter] = DeviceFactory.get_device(device_type) 35 device_object = device_class(device_config) 36 try: 37 yield device_object 38 finally: # to make sure we close all running processes execution 39 device_object.close() 40 41 42def determine_scope(fixture_name, config): 43 if dut_scope := config.getoption("--dut-scope", None): 44 return dut_scope 45 return 'function' 46 47 48@pytest.fixture(scope=determine_scope) 49def unlaunched_dut(request: pytest.FixtureRequest, device_object: DeviceAdapter) -> Generator[DeviceAdapter, None, None]: 50 """Return device object - with logs connected, but not run""" 51 device_object.initialize_log_files(request.node.name) 52 try: 53 yield device_object 54 finally: # to make sure we close all running processes execution 55 device_object.close() 56 57@pytest.fixture(scope=determine_scope) 58def dut(request: pytest.FixtureRequest, device_object: DeviceAdapter) -> Generator[DeviceAdapter, None, None]: 59 """Return launched device - with run application.""" 60 device_object.initialize_log_files(request.node.name) 61 try: 62 device_object.launch() 63 yield device_object 64 finally: # to make sure we close all running processes execution 65 device_object.close() 66 67 68@pytest.fixture(scope=determine_scope) 69def shell(dut: DeviceAdapter) -> Shell: 70 """Return ready to use shell interface""" 71 shell = Shell(dut, timeout=20.0) 72 if prompt := find_in_config(Path(dut.device_config.app_build_dir) / 'zephyr' / '.config', 73 'CONFIG_SHELL_PROMPT_UART'): 74 shell.prompt = prompt 75 logger.info('Wait for prompt') 76 if not shell.wait_for_prompt(): 77 pytest.fail('Prompt not found') 78 if dut.device_config.type == 'hardware': 79 # after booting up the device, there might appear additional logs 80 # after first prompt, so we need to wait and clear the buffer 81 time.sleep(0.5) 82 dut.clear_buffer() 83 return shell 84 85 86@pytest.fixture(scope='session') 87def is_mcumgr_available() -> None: 88 if not MCUmgr.is_available(): 89 pytest.skip('mcumgr not available') 90 91 92@pytest.fixture() 93def mcumgr(is_mcumgr_available: None, dut: DeviceAdapter) -> Generator[MCUmgr, None, None]: 94 yield MCUmgr.create_for_serial(dut.device_config.serial) 95