summaryrefslogtreecommitdiffstats
path: root/documentation/dev-manual
diff options
context:
space:
mode:
authorAntonin Godard <antonin.godard@bootlin.com>2024-12-26 16:20:17 +0100
committerSteve Sakoman <steve@sakoman.com>2025-01-09 08:41:04 -0800
commitac2d3a537751ddc3399f82fc85bfb4a6dd38cf7d (patch)
tree4874a7fe52d07cbf9d7d177f9765ddcec91a881c /documentation/dev-manual
parent2497f29afd1ff66964b84dc79a7cd1126bbc94fa (diff)
downloadpoky-ac2d3a537751ddc3399f82fc85bfb4a6dd38cf7d.tar.gz
ref-manual: move runtime-testing section to the test-manual
In the same fashion as the previous commit ("ref-manual/packages: move ptest section to the test-manual"), move the runtime testing section of the development tasks manual to the test environment manual. Add a link to it from the test-manual/intro document. (From yocto-docs rev: 3128bf149f40928e6c2a3e264590a0c6c9778c6a) Signed-off-by: Antonin Godard <antonin.godard@bootlin.com> (cherry picked from commit 6b44257874858db3aa426d3e84a79c41cb4937a3) Signed-off-by: Antonin Godard <antonin.godard@bootlin.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'documentation/dev-manual')
-rw-r--r--documentation/dev-manual/index.rst1
-rw-r--r--documentation/dev-manual/runtime-testing.rst600
2 files changed, 0 insertions, 601 deletions
diff --git a/documentation/dev-manual/index.rst b/documentation/dev-manual/index.rst
index 9ccf60f701..ef0512d246 100644
--- a/documentation/dev-manual/index.rst
+++ b/documentation/dev-manual/index.rst
@@ -39,7 +39,6 @@ Yocto Project Development Tasks Manual
39 external-scm 39 external-scm
40 read-only-rootfs 40 read-only-rootfs
41 build-quality 41 build-quality
42 runtime-testing
43 debugging 42 debugging
44 licenses 43 licenses
45 security-subjects 44 security-subjects
diff --git a/documentation/dev-manual/runtime-testing.rst b/documentation/dev-manual/runtime-testing.rst
deleted file mode 100644
index bd3f42ac09..0000000000
--- a/documentation/dev-manual/runtime-testing.rst
+++ /dev/null
@@ -1,600 +0,0 @@
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- *"EdgeRouterTarget":* Choose "EdgeRouterTarget" if you are deploying
166 images and running tests on the Ubiquiti Networks EdgeRouter Lite.
167 For information on how to use these tests, see the comments at the
168 top of the EdgeRouterTarget
169 ``meta-yocto-bsp/lib/oeqa/controllers/edgeroutertarget.py`` file.
170
171- *"GrubTarget":* Choose "GrubTarget" if you are deploying images and running
172 tests on any generic PC that boots using GRUB. For information on how
173 to use these tests, see the comments at the top of the GrubTarget
174 ``meta-yocto-bsp/lib/oeqa/controllers/grubtarget.py`` file.
175
176- *"your-target":* Create your own custom target if you want to run
177 tests when you are deploying images and running tests on a custom
178 machine within your BSP layer. To do this, you need to add a Python
179 unit that defines the target class under ``lib/oeqa/controllers/``
180 within your layer. You must also provide an empty ``__init__.py``.
181 For examples, see files in ``meta-yocto-bsp/lib/oeqa/controllers/``.
182
183Selecting SystemdbootTarget
184---------------------------
185
186If you did not set :term:`TEST_TARGET` to "SystemdbootTarget", then you do
187not need any information in this section. You can skip down to the
188":ref:`dev-manual/runtime-testing:running tests`" section.
189
190If you did set :term:`TEST_TARGET` to "SystemdbootTarget", you also need to
191perform a one-time setup of your controller image by doing the following:
192
193#. *Set EFI_PROVIDER:* Be sure that :term:`EFI_PROVIDER` is as follows::
194
195 EFI_PROVIDER = "systemd-boot"
196
197#. *Build the controller image:* Build the ``core-image-testmaster`` image.
198 The ``core-image-testmaster`` recipe is provided as an example for a
199 "controller" image and you can customize the image recipe as you would
200 any other recipe.
201
202 Image recipe requirements are:
203
204 - Inherits ``core-image`` so that kernel modules are installed.
205
206 - Installs normal linux utilities not BusyBox ones (e.g. ``bash``,
207 ``coreutils``, ``tar``, ``gzip``, and ``kmod``).
208
209 - Uses a custom :term:`Initramfs` image with a custom
210 installer. A normal image that you can install usually creates a
211 single root filesystem partition. This image uses another installer that
212 creates a specific partition layout. Not all Board Support
213 Packages (BSPs) can use an installer. For such cases, you need to
214 manually create the following partition layout on the target:
215
216 - First partition mounted under ``/boot``, labeled "boot".
217
218 - The main root filesystem partition where this image gets installed,
219 which is mounted under ``/``.
220
221 - Another partition labeled "testrootfs" where test images get
222 deployed.
223
224#. *Install image:* Install the image that you just built on the target
225 system.
226
227The final thing you need to do when setting :term:`TEST_TARGET` to
228"SystemdbootTarget" is to set up the test image:
229
230#. *Set up your local.conf file:* Make sure you have the following
231 statements in your ``local.conf`` file::
232
233 IMAGE_FSTYPES += "tar.gz"
234 IMAGE_CLASSES += "testimage"
235 TEST_TARGET = "SystemdbootTarget"
236 TEST_TARGET_IP = "192.168.2.3"
237
238#. *Build your test image:* Use BitBake to build the image::
239
240 $ bitbake core-image-sato
241
242Power Control
243-------------
244
245For most hardware targets other than "simpleremote", you can control
246power:
247
248- You can use :term:`TEST_POWERCONTROL_CMD` together with
249 :term:`TEST_POWERCONTROL_EXTRA_ARGS` as a command that runs on the host
250 and does power cycling. The test code passes one argument to that
251 command: off, on or cycle (off then on). Here is an example that
252 could appear in your ``local.conf`` file::
253
254 TEST_POWERCONTROL_CMD = "powercontrol.exp test 10.11.12.1 nuc1"
255
256 In this example, the expect
257 script does the following:
258
259 .. code-block:: shell
260
261 ssh test@10.11.12.1 "pyctl nuc1 arg"
262
263 It then runs a Python script that controls power for a label called
264 ``nuc1``.
265
266 .. note::
267
268 You need to customize :term:`TEST_POWERCONTROL_CMD` and
269 :term:`TEST_POWERCONTROL_EXTRA_ARGS` for your own setup. The one requirement
270 is that it accepts "on", "off", and "cycle" as the last argument.
271
272- When no command is defined, it connects to the device over SSH and
273 uses the classic reboot command to reboot the device. Classic reboot
274 is fine as long as the machine actually reboots (i.e. the SSH test
275 has not failed). It is useful for scenarios where you have a simple
276 setup, typically with a single board, and where some manual
277 interaction is okay from time to time.
278
279If you have no hardware to automatically perform power control but still
280wish to experiment with automated hardware testing, you can use the
281``dialog-power-control`` script that shows a dialog prompting you to perform
282the required power action. This script requires either KDialog or Zenity
283to be installed. To use this script, set the
284:term:`TEST_POWERCONTROL_CMD`
285variable as follows::
286
287 TEST_POWERCONTROL_CMD = "${COREBASE}/scripts/contrib/dialog-power-control"
288
289Serial Console Connection
290-------------------------
291
292For test target classes requiring a serial console to interact with the
293bootloader (e.g. BeagleBoneTarget, EdgeRouterTarget, and GrubTarget),
294you need to specify a command to use to connect to the serial console of
295the target machine by using the
296:term:`TEST_SERIALCONTROL_CMD`
297variable and optionally the
298:term:`TEST_SERIALCONTROL_EXTRA_ARGS`
299variable.
300
301These cases could be a serial terminal program if the machine is
302connected to a local serial port, or a ``telnet`` or ``ssh`` command
303connecting to a remote console server. Regardless of the case, the
304command simply needs to connect to the serial console and forward that
305connection to standard input and output as any normal terminal program
306does. For example, to use the picocom terminal program on serial device
307``/dev/ttyUSB0`` at 115200bps, you would set the variable as follows::
308
309 TEST_SERIALCONTROL_CMD = "picocom /dev/ttyUSB0 -b 115200"
310
311For local
312devices where the serial port device disappears when the device reboots,
313an additional "serdevtry" wrapper script is provided. To use this
314wrapper, simply prefix the terminal command with
315``${COREBASE}/scripts/contrib/serdevtry``::
316
317 TEST_SERIALCONTROL_CMD = "${COREBASE}/scripts/contrib/serdevtry picocom -b 115200 /dev/ttyUSB0"
318
319Running Tests
320=============
321
322You can start the tests automatically or manually:
323
324- *Automatically running tests:* To run the tests automatically after the
325 OpenEmbedded build system successfully creates an image, first set the
326 :term:`TESTIMAGE_AUTO` variable to "1" in your ``local.conf`` file in the
327 :term:`Build Directory`::
328
329 TESTIMAGE_AUTO = "1"
330
331 Next, build your image. If the image successfully builds, the
332 tests run::
333
334 bitbake core-image-sato
335
336- *Manually running tests:* To manually run the tests, first globally
337 inherit the :ref:`ref-classes-testimage` class by editing your
338 ``local.conf`` file::
339
340 IMAGE_CLASSES += "testimage"
341
342 Next, use BitBake to run the tests::
343
344 bitbake -c testimage image
345
346All test files reside in ``meta/lib/oeqa/runtime/cases`` in the
347:term:`Source Directory`. A test name maps
348directly to a Python module. Each test module may contain a number of
349individual tests. Tests are usually grouped together by the area tested
350(e.g tests for systemd reside in ``meta/lib/oeqa/runtime/cases/systemd.py``).
351
352You can add tests to any layer provided you place them in the proper
353area and you extend :term:`BBPATH` in
354the ``local.conf`` file as normal. Be sure that tests reside in
355``layer/lib/oeqa/runtime/cases``.
356
357.. note::
358
359 Be sure that module names do not collide with module names used in
360 the default set of test modules in ``meta/lib/oeqa/runtime/cases``.
361
362You can change the set of tests run by appending or overriding
363:term:`TEST_SUITES` variable in
364``local.conf``. Each name in :term:`TEST_SUITES` represents a required test
365for the image. Test modules named within :term:`TEST_SUITES` cannot be
366skipped even if a test is not suitable for an image (e.g. running the
367RPM tests on an image without ``rpm``). Appending "auto" to
368:term:`TEST_SUITES` causes the build system to try to run all tests that are
369suitable for the image (i.e. each test module may elect to skip itself).
370
371The order you list tests in :term:`TEST_SUITES` is important and influences
372test dependencies. Consequently, tests that depend on other tests should
373be added after the test on which they depend. For example, since the
374``ssh`` test depends on the ``ping`` test, "ssh" needs to come after
375"ping" in the list. The test class provides no re-ordering or dependency
376handling.
377
378.. note::
379
380 Each module can have multiple classes with multiple test methods.
381 And, Python ``unittest`` rules apply.
382
383Here are some things to keep in mind when running tests:
384
385- The default tests for the image are defined as::
386
387 DEFAULT_TEST_SUITES:pn-image = "ping ssh df connman syslog xorg scp vnc date rpm dnf dmesg"
388
389- Add your own test to the list of the by using the following::
390
391 TEST_SUITES:append = " mytest"
392
393- Run a specific list of tests as follows::
394
395 TEST_SUITES = "test1 test2 test3"
396
397 Remember, order is important. Be sure to place a test that is
398 dependent on another test later in the order.
399
400Exporting Tests
401===============
402
403You can export tests so that they can run independently of the build
404system. Exporting tests is required if you want to be able to hand the
405test execution off to a scheduler. You can only export tests that are
406defined in :term:`TEST_SUITES`.
407
408If your image is already built, make sure the following are set in your
409``local.conf`` file::
410
411 INHERIT += "testexport"
412 TEST_TARGET_IP = "IP-address-for-the-test-target"
413 TEST_SERVER_IP = "IP-address-for-the-test-server"
414
415You can then export the tests with the
416following BitBake command form::
417
418 $ bitbake image -c testexport
419
420Exporting the tests places them in the :term:`Build Directory` in
421``tmp/testexport/``\ image, which is controlled by the :term:`TEST_EXPORT_DIR`
422variable.
423
424You can now run the tests outside of the build environment::
425
426 $ cd tmp/testexport/image
427 $ ./runexported.py testdata.json
428
429Here is a complete example that shows IP addresses and uses the
430``core-image-sato`` image::
431
432 INHERIT += "testexport"
433 TEST_TARGET_IP = "192.168.7.2"
434 TEST_SERVER_IP = "192.168.7.1"
435
436Use BitBake to export the tests::
437
438 $ bitbake core-image-sato -c testexport
439
440Run the tests outside of
441the build environment using the following::
442
443 $ cd tmp/testexport/core-image-sato
444 $ ./runexported.py testdata.json
445
446Writing New Tests
447=================
448
449As mentioned previously, all new test files need to be in the proper
450place for the build system to find them. New tests for additional
451functionality outside of the core should be added to the layer that adds
452the functionality, in ``layer/lib/oeqa/runtime/cases`` (as long as
453:term:`BBPATH` is extended in the
454layer's ``layer.conf`` file as normal). Just remember the following:
455
456- Filenames need to map directly to test (module) names.
457
458- Do not use module names that collide with existing core tests.
459
460- Minimally, an empty ``__init__.py`` file must be present in the runtime
461 directory.
462
463To create a new test, start by copying an existing module (e.g.
464``oe_syslog.py`` or ``gcc.py`` are good ones to use). Test modules can use
465code from ``meta/lib/oeqa/utils``, which are helper classes.
466
467.. note::
468
469 Structure shell commands such that you rely on them and they return a
470 single code for success. Be aware that sometimes you will need to
471 parse the output. See the ``df.py`` and ``date.py`` modules for examples.
472
473You will notice that all test classes inherit ``oeRuntimeTest``, which
474is found in ``meta/lib/oetest.py``. This base class offers some helper
475attributes, which are described in the following sections:
476
477Class Methods
478-------------
479
480Class methods are as follows:
481
482- *hasPackage(pkg):* Returns "True" if ``pkg`` is in the installed
483 package list of the image, which is based on the manifest file that
484 is generated during the :ref:`ref-tasks-rootfs` task.
485
486- *hasFeature(feature):* Returns "True" if the feature is in
487 :term:`IMAGE_FEATURES` or
488 :term:`DISTRO_FEATURES`.
489
490Class Attributes
491----------------
492
493Class attributes are as follows:
494
495- *pscmd:* Equals "ps -ef" if ``procps`` is installed in the image.
496 Otherwise, ``pscmd`` equals "ps" (busybox).
497
498- *tc:* The called test context, which gives access to the
499 following attributes:
500
501 - *d:* The BitBake datastore, which allows you to use stuff such
502 as ``oeRuntimeTest.tc.d.getVar("VIRTUAL-RUNTIME_init_manager")``.
503
504 - *testslist and testsrequired:* Used internally. The tests
505 do not need these.
506
507 - *filesdir:* The absolute path to
508 ``meta/lib/oeqa/runtime/files``, which contains helper files for
509 tests meant for copying on the target such as small files written
510 in C for compilation.
511
512 - *target:* The target controller object used to deploy and
513 start an image on a particular target (e.g. Qemu, SimpleRemote,
514 and SystemdbootTarget). Tests usually use the following:
515
516 - *ip:* The target's IP address.
517
518 - *server_ip:* The host's IP address, which is usually used
519 by the DNF test suite.
520
521 - *run(cmd, timeout=None):* The single, most used method.
522 This command is a wrapper for: ``ssh root@host "cmd"``. The
523 command returns a tuple: (status, output), which are what their
524 names imply - the return code of "cmd" and whatever output it
525 produces. The optional timeout argument represents the number
526 of seconds the test should wait for "cmd" to return. If the
527 argument is "None", the test uses the default instance's
528 timeout period, which is 300 seconds. If the argument is "0",
529 the test runs until the command returns.
530
531 - *copy_to(localpath, remotepath):*
532 ``scp localpath root@ip:remotepath``.
533
534 - *copy_from(remotepath, localpath):*
535 ``scp root@host:remotepath localpath``.
536
537Instance Attributes
538-------------------
539
540There is a single instance attribute, which is ``target``. The ``target``
541instance attribute is identical to the class attribute of the same name,
542which is described in the previous section. This attribute exists as
543both an instance and class attribute so tests can use
544``self.target.run(cmd)`` in instance methods instead of
545``oeRuntimeTest.tc.target.run(cmd)``.
546
547Installing Packages in the DUT Without the Package Manager
548==========================================================
549
550When a test requires a package built by BitBake, it is possible to
551install that package. Installing the package does not require a package
552manager be installed in the device under test (DUT). It does, however,
553require an SSH connection and the target must be using the
554``sshcontrol`` class.
555
556.. note::
557
558 This method uses ``scp`` to copy files from the host to the target, which
559 causes permissions and special attributes to be lost.
560
561A JSON file is used to define the packages needed by a test. This file
562must be in the same path as the file used to define the tests.
563Furthermore, the filename must map directly to the test module name with
564a ``.json`` extension.
565
566The JSON file must include an object with the test name as keys of an
567object or an array. This object (or array of objects) uses the following
568data:
569
570- "pkg" --- a mandatory string that is the name of the package to be
571 installed.
572
573- "rm" --- an optional boolean, which defaults to "false", that specifies
574 to remove the package after the test.
575
576- "extract" --- an optional boolean, which defaults to "false", that
577 specifies if the package must be extracted from the package format.
578 When set to "true", the package is not automatically installed into
579 the DUT.
580
581Here is an example JSON file that handles test "foo" installing
582package "bar" and test "foobar" installing packages "foo" and "bar".
583Once the test is complete, the packages are removed from the DUT::
584
585 {
586 "foo": {
587 "pkg": "bar"
588 },
589 "foobar": [
590 {
591 "pkg": "foo",
592 "rm": true
593 },
594 {
595 "pkg": "bar",
596 "rm": true
597 }
598 ]
599 }
600