1# Copyright (c) 2023 Nordic Semiconductor ASA 2# 3# SPDX-License-Identifier: Apache-2.0 4 5from __future__ import annotations 6 7import logging 8import os 9 10import pytest 11 12from twister_harness.twister_harness_config import TwisterHarnessConfig 13 14logger = logging.getLogger(__name__) 15 16pytest_plugins = ( 17 'twister_harness.fixtures' 18) 19 20 21def pytest_addoption(parser: pytest.Parser): 22 twister_harness_group = parser.getgroup('Twister harness') 23 twister_harness_group.addoption( 24 '--twister-harness', 25 action='store_true', 26 default=False, 27 help='Activate Twister harness plugin.' 28 ) 29 parser.addini( 30 'twister_harness', 31 'Activate Twister harness plugin', 32 type='bool' 33 ) 34 twister_harness_group.addoption( 35 '--base-timeout', 36 type=float, 37 default=60.0, 38 help='Set base timeout (in seconds) used during monitoring if some ' 39 'operations are finished in a finite amount of time.' 40 ) 41 twister_harness_group.addoption( 42 '--flash-timeout', 43 type=float, 44 default=60.0, 45 help='Set timeout for device flashing (in seconds).' 46 ) 47 twister_harness_group.addoption( 48 '--build-dir', 49 metavar='PATH', 50 help='Directory with built application.' 51 ) 52 twister_harness_group.addoption( 53 '--device-type', 54 choices=('native', 'qemu', 'hardware', 'unit', 'custom'), 55 help='Choose type of device (hardware, qemu, etc.).' 56 ) 57 twister_harness_group.addoption( 58 '--platform', 59 help='Name of used platform (qemu_x86, nrf52840dk/nrf52840, etc.).' 60 ) 61 twister_harness_group.addoption( 62 '--device-serial', 63 help='Serial device for accessing the board (e.g., /dev/ttyACM0).' 64 ) 65 twister_harness_group.addoption( 66 '--device-serial-baud', 67 type=int, 68 default=115200, 69 help='Serial device baud rate (default 115200).' 70 ) 71 twister_harness_group.addoption( 72 '--runner', 73 help='Use the specified west runner (pyocd, nrfjprog, etc.).' 74 ) 75 twister_harness_group.addoption( 76 '--runner-params', 77 action='append', 78 help='Use the specified west runner params.' 79 ) 80 twister_harness_group.addoption( 81 '--device-id', 82 help='ID of connected hardware device (for example 000682459367).' 83 ) 84 twister_harness_group.addoption( 85 '--device-product', 86 help='Product name of connected hardware device (e.g. "STM32 STLink").' 87 ) 88 twister_harness_group.addoption( 89 '--device-serial-pty', 90 help='Script for controlling pseudoterminal.' 91 ) 92 twister_harness_group.addoption( 93 '--flash-before', 94 type=bool, 95 help='Flash device before attaching to serial port' 96 'This is useful for devices that share the same port for programming' 97 'and serial console, or use soft-USB, where flash must come first.' 98 ) 99 twister_harness_group.addoption( 100 '--west-flash-extra-args', 101 help='Extend parameters for west flash. ' 102 'E.g. --west-flash-extra-args="--board-id=foobar,--erase" ' 103 'will translate to "west flash -- --board-id=foobar --erase".' 104 ) 105 twister_harness_group.addoption( 106 '--pre-script', 107 metavar='PATH', 108 help='Script executed before flashing and connecting to serial.' 109 ) 110 twister_harness_group.addoption( 111 '--post-flash-script', 112 metavar='PATH', 113 help='Script executed after flashing.' 114 ) 115 twister_harness_group.addoption( 116 '--post-script', 117 metavar='PATH', 118 help='Script executed after closing serial connection.' 119 ) 120 twister_harness_group.addoption( 121 '--dut-scope', 122 choices=('function', 'class', 'module', 'package', 'session'), 123 help='The scope for which `dut` and `shell` fixtures are shared.' 124 ) 125 twister_harness_group.addoption( 126 '--twister-fixture', action='append', dest='fixtures', metavar='FIXTURE', default=[], 127 help='Twister fixture supported by this platform. May be given multiple times.' 128 ) 129 twister_harness_group.addoption( 130 '--extra-test-args', 131 help='Additional args passed to the test binary' 132 ) 133 134 135def pytest_configure(config: pytest.Config): 136 if config.getoption('help'): 137 return 138 139 if not (config.getoption('twister_harness') or config.getini('twister_harness')): 140 return 141 142 _normalize_paths(config) 143 _validate_options(config) 144 145 config.twister_harness_config = TwisterHarnessConfig.create(config) # type: ignore 146 147 148def _validate_options(config: pytest.Config) -> None: 149 if not config.option.build_dir: 150 raise Exception('--build-dir has to be provided') 151 if not os.path.isdir(config.option.build_dir): 152 raise Exception(f'Provided --build-dir does not exist: {config.option.build_dir}') 153 if not config.option.device_type: 154 raise Exception('--device-type has to be provided') 155 156 157def _normalize_paths(config: pytest.Config) -> None: 158 """Normalize paths provided by user via CLI""" 159 config.option.build_dir = _normalize_path(config.option.build_dir) 160 config.option.pre_script = _normalize_path(config.option.pre_script) 161 config.option.post_script = _normalize_path(config.option.post_script) 162 config.option.post_flash_script = _normalize_path(config.option.post_flash_script) 163 164 165def _normalize_path(path: str | None) -> str: 166 if path is not None: 167 path = os.path.expanduser(os.path.expandvars(path)) 168 path = os.path.normpath(os.path.abspath(path)) 169 return path 170