Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 1 | U-Boot pytest suite |
| 2 | =================== |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 3 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 4 | Introduction |
| 5 | ------------ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 6 | |
| 7 | This tool aims to test U-Boot by executing U-Boot shell commands using the |
| 8 | console interface. A single top-level script exists to execute or attach to the |
| 9 | U-Boot console, run the entire script of tests against it, and summarize the |
| 10 | results. Advantages of this approach are: |
| 11 | |
| 12 | - Testing is performed in the same way a user or script would interact with |
| 13 | U-Boot; there can be no disconnect. |
| 14 | - There is no need to write or embed test-related code into U-Boot itself. |
| 15 | It is asserted that writing test-related code in Python is simpler and more |
Simon Glass | fc32833 | 2021-03-07 17:35:17 -0700 | [diff] [blame] | 16 | flexible than writing it all in C. But see :doc:`tests_writing` for caveats |
| 17 | and more discussion / analysis. |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 18 | - It is reasonably simple to interact with U-Boot in this way. |
| 19 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 20 | Requirements |
| 21 | ------------ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 22 | |
| 23 | The test suite is implemented using pytest. Interaction with the U-Boot console |
| 24 | involves executing some binary and interacting with its stdin/stdout. You will |
| 25 | need to implement various "hook" scripts that are called by the test suite at |
| 26 | the appropriate time. |
| 27 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 28 | In order to run the test suite at a minimum we require that both Python 3 and |
| 29 | pip for Python 3 are installed. All of the required python modules are |
| 30 | described in the requirements.txt file in the /test/py/ directory and can be |
| 31 | installed via the command |
| 32 | |
| 33 | .. code-block:: bash |
| 34 | |
| 35 | pip install -r requirements.txt |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 36 | |
Tom Rini | ddaa8be | 2019-10-24 11:59:26 -0400 | [diff] [blame] | 37 | In order to execute certain tests on their supported platforms other tools |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 38 | will be required. The following is an incomplete list: |
Tom Rini | ddaa8be | 2019-10-24 11:59:26 -0400 | [diff] [blame] | 39 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 40 | * gdisk |
| 41 | * dfu-util |
| 42 | * dtc |
| 43 | * openssl |
| 44 | * sudo OR guestmount |
| 45 | * e2fsprogs |
| 46 | * util-linux |
| 47 | * coreutils |
| 48 | * dosfstools |
| 49 | * efitools |
Heinrich Schuchardt | 88991b9 | 2022-10-08 01:19:22 +0200 | [diff] [blame] | 50 | * guestfs-tools |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 51 | * mount |
| 52 | * mtools |
| 53 | * sbsigntool |
| 54 | * udisks2 |
AKASHI Takahiro | fe6ca4d | 2020-04-14 11:51:49 +0900 | [diff] [blame] | 55 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 56 | Please use the appropriate commands for your distribution to match these tools |
Tom Rini | ddaa8be | 2019-10-24 11:59:26 -0400 | [diff] [blame] | 57 | up with the package that provides them. |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 58 | |
| 59 | The test script supports either: |
| 60 | |
| 61 | - Executing a sandbox port of U-Boot on the local machine as a sub-process, |
| 62 | and interacting with it over stdin/stdout. |
| 63 | - Executing an external "hook" scripts to flash a U-Boot binary onto a |
| 64 | physical board, attach to the board's console stream, and reset the board. |
| 65 | Further details are described later. |
| 66 | |
Heinrich Schuchardt | 88991b9 | 2022-10-08 01:19:22 +0200 | [diff] [blame] | 67 | The usage of command 'sudo' should be avoided in tests. To create disk images |
| 68 | use command virt-make-fs which is provided by package guestfs-tools. This |
| 69 | command creates a virtual machine with QEMU in which the disk image is |
| 70 | generated. |
| 71 | |
| 72 | Command virt-make-fs needs read access to the current kernel. On Ubuntu only |
| 73 | root has this privilege. You can add a script /etc/initramfs-tools/hooks/vmlinuz |
| 74 | with the following content to overcome the problem: |
| 75 | |
| 76 | .. code-block:: bash |
| 77 | |
| 78 | #!/bin/sh |
| 79 | echo "chmod a+r vmlinuz-*" |
| 80 | chmod a+r /boot/vmlinuz-* |
| 81 | |
| 82 | The script should be chmod 755. It will be invoked whenever the initial RAM file |
| 83 | system is updated. |
| 84 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 85 | Using `virtualenv` to provide requirements |
| 86 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 87 | |
Tom Rini | ddaa8be | 2019-10-24 11:59:26 -0400 | [diff] [blame] | 88 | The recommended way to run the test suite, in order to ensure reproducibility |
| 89 | is to use `virtualenv` to set up the necessary environment. This can be done |
| 90 | via the following commands: |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 91 | |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 92 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 93 | .. code-block:: console |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 94 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 95 | $ cd /path/to/u-boot |
| 96 | $ sudo apt-get install python3 python3-virtualenv |
| 97 | $ virtualenv -p /usr/bin/python3 venv |
| 98 | $ . ./venv/bin/activate |
| 99 | $ pip install -r test/py/requirements.txt |
| 100 | |
| 101 | Testing sandbox |
| 102 | --------------- |
| 103 | |
| 104 | To run the test suite on the sandbox port (U-Boot built as a native user-space |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 105 | application), simply execute: |
| 106 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 107 | .. code-block:: bash |
| 108 | |
| 109 | ./test/py/test.py --bd sandbox --build |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 110 | |
| 111 | The `--bd` option tells the test suite which board type is being tested. This |
| 112 | lets the test suite know which features the board has, and hence exactly what |
| 113 | can be tested. |
| 114 | |
| 115 | The `--build` option tells U-Boot to compile U-Boot. Alternatively, you may |
| 116 | omit this option and build U-Boot yourself, in whatever way you choose, before |
| 117 | running the test script. |
| 118 | |
| 119 | The test script will attach to U-Boot, execute all valid tests for the board, |
| 120 | then print a summary of the test process. A complete log of the test session |
| 121 | will be written to `${build_dir}/test-log.html`. This is best viewed in a web |
| 122 | browser, but may be read directly as plain text, perhaps with the aid of the |
| 123 | `html2text` utility. |
| 124 | |
Simon Glass | 35839ed | 2021-10-08 09:15:23 -0600 | [diff] [blame] | 125 | If sandbox crashes (e.g. with a segfault) you will see message like this:: |
| 126 | |
| 127 | |
| 128 | test/py/u_boot_spawn.py:171: in expect |
| 129 | c = os.read(self.fd, 1024).decode(errors='replace') |
| 130 | E ValueError: U-Boot exited with signal 11 (Signals.SIGSEGV) |
| 131 | |
| 132 | |
Simon Glass | b04f64a | 2021-10-05 20:18:00 -0600 | [diff] [blame] | 133 | Controlling output |
| 134 | ~~~~~~~~~~~~~~~~~~ |
| 135 | |
| 136 | By default a short backtrace is reported. If you would like a longer one, |
| 137 | pass ``--tb=long`` when running the test. See the pytest documentation for |
| 138 | more options. |
| 139 | |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 140 | Running tests in parallel |
| 141 | ~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 142 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 143 | Note: Not all tests can run in parallel at present, so the usual approach is |
| 144 | to just run those that can. |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 145 | |
| 146 | First install support for parallel tests:: |
| 147 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 148 | sudo apt install python3-pytest-xdist |
| 149 | |
| 150 | or::: |
| 151 | |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 152 | pip3 install pytest-xdist |
| 153 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 154 | Then run the tests in parallel using the -n flag:: |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 155 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 156 | test/py/test.py -B sandbox --build --build-dir /tmp/b/sandbox -q -k \ |
| 157 | 'not slow and not bootstd and not spi_flash' -n16 |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 158 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 159 | You can also use `make pcheck` to run all tests in parallel. This uses a maximum |
| 160 | of 16 threads, since the setup time is significant and there are under 1000 |
| 161 | tests. |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 162 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 163 | Note that the `test-log.html` output does not work correctly at present with |
| 164 | parallel testing. All the threads write to it at once, so it is garbled. |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 165 | |
Simon Glass | d1962ac | 2022-08-06 17:51:59 -0600 | [diff] [blame] | 166 | Note that the `tools/` tests still run each tool's tests once after the other, |
| 167 | although within that, they do run in parallel. So for example, the buildman |
| 168 | tests run in parallel, then the binman tests run in parallel. There would be a |
| 169 | significant advantage to running them all in parallel together, but that would |
| 170 | require a large amount of refactoring, e.g. with more use of pytest fixtures. |
| 171 | The code-coverage tests are omitted since they cannot run in parallel due to a |
| 172 | Python limitation. |
Simon Glass | 5f8cefb | 2021-09-19 15:14:51 -0600 | [diff] [blame] | 173 | |
| 174 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 175 | Testing under a debugger |
| 176 | ~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 177 | |
| 178 | If you need to run sandbox under a debugger, you may pass the command-line |
| 179 | option `--gdbserver COMM`. This causes two things to happens: |
| 180 | |
| 181 | - Instead of running U-Boot directly, it will be run under gdbserver, with |
| 182 | debug communication via the channel `COMM`. You can attach a debugger to the |
| 183 | sandbox process in order to debug it. See `man gdbserver` and the example |
| 184 | below for details of valid values for `COMM`. |
| 185 | - All timeouts in tests are disabled, allowing U-Boot an arbitrary amount of |
| 186 | time to execute commands. This is useful if U-Boot is stopped at a breakpoint |
| 187 | during debugging. |
| 188 | |
| 189 | A usage example is: |
| 190 | |
| 191 | Window 1: |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 192 | |
| 193 | .. code-block:: bash |
| 194 | |
| 195 | ./test/py/test.py --bd sandbox --gdbserver localhost:1234 |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 196 | |
| 197 | Window 2: |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 198 | |
| 199 | .. code-block:: bash |
| 200 | |
| 201 | gdb ./build-sandbox/u-boot -ex 'target remote localhost:1234' |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 202 | |
| 203 | Alternatively, you could leave off the `-ex` option and type the command |
| 204 | manually into gdb once it starts. |
| 205 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 206 | You can use any debugger you wish, as long as it speaks the gdb remote |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 207 | protocol, or any graphical wrapper around gdb. |
| 208 | |
| 209 | Some tests deliberately cause the sandbox process to exit, e.g. to test the |
| 210 | reset command, or sandbox's CTRL-C handling. When this happens, you will need |
| 211 | to attach the debugger to the new sandbox instance. If these tests are not |
| 212 | relevant to your debugging session, you can skip them using pytest's -k |
| 213 | command-line option; see the next section. |
| 214 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 215 | Command-line options |
| 216 | -------------------- |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 217 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 218 | --board-type, --bd, -B |
| 219 | set the type of the board to be tested. For example, `sandbox` or `seaboard`. |
| 220 | |
| 221 | --board-identity`, --id |
| 222 | sets the identity of the board to be tested. This allows differentiation |
| 223 | between multiple instances of the same type of physical board that are |
| 224 | attached to the same host machine. This parameter is not interpreted by th |
| 225 | test script in any way, but rather is simply passed to the hook scripts |
| 226 | described below, and may be used in any site-specific way deemed necessary. |
| 227 | |
| 228 | --build |
| 229 | indicates that the test script should compile U-Boot itself before running |
| 230 | the tests. If using this option, make sure that any environment variables |
| 231 | required by the build process are already set, such as `$CROSS_COMPILE`. |
| 232 | |
| 233 | --buildman |
| 234 | indicates that `--build` should use buildman to build U-Boot. There is no need |
| 235 | to set $CROSS_COMPILE` in this case since buildman handles it. |
| 236 | |
| 237 | --build-dir |
| 238 | sets the directory containing the compiled U-Boot binaries. If omitted, this |
| 239 | is `${source_dir}/build-${board_type}`. |
| 240 | |
| 241 | --result-dir |
| 242 | sets the directory to write results, such as log files, into. |
| 243 | If omitted, the build directory is used. |
| 244 | |
| 245 | --persistent-data-dir |
| 246 | sets the directory used to store persistent test data. This is test data that |
| 247 | may be re-used across test runs, such as file-system images. |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 248 | |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 249 | `pytest` also implements a number of its own command-line options. Commonly used |
| 250 | options are mentioned below. Please see `pytest` documentation for complete |
| 251 | details. Execute `py.test --version` for a brief summary. Note that U-Boot's |
| 252 | test.py script passes all command-line arguments directly to `pytest` for |
| 253 | processing. |
| 254 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 255 | -k |
| 256 | selects which tests to run. The default is to run all known tests. This |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 257 | option takes a single argument which is used to filter test names. Simple |
| 258 | logical operators are supported. For example: |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 259 | |
| 260 | - `'-k ums'` runs only tests with "ums" in their name. |
| 261 | - `'-k ut_dm'` runs only tests with "ut_dm" in their name. Note that in this |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 262 | case, "ut_dm" is a parameter to a test rather than the test name. The full |
| 263 | test name is e.g. "test_ut[ut_dm_leak]". |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 264 | - `'-k not reset'` runs everything except tests with "reset" in their name. |
| 265 | - `'-k ut or hush'` runs only tests with "ut" or "hush" in their name. |
| 266 | - `'-k not (ut or hush)'` runs everything except tests with "ut" or "hush" in |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 267 | their name. |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 268 | |
| 269 | -s |
| 270 | prevents pytest from hiding a test's stdout. This allows you to see |
Stephen Warren | d70facf | 2016-02-08 14:49:02 -0700 | [diff] [blame] | 271 | U-Boot's console log in real time on pytest's stdout. |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 272 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 273 | Testing real hardware |
| 274 | --------------------- |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 275 | |
| 276 | The tools and techniques used to interact with real hardware will vary |
| 277 | radically between different host and target systems, and the whims of the user. |
| 278 | For this reason, the test suite does not attempt to directly interact with real |
| 279 | hardware in any way. Rather, it executes a standardized set of "hook" scripts |
| 280 | via `$PATH`. These scripts implement certain actions on behalf of the test |
| 281 | suite. This keeps the test suite simple and isolated from system variances |
| 282 | unrelated to U-Boot features. |
| 283 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 284 | Hook scripts |
| 285 | ~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 286 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 287 | Environment variables |
| 288 | ''''''''''''''''''''' |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 289 | |
| 290 | The following environment variables are set when running hook scripts: |
| 291 | |
| 292 | - `UBOOT_BOARD_TYPE` the board type being tested. |
| 293 | - `UBOOT_BOARD_IDENTITY` the board identity being tested, or `na` if none was |
| 294 | specified. |
| 295 | - `UBOOT_SOURCE_DIR` the U-Boot source directory. |
| 296 | - `UBOOT_TEST_PY_DIR` the full path to `test/py/` in the source directory. |
| 297 | - `UBOOT_BUILD_DIR` the U-Boot build directory. |
| 298 | - `UBOOT_RESULT_DIR` the test result directory. |
Masahiro Yamada | 3aca4a4 | 2017-10-19 19:08:52 +0900 | [diff] [blame] | 299 | - `UBOOT_PERSISTENT_DATA_DIR` the test persistent data directory. |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 300 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 301 | u-boot-test-console |
| 302 | ''''''''''''''''''' |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 303 | |
| 304 | This script provides access to the U-Boot console. The script's stdin/stdout |
| 305 | should be connected to the board's console. This process should continue to run |
| 306 | indefinitely, until killed. The test suite will run this script in parallel |
| 307 | with all other hooks. |
| 308 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 309 | This script may be implemented e.g. by executing `cu`, `kermit`, `conmux`, etc. |
| 310 | via exec(). |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 311 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 312 | If you are able to run U-Boot under a hardware simulator such as QEMU, then |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 313 | you would likely spawn that simulator from this script. However, note that |
| 314 | `u-boot-test-reset` may be called multiple times per test script run, and must |
| 315 | cause U-Boot to start execution from scratch each time. Hopefully your |
| 316 | simulator includes a virtual reset button! If not, you can launch the |
| 317 | simulator from `u-boot-test-reset` instead, while arranging for this console |
| 318 | process to always communicate with the current simulator instance. |
| 319 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 320 | u-boot-test-flash |
| 321 | ''''''''''''''''' |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 322 | |
| 323 | Prior to running the test suite against a board, some arrangement must be made |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 324 | so that the board executes the particular U-Boot binary to be tested. Often |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 325 | this involves writing the U-Boot binary to the board's flash ROM. The test |
| 326 | suite calls this hook script for that purpose. |
| 327 | |
| 328 | This script should perform the entire flashing process synchronously; the |
| 329 | script should only exit once flashing is complete, and a board reset will |
| 330 | cause the newly flashed U-Boot binary to be executed. |
| 331 | |
| 332 | It is conceivable that this script will do nothing. This might be useful in |
| 333 | the following cases: |
| 334 | |
| 335 | - Some other process has already written the desired U-Boot binary into the |
| 336 | board's flash prior to running the test suite. |
| 337 | - The board allows U-Boot to be downloaded directly into RAM, and executed |
| 338 | from there. Use of this feature will reduce wear on the board's flash, so |
| 339 | may be preferable if available, and if cold boot testing of U-Boot is not |
| 340 | required. If this feature is used, the `u-boot-test-reset` script should |
Masahiro Yamada | 3aca4a4 | 2017-10-19 19:08:52 +0900 | [diff] [blame] | 341 | perform this download, since the board could conceivably be reset multiple |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 342 | times in a single test run. |
| 343 | |
| 344 | It is up to the user to determine if those situations exist, and to code this |
| 345 | hook script appropriately. |
| 346 | |
| 347 | This script will typically be implemented by calling out to some SoC- or |
| 348 | board-specific vendor flashing utility. |
| 349 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 350 | u-boot-test-reset |
| 351 | ''''''''''''''''' |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 352 | |
| 353 | Whenever the test suite needs to reset the target board, this script is |
| 354 | executed. This is guaranteed to happen at least once, prior to executing the |
| 355 | first test function. If any test fails, the test infra-structure will execute |
| 356 | this script again to restore U-Boot to an operational state before running the |
| 357 | next test function. |
| 358 | |
| 359 | This script will likely be implemented by communicating with some form of |
| 360 | relay or electronic switch attached to the board's reset signal. |
| 361 | |
| 362 | The semantics of this script require that when it is executed, U-Boot will |
| 363 | start running from scratch. If the U-Boot binary to be tested has been written |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 364 | to flash, pulsing the board's reset signal is likely all this script needs to |
| 365 | do. However, in some scenarios, this script may perform other actions. For |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 366 | example, it may call out to some SoC- or board-specific vendor utility in order |
| 367 | to download the U-Boot binary directly into RAM and execute it. This would |
| 368 | avoid the need for `u-boot-test-flash` to actually write U-Boot to flash, thus |
| 369 | saving wear on the flash chip(s). |
| 370 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 371 | Examples |
| 372 | '''''''' |
Stephen Warren | 5b2beab | 2016-04-06 11:46:59 -0600 | [diff] [blame] | 373 | |
Tom Rini | 85ae52b | 2021-02-24 17:05:04 -0500 | [diff] [blame] | 374 | https://source.denx.de/u-boot/u-boot-test-hooks contains some working example hook |
Stephen Warren | 5b2beab | 2016-04-06 11:46:59 -0600 | [diff] [blame] | 375 | scripts, and may be useful as a reference when implementing hook scripts for |
| 376 | your platform. These scripts are not considered part of U-Boot itself. |
| 377 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 378 | Board-type-specific configuration |
| 379 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 380 | |
| 381 | Each board has a different configuration and behaviour. Many of these |
| 382 | differences can be automatically detected by parsing the `.config` file in the |
| 383 | build directory. However, some differences can't yet be handled automatically. |
| 384 | |
| 385 | For each board, an optional Python module `u_boot_board_${board_type}` may exist |
| 386 | to provide board-specific information to the test script. Any global value |
| 387 | defined in these modules is available for use by any test function. The data |
| 388 | contained in these scripts must be purely derived from U-Boot source code. |
| 389 | Hence, these configuration files are part of the U-Boot source tree too. |
| 390 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 391 | Execution environment configuration |
| 392 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 393 | |
| 394 | Each user's hardware setup may enable testing different subsets of the features |
| 395 | implemented by a particular board's configuration of U-Boot. For example, a |
| 396 | U-Boot configuration may support USB device mode and USB Mass Storage, but this |
| 397 | can only be tested if a USB cable is connected between the board and the host |
| 398 | machine running the test script. |
| 399 | |
| 400 | For each board, optional Python modules `u_boot_boardenv_${board_type}` and |
| 401 | `u_boot_boardenv_${board_type}_${board_identity}` may exist to provide |
| 402 | board-specific and board-identity-specific information to the test script. Any |
| 403 | global value defined in these modules is available for use by any test |
| 404 | function. The data contained in these is specific to a particular user's |
| 405 | hardware configuration. Hence, these configuration files are not part of the |
| 406 | U-Boot source tree, and should be installed outside of the source tree. Users |
| 407 | should set `$PYTHONPATH` prior to running the test script to allow these |
| 408 | modules to be loaded. |
| 409 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 410 | Board module parameter usage |
| 411 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 412 | |
| 413 | The test scripts rely on the following variables being defined by the board |
| 414 | module: |
| 415 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 416 | - none at present |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 417 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 418 | U-Boot `.config` feature usage |
| 419 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 420 | |
| 421 | The test scripts rely on various U-Boot `.config` features, either directly in |
| 422 | order to test those features, or indirectly in order to query information from |
| 423 | the running U-Boot instance in order to test other features. |
| 424 | |
| 425 | One example is that testing of the `md` command requires knowledge of a RAM |
| 426 | address to use for the test. This data is parsed from the output of the |
| 427 | `bdinfo` command, and hence relies on CONFIG_CMD_BDI being enabled. |
| 428 | |
| 429 | For a complete list of dependencies, please search the test scripts for |
| 430 | instances of: |
| 431 | |
| 432 | - `buildconfig.get(...` |
| 433 | - `@pytest.mark.buildconfigspec(...` |
Heinrich Schuchardt | 10feb30 | 2019-04-22 09:18:55 +0200 | [diff] [blame] | 434 | - `@pytest.mark.notbuildconfigspec(...` |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 435 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 436 | Complete invocation example |
| 437 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 438 | |
| 439 | Assuming that you have installed the hook scripts into $HOME/ubtest/bin, and |
| 440 | any required environment configuration Python modules into $HOME/ubtest/py, |
| 441 | then you would likely invoke the test script as follows: |
| 442 | |
| 443 | If U-Boot has already been built: |
| 444 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 445 | .. code-block:: bash |
| 446 | |
| 447 | PATH=$HOME/ubtest/bin:$PATH \ |
Liam Beguin | be91691 | 2018-03-14 19:15:13 -0400 | [diff] [blame] | 448 | PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 449 | ./test/py/test.py --bd seaboard |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 450 | |
| 451 | If you want the test script to compile U-Boot for you too, then you likely |
| 452 | need to set `$CROSS_COMPILE` to allow this, and invoke the test script as |
Simon Glass | f5ec7ee | 2020-03-18 09:43:01 -0600 | [diff] [blame] | 453 | follows: |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 454 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 455 | .. code-block:: bash |
| 456 | |
| 457 | CROSS_COMPILE=arm-none-eabi- \ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 458 | PATH=$HOME/ubtest/bin:$PATH \ |
Liam Beguin | be91691 | 2018-03-14 19:15:13 -0400 | [diff] [blame] | 459 | PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \ |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 460 | ./test/py/test.py --bd seaboard --build |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 461 | |
Simon Glass | f5ec7ee | 2020-03-18 09:43:01 -0600 | [diff] [blame] | 462 | or, using buildman to handle it: |
| 463 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 464 | .. code-block:: bash |
| 465 | |
Simon Glass | f5ec7ee | 2020-03-18 09:43:01 -0600 | [diff] [blame] | 466 | PATH=$HOME/ubtest/bin:$PATH \ |
| 467 | PYTHONPATH=${HOME}/ubtest/py/${HOSTNAME}:${PYTHONPATH} \ |
| 468 | ./test/py/test.py --bd seaboard --build --buildman |
Simon Glass | f5ec7ee | 2020-03-18 09:43:01 -0600 | [diff] [blame] | 469 | |
Heinrich Schuchardt | 0157619 | 2021-01-18 20:24:03 +0100 | [diff] [blame] | 470 | Writing tests |
| 471 | ------------- |
Stephen Warren | d201506 | 2016-01-15 11:15:24 -0700 | [diff] [blame] | 472 | |
| 473 | Please refer to the pytest documentation for details of writing pytest tests. |
| 474 | Details specific to the U-Boot test suite are described below. |
| 475 | |
| 476 | A test fixture named `u_boot_console` should be used by each test function. This |
| 477 | provides the means to interact with the U-Boot console, and retrieve board and |
| 478 | environment configuration information. |
| 479 | |
| 480 | The function `u_boot_console.run_command()` executes a shell command on the |
| 481 | U-Boot console, and returns all output from that command. This allows |
| 482 | validation or interpretation of the command output. This function validates |
| 483 | that certain strings are not seen on the U-Boot console. These include shell |
| 484 | error messages and the U-Boot sign-on message (in order to detect unexpected |
| 485 | board resets). See the source of `u_boot_console_base.py` for a complete list of |
| 486 | "bad" strings. Some test scenarios are expected to trigger these strings. Use |
| 487 | `u_boot_console.disable_check()` to temporarily disable checking for specific |
| 488 | strings. See `test_unknown_cmd.py` for an example. |
| 489 | |
| 490 | Board- and board-environment configuration values may be accessed as sub-fields |
| 491 | of the `u_boot_console.config` object, for example |
| 492 | `u_boot_console.config.ram_base`. |
| 493 | |
| 494 | Build configuration values (from `.config`) may be accessed via the dictionary |
| 495 | `u_boot_console.config.buildconfig`, with keys equal to the Kconfig variable |
| 496 | names. |