summaryrefslogtreecommitdiffstats
path: root/meta/classes/testimage.bbclass
diff options
context:
space:
mode:
authorAlejandro Hernandez Samaniego <alejandro@enedino.org>2020-02-08 02:32:02 -0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2020-02-13 12:19:14 +0000
commita3416a5933892df940514842a34120658096ca07 (patch)
tree270a9a6ee9903866341a9cd3209c5ede69796fcb /meta/classes/testimage.bbclass
parente5978093075fe84ac949b2f4022f92e3f83ec2c0 (diff)
downloadpoky-a3416a5933892df940514842a34120658096ca07.tar.gz
testimage: Extend runtime testing infrastructure to allow unconventional booting processes to be tested
The current runtime infrastructure contains hardcoded values which Ill refer to as patterns, these patterns are either searched through or sent via the serial terminal to communicate between HOST and TARGET. These patterns are required since they allow us to check when a device has finished booting, to log in, and to check whether a command sent from our tests has returned, this way we are able to check both the status of the commands that were sent along with its output. The testing process goes somewhat as follows: 1. Launch QEMU and start booting. 2. Check when the device has booted by looking for the pattern login:. 3. Log in as the root user (default for our images). 4. Check that we were able to log in succesfully. 5. Start running the runtime test cases defined by TEST_SUITES. 6. One of such test cases could send a command to the QEMU target. 7. Check whether that command returned. 8. Check its output and status, return whether the test case passed or failed. This patch allows this set of patterns to be defined instead of being hardcoded, but it also automatically sets the defaults that we have been using in the past if they have not been manually defined, for this reason, the patch is less invasive and should not affect in any way how tests are currently being run. Cases that can be enabled with this patch: - A customized image that does not use the root user (or maybe we want to check what happens if we dont use the root user). - An image where the PS1 env variable has been modified, and the prompt pattern wouldnt match the default. - Baremetal applications, which do not follow the conventional way of booting Linux and would probably not show a prompt for a user to log in, same applies for testing bootloaders. - poky-tiny: Using DISTRO=poky-tiny and an image such as the core-image-tiny from meta-intel, which boots directly to RAM, and does not show a log in prompt since it does not contain a conventional init process. The code itself contains comments that should be self explanatory but here is an example on how these patterns can be defined in a hypothetical case where we want to run test cases as the webserver user instead: TESTIMAGE_BOOT_PATTERNS = "send_login_user search_login_succeeded" TESTIMAGE_BOOT_PATTERNS[send_login_user] = "webserver\n" TESTIMAGE_BOOT_PATTERNS[search_login_succeeded] = "webserver@[a-zA-Z0-9\-]+:~#" The variable TESTIMAGE_BOOT_PATTERNS defines which patterns to override when used to communicate with the target when booting, anyone familiar with the PACKAGECONFIG syntax should have no trouble setting these. Other patterns would still be set up as default, e.g. search_reached_prompt would still be login: The accepted flags for TESTIMAGE_BOOT_PATTERNS are the following: search_reached_prompt, send_login_user, search_login_succeeded, search_cmd_finished. They are prefixed with either search/send, to differentiate if the pattern is meant to be sent or searched to/from the target terminal. A working example of this code that falls under the baremetal case mentioned above along with a test case is present on the meta-freertos layer, which tests an RTOS image built with OpenEmbedded and automatically runs a test case on it after booting such image: As usual, INHERIT += "testimage" needs to be present on local.conf $ bitbake freertos-demo -c testimage RESULTS: RESULTS - freertos_echo.FreeRTOSTest.test_freertos_echo: PASSED (2.00s) SUMMARY: freertos-demo () - Ran 1 test in 2.006s freertos-demo - OK - All required tests passed (successes=1, skipped=0, failures=0, errors=0) (From OE-Core rev: 3ab2cbfeff371e8791b031a2852eeef80101a831) Signed-off-by: Alejandro Hernandez Samaniego <aehs29@gmail.com> Signed-off-by: Alejandro Hernandez Samaniego <alejandro@enedino.org> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes/testimage.bbclass')
-rw-r--r--meta/classes/testimage.bbclass39
1 files changed, 39 insertions, 0 deletions
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass
index 0d55c3247e..75f0f2c3e3 100644
--- a/meta/classes/testimage.bbclass
+++ b/meta/classes/testimage.bbclass
@@ -34,6 +34,17 @@ TESTIMAGE_AUTO ??= "0"
34# TEST_QEMUPARAMS can be used to pass extra parameters to qemu, e.g. "-m 1024" for setting the amount of ram to 1 GB. 34# TEST_QEMUPARAMS can be used to pass extra parameters to qemu, e.g. "-m 1024" for setting the amount of ram to 1 GB.
35# TEST_RUNQEMUPARAMS can be used to pass extra parameters to runqemu, e.g. "gl" to enable OpenGL acceleration. 35# TEST_RUNQEMUPARAMS can be used to pass extra parameters to runqemu, e.g. "gl" to enable OpenGL acceleration.
36 36
37# TESTIMAGE_BOOT_PATTERNS can be used to override certain patterns used to communicate with the target when booting,
38# if a pattern is not specifically present on this variable a default will be used when booting the target.
39# TESTIMAGE_BOOT_PATTERNS[<flag>] overrides the pattern used for that specific flag, where flag comes from a list of accepted flags
40# e.g. normally the system boots and waits for a login prompt (login:), after that it sends the command: "root\n" to log as the root user
41# if we wanted to log in as the hypothetical "webserver" user for example we could set the following:
42# TESTIMAGE_BOOT_PATTERNS = "send_login_user search_login_succeeded"
43# TESTIMAGE_BOOT_PATTERNS[send_login_user] = "webserver\n"
44# TESTIMAGE_BOOT_PATTERNS[search_login_succeeded] = "webserver@[a-zA-Z0-9\-]+:~#"
45# The accepted flags are the following: search_reached_prompt, send_login_user, search_login_succeeded, search_cmd_finished.
46# They are prefixed with either search/send, to differentiate if the pattern is meant to be sent or searched to/from the target terminal
47
37TEST_LOG_DIR ?= "${WORKDIR}/testimage" 48TEST_LOG_DIR ?= "${WORKDIR}/testimage"
38 49
39TEST_EXPORT_DIR ?= "${TMPDIR}/testimage/${PN}" 50TEST_EXPORT_DIR ?= "${TMPDIR}/testimage/${PN}"
@@ -68,6 +79,8 @@ TEST_TARGET ?= "qemu"
68TEST_QEMUPARAMS ?= "" 79TEST_QEMUPARAMS ?= ""
69TEST_RUNQEMUPARAMS ?= "" 80TEST_RUNQEMUPARAMS ?= ""
70 81
82TESTIMAGE_BOOT_PATTERNS ?= ""
83
71TESTIMAGEDEPENDS = "" 84TESTIMAGEDEPENDS = ""
72TESTIMAGEDEPENDS_append_qemuall = " qemu-native:do_populate_sysroot qemu-helper-native:do_populate_sysroot qemu-helper-native:do_addto_recipe_sysroot" 85TESTIMAGEDEPENDS_append_qemuall = " qemu-native:do_populate_sysroot qemu-helper-native:do_populate_sysroot qemu-helper-native:do_addto_recipe_sysroot"
73TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'cpio-native:do_populate_sysroot', '', d)}" 86TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'cpio-native:do_populate_sysroot', '', d)}"
@@ -150,6 +163,29 @@ def get_testimage_json_result_dir(d):
150def get_testimage_result_id(configuration): 163def get_testimage_result_id(configuration):
151 return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'], configuration['MACHINE'], configuration['STARTTIME']) 164 return '%s_%s_%s_%s' % (configuration['TEST_TYPE'], configuration['IMAGE_BASENAME'], configuration['MACHINE'], configuration['STARTTIME'])
152 165
166def get_testimage_boot_patterns(d):
167 from collections import defaultdict
168 boot_patterns = defaultdict(str)
169 # Only accept certain values
170 accepted_patterns = ['search_reached_prompt', 'send_login_user', 'search_login_succeeded', 'search_cmd_finished']
171 # Not all patterns need to be overriden, e.g. perhaps we only want to change the user
172 boot_patterns_flags = d.getVarFlags('TESTIMAGE_BOOT_PATTERNS') or {}
173 if boot_patterns_flags:
174 patterns_set = [p for p in boot_patterns_flags.items() if p[0] in d.getVar('TESTIMAGE_BOOT_PATTERNS').split()]
175 for flag, flagval in patterns_set:
176 if flag not in accepted_patterns:
177 bb.fatal('Testimage: The only accepted boot patterns are: search_reached_prompt,send_login_user, \
178 search_login_succeeded,search_cmd_finished\n Make sure your TESTIMAGE_BOOT_PATTERNS=%s \
179 contains an accepted flag.' % d.getVar('TESTIMAGE_BOOT_PATTERNS'))
180 return
181 # We know boot prompt is searched through in binary format, others might be expressions
182 if flag == 'search_reached_prompt':
183 boot_patterns[flag] = flagval.encode()
184 else:
185 boot_patterns[flag] = flagval.encode().decode('unicode-escape')
186 return boot_patterns
187
188
153def testimage_main(d): 189def testimage_main(d):
154 import os 190 import os
155 import json 191 import json
@@ -259,6 +295,9 @@ def testimage_main(d):
259 'serial_ports': len(d.getVar("SERIAL_CONSOLES").split()), 295 'serial_ports': len(d.getVar("SERIAL_CONSOLES").split()),
260 } 296 }
261 297
298 if d.getVar("TESTIMAGE_BOOT_PATTERNS"):
299 target_kwargs['boot_patterns'] = get_testimage_boot_patterns(d)
300
262 # TODO: Currently BBPATH is needed for custom loading of targets. 301 # TODO: Currently BBPATH is needed for custom loading of targets.
263 # It would be better to find these modules using instrospection. 302 # It would be better to find these modules using instrospection.
264 target_kwargs['target_modules_path'] = d.getVar('BBPATH') 303 target_kwargs['target_modules_path'] = d.getVar('BBPATH')