summaryrefslogtreecommitdiff
path: root/test/run_device_tests.py
diff options
context:
space:
mode:
authorJeremy Bettis <jbettis@google.com>2022-07-08 10:58:19 -0600
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-07-12 19:13:33 +0000
commit7540e7b47b55447475bb8191fb3520dd67cf7998 (patch)
tree13309dbcf1db48e60fa2c2e5aed79f63bce00b5e /test/run_device_tests.py
parent7c114b8e1a3bb29991da70b9de394ac5d4f6c909 (diff)
downloadchrome-ec-7540e7b47b55447475bb8191fb3520dd67cf7998.tar.gz
ec: Format all python files with black and isort
find . \( -path ./private -prune \) -o -name '*.py' -print | xargs black find . \( -path ./private -prune \) -o -name '*.py' -print | xargs ~/chromiumos/chromite/scripts/isort --settings-file=.isort.cfg BRANCH=None BUG=b:238434058 TEST=None Signed-off-by: Jeremy Bettis <jbettis@google.com> Change-Id: I63462d6f15d1eaf3db84eb20d1404ee976be8382 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3749242 Commit-Queue: Jeremy Bettis <jbettis@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org> Tested-by: Jeremy Bettis <jbettis@chromium.org> Commit-Queue: Jack Rosenthal <jrosenth@chromium.org> Auto-Submit: Jeremy Bettis <jbettis@chromium.org> Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
Diffstat (limited to 'test/run_device_tests.py')
-rwxr-xr-xtest/run_device_tests.py543
1 files changed, 310 insertions, 233 deletions
diff --git a/test/run_device_tests.py b/test/run_device_tests.py
index 8de2fa417c..09f255f43e 100755
--- a/test/run_device_tests.py
+++ b/test/run_device_tests.py
@@ -51,63 +51,74 @@ import time
from concurrent.futures.thread import ThreadPoolExecutor
from enum import Enum
from pathlib import Path
-from typing import Optional, BinaryIO, List
+from typing import BinaryIO, List, Optional
# pylint: disable=import-error
import colorama # type: ignore[import]
-from contextlib2 import ExitStack
import fmap
+from contextlib2 import ExitStack
+
# pylint: enable=import-error
EC_DIR = Path(os.path.dirname(os.path.realpath(__file__))).parent
-JTRACE_FLASH_SCRIPT = os.path.join(EC_DIR, 'util/flash_jlink.py')
-SERVO_MICRO_FLASH_SCRIPT = os.path.join(EC_DIR, 'util/flash_ec')
+JTRACE_FLASH_SCRIPT = os.path.join(EC_DIR, "util/flash_jlink.py")
+SERVO_MICRO_FLASH_SCRIPT = os.path.join(EC_DIR, "util/flash_ec")
-ALL_TESTS_PASSED_REGEX = re.compile(r'Pass!\r\n')
-ALL_TESTS_FAILED_REGEX = re.compile(r'Fail! \(\d+ tests\)\r\n')
+ALL_TESTS_PASSED_REGEX = re.compile(r"Pass!\r\n")
+ALL_TESTS_FAILED_REGEX = re.compile(r"Fail! \(\d+ tests\)\r\n")
-SINGLE_CHECK_PASSED_REGEX = re.compile(r'Pass: .*')
-SINGLE_CHECK_FAILED_REGEX = re.compile(r'.*failed:.*')
+SINGLE_CHECK_PASSED_REGEX = re.compile(r"Pass: .*")
+SINGLE_CHECK_FAILED_REGEX = re.compile(r".*failed:.*")
-ASSERTION_FAILURE_REGEX = re.compile(r'ASSERTION FAILURE.*')
+ASSERTION_FAILURE_REGEX = re.compile(r"ASSERTION FAILURE.*")
DATA_ACCESS_VIOLATION_8020000_REGEX = re.compile(
- r'Data access violation, mfar = 8020000\r\n')
+ r"Data access violation, mfar = 8020000\r\n"
+)
DATA_ACCESS_VIOLATION_8040000_REGEX = re.compile(
- r'Data access violation, mfar = 8040000\r\n')
+ r"Data access violation, mfar = 8040000\r\n"
+)
DATA_ACCESS_VIOLATION_80C0000_REGEX = re.compile(
- r'Data access violation, mfar = 80c0000\r\n')
+ r"Data access violation, mfar = 80c0000\r\n"
+)
DATA_ACCESS_VIOLATION_80E0000_REGEX = re.compile(
- r'Data access violation, mfar = 80e0000\r\n')
+ r"Data access violation, mfar = 80e0000\r\n"
+)
DATA_ACCESS_VIOLATION_20000000_REGEX = re.compile(
- r'Data access violation, mfar = 20000000\r\n')
+ r"Data access violation, mfar = 20000000\r\n"
+)
DATA_ACCESS_VIOLATION_24000000_REGEX = re.compile(
- r'Data access violation, mfar = 24000000\r\n')
+ r"Data access violation, mfar = 24000000\r\n"
+)
-BLOONCHIPPER = 'bloonchipper'
-DARTMONKEY = 'dartmonkey'
+BLOONCHIPPER = "bloonchipper"
+DARTMONKEY = "dartmonkey"
-JTRACE = 'jtrace'
-SERVO_MICRO = 'servo_micro'
+JTRACE = "jtrace"
+SERVO_MICRO = "servo_micro"
-GCC = 'gcc'
-CLANG = 'clang'
+GCC = "gcc"
+CLANG = "clang"
-TEST_ASSETS_BUCKET = 'gs://chromiumos-test-assets-public/fpmcu/RO'
+TEST_ASSETS_BUCKET = "gs://chromiumos-test-assets-public/fpmcu/RO"
DARTMONKEY_IMAGE_PATH = os.path.join(
- TEST_ASSETS_BUCKET, 'dartmonkey_v2.0.2887-311310808.bin')
+ TEST_ASSETS_BUCKET, "dartmonkey_v2.0.2887-311310808.bin"
+)
NOCTURNE_FP_IMAGE_PATH = os.path.join(
- TEST_ASSETS_BUCKET, 'nocturne_fp_v2.2.64-58cf5974e.bin')
-NAMI_FP_IMAGE_PATH = os.path.join(
- TEST_ASSETS_BUCKET, 'nami_fp_v2.2.144-7a08e07eb.bin')
+ TEST_ASSETS_BUCKET, "nocturne_fp_v2.2.64-58cf5974e.bin"
+)
+NAMI_FP_IMAGE_PATH = os.path.join(TEST_ASSETS_BUCKET, "nami_fp_v2.2.144-7a08e07eb.bin")
BLOONCHIPPER_V4277_IMAGE_PATH = os.path.join(
- TEST_ASSETS_BUCKET, 'bloonchipper_v2.0.4277-9f652bb3.bin')
+ TEST_ASSETS_BUCKET, "bloonchipper_v2.0.4277-9f652bb3.bin"
+)
BLOONCHIPPER_V5938_IMAGE_PATH = os.path.join(
- TEST_ASSETS_BUCKET, 'bloonchipper_v2.0.5938-197506c1.bin')
+ TEST_ASSETS_BUCKET, "bloonchipper_v2.0.5938-197506c1.bin"
+)
class ImageType(Enum):
"""EC Image type to use for the test."""
+
RO = 1
RW = 2
@@ -115,9 +126,16 @@ class ImageType(Enum):
class BoardConfig:
"""Board-specific configuration."""
- def __init__(self, name, servo_uart_name, servo_power_enable,
- rollback_region0_regex, rollback_region1_regex, mpu_regex,
- variants):
+ def __init__(
+ self,
+ name,
+ servo_uart_name,
+ servo_power_enable,
+ rollback_region0_regex,
+ rollback_region1_regex,
+ mpu_regex,
+ variants,
+ ):
self.name = name
self.servo_uart_name = servo_uart_name
self.servo_power_enable = servo_power_enable
@@ -130,18 +148,31 @@ class BoardConfig:
class TestConfig:
"""Configuration for a given test."""
- def __init__(self, test_name, image_to_use=ImageType.RW,
- finish_regexes=None, fail_regexes=None, toggle_power=False,
- test_args=None, num_flash_attempts=2, timeout_secs=10,
- enable_hw_write_protect=False, ro_image=None, build_board=None,
- config_name=None):
+ def __init__(
+ self,
+ test_name,
+ image_to_use=ImageType.RW,
+ finish_regexes=None,
+ fail_regexes=None,
+ toggle_power=False,
+ test_args=None,
+ num_flash_attempts=2,
+ timeout_secs=10,
+ enable_hw_write_protect=False,
+ ro_image=None,
+ build_board=None,
+ config_name=None,
+ ):
if test_args is None:
test_args = []
if finish_regexes is None:
finish_regexes = [ALL_TESTS_PASSED_REGEX, ALL_TESTS_FAILED_REGEX]
if fail_regexes is None:
- fail_regexes = [SINGLE_CHECK_FAILED_REGEX, ALL_TESTS_FAILED_REGEX,
- ASSERTION_FAILURE_REGEX]
+ fail_regexes = [
+ SINGLE_CHECK_FAILED_REGEX,
+ ALL_TESTS_FAILED_REGEX,
+ ASSERTION_FAILURE_REGEX,
+ ]
if config_name is None:
config_name = test_name
@@ -177,68 +208,104 @@ class AllTests:
@staticmethod
def get_public_tests(board_config: BoardConfig) -> List[TestConfig]:
tests = [
- TestConfig(test_name='aes'),
- TestConfig(test_name='cec'),
- TestConfig(test_name='cortexm_fpu'),
- TestConfig(test_name='crc'),
- TestConfig(test_name='flash_physical', image_to_use=ImageType.RO,
- toggle_power=True),
- TestConfig(test_name='flash_write_protect',
- image_to_use=ImageType.RO,
- toggle_power=True, enable_hw_write_protect=True),
- TestConfig(test_name='fpsensor_hw'),
- TestConfig(config_name='fpsensor_spi_ro', test_name='fpsensor',
- image_to_use=ImageType.RO, test_args=['spi']),
- TestConfig(config_name='fpsensor_spi_rw', test_name='fpsensor',
- test_args=['spi']),
- TestConfig(config_name='fpsensor_uart_ro', test_name='fpsensor',
- image_to_use=ImageType.RO, test_args=['uart']),
- TestConfig(config_name='fpsensor_uart_rw', test_name='fpsensor',
- test_args=['uart']),
- TestConfig(config_name='mpu_ro', test_name='mpu',
- image_to_use=ImageType.RO,
- finish_regexes=[board_config.mpu_regex]),
- TestConfig(config_name='mpu_rw', test_name='mpu',
- finish_regexes=[board_config.mpu_regex]),
- TestConfig(test_name='mutex'),
- TestConfig(test_name='pingpong'),
- TestConfig(test_name='printf'),
- TestConfig(test_name='queue'),
- TestConfig(config_name='rollback_region0', test_name='rollback',
- finish_regexes=[board_config.rollback_region0_regex],
- test_args=['region0']),
- TestConfig(config_name='rollback_region1', test_name='rollback',
- finish_regexes=[board_config.rollback_region1_regex],
- test_args=['region1']),
- TestConfig(test_name='rollback_entropy', image_to_use=ImageType.RO),
- TestConfig(test_name='rtc'),
- TestConfig(test_name='sha256'),
- TestConfig(test_name='sha256_unrolled'),
- TestConfig(test_name='static_if'),
- TestConfig(test_name='stdlib'),
- TestConfig(config_name='system_is_locked_wp_on',
- test_name='system_is_locked', test_args=['wp_on'],
- toggle_power=True, enable_hw_write_protect=True),
- TestConfig(config_name='system_is_locked_wp_off',
- test_name='system_is_locked', test_args=['wp_off'],
- toggle_power=True, enable_hw_write_protect=False),
- TestConfig(test_name='timer_dos'),
- TestConfig(test_name='utils', timeout_secs=20),
- TestConfig(test_name='utils_str'),
+ TestConfig(test_name="aes"),
+ TestConfig(test_name="cec"),
+ TestConfig(test_name="cortexm_fpu"),
+ TestConfig(test_name="crc"),
+ TestConfig(
+ test_name="flash_physical", image_to_use=ImageType.RO, toggle_power=True
+ ),
+ TestConfig(
+ test_name="flash_write_protect",
+ image_to_use=ImageType.RO,
+ toggle_power=True,
+ enable_hw_write_protect=True,
+ ),
+ TestConfig(test_name="fpsensor_hw"),
+ TestConfig(
+ config_name="fpsensor_spi_ro",
+ test_name="fpsensor",
+ image_to_use=ImageType.RO,
+ test_args=["spi"],
+ ),
+ TestConfig(
+ config_name="fpsensor_spi_rw", test_name="fpsensor", test_args=["spi"]
+ ),
+ TestConfig(
+ config_name="fpsensor_uart_ro",
+ test_name="fpsensor",
+ image_to_use=ImageType.RO,
+ test_args=["uart"],
+ ),
+ TestConfig(
+ config_name="fpsensor_uart_rw", test_name="fpsensor", test_args=["uart"]
+ ),
+ TestConfig(
+ config_name="mpu_ro",
+ test_name="mpu",
+ image_to_use=ImageType.RO,
+ finish_regexes=[board_config.mpu_regex],
+ ),
+ TestConfig(
+ config_name="mpu_rw",
+ test_name="mpu",
+ finish_regexes=[board_config.mpu_regex],
+ ),
+ TestConfig(test_name="mutex"),
+ TestConfig(test_name="pingpong"),
+ TestConfig(test_name="printf"),
+ TestConfig(test_name="queue"),
+ TestConfig(
+ config_name="rollback_region0",
+ test_name="rollback",
+ finish_regexes=[board_config.rollback_region0_regex],
+ test_args=["region0"],
+ ),
+ TestConfig(
+ config_name="rollback_region1",
+ test_name="rollback",
+ finish_regexes=[board_config.rollback_region1_regex],
+ test_args=["region1"],
+ ),
+ TestConfig(test_name="rollback_entropy", image_to_use=ImageType.RO),
+ TestConfig(test_name="rtc"),
+ TestConfig(test_name="sha256"),
+ TestConfig(test_name="sha256_unrolled"),
+ TestConfig(test_name="static_if"),
+ TestConfig(test_name="stdlib"),
+ TestConfig(
+ config_name="system_is_locked_wp_on",
+ test_name="system_is_locked",
+ test_args=["wp_on"],
+ toggle_power=True,
+ enable_hw_write_protect=True,
+ ),
+ TestConfig(
+ config_name="system_is_locked_wp_off",
+ test_name="system_is_locked",
+ test_args=["wp_off"],
+ toggle_power=True,
+ enable_hw_write_protect=False,
+ ),
+ TestConfig(test_name="timer_dos"),
+ TestConfig(test_name="utils", timeout_secs=20),
+ TestConfig(test_name="utils_str"),
]
if board_config.name == BLOONCHIPPER:
- tests.append(TestConfig(test_name='stm32f_rtc'))
+ tests.append(TestConfig(test_name="stm32f_rtc"))
# Run panic data tests for all boards and RO versions.
for variant_name, variant_info in board_config.variants.items():
tests.append(
- TestConfig(config_name='panic_data_' + variant_name,
- test_name='panic_data',
- fail_regexes=[SINGLE_CHECK_FAILED_REGEX,
- ALL_TESTS_FAILED_REGEX],
- ro_image=variant_info.get('ro_image_path'),
- build_board=variant_info.get('build_board')))
+ TestConfig(
+ config_name="panic_data_" + variant_name,
+ test_name="panic_data",
+ fail_regexes=[SINGLE_CHECK_FAILED_REGEX, ALL_TESTS_FAILED_REGEX],
+ ro_image=variant_info.get("ro_image_path"),
+ build_board=variant_info.get("build_board"),
+ )
+ )
return tests
@@ -248,75 +315,72 @@ class AllTests:
tests = []
try:
current_dir = os.path.dirname(__file__)
- private_dir = os.path.join(current_dir, os.pardir, 'private/test')
+ private_dir = os.path.join(current_dir, os.pardir, "private/test")
have_private = os.path.isdir(private_dir)
if not have_private:
return []
sys.path.append(private_dir)
import private_tests # pylint: disable=import-error
+
for test_args in private_tests.tests:
tests.append(TestConfig(**test_args))
# Catch all exceptions to avoid disruptions in public repo
except BaseException as e:
- logging.debug('Failed to get list of private tests: %s', str(e))
- logging.debug('Ignore error and continue.')
+ logging.debug("Failed to get list of private tests: %s", str(e))
+ logging.debug("Ignore error and continue.")
return []
return tests
BLOONCHIPPER_CONFIG = BoardConfig(
name=BLOONCHIPPER,
- servo_uart_name='raw_fpmcu_console_uart_pty',
- servo_power_enable='fpmcu_pp3300',
+ servo_uart_name="raw_fpmcu_console_uart_pty",
+ servo_power_enable="fpmcu_pp3300",
rollback_region0_regex=DATA_ACCESS_VIOLATION_8020000_REGEX,
rollback_region1_regex=DATA_ACCESS_VIOLATION_8040000_REGEX,
mpu_regex=DATA_ACCESS_VIOLATION_20000000_REGEX,
variants={
- 'bloonchipper_v2.0.4277': {
- 'ro_image_path': BLOONCHIPPER_V4277_IMAGE_PATH
- },
- 'bloonchipper_v2.0.5938': {
- 'ro_image_path': BLOONCHIPPER_V5938_IMAGE_PATH
- }
- }
+ "bloonchipper_v2.0.4277": {"ro_image_path": BLOONCHIPPER_V4277_IMAGE_PATH},
+ "bloonchipper_v2.0.5938": {"ro_image_path": BLOONCHIPPER_V5938_IMAGE_PATH},
+ },
)
DARTMONKEY_CONFIG = BoardConfig(
name=DARTMONKEY,
- servo_uart_name='raw_fpmcu_console_uart_pty',
- servo_power_enable='fpmcu_pp3300',
+ servo_uart_name="raw_fpmcu_console_uart_pty",
+ servo_power_enable="fpmcu_pp3300",
rollback_region0_regex=DATA_ACCESS_VIOLATION_80C0000_REGEX,
rollback_region1_regex=DATA_ACCESS_VIOLATION_80E0000_REGEX,
mpu_regex=DATA_ACCESS_VIOLATION_24000000_REGEX,
# For dartmonkey board, run panic data test also on nocturne_fp and
# nami_fp boards with appropriate RO image.
variants={
- 'dartmonkey_v2.0.2887': {
- 'ro_image_path': DARTMONKEY_IMAGE_PATH
+ "dartmonkey_v2.0.2887": {"ro_image_path": DARTMONKEY_IMAGE_PATH},
+ "nocturne_fp_v2.2.64": {
+ "ro_image_path": NOCTURNE_FP_IMAGE_PATH,
+ "build_board": "nocturne_fp",
},
- 'nocturne_fp_v2.2.64': {
- 'ro_image_path': NOCTURNE_FP_IMAGE_PATH,
- 'build_board': 'nocturne_fp'
+ "nami_fp_v2.2.144": {
+ "ro_image_path": NAMI_FP_IMAGE_PATH,
+ "build_board": "nami_fp",
},
- 'nami_fp_v2.2.144': {
- 'ro_image_path': NAMI_FP_IMAGE_PATH,
- 'build_board': 'nami_fp'
- }
- }
+ },
)
BOARD_CONFIGS = {
- 'bloonchipper': BLOONCHIPPER_CONFIG,
- 'dartmonkey': DARTMONKEY_CONFIG,
+ "bloonchipper": BLOONCHIPPER_CONFIG,
+ "dartmonkey": DARTMONKEY_CONFIG,
}
def read_file_gsutil(path: str) -> bytes:
"""Get data from bucket, using gsutil tool"""
- cmd = ['gsutil', 'cat', path]
+ cmd = ["gsutil", "cat", path]
- logging.debug('Running command: "%s"', ' '.join(cmd))
- gsutil = subprocess.run(cmd, stdout=subprocess.PIPE) # pylint: disable=subprocess-run-check
+ logging.debug('Running command: "%s"', " ".join(cmd))
+ gsutil = subprocess.run(
+ cmd, stdout=subprocess.PIPE
+ ) # pylint: disable=subprocess-run-check
gsutil.check_returncode()
return gsutil.stdout
@@ -324,9 +388,9 @@ def read_file_gsutil(path: str) -> bytes:
def find_section_offset_size(section: str, image: bytes) -> (int, int):
"""Get offset and size of the section in image"""
- areas = fmap.fmap_decode(image)['areas']
- area = next(area for area in areas if area['name'] == section)
- return area['offset'], area['size']
+ areas = fmap.fmap_decode(image)["areas"]
+ area = next(area for area in areas if area["name"] == section)
+ return area["offset"], area["size"]
def read_section(src: bytes, section: str) -> bytes:
@@ -341,10 +405,10 @@ def write_section(data: bytes, image: bytearray, section: str):
(section_start, section_size) = find_section_offset_size(section, image)
if section_size < len(data):
- raise ValueError(section + ' section size is not enough to store data')
+ raise ValueError(section + " section size is not enough to store data")
section_end = section_start + section_size
- filling = bytes([0xff for _ in range(section_size - len(data))])
+ filling = bytes([0xFF for _ in range(section_size - len(data))])
image[section_start:section_end] = data + filling
@@ -355,12 +419,14 @@ def copy_section(src: bytes, dst: bytearray, section: str):
(dst_start, dst_size) = find_section_offset_size(section, dst)
if dst_size < src_size:
- raise ValueError('Section ' + section + ' from source image has '
- 'greater size than the section in destination image')
+ raise ValueError(
+ "Section " + section + " from source image has "
+ "greater size than the section in destination image"
+ )
src_end = src_start + src_size
dst_end = dst_start + dst_size
- filling = bytes([0xff for _ in range(dst_size - src_size)])
+ filling = bytes([0xFF for _ in range(dst_size - src_size)])
dst[dst_start:dst_end] = src[src_start:src_end] + filling
@@ -368,28 +434,28 @@ def copy_section(src: bytes, dst: bytearray, section: str):
def replace_ro(image: bytearray, ro: bytes):
"""Replace RO in image with provided one"""
# Backup RO public key since its private part was used to sign RW.
- ro_pubkey = read_section(image, 'KEY_RO')
+ ro_pubkey = read_section(image, "KEY_RO")
# Copy RO part of the firmware to the image. Please note that RO public key
# is copied too since EC_RO area includes KEY_RO area.
- copy_section(ro, image, 'EC_RO')
+ copy_section(ro, image, "EC_RO")
# Restore RO public key.
- write_section(ro_pubkey, image, 'KEY_RO')
+ write_section(ro_pubkey, image, "KEY_RO")
def get_console(board_config: BoardConfig) -> Optional[str]:
"""Get the name of the console for a given board."""
cmd = [
- 'dut-control',
+ "dut-control",
board_config.servo_uart_name,
]
- logging.debug('Running command: "%s"', ' '.join(cmd))
+ logging.debug('Running command: "%s"', " ".join(cmd))
with subprocess.Popen(cmd, stdout=subprocess.PIPE) as proc:
for line in io.TextIOWrapper(proc.stdout): # type: ignore[arg-type]
logging.debug(line)
- pty = line.split(':')
+ pty = line.split(":")
if len(pty) == 2 and pty[0] == board_config.servo_uart_name:
return pty[1].strip()
@@ -399,77 +465,82 @@ def get_console(board_config: BoardConfig) -> Optional[str]:
def power(board_config: BoardConfig, on: bool) -> None:
"""Turn power to board on/off."""
if on:
- state = 'pp3300'
+ state = "pp3300"
else:
- state = 'off'
+ state = "off"
cmd = [
- 'dut-control',
- board_config.servo_power_enable + ':' + state,
+ "dut-control",
+ board_config.servo_power_enable + ":" + state,
]
- logging.debug('Running command: "%s"', ' '.join(cmd))
+ logging.debug('Running command: "%s"', " ".join(cmd))
subprocess.run(cmd).check_returncode() # pylint: disable=subprocess-run-check
def hw_write_protect(enable: bool) -> None:
"""Enable/disable hardware write protect."""
if enable:
- state = 'force_on'
+ state = "force_on"
else:
- state = 'force_off'
+ state = "force_off"
cmd = [
- 'dut-control',
- 'fw_wp_state:' + state,
- ]
- logging.debug('Running command: "%s"', ' '.join(cmd))
+ "dut-control",
+ "fw_wp_state:" + state,
+ ]
+ logging.debug('Running command: "%s"', " ".join(cmd))
subprocess.run(cmd).check_returncode() # pylint: disable=subprocess-run-check
def build(test_name: str, board_name: str, compiler: str) -> None:
"""Build specified test for specified board."""
- cmd = ['make']
+ cmd = ["make"]
if compiler == CLANG:
- cmd = cmd + ['CC=arm-none-eabi-clang']
+ cmd = cmd + ["CC=arm-none-eabi-clang"]
cmd = cmd + [
- 'BOARD=' + board_name,
- 'test-' + test_name,
- '-j',
+ "BOARD=" + board_name,
+ "test-" + test_name,
+ "-j",
]
- logging.debug('Running command: "%s"', ' '.join(cmd))
+ logging.debug('Running command: "%s"', " ".join(cmd))
subprocess.run(cmd).check_returncode() # pylint: disable=subprocess-run-check
-def flash(image_path: str, board: str, flasher: str, remote_ip: str,
- remote_port: int) -> bool:
+def flash(
+ image_path: str, board: str, flasher: str, remote_ip: str, remote_port: int
+) -> bool:
"""Flash specified test to specified board."""
- logging.info('Flashing test')
+ logging.info("Flashing test")
cmd = []
if flasher == JTRACE:
cmd.append(JTRACE_FLASH_SCRIPT)
if remote_ip:
- cmd.extend(['--remote', remote_ip + ':' + str(remote_port)])
+ cmd.extend(["--remote", remote_ip + ":" + str(remote_port)])
elif flasher == SERVO_MICRO:
cmd.append(SERVO_MICRO_FLASH_SCRIPT)
else:
logging.error('Unknown flasher: "%s"', flasher)
return False
- cmd.extend([
- '--board', board,
- '--image', image_path,
- ])
- logging.debug('Running command: "%s"', ' '.join(cmd))
+ cmd.extend(
+ [
+ "--board",
+ board,
+ "--image",
+ image_path,
+ ]
+ )
+ logging.debug('Running command: "%s"', " ".join(cmd))
completed_process = subprocess.run(cmd) # pylint: disable=subprocess-run-check
return completed_process.returncode == 0
def patch_image(test: TestConfig, image_path: str):
"""Replace RO part of the firmware with provided one."""
- with open(image_path, 'rb+') as f:
+ with open(image_path, "rb+") as f:
image = bytearray(f.read())
ro = read_file_gsutil(test.ro_image)
replace_ro(image, ro)
@@ -478,8 +549,9 @@ def patch_image(test: TestConfig, image_path: str):
f.truncate()
-def readline(executor: ThreadPoolExecutor, f: BinaryIO, timeout_secs: int) -> \
- Optional[bytes]:
+def readline(
+ executor: ThreadPoolExecutor, f: BinaryIO, timeout_secs: int
+) -> Optional[bytes]:
"""Read a line with timeout."""
a = executor.submit(f.readline)
try:
@@ -488,8 +560,7 @@ def readline(executor: ThreadPoolExecutor, f: BinaryIO, timeout_secs: int) -> \
return None
-def readlines_until_timeout(executor, f: BinaryIO, timeout_secs: int) -> \
- List[bytes]:
+def readlines_until_timeout(executor, f: BinaryIO, timeout_secs: int) -> List[bytes]:
"""Continuously read lines for timeout_secs."""
lines: List[bytes] = []
while True:
@@ -519,19 +590,20 @@ def process_console_output_line(line: bytes, test: TestConfig):
return None
-def run_test(test: TestConfig, console: io.FileIO,
- executor: ThreadPoolExecutor) -> bool:
+def run_test(
+ test: TestConfig, console: io.FileIO, executor: ThreadPoolExecutor
+) -> bool:
"""Run specified test."""
start = time.time()
# Wait for boot to finish
time.sleep(1)
- console.write('\n'.encode())
+ console.write("\n".encode())
if test.image_to_use == ImageType.RO:
- console.write('reboot ro\n'.encode())
+ console.write("reboot ro\n".encode())
time.sleep(1)
- test_cmd = 'runtest ' + ' '.join(test.test_args) + '\n'
+ test_cmd = "runtest " + " ".join(test.test_args) + "\n"
console.write(test_cmd.encode())
while True:
@@ -540,7 +612,7 @@ def run_test(test: TestConfig, console: io.FileIO,
if not line:
now = time.time()
if now - start > test.timeout_secs:
- logging.debug('Test timed out')
+ logging.debug("Test timed out")
return False
continue
@@ -569,15 +641,18 @@ def run_test(test: TestConfig, console: io.FileIO,
def get_test_list(config: BoardConfig, test_args) -> List[TestConfig]:
"""Get a list of tests to run."""
- if test_args == 'all':
+ if test_args == "all":
return AllTests.get(config)
test_list = []
for t in test_args:
- logging.debug('test: %s', t)
+ logging.debug("test: %s", t)
test_regex = re.compile(t)
- tests = [test for test in AllTests.get(config)
- if test_regex.fullmatch(test.config_name)]
+ tests = [
+ test
+ for test in AllTests.get(config)
+ if test_regex.fullmatch(test.config_name)
+ ]
if not tests:
logging.error('Unable to find test config for "%s"', t)
sys.exit(1)
@@ -588,7 +663,7 @@ def get_test_list(config: BoardConfig, test_args) -> List[TestConfig]:
def parse_remote_arg(remote: str) -> str:
if not remote:
- return ''
+ return ""
try:
ip = socket.gethostbyname(remote)
@@ -601,67 +676,69 @@ def parse_remote_arg(remote: str) -> str:
def main():
parser = argparse.ArgumentParser()
- default_board = 'bloonchipper'
- parser.add_argument(
- '--board', '-b',
- help='Board (default: ' + default_board + ')',
- default=default_board)
-
- default_tests = 'all'
+ default_board = "bloonchipper"
parser.add_argument(
- '--tests', '-t',
- nargs='+',
- help='Tests (default: ' + default_tests + ')',
- default=default_tests)
+ "--board",
+ "-b",
+ help="Board (default: " + default_board + ")",
+ default=default_board,
+ )
- log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
+ default_tests = "all"
parser.add_argument(
- '--log_level', '-l',
- choices=log_level_choices,
- default='DEBUG'
+ "--tests",
+ "-t",
+ nargs="+",
+ help="Tests (default: " + default_tests + ")",
+ default=default_tests,
)
+ log_level_choices = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
+ parser.add_argument("--log_level", "-l", choices=log_level_choices, default="DEBUG")
+
flasher_choices = [SERVO_MICRO, JTRACE]
- parser.add_argument(
- '--flasher', '-f',
- choices=flasher_choices,
- default=JTRACE
- )
+ parser.add_argument("--flasher", "-f", choices=flasher_choices, default=JTRACE)
compiler_options = [GCC, CLANG]
- parser.add_argument('--compiler', '-c',
- choices=compiler_options,
- default=GCC)
+ parser.add_argument("--compiler", "-c", choices=compiler_options, default=GCC)
# This might be expanded to serve as a "remote" for flash_ec also, so
# we will leave it generic.
parser.add_argument(
- '--remote', '-n',
- help='The remote host connected to one or both of: J-Link and Servo.',
+ "--remote",
+ "-n",
+ help="The remote host connected to one or both of: J-Link and Servo.",
)
- parser.add_argument('--jlink_port', '-j',
- type=int,
- help='The port to use when connecting to JLink.')
- parser.add_argument('--console_port', '-p',
- type=int,
- help='The port connected to the FPMCU console.')
+ parser.add_argument(
+ "--jlink_port", "-j", type=int, help="The port to use when connecting to JLink."
+ )
+ parser.add_argument(
+ "--console_port",
+ "-p",
+ type=int,
+ help="The port connected to the FPMCU console.",
+ )
args = parser.parse_args()
logging.basicConfig(level=args.log_level)
if args.jlink_port and not args.flasher == JTRACE:
- logging.error('jlink_port specified, but flasher is not set to J-Link.')
+ logging.error("jlink_port specified, but flasher is not set to J-Link.")
sys.exit(1)
if args.remote and not (args.jlink_port or args.console_port):
- logging.error('jlink_port or console_port must be specified when using '
- 'the remote option.')
+ logging.error(
+ "jlink_port or console_port must be specified when using "
+ "the remote option."
+ )
sys.exit(1)
if (args.jlink_port or args.console_port) and not args.remote:
- logging.error('The remote option must be specified when using the '
- 'jlink_port or console_port options.')
+ logging.error(
+ "The remote option must be specified when using the "
+ "jlink_port or console_port options."
+ )
sys.exit(1)
if args.board not in BOARD_CONFIGS:
@@ -675,9 +752,7 @@ def main():
e = ThreadPoolExecutor(max_workers=1)
test_list = get_test_list(board_config, args.tests)
- logging.debug(
- 'Running tests: %s', [
- test.config_name for test in test_list])
+ logging.debug("Running tests: %s", [test.config_name for test in test_list])
for test in test_list:
build_board = args.board
@@ -689,15 +764,17 @@ def main():
# build test binary
build(test.test_name, build_board, args.compiler)
- image_path = os.path.join(EC_DIR, 'build', build_board, test.test_name,
- test.test_name + '.bin')
+ image_path = os.path.join(
+ EC_DIR, "build", build_board, test.test_name, test.test_name + ".bin"
+ )
if test.ro_image is not None:
try:
patch_image(test, image_path)
except Exception as exception:
- logging.warning('An exception occurred while patching '
- 'image: %s', exception)
+ logging.warning(
+ "An exception occurred while patching " "image: %s", exception
+ )
test.passed = False
continue
@@ -706,16 +783,16 @@ def main():
# flash_write_protect test is run; works after second attempt.
flash_succeeded = False
for i in range(0, test.num_flash_attempts):
- logging.debug('Flash attempt %d', i + 1)
- if flash(image_path, args.board, args.flasher, remote_ip,
- args.jlink_port):
+ logging.debug("Flash attempt %d", i + 1)
+ if flash(image_path, args.board, args.flasher, remote_ip, args.jlink_port):
flash_succeeded = True
break
time.sleep(1)
if not flash_succeeded:
- logging.debug('Flashing failed after max attempts: %d',
- test.num_flash_attempts)
+ logging.debug(
+ "Flashing failed after max attempts: %d", test.num_flash_attempts
+ )
test.passed = False
continue
@@ -733,11 +810,11 @@ def main():
if remote_ip and args.console_port:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((remote_ip, args.console_port))
- console = stack.enter_context(
- s.makefile(mode='rwb', buffering=0))
+ console = stack.enter_context(s.makefile(mode="rwb", buffering=0))
else:
console = stack.enter_context(
- open(get_console(board_config), 'wb+', buffering=0))
+ open(get_console(board_config), "wb+", buffering=0)
+ )
test.passed = run_test(test, console, executor=e)
@@ -745,11 +822,11 @@ def main():
exit_code = 0
for test in test_list:
# print results
- print('Test "' + test.config_name + '": ', end='')
+ print('Test "' + test.config_name + '": ', end="")
if test.passed:
- print(colorama.Fore.GREEN + 'PASSED')
+ print(colorama.Fore.GREEN + "PASSED")
else:
- print(colorama.Fore.RED + 'FAILED')
+ print(colorama.Fore.RED + "FAILED")
exit_code = 1
print(colorama.Style.RESET_ALL)
@@ -758,5 +835,5 @@ def main():
sys.exit(exit_code)
-if __name__ == '__main__':
+if __name__ == "__main__":
sys.exit(main())