xref: /rk3399_rockchip-uboot/test/py/README.md (revision 5b2beab5cdf6209e5b4027312d8f9e2a13f1ce46)
1d201506cSStephen Warren# U-Boot pytest suite
2d201506cSStephen Warren
3d201506cSStephen Warren## Introduction
4d201506cSStephen Warren
5d201506cSStephen WarrenThis tool aims to test U-Boot by executing U-Boot shell commands using the
6d201506cSStephen Warrenconsole interface. A single top-level script exists to execute or attach to the
7d201506cSStephen WarrenU-Boot console, run the entire script of tests against it, and summarize the
8d201506cSStephen Warrenresults. Advantages of this approach are:
9d201506cSStephen Warren
10d201506cSStephen Warren- Testing is performed in the same way a user or script would interact with
11d201506cSStephen Warren  U-Boot; there can be no disconnect.
12d201506cSStephen Warren- There is no need to write or embed test-related code into U-Boot itself.
13d201506cSStephen Warren  It is asserted that writing test-related code in Python is simpler and more
14d201506cSStephen Warren  flexible that writing it all in C.
15d201506cSStephen Warren- It is reasonably simple to interact with U-Boot in this way.
16d201506cSStephen Warren
17d201506cSStephen Warren## Requirements
18d201506cSStephen Warren
19d201506cSStephen WarrenThe test suite is implemented using pytest. Interaction with the U-Boot console
20d201506cSStephen Warreninvolves executing some binary and interacting with its stdin/stdout. You will
21d201506cSStephen Warrenneed to implement various "hook" scripts that are called by the test suite at
22d201506cSStephen Warrenthe appropriate time.
23d201506cSStephen Warren
24d201506cSStephen WarrenOn Debian or Debian-like distributions, the following packages are required.
25d201506cSStephen WarrenSimilar package names should exist in other distributions.
26d201506cSStephen Warren
27d201506cSStephen Warren| Package        | Version tested (Ubuntu 14.04) |
28d201506cSStephen Warren| -------------- | ----------------------------- |
29d201506cSStephen Warren| python         | 2.7.5-5ubuntu3                |
30d201506cSStephen Warren| python-pytest  | 2.5.1-1                       |
31d201506cSStephen Warren
32d201506cSStephen WarrenThe test script supports either:
33d201506cSStephen Warren
34d201506cSStephen Warren- Executing a sandbox port of U-Boot on the local machine as a sub-process,
35d201506cSStephen Warren  and interacting with it over stdin/stdout.
36d201506cSStephen Warren- Executing an external "hook" scripts to flash a U-Boot binary onto a
37d201506cSStephen Warren  physical board, attach to the board's console stream, and reset the board.
38d201506cSStephen Warren  Further details are described later.
39d201506cSStephen Warren
40d201506cSStephen Warren### Using `virtualenv` to provide requirements
41d201506cSStephen Warren
42d201506cSStephen WarrenOlder distributions (e.g. Ubuntu 10.04) may not provide all the required
43d201506cSStephen Warrenpackages, or may provide versions that are too old to run the test suite. One
44d201506cSStephen Warrencan use the Python `virtualenv` script to locally install more up-to-date
45d201506cSStephen Warrenversions of the required packages without interfering with the OS installation.
46d201506cSStephen WarrenFor example:
47d201506cSStephen Warren
48d201506cSStephen Warren```bash
49d201506cSStephen Warren$ cd /path/to/u-boot
50d201506cSStephen Warren$ sudo apt-get install python python-virtualenv
51d201506cSStephen Warren$ virtualenv venv
52d201506cSStephen Warren$ . ./venv/bin/activate
53d201506cSStephen Warren$ pip install pytest
54d201506cSStephen Warren```
55d201506cSStephen Warren
56d201506cSStephen Warren## Testing sandbox
57d201506cSStephen Warren
58d201506cSStephen WarrenTo run the testsuite on the sandbox port (U-Boot built as a native user-space
59d201506cSStephen Warrenapplication), simply execute:
60d201506cSStephen Warren
61d201506cSStephen Warren```
62d201506cSStephen Warren./test/py/test.py --bd sandbox --build
63d201506cSStephen Warren```
64d201506cSStephen Warren
65d201506cSStephen WarrenThe `--bd` option tells the test suite which board type is being tested. This
66d201506cSStephen Warrenlets the test suite know which features the board has, and hence exactly what
67d201506cSStephen Warrencan be tested.
68d201506cSStephen Warren
69d201506cSStephen WarrenThe `--build` option tells U-Boot to compile U-Boot. Alternatively, you may
70d201506cSStephen Warrenomit this option and build U-Boot yourself, in whatever way you choose, before
71d201506cSStephen Warrenrunning the test script.
72d201506cSStephen Warren
73d201506cSStephen WarrenThe test script will attach to U-Boot, execute all valid tests for the board,
74d201506cSStephen Warrenthen print a summary of the test process. A complete log of the test session
75d201506cSStephen Warrenwill be written to `${build_dir}/test-log.html`. This is best viewed in a web
76d201506cSStephen Warrenbrowser, but may be read directly as plain text, perhaps with the aid of the
77d201506cSStephen Warren`html2text` utility.
78d201506cSStephen Warren
79d70facf8SStephen Warren### Testing under a debugger
80d70facf8SStephen Warren
81d70facf8SStephen WarrenIf you need to run sandbox under a debugger, you may pass the command-line
82d70facf8SStephen Warrenoption `--gdbserver COMM`. This causes two things to happens:
83d70facf8SStephen Warren
84d70facf8SStephen Warren- Instead of running U-Boot directly, it will be run under gdbserver, with
85d70facf8SStephen Warren  debug communication via the channel `COMM`. You can attach a debugger to the
86d70facf8SStephen Warren  sandbox process in order to debug it. See `man gdbserver` and the example
87d70facf8SStephen Warren  below for details of valid values for `COMM`.
88d70facf8SStephen Warren- All timeouts in tests are disabled, allowing U-Boot an arbitrary amount of
89d70facf8SStephen Warren  time to execute commands. This is useful if U-Boot is stopped at a breakpoint
90d70facf8SStephen Warren  during debugging.
91d70facf8SStephen Warren
92d70facf8SStephen WarrenA usage example is:
93d70facf8SStephen Warren
94d70facf8SStephen WarrenWindow 1:
95d70facf8SStephen Warren```shell
96d70facf8SStephen Warren./test/py/test.py --bd sandbox --gdbserver localhost:1234
97d70facf8SStephen Warren```
98d70facf8SStephen Warren
99d70facf8SStephen WarrenWindow 2:
100d70facf8SStephen Warren```shell
101d70facf8SStephen Warrengdb ./build-sandbox/u-boot -ex 'target remote localhost:1234'
102d70facf8SStephen Warren```
103d70facf8SStephen Warren
104d70facf8SStephen WarrenAlternatively, you could leave off the `-ex` option and type the command
105d70facf8SStephen Warrenmanually into gdb once it starts.
106d70facf8SStephen Warren
107d70facf8SStephen WarrenYou can use any debugger you wish, so long as it speaks the gdb remote
108d70facf8SStephen Warrenprotocol, or any graphical wrapper around gdb.
109d70facf8SStephen Warren
110d70facf8SStephen WarrenSome tests deliberately cause the sandbox process to exit, e.g. to test the
111d70facf8SStephen Warrenreset command, or sandbox's CTRL-C handling. When this happens, you will need
112d70facf8SStephen Warrento attach the debugger to the new sandbox instance. If these tests are not
113d70facf8SStephen Warrenrelevant to your debugging session, you can skip them using pytest's -k
114d70facf8SStephen Warrencommand-line option; see the next section.
115d70facf8SStephen Warren
116d201506cSStephen Warren## Command-line options
117d201506cSStephen Warren
118d201506cSStephen Warren- `--board-type`, `--bd`, `-B` set the type of the board to be tested. For
119d201506cSStephen Warren  example, `sandbox` or `seaboard`.
120d201506cSStephen Warren- `--board-identity`, `--id` set the identity of the board to be tested.
121d201506cSStephen Warren  This allows differentiation between multiple instances of the same type of
122d201506cSStephen Warren  physical board that are attached to the same host machine. This parameter is
123d201506cSStephen Warren  not interpreted by the test script in any way, but rather is simply passed
124d201506cSStephen Warren  to the hook scripts described below, and may be used in any site-specific
125d201506cSStephen Warren  way deemed necessary.
126d201506cSStephen Warren- `--build` indicates that the test script should compile U-Boot itself
127d201506cSStephen Warren  before running the tests. If using this option, make sure that any
128d201506cSStephen Warren  environment variables required by the build process are already set, such as
129d201506cSStephen Warren  `$CROSS_COMPILE`.
130d201506cSStephen Warren- `--build-dir` sets the directory containing the compiled U-Boot binaries.
131d201506cSStephen Warren  If omitted, this is `${source_dir}/build-${board_type}`.
132d201506cSStephen Warren- `--result-dir` sets the directory to write results, such as log files,
133d201506cSStephen Warren  into. If omitted, the build directory is used.
134d201506cSStephen Warren- `--persistent-data-dir` sets the directory used to store persistent test
135d201506cSStephen Warren  data. This is test data that may be re-used across test runs, such as file-
136d201506cSStephen Warren  system images.
137d201506cSStephen Warren
138d70facf8SStephen Warren`pytest` also implements a number of its own command-line options. Commonly used
139d70facf8SStephen Warrenoptions are mentioned below. Please see `pytest` documentation for complete
140d70facf8SStephen Warrendetails. Execute `py.test --version` for a brief summary. Note that U-Boot's
141d70facf8SStephen Warrentest.py script passes all command-line arguments directly to `pytest` for
142d70facf8SStephen Warrenprocessing.
143d70facf8SStephen Warren
144d70facf8SStephen Warren- `-k` selects which tests to run. The default is to run all known tests. This
145d70facf8SStephen Warren  option takes a single argument which is used to filter test names. Simple
146d70facf8SStephen Warren  logical operators are supported. For example:
147d70facf8SStephen Warren  - `'ums'` runs only tests with "ums" in their name.
148d70facf8SStephen Warren  - ``ut_dm'` runs only tests with "ut_dm" in their name. Note that in this
149d70facf8SStephen Warren    case, "ut_dm" is a parameter to a test rather than the test name. The full
150d70facf8SStephen Warren    test name is e.g. "test_ut[ut_dm_leak]".
151d70facf8SStephen Warren  - `'not reset'` runs everything except tests with "reset" in their name.
152d70facf8SStephen Warren  - `'ut or hush'` runs only tests with "ut" or "hush" in their name.
153d70facf8SStephen Warren  - `'not (ut or hush)'` runs everything except tests with "ut" or "hush" in
154d70facf8SStephen Warren    their name.
155d70facf8SStephen Warren- `-s` prevents pytest from hiding a test's stdout. This allows you to see
156d70facf8SStephen Warren  U-Boot's console log in real time on pytest's stdout.
157d201506cSStephen Warren
158d201506cSStephen Warren## Testing real hardware
159d201506cSStephen Warren
160d201506cSStephen WarrenThe tools and techniques used to interact with real hardware will vary
161d201506cSStephen Warrenradically between different host and target systems, and the whims of the user.
162d201506cSStephen WarrenFor this reason, the test suite does not attempt to directly interact with real
163d201506cSStephen Warrenhardware in any way. Rather, it executes a standardized set of "hook" scripts
164d201506cSStephen Warrenvia `$PATH`. These scripts implement certain actions on behalf of the test
165d201506cSStephen Warrensuite. This keeps the test suite simple and isolated from system variances
166d201506cSStephen Warrenunrelated to U-Boot features.
167d201506cSStephen Warren
168d201506cSStephen Warren### Hook scripts
169d201506cSStephen Warren
170d201506cSStephen Warren#### Environment variables
171d201506cSStephen Warren
172d201506cSStephen WarrenThe following environment variables are set when running hook scripts:
173d201506cSStephen Warren
174d201506cSStephen Warren- `UBOOT_BOARD_TYPE` the board type being tested.
175d201506cSStephen Warren- `UBOOT_BOARD_IDENTITY` the board identity being tested, or `na` if none was
176d201506cSStephen Warren  specified.
177d201506cSStephen Warren- `UBOOT_SOURCE_DIR` the U-Boot source directory.
178d201506cSStephen Warren- `UBOOT_TEST_PY_DIR` the full path to `test/py/` in the source directory.
179d201506cSStephen Warren- `UBOOT_BUILD_DIR` the U-Boot build directory.
180d201506cSStephen Warren- `UBOOT_RESULT_DIR` the test result directory.
181d201506cSStephen Warren- `UBOOT_PERSISTENT_DATA_DIR` the test peristent data directory.
182d201506cSStephen Warren
183d201506cSStephen Warren#### `u-boot-test-console`
184d201506cSStephen Warren
185d201506cSStephen WarrenThis script provides access to the U-Boot console. The script's stdin/stdout
186d201506cSStephen Warrenshould be connected to the board's console. This process should continue to run
187d201506cSStephen Warrenindefinitely, until killed. The test suite will run this script in parallel
188d201506cSStephen Warrenwith all other hooks.
189d201506cSStephen Warren
190d201506cSStephen WarrenThis script may be implemented e.g. by exec()ing `cu`, `kermit`, `conmux`, etc.
191d201506cSStephen Warren
192d201506cSStephen WarrenIf you are able to run U-Boot under a hardware simulator such as qemu, then
193d201506cSStephen Warrenyou would likely spawn that simulator from this script. However, note that
194d201506cSStephen Warren`u-boot-test-reset` may be called multiple times per test script run, and must
195d201506cSStephen Warrencause U-Boot to start execution from scratch each time. Hopefully your
196d201506cSStephen Warrensimulator includes a virtual reset button! If not, you can launch the
197d201506cSStephen Warrensimulator from `u-boot-test-reset` instead, while arranging for this console
198d201506cSStephen Warrenprocess to always communicate with the current simulator instance.
199d201506cSStephen Warren
200d201506cSStephen Warren#### `u-boot-test-flash`
201d201506cSStephen Warren
202d201506cSStephen WarrenPrior to running the test suite against a board, some arrangement must be made
203d201506cSStephen Warrenso that the board executes the particular U-Boot binary to be tested. Often,
204d201506cSStephen Warrenthis involves writing the U-Boot binary to the board's flash ROM. The test
205d201506cSStephen Warrensuite calls this hook script for that purpose.
206d201506cSStephen Warren
207d201506cSStephen WarrenThis script should perform the entire flashing process synchronously; the
208d201506cSStephen Warrenscript should only exit once flashing is complete, and a board reset will
209d201506cSStephen Warrencause the newly flashed U-Boot binary to be executed.
210d201506cSStephen Warren
211d201506cSStephen WarrenIt is conceivable that this script will do nothing. This might be useful in
212d201506cSStephen Warrenthe following cases:
213d201506cSStephen Warren
214d201506cSStephen Warren- Some other process has already written the desired U-Boot binary into the
215d201506cSStephen Warren  board's flash prior to running the test suite.
216d201506cSStephen Warren- The board allows U-Boot to be downloaded directly into RAM, and executed
217d201506cSStephen Warren  from there. Use of this feature will reduce wear on the board's flash, so
218d201506cSStephen Warren  may be preferable if available, and if cold boot testing of U-Boot is not
219d201506cSStephen Warren  required. If this feature is used, the `u-boot-test-reset` script should
220d201506cSStephen Warren  peform this download, since the board could conceivably be reset multiple
221d201506cSStephen Warren  times in a single test run.
222d201506cSStephen Warren
223d201506cSStephen WarrenIt is up to the user to determine if those situations exist, and to code this
224d201506cSStephen Warrenhook script appropriately.
225d201506cSStephen Warren
226d201506cSStephen WarrenThis script will typically be implemented by calling out to some SoC- or
227d201506cSStephen Warrenboard-specific vendor flashing utility.
228d201506cSStephen Warren
229d201506cSStephen Warren#### `u-boot-test-reset`
230d201506cSStephen Warren
231d201506cSStephen WarrenWhenever the test suite needs to reset the target board, this script is
232d201506cSStephen Warrenexecuted. This is guaranteed to happen at least once, prior to executing the
233d201506cSStephen Warrenfirst test function. If any test fails, the test infra-structure will execute
234d201506cSStephen Warrenthis script again to restore U-Boot to an operational state before running the
235d201506cSStephen Warrennext test function.
236d201506cSStephen Warren
237d201506cSStephen WarrenThis script will likely be implemented by communicating with some form of
238d201506cSStephen Warrenrelay or electronic switch attached to the board's reset signal.
239d201506cSStephen Warren
240d201506cSStephen WarrenThe semantics of this script require that when it is executed, U-Boot will
241d201506cSStephen Warrenstart running from scratch. If the U-Boot binary to be tested has been written
242d201506cSStephen Warrento flash, pulsing the board's reset signal is likely all this script need do.
243d201506cSStephen WarrenHowever, in some scenarios, this script may perform other actions. For
244d201506cSStephen Warrenexample, it may call out to some SoC- or board-specific vendor utility in order
245d201506cSStephen Warrento download the U-Boot binary directly into RAM and execute it. This would
246d201506cSStephen Warrenavoid the need for `u-boot-test-flash` to actually write U-Boot to flash, thus
247d201506cSStephen Warrensaving wear on the flash chip(s).
248d201506cSStephen Warren
249*5b2beab5SStephen Warren#### Examples
250*5b2beab5SStephen Warren
251*5b2beab5SStephen Warrenhttps://github.com/swarren/uboot-test-hooks contains some working example hook
252*5b2beab5SStephen Warrenscripts, and may be useful as a reference when implementing hook scripts for
253*5b2beab5SStephen Warrenyour platform. These scripts are not considered part of U-Boot itself.
254*5b2beab5SStephen Warren
255d201506cSStephen Warren### Board-type-specific configuration
256d201506cSStephen Warren
257d201506cSStephen WarrenEach board has a different configuration and behaviour. Many of these
258d201506cSStephen Warrendifferences can be automatically detected by parsing the `.config` file in the
259d201506cSStephen Warrenbuild directory. However, some differences can't yet be handled automatically.
260d201506cSStephen Warren
261d201506cSStephen WarrenFor each board, an optional Python module `u_boot_board_${board_type}` may exist
262d201506cSStephen Warrento provide board-specific information to the test script. Any global value
263d201506cSStephen Warrendefined in these modules is available for use by any test function. The data
264d201506cSStephen Warrencontained in these scripts must be purely derived from U-Boot source code.
265d201506cSStephen WarrenHence, these configuration files are part of the U-Boot source tree too.
266d201506cSStephen Warren
267d201506cSStephen Warren### Execution environment configuration
268d201506cSStephen Warren
269d201506cSStephen WarrenEach user's hardware setup may enable testing different subsets of the features
270d201506cSStephen Warrenimplemented by a particular board's configuration of U-Boot. For example, a
271d201506cSStephen WarrenU-Boot configuration may support USB device mode and USB Mass Storage, but this
272d201506cSStephen Warrencan only be tested if a USB cable is connected between the board and the host
273d201506cSStephen Warrenmachine running the test script.
274d201506cSStephen Warren
275d201506cSStephen WarrenFor each board, optional Python modules `u_boot_boardenv_${board_type}` and
276d201506cSStephen Warren`u_boot_boardenv_${board_type}_${board_identity}` may exist to provide
277d201506cSStephen Warrenboard-specific and board-identity-specific information to the test script. Any
278d201506cSStephen Warrenglobal value defined in these modules is available for use by any test
279d201506cSStephen Warrenfunction. The data contained in these is specific to a particular user's
280d201506cSStephen Warrenhardware configuration. Hence, these configuration files are not part of the
281d201506cSStephen WarrenU-Boot source tree, and should be installed outside of the source tree. Users
282d201506cSStephen Warrenshould set `$PYTHONPATH` prior to running the test script to allow these
283d201506cSStephen Warrenmodules to be loaded.
284d201506cSStephen Warren
285d201506cSStephen Warren### Board module parameter usage
286d201506cSStephen Warren
287d201506cSStephen WarrenThe test scripts rely on the following variables being defined by the board
288d201506cSStephen Warrenmodule:
289d201506cSStephen Warren
290d201506cSStephen Warren- None at present.
291d201506cSStephen Warren
292d201506cSStephen Warren### U-Boot `.config` feature usage
293d201506cSStephen Warren
294d201506cSStephen WarrenThe test scripts rely on various U-Boot `.config` features, either directly in
295d201506cSStephen Warrenorder to test those features, or indirectly in order to query information from
296d201506cSStephen Warrenthe running U-Boot instance in order to test other features.
297d201506cSStephen Warren
298d201506cSStephen WarrenOne example is that testing of the `md` command requires knowledge of a RAM
299d201506cSStephen Warrenaddress to use for the test. This data is parsed from the output of the
300d201506cSStephen Warren`bdinfo` command, and hence relies on CONFIG_CMD_BDI being enabled.
301d201506cSStephen Warren
302d201506cSStephen WarrenFor a complete list of dependencies, please search the test scripts for
303d201506cSStephen Warreninstances of:
304d201506cSStephen Warren
305d201506cSStephen Warren- `buildconfig.get(...`
306d201506cSStephen Warren- `@pytest.mark.buildconfigspec(...`
307d201506cSStephen Warren
308d201506cSStephen Warren### Complete invocation example
309d201506cSStephen Warren
310d201506cSStephen WarrenAssuming that you have installed the hook scripts into $HOME/ubtest/bin, and
311d201506cSStephen Warrenany required environment configuration Python modules into $HOME/ubtest/py,
312d201506cSStephen Warrenthen you would likely invoke the test script as follows:
313d201506cSStephen Warren
314d201506cSStephen WarrenIf U-Boot has already been built:
315d201506cSStephen Warren
316d201506cSStephen Warren```bash
317d201506cSStephen WarrenPATH=$HOME/ubtest/bin:$PATH \
318d201506cSStephen Warren    PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \
319d201506cSStephen Warren    ./test/py/test.py --bd seaboard
320d201506cSStephen Warren```
321d201506cSStephen Warren
322d201506cSStephen WarrenIf you want the test script to compile U-Boot for you too, then you likely
323d201506cSStephen Warrenneed to set `$CROSS_COMPILE` to allow this, and invoke the test script as
324d201506cSStephen Warrenfollow:
325d201506cSStephen Warren
326d201506cSStephen Warren```bash
327d201506cSStephen WarrenCROSS_COMPILE=arm-none-eabi- \
328d201506cSStephen Warren    PATH=$HOME/ubtest/bin:$PATH \
329d201506cSStephen Warren    PYTHONPATH=${HOME}/ubtest/py:${PYTHONPATH} \
330d201506cSStephen Warren    ./test/py/test.py --bd seaboard --build
331d201506cSStephen Warren```
332d201506cSStephen Warren
333d201506cSStephen Warren## Writing tests
334d201506cSStephen Warren
335d201506cSStephen WarrenPlease refer to the pytest documentation for details of writing pytest tests.
336d201506cSStephen WarrenDetails specific to the U-Boot test suite are described below.
337d201506cSStephen Warren
338d201506cSStephen WarrenA test fixture named `u_boot_console` should be used by each test function. This
339d201506cSStephen Warrenprovides the means to interact with the U-Boot console, and retrieve board and
340d201506cSStephen Warrenenvironment configuration information.
341d201506cSStephen Warren
342d201506cSStephen WarrenThe function `u_boot_console.run_command()` executes a shell command on the
343d201506cSStephen WarrenU-Boot console, and returns all output from that command. This allows
344d201506cSStephen Warrenvalidation or interpretation of the command output. This function validates
345d201506cSStephen Warrenthat certain strings are not seen on the U-Boot console. These include shell
346d201506cSStephen Warrenerror messages and the U-Boot sign-on message (in order to detect unexpected
347d201506cSStephen Warrenboard resets). See the source of `u_boot_console_base.py` for a complete list of
348d201506cSStephen Warren"bad" strings. Some test scenarios are expected to trigger these strings. Use
349d201506cSStephen Warren`u_boot_console.disable_check()` to temporarily disable checking for specific
350d201506cSStephen Warrenstrings. See `test_unknown_cmd.py` for an example.
351d201506cSStephen Warren
352d201506cSStephen WarrenBoard- and board-environment configuration values may be accessed as sub-fields
353d201506cSStephen Warrenof the `u_boot_console.config` object, for example
354d201506cSStephen Warren`u_boot_console.config.ram_base`.
355d201506cSStephen Warren
356d201506cSStephen WarrenBuild configuration values (from `.config`) may be accessed via the dictionary
357d201506cSStephen Warren`u_boot_console.config.buildconfig`, with keys equal to the Kconfig variable
358d201506cSStephen Warrennames.
359