1.. SPDX-License-Identifier: CC-BY-SA-2.0-UK
2
3Performing Automated Runtime Testing
4************************************
5
6The OpenEmbedded build system makes available a series of automated
7tests for images to verify runtime functionality. You can run these
8tests on either QEMU or actual target hardware. Tests are written in
9Python making use of the ``unittest`` module, and the majority of them
10run commands on the target system over SSH. This section describes how
11you set up the environment to use these tests, run available tests, and
12write and add your own tests.
13
14For information on the test and QA infrastructure available within the
15Yocto Project, see the ":ref:`ref-manual/release-process:testing and quality assurance`"
16section in the Yocto Project Reference Manual.
17
18Enabling Tests
19==============
20
21Depending on whether you are planning to run tests using QEMU or on the
22hardware, you have to take different steps to enable the tests. See the
23following subsections for information on how to enable both types of
24tests.
25
26Enabling Runtime Tests on QEMU
27------------------------------
28
29In order to run tests, you need to do the following:
30
31-  *Set up to avoid interaction with sudo for networking:* To
32   accomplish this, you must do one of the following:
33
34   -  Add ``NOPASSWD`` for your user in ``/etc/sudoers`` either for all
35      commands or just for ``runqemu-ifup``. You must provide the full
36      path as that can change if you are using multiple clones of the
37      source repository.
38
39      .. note::
40
41         On some distributions, you also need to comment out "Defaults
42         requiretty" in ``/etc/sudoers``.
43
44   -  Manually configure a tap interface for your system.
45
46   -  Run as root the script in ``scripts/runqemu-gen-tapdevs``, which
47      should generate a list of tap devices. This is the option
48      typically chosen for Autobuilder-type environments.
49
50      .. note::
51
52         -  Be sure to use an absolute path when calling this script
53            with sudo.
54
55         -  Ensure that your host has the package ``iptables`` installed.
56
57         -  The package recipe ``qemu-helper-native`` is required to run
58            this script. Build the package using the following command::
59
60               $ bitbake qemu-helper-native
61
62-  *Set the DISPLAY variable:* You need to set this variable so that
63   you have an X server available (e.g. start ``vncserver`` for a
64   headless machine).
65
66-  *Be sure your host's firewall accepts incoming connections from
67   192.168.7.0/24:* Some of the tests (in particular DNF tests) start an
68   HTTP server on a random high number port, which is used to serve
69   files to the target. The DNF module serves
70   ``${WORKDIR}/oe-rootfs-repo`` so it can run DNF channel commands.
71   That means your host's firewall must accept incoming connections from
72   192.168.7.0/24, which is the default IP range used for tap devices by
73   ``runqemu``.
74
75-  *Be sure your host has the correct packages installed:* Depending
76   your host's distribution, you need to have the following packages
77   installed:
78
79   -  Ubuntu and Debian: ``sysstat`` and ``iproute2``
80
81   -  openSUSE: ``sysstat`` and ``iproute2``
82
83   -  Fedora: ``sysstat`` and ``iproute``
84
85   -  CentOS: ``sysstat`` and ``iproute``
86
87Once you start running the tests, the following happens:
88
89#. A copy of the root filesystem is written to ``${WORKDIR}/testimage``.
90
91#. The image is booted under QEMU using the standard ``runqemu`` script.
92
93#. A default timeout of 500 seconds occurs to allow for the boot process
94   to reach the login prompt. You can change the timeout period by
95   setting
96   :term:`TEST_QEMUBOOT_TIMEOUT`
97   in the ``local.conf`` file.
98
99#. Once the boot process is reached and the login prompt appears, the
100   tests run. The full boot log is written to
101   ``${WORKDIR}/testimage/qemu_boot_log``.
102
103#. Each test module loads in the order found in :term:`TEST_SUITES`. You can
104   find the full output of the commands run over SSH in
105   ``${WORKDIR}/testimgage/ssh_target_log``.
106
107#. If no failures occur, the task running the tests ends successfully.
108   You can find the output from the ``unittest`` in the task log at
109   ``${WORKDIR}/temp/log.do_testimage``.
110
111Enabling Runtime Tests on Hardware
112----------------------------------
113
114The OpenEmbedded build system can run tests on real hardware, and for
115certain devices it can also deploy the image to be tested onto the
116device beforehand.
117
118For automated deployment, a "controller image" is installed onto the
119hardware once as part of setup. Then, each time tests are to be run, the
120following occurs:
121
122#. The controller image is booted into and used to write the image to be
123   tested to a second partition.
124
125#. The device is then rebooted using an external script that you need to
126   provide.
127
128#. The device boots into the image to be tested.
129
130When running tests (independent of whether the image has been deployed
131automatically or not), the device is expected to be connected to a
132network on a pre-determined IP address. You can either use static IP
133addresses written into the image, or set the image to use DHCP and have
134your DHCP server on the test network assign a known IP address based on
135the MAC address of the device.
136
137In order to run tests on hardware, you need to set :term:`TEST_TARGET` to an
138appropriate value. For QEMU, you do not have to change anything, the
139default value is "qemu". For running tests on hardware, the following
140options are available:
141
142-  *"simpleremote":* Choose "simpleremote" if you are going to run tests
143   on a target system that is already running the image to be tested and
144   is available on the network. You can use "simpleremote" in
145   conjunction with either real hardware or an image running within a
146   separately started QEMU or any other virtual machine manager.
147
148-  *"SystemdbootTarget":* Choose "SystemdbootTarget" if your hardware is
149   an EFI-based machine with ``systemd-boot`` as bootloader and
150   ``core-image-testmaster`` (or something similar) is installed. Also,
151   your hardware under test must be in a DHCP-enabled network that gives
152   it the same IP address for each reboot.
153
154   If you choose "SystemdbootTarget", there are additional requirements
155   and considerations. See the
156   ":ref:`dev-manual/runtime-testing:selecting systemdboottarget`" section, which
157   follows, for more information.
158
159-  *"BeagleBoneTarget":* Choose "BeagleBoneTarget" if you are deploying
160   images and running tests on the BeagleBone "Black" or original
161   "White" hardware. For information on how to use these tests, see the
162   comments at the top of the BeagleBoneTarget
163   ``meta-yocto-bsp/lib/oeqa/controllers/beaglebonetarget.py`` file.
164
165-  *"GrubTarget":* Choose "GrubTarget" if you are deploying images and running
166   tests on any generic PC that boots using GRUB. For information on how
167   to use these tests, see the comments at the top of the GrubTarget
168   ``meta-yocto-bsp/lib/oeqa/controllers/grubtarget.py`` file.
169
170-  *"your-target":* Create your own custom target if you want to run
171   tests when you are deploying images and running tests on a custom
172   machine within your BSP layer. To do this, you need to add a Python
173   unit that defines the target class under ``lib/oeqa/controllers/``
174   within your layer. You must also provide an empty ``__init__.py``.
175   For examples, see files in ``meta-yocto-bsp/lib/oeqa/controllers/``.
176
177Selecting SystemdbootTarget
178---------------------------
179
180If you did not set :term:`TEST_TARGET` to "SystemdbootTarget", then you do
181not need any information in this section. You can skip down to the
182":ref:`dev-manual/runtime-testing:running tests`" section.
183
184If you did set :term:`TEST_TARGET` to "SystemdbootTarget", you also need to
185perform a one-time setup of your controller image by doing the following:
186
187#. *Set EFI_PROVIDER:* Be sure that :term:`EFI_PROVIDER` is as follows::
188
189      EFI_PROVIDER = "systemd-boot"
190
191#. *Build the controller image:* Build the ``core-image-testmaster`` image.
192   The ``core-image-testmaster`` recipe is provided as an example for a
193   "controller" image and you can customize the image recipe as you would
194   any other recipe.
195
196   Image recipe requirements are:
197
198   -  Inherits ``core-image`` so that kernel modules are installed.
199
200   -  Installs normal linux utilities not BusyBox ones (e.g. ``bash``,
201      ``coreutils``, ``tar``, ``gzip``, and ``kmod``).
202
203   -  Uses a custom :term:`Initramfs` image with a custom
204      installer. A normal image that you can install usually creates a
205      single root filesystem partition. This image uses another installer that
206      creates a specific partition layout. Not all Board Support
207      Packages (BSPs) can use an installer. For such cases, you need to
208      manually create the following partition layout on the target:
209
210      -  First partition mounted under ``/boot``, labeled "boot".
211
212      -  The main root filesystem partition where this image gets installed,
213         which is mounted under ``/``.
214
215      -  Another partition labeled "testrootfs" where test images get
216         deployed.
217
218#. *Install image:* Install the image that you just built on the target
219   system.
220
221The final thing you need to do when setting :term:`TEST_TARGET` to
222"SystemdbootTarget" is to set up the test image:
223
224#. *Set up your local.conf file:* Make sure you have the following
225   statements in your ``local.conf`` file::
226
227      IMAGE_FSTYPES += "tar.gz"
228      IMAGE_CLASSES += "testimage"
229      TEST_TARGET = "SystemdbootTarget"
230      TEST_TARGET_IP = "192.168.2.3"
231
232#. *Build your test image:* Use BitBake to build the image::
233
234      $ bitbake core-image-sato
235
236Power Control
237-------------
238
239For most hardware targets other than "simpleremote", you can control
240power:
241
242-  You can use :term:`TEST_POWERCONTROL_CMD` together with
243   :term:`TEST_POWERCONTROL_EXTRA_ARGS` as a command that runs on the host
244   and does power cycling. The test code passes one argument to that
245   command: off, on or cycle (off then on). Here is an example that
246   could appear in your ``local.conf`` file::
247
248      TEST_POWERCONTROL_CMD = "powercontrol.exp test 10.11.12.1 nuc1"
249
250   In this example, the expect
251   script does the following:
252
253   .. code-block:: shell
254
255      ssh test@10.11.12.1 "pyctl nuc1 arg"
256
257   It then runs a Python script that controls power for a label called
258   ``nuc1``.
259
260   .. note::
261
262      You need to customize :term:`TEST_POWERCONTROL_CMD` and
263      :term:`TEST_POWERCONTROL_EXTRA_ARGS` for your own setup. The one requirement
264      is that it accepts "on", "off", and "cycle" as the last argument.
265
266-  When no command is defined, it connects to the device over SSH and
267   uses the classic reboot command to reboot the device. Classic reboot
268   is fine as long as the machine actually reboots (i.e. the SSH test
269   has not failed). It is useful for scenarios where you have a simple
270   setup, typically with a single board, and where some manual
271   interaction is okay from time to time.
272
273If you have no hardware to automatically perform power control but still
274wish to experiment with automated hardware testing, you can use the
275``dialog-power-control`` script that shows a dialog prompting you to perform
276the required power action. This script requires either KDialog or Zenity
277to be installed. To use this script, set the
278:term:`TEST_POWERCONTROL_CMD`
279variable as follows::
280
281   TEST_POWERCONTROL_CMD = "${COREBASE}/scripts/contrib/dialog-power-control"
282
283Serial Console Connection
284-------------------------
285
286For test target classes requiring a serial console to interact with the
287bootloader (e.g. BeagleBoneTarget and GrubTarget),
288you need to specify a command to use to connect to the serial console of
289the target machine by using the
290:term:`TEST_SERIALCONTROL_CMD`
291variable and optionally the
292:term:`TEST_SERIALCONTROL_EXTRA_ARGS`
293variable.
294
295These cases could be a serial terminal program if the machine is
296connected to a local serial port, or a ``telnet`` or ``ssh`` command
297connecting to a remote console server. Regardless of the case, the
298command simply needs to connect to the serial console and forward that
299connection to standard input and output as any normal terminal program
300does. For example, to use the picocom terminal program on serial device
301``/dev/ttyUSB0`` at 115200bps, you would set the variable as follows::
302
303   TEST_SERIALCONTROL_CMD = "picocom /dev/ttyUSB0 -b 115200"
304
305For local
306devices where the serial port device disappears when the device reboots,
307an additional "serdevtry" wrapper script is provided. To use this
308wrapper, simply prefix the terminal command with
309``${COREBASE}/scripts/contrib/serdevtry``::
310
311   TEST_SERIALCONTROL_CMD = "${COREBASE}/scripts/contrib/serdevtry picocom -b 115200 /dev/ttyUSB0"
312
313Running Tests
314=============
315
316You can start the tests automatically or manually:
317
318-  *Automatically running tests:* To run the tests automatically after the
319   OpenEmbedded build system successfully creates an image, first set the
320   :term:`TESTIMAGE_AUTO` variable to "1" in your ``local.conf`` file in the
321   :term:`Build Directory`::
322
323      TESTIMAGE_AUTO = "1"
324
325   Next, build your image. If the image successfully builds, the
326   tests run::
327
328      bitbake core-image-sato
329
330-  *Manually running tests:* To manually run the tests, first globally
331   inherit the :ref:`ref-classes-testimage` class by editing your
332   ``local.conf`` file::
333
334      IMAGE_CLASSES += "testimage"
335
336   Next, use BitBake to run the tests::
337
338      bitbake -c testimage image
339
340All test files reside in ``meta/lib/oeqa/runtime/cases`` in the
341:term:`Source Directory`. A test name maps
342directly to a Python module. Each test module may contain a number of
343individual tests. Tests are usually grouped together by the area tested
344(e.g tests for systemd reside in ``meta/lib/oeqa/runtime/cases/systemd.py``).
345
346You can add tests to any layer provided you place them in the proper
347area and you extend :term:`BBPATH` in
348the ``local.conf`` file as normal. Be sure that tests reside in
349``layer/lib/oeqa/runtime/cases``.
350
351.. note::
352
353   Be sure that module names do not collide with module names used in
354   the default set of test modules in ``meta/lib/oeqa/runtime/cases``.
355
356You can change the set of tests run by appending or overriding
357:term:`TEST_SUITES` variable in
358``local.conf``. Each name in :term:`TEST_SUITES` represents a required test
359for the image. Test modules named within :term:`TEST_SUITES` cannot be
360skipped even if a test is not suitable for an image (e.g. running the
361RPM tests on an image without ``rpm``). Appending "auto" to
362:term:`TEST_SUITES` causes the build system to try to run all tests that are
363suitable for the image (i.e. each test module may elect to skip itself).
364
365The order you list tests in :term:`TEST_SUITES` is important and influences
366test dependencies. Consequently, tests that depend on other tests should
367be added after the test on which they depend. For example, since the
368``ssh`` test depends on the ``ping`` test, "ssh" needs to come after
369"ping" in the list. The test class provides no re-ordering or dependency
370handling.
371
372.. note::
373
374   Each module can have multiple classes with multiple test methods.
375   And, Python ``unittest`` rules apply.
376
377Here are some things to keep in mind when running tests:
378
379-  The default tests for the image are defined as::
380
381      DEFAULT_TEST_SUITES:pn-image = "ping ssh df connman syslog xorg scp vnc date rpm dnf dmesg"
382
383-  Add your own test to the list of the by using the following::
384
385      TEST_SUITES:append = " mytest"
386
387-  Run a specific list of tests as follows::
388
389     TEST_SUITES = "test1 test2 test3"
390
391   Remember, order is important. Be sure to place a test that is
392   dependent on another test later in the order.
393
394Exporting Tests
395===============
396
397You can export tests so that they can run independently of the build
398system. Exporting tests is required if you want to be able to hand the
399test execution off to a scheduler. You can only export tests that are
400defined in :term:`TEST_SUITES`.
401
402If your image is already built, make sure the following are set in your
403``local.conf`` file::
404
405   INHERIT += "testexport"
406   TEST_TARGET_IP = "IP-address-for-the-test-target"
407   TEST_SERVER_IP = "IP-address-for-the-test-server"
408
409You can then export the tests with the
410following BitBake command form::
411
412   $ bitbake image -c testexport
413
414Exporting the tests places them in the :term:`Build Directory` in
415``tmp/testexport/``\ image, which is controlled by the :term:`TEST_EXPORT_DIR`
416variable.
417
418You can now run the tests outside of the build environment::
419
420   $ cd tmp/testexport/image
421   $ ./runexported.py testdata.json
422
423Here is a complete example that shows IP addresses and uses the
424``core-image-sato`` image::
425
426   INHERIT += "testexport"
427   TEST_TARGET_IP = "192.168.7.2"
428   TEST_SERVER_IP = "192.168.7.1"
429
430Use BitBake to export the tests::
431
432   $ bitbake core-image-sato -c testexport
433
434Run the tests outside of
435the build environment using the following::
436
437   $ cd tmp/testexport/core-image-sato
438   $ ./runexported.py testdata.json
439
440Writing New Tests
441=================
442
443As mentioned previously, all new test files need to be in the proper
444place for the build system to find them. New tests for additional
445functionality outside of the core should be added to the layer that adds
446the functionality, in ``layer/lib/oeqa/runtime/cases`` (as long as
447:term:`BBPATH` is extended in the
448layer's ``layer.conf`` file as normal). Just remember the following:
449
450-  Filenames need to map directly to test (module) names.
451
452-  Do not use module names that collide with existing core tests.
453
454-  Minimally, an empty ``__init__.py`` file must be present in the runtime
455   directory.
456
457To create a new test, start by copying an existing module (e.g.
458``oe_syslog.py`` or ``gcc.py`` are good ones to use). Test modules can use
459code from ``meta/lib/oeqa/utils``, which are helper classes.
460
461.. note::
462
463   Structure shell commands such that you rely on them and they return a
464   single code for success. Be aware that sometimes you will need to
465   parse the output. See the ``df.py`` and ``date.py`` modules for examples.
466
467You will notice that all test classes inherit ``oeRuntimeTest``, which
468is found in ``meta/lib/oetest.py``. This base class offers some helper
469attributes, which are described in the following sections:
470
471Class Methods
472-------------
473
474Class methods are as follows:
475
476-  *hasPackage(pkg):* Returns "True" if ``pkg`` is in the installed
477   package list of the image, which is based on the manifest file that
478   is generated during the :ref:`ref-tasks-rootfs` task.
479
480-  *hasFeature(feature):* Returns "True" if the feature is in
481   :term:`IMAGE_FEATURES` or
482   :term:`DISTRO_FEATURES`.
483
484Class Attributes
485----------------
486
487Class attributes are as follows:
488
489-  *pscmd:* Equals "ps -ef" if ``procps`` is installed in the image.
490   Otherwise, ``pscmd`` equals "ps" (busybox).
491
492-  *tc:* The called test context, which gives access to the
493   following attributes:
494
495   -  *d:* The BitBake datastore, which allows you to use stuff such
496      as ``oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager")``.
497
498   -  *testslist and testsrequired:* Used internally. The tests
499      do not need these.
500
501   -  *filesdir:* The absolute path to
502      ``meta/lib/oeqa/runtime/files``, which contains helper files for
503      tests meant for copying on the target such as small files written
504      in C for compilation.
505
506   -  *target:* The target controller object used to deploy and
507      start an image on a particular target (e.g. Qemu, SimpleRemote,
508      and SystemdbootTarget). Tests usually use the following:
509
510      -  *ip:* The target's IP address.
511
512      -  *server_ip:* The host's IP address, which is usually used
513         by the DNF test suite.
514
515      -  *run(cmd, timeout=None):* The single, most used method.
516         This command is a wrapper for: ``ssh root@host "cmd"``. The
517         command returns a tuple: (status, output), which are what their
518         names imply - the return code of "cmd" and whatever output it
519         produces. The optional timeout argument represents the number
520         of seconds the test should wait for "cmd" to return. If the
521         argument is "None", the test uses the default instance's
522         timeout period, which is 300 seconds. If the argument is "0",
523         the test runs until the command returns.
524
525      -  *copy_to(localpath, remotepath):*
526         ``scp localpath root@ip:remotepath``.
527
528      -  *copy_from(remotepath, localpath):*
529         ``scp root@host:remotepath localpath``.
530
531Instance Attributes
532-------------------
533
534There is a single instance attribute, which is ``target``. The ``target``
535instance attribute is identical to the class attribute of the same name,
536which is described in the previous section. This attribute exists as
537both an instance and class attribute so tests can use
538``self.target.run(cmd)`` in instance methods instead of
539``oeRuntimeTest.tc.target.run(cmd)``.
540
541Installing Packages in the DUT Without the Package Manager
542==========================================================
543
544When a test requires a package built by BitBake, it is possible to
545install that package. Installing the package does not require a package
546manager be installed in the device under test (DUT). It does, however,
547require an SSH connection and the target must be using the
548``sshcontrol`` class.
549
550.. note::
551
552   This method uses ``scp`` to copy files from the host to the target, which
553   causes permissions and special attributes to be lost.
554
555A JSON file is used to define the packages needed by a test. This file
556must be in the same path as the file used to define the tests.
557Furthermore, the filename must map directly to the test module name with
558a ``.json`` extension.
559
560The JSON file must include an object with the test name as keys of an
561object or an array. This object (or array of objects) uses the following
562data:
563
564-  "pkg" --- a mandatory string that is the name of the package to be
565   installed.
566
567-  "rm" --- an optional boolean, which defaults to "false", that specifies
568   to remove the package after the test.
569
570-  "extract" --- an optional boolean, which defaults to "false", that
571   specifies if the package must be extracted from the package format.
572   When set to "true", the package is not automatically installed into
573   the DUT.
574
575Here is an example JSON file that handles test "foo" installing
576package "bar" and test "foobar" installing packages "foo" and "bar".
577Once the test is complete, the packages are removed from the DUT::
578
579     {
580         "foo": {
581             "pkg": "bar"
582         },
583         "foobar": [
584             {
585                 "pkg": "foo",
586                 "rm": true
587             },
588             {
589                 "pkg": "bar",
590                 "rm": true
591             }
592         ]
593     }
594
595