Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 1 | # Copyright lowRISC contributors. |
| 2 | # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| 3 | # SPDX-License-Identifier: Apache-2.0 |
| 4 | |
| 5 | import logging |
| 6 | import os |
| 7 | import shutil |
| 8 | import subprocess |
| 9 | from pathlib import Path |
| 10 | |
| 11 | import pytest |
| 12 | import yaml |
| 13 | |
| 14 | |
| 15 | def pytest_addoption(parser): |
| 16 | """Test harness configuration options.""" |
| 17 | parser.addoption("--test_bin", action="store", default="") |
| 18 | parser.addoption("--rom_bin", action="store", default="") |
| 19 | parser.addoption("--verilator_model", action="store", default="") |
| 20 | parser.addoption("--openocd", action="store", default="openocd") |
Miguel Young de la Sota | 04c8152 | 2019-10-14 13:27:19 -0500 | [diff] [blame] | 21 | parser.addoption("--uart_timeout", action="store", default="60") |
Miguel Young de la Sota | 8a0c2cb | 2019-10-21 12:45:50 -0500 | [diff] [blame] | 22 | parser.addoption("--fpga_uart", action="store", default="") |
| 23 | parser.addoption("--spiflash", action="store", default="") |
Timothy Chen | 0726964 | 2019-11-05 15:05:11 -0800 | [diff] [blame] | 24 | parser.addoption("--log", action="store", default="") |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 25 | |
| 26 | @pytest.hookimpl(tryfirst=True) |
| 27 | def pytest_exception_interact(node, call, report): |
| 28 | """Dump all log files in case of a test failure.""" |
| 29 | try: |
| 30 | if not report.failed: |
| 31 | return |
Philipp Wagner | 416770c | 2019-12-02 18:17:23 +0000 | [diff] [blame] | 32 | if not 'tmp_path' in node.funcargs: |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 33 | return |
| 34 | except: |
| 35 | return |
| 36 | |
Philipp Wagner | 416770c | 2019-12-02 18:17:23 +0000 | [diff] [blame] | 37 | tmp_path = str(node.funcargs['tmp_path']) |
Greg Chadwick | 941be0f | 2020-04-21 14:31:04 +0100 | [diff] [blame] | 38 | logging.debug("================= DUMP OF ALL TEMPORARY FILES =================") |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 39 | |
Philipp Wagner | 416770c | 2019-12-02 18:17:23 +0000 | [diff] [blame] | 40 | for f in os.listdir(tmp_path): |
| 41 | f_abs = os.path.join(tmp_path, f) |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 42 | if not os.path.isfile(f_abs): |
| 43 | continue |
Greg Chadwick | 941be0f | 2020-04-21 14:31:04 +0100 | [diff] [blame] | 44 | logging.debug("vvvvvvvvvvvvvvvvvvvv {} vvvvvvvvvvvvvvvvvvvv".format(f)) |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 45 | with open(f_abs, 'r') as fp: |
Greg Chadwick | 941be0f | 2020-04-21 14:31:04 +0100 | [diff] [blame] | 46 | for line in fp.readlines(): |
| 47 | logging.debug(line.rstrip()) |
| 48 | logging.debug("^^^^^^^^^^^^^^^^^^^^ {} ^^^^^^^^^^^^^^^^^^^^".format(f)) |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 49 | |
| 50 | |
| 51 | @pytest.fixture(scope="session") |
| 52 | def localconf(request): |
| 53 | """Host-local configuration.""" |
| 54 | if os.getenv('OPENTITAN_TEST_LOCALCONF') and os.path.isfile( |
| 55 | os.environ['OPENTITAN_TEST_LOCALCONF']): |
| 56 | localconf_yaml_file = os.environ['OPENTITAN_TEST_LOCALCONF'] |
| 57 | else: |
| 58 | XDG_CONFIG_HOME = os.getenv( |
| 59 | 'XDG_CONFIG_HOME', os.path.join(os.environ['HOME'], '.config')) |
| 60 | localconf_yaml_file = os.path.join(XDG_CONFIG_HOME, 'opentitan', |
| 61 | 'test-localconf.yaml') |
| 62 | logging.getLogger(__name__).info('Reading configuration from ' + |
| 63 | localconf_yaml_file) |
| 64 | |
| 65 | with open(str(localconf_yaml_file), 'r') as fp: |
| 66 | return yaml.load(fp) |
| 67 | |
| 68 | |
| 69 | @pytest.fixture(scope="session") |
| 70 | def topsrcdir(request): |
| 71 | """Return the top-level source directory as Path object.""" |
| 72 | # TODO: Consider making this configurable using a pytest arg. |
Miguel Young de la Sota | 7a363d0 | 2019-10-21 16:35:20 -0500 | [diff] [blame] | 73 | path = (Path(os.path.dirname(__file__)) / '..' / '..').resolve() |
| 74 | assert path.is_dir() |
| 75 | return path |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 76 | |
| 77 | |
| 78 | @pytest.fixture(scope="session") |
| 79 | def sw_test_bin(pytestconfig): |
| 80 | """Return path to software test binary.""" |
Miguel Young de la Sota | 7a363d0 | 2019-10-21 16:35:20 -0500 | [diff] [blame] | 81 | path = Path(pytestconfig.getoption('test_bin')).resolve() |
| 82 | assert path.is_file() |
| 83 | return path |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 84 | |
| 85 | @pytest.fixture(scope="session") |
| 86 | def rom_bin(pytestconfig): |
| 87 | """Return path to boot_rom binary.""" |
Miguel Young de la Sota | 7a363d0 | 2019-10-21 16:35:20 -0500 | [diff] [blame] | 88 | path = Path(pytestconfig.getoption('rom_bin')).resolve() |
| 89 | assert path.is_file() |
| 90 | return path |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 91 | |
| 92 | |
| 93 | @pytest.fixture(scope="session") |
| 94 | def sim_top_build(pytestconfig): |
| 95 | """Return path to Verilator sim model.""" |
Miguel Young de la Sota | 7a363d0 | 2019-10-21 16:35:20 -0500 | [diff] [blame] | 96 | path = Path(pytestconfig.getoption('verilator_model')).resolve() |
| 97 | assert path.is_file() |
| 98 | return path |
Miguel Osorio | 9a8e4b8 | 2019-09-25 07:58:24 -0700 | [diff] [blame] | 99 | |
| 100 | |
| 101 | @pytest.fixture(scope="session") |
| 102 | def openocd(pytestconfig): |
| 103 | """Return path to OpenOCD executable.""" |
Miguel Young de la Sota | e7d8643 | 2019-10-23 10:39:07 -0500 | [diff] [blame] | 104 | path = Path(pytestconfig.getoption('openocd')) |
| 105 | # TODO: Require that the OpenOCD executable be passed as a command-line |
| 106 | # argument in the future, rather than relying on $PATH lookup. |
| 107 | # assert path.is_file() |
Miguel Young de la Sota | 7a363d0 | 2019-10-21 16:35:20 -0500 | [diff] [blame] | 108 | return path |
Miguel Young de la Sota | 04c8152 | 2019-10-14 13:27:19 -0500 | [diff] [blame] | 109 | |
| 110 | @pytest.fixture(scope="session") |
| 111 | def uart_timeout(pytestconfig): |
| 112 | """Return the timeout in seconds for UART to print PASS.""" |
| 113 | return int(pytestconfig.getoption('uart_timeout')) |
Miguel Young de la Sota | 8a0c2cb | 2019-10-21 12:45:50 -0500 | [diff] [blame] | 114 | |
| 115 | @pytest.fixture(scope="session") |
| 116 | def fpga_uart(pytestconfig): |
| 117 | """Return the path to the UART attached to the FPGA.""" |
| 118 | path = Path(pytestconfig.getoption('fpga_uart')).resolve() |
Timothy Chen | 4dda5f0 | 2019-10-29 17:17:05 -0700 | [diff] [blame] | 119 | assert path.exists() and not path.is_dir() |
Miguel Young de la Sota | 8a0c2cb | 2019-10-21 12:45:50 -0500 | [diff] [blame] | 120 | return path |
| 121 | |
| 122 | @pytest.fixture(scope="session") |
| 123 | def spiflash(pytestconfig): |
| 124 | """Return the path to the spiflash executable.""" |
| 125 | path = Path(pytestconfig.getoption('spiflash')).resolve() |
| 126 | assert path.is_file() |
| 127 | return path |
Timothy Chen | 0726964 | 2019-11-05 15:05:11 -0800 | [diff] [blame] | 128 | |
| 129 | @pytest.fixture(scope="session") |
| 130 | def logfile(pytestconfig): |
| 131 | """Return path to logfile.""" |
| 132 | log = pytestconfig.getoption('log') |
| 133 | if not log: |
| 134 | return |
Timothy Chen | 7d1436d | 2019-12-04 17:26:14 -0800 | [diff] [blame] | 135 | # The strict option is only availabe on python 3.6 |
| 136 | # CI currently uses >=3.5.2 |
| 137 | # Turns out however even not using resolve doesn't work. |
| 138 | # The logging function in 3.5 uses os.path.isabs to check whether |
| 139 | # path is absolute and does not accept POSIXPATH objects |
| 140 | # path = Path(log).resolve(strict=False) |
| 141 | # assert not path.is_dir() |
| 142 | |
| 143 | path = os.path.abspath(log) |
| 144 | assert not os.path.isdir(path) |
Timothy Chen | 0726964 | 2019-11-05 15:05:11 -0800 | [diff] [blame] | 145 | return path |