diff options
author | Mariano Lopez <mariano.lopez@linux.intel.com> | 2017-01-05 13:33:07 +0000 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-01-23 12:05:20 +0000 |
commit | 3857e5c91da678d7bdc07712a1df9daa14354986 (patch) | |
tree | 475105c96bead7bf1cde8c02df595353b606e99c /meta/classes | |
parent | 211c5be54cde325242c7788f7e3eeb3f6eea7ac8 (diff) | |
download | poky-3857e5c91da678d7bdc07712a1df9daa14354986.tar.gz |
testimage.bbclass: Migrate class to use new runtime framework
This migrates testimage class to use the new framework. Most of
the code added here is to get rid off the data store dependency.
[YOCTO #10234]
(From OE-Core rev: 2aa5a4954d7610f31875ba7e655f25f8892517b6)
Signed-off-by: Mariano Lopez <mariano.lopez@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes')
-rw-r--r-- | meta/classes/testimage.bbclass | 186 |
1 files changed, 144 insertions, 42 deletions
diff --git a/meta/classes/testimage.bbclass b/meta/classes/testimage.bbclass index 62ecaef502..016c1c136a 100644 --- a/meta/classes/testimage.bbclass +++ b/meta/classes/testimage.bbclass | |||
@@ -77,6 +77,7 @@ TESTIMAGEDEPENDS_qemuall += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'creat | |||
77 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}" | 77 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}" |
78 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'ipk', 'opkg-utils-native:do_populate_sysroot', '', d)}" | 78 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'ipk', 'opkg-utils-native:do_populate_sysroot', '', d)}" |
79 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'deb', 'apt-native:do_populate_sysroot', '', d)}" | 79 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'deb', 'apt-native:do_populate_sysroot', '', d)}" |
80 | TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}" | ||
80 | 81 | ||
81 | 82 | ||
82 | TESTIMAGELOCK = "${TMPDIR}/testimage.lock" | 83 | TESTIMAGELOCK = "${TMPDIR}/testimage.lock" |
@@ -112,6 +113,9 @@ testimage_dump_host () { | |||
112 | } | 113 | } |
113 | 114 | ||
114 | python do_testimage() { | 115 | python do_testimage() { |
116 | |||
117 | testimage_sanity(d) | ||
118 | |||
115 | testimage_main(d) | 119 | testimage_main(d) |
116 | } | 120 | } |
117 | 121 | ||
@@ -120,67 +124,165 @@ do_testimage[nostamp] = "1" | |||
120 | do_testimage[depends] += "${TESTIMAGEDEPENDS}" | 124 | do_testimage[depends] += "${TESTIMAGEDEPENDS}" |
121 | do_testimage[lockfiles] += "${TESTIMAGELOCK}" | 125 | do_testimage[lockfiles] += "${TESTIMAGELOCK}" |
122 | 126 | ||
127 | def testimage_sanity(d): | ||
128 | if (d.getVar('TEST_TARGET') == 'simpleremote' | ||
129 | and (not d.getVar('TEST_TARGET_IP') | ||
130 | or not d.getVar('TEST_SERVER_IP'))): | ||
131 | bb.fatal('When TEST_TARGET is set to "simpleremote" ' | ||
132 | 'TEST_TARGET_IP and TEST_SERVER_IP are needed too.') | ||
133 | |||
123 | def testimage_main(d): | 134 | def testimage_main(d): |
124 | import unittest | ||
125 | import os | 135 | import os |
126 | import oeqa.runtime | ||
127 | import time | ||
128 | import signal | 136 | import signal |
129 | from oeqa.oetest import ImageTestContext | 137 | import json |
130 | from oeqa.targetcontrol import get_target_controller | 138 | import sys |
131 | from bb.utils import export_proxies | 139 | import logging |
132 | from oeqa.utils.dump import HostDumper | 140 | import time |
133 | 141 | ||
142 | from bb.utils import export_proxies | ||
143 | from oeqa.runtime.context import OERuntimeTestContext | ||
144 | from oeqa.runtime.context import OERuntimeTestContextExecutor | ||
145 | from oeqa.core.target.qemu import supported_fstypes | ||
146 | from oeqa.utils import make_logger_bitbake_compatible | ||
147 | |||
148 | def sigterm_exception(signum, stackframe): | ||
149 | """ | ||
150 | Catch SIGTERM from worker in order to stop qemu. | ||
151 | """ | ||
152 | raise RuntimeError | ||
153 | |||
154 | logger = make_logger_bitbake_compatible(logging.getLogger("BitBake")) | ||
134 | pn = d.getVar("PN") | 155 | pn = d.getVar("PN") |
156 | |||
135 | bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR")) | 157 | bb.utils.mkdirhier(d.getVar("TEST_LOG_DIR")) |
136 | test_create_extract_dirs(d) | 158 | #test_create_extract_dirs(d) |
159 | |||
160 | image_name = ("%s/%s" % (d.getVar('DEPLOY_DIR_IMAGE'), | ||
161 | d.getVar('IMAGE_LINK_NAME'))) | ||
162 | |||
163 | tdname = "%s.testdata.json" % image_name | ||
164 | td = json.load(open(tdname, "r")) | ||
165 | |||
166 | image_manifest = "%s.manifest" % image_name | ||
167 | image_packages = OERuntimeTestContextExecutor.readPackagesManifest(image_manifest) | ||
168 | |||
169 | # Get machine | ||
170 | machine = d.getVar("MACHINE") | ||
171 | |||
172 | # Get rootfs | ||
173 | fstypes = [fs for fs in d.getVar('IMAGE_FSTYPES').split(' ') | ||
174 | if fs in supported_fstypes] | ||
175 | if not fstypes: | ||
176 | bb.fatal('Unsupported image type built. Add a comptible image to ' | ||
177 | 'IMAGE_FSTYPES. Supported types: %s' % | ||
178 | ', '.join(supported_fstypes)) | ||
179 | rootfs = '%s.%s' % (image_name, fstypes[0]) | ||
180 | |||
181 | # Get tmpdir (not really used, just for compatibility) | ||
182 | tmpdir = d.getVar("TMPDIR") | ||
183 | |||
184 | # Get deploy_dir_image (not really used, just for compatibility) | ||
185 | dir_image = d.getVar("DEPLOY_DIR_IMAGE") | ||
186 | |||
187 | # Get bootlog | ||
188 | bootlog = os.path.join(d.getVar("TEST_LOG_DIR"), | ||
189 | 'qemu_boot_log.%s' % d.getVar('DATETIME')) | ||
190 | |||
191 | # Get display | ||
192 | display = d.getVar("BB_ORIGENV").getVar("DISPLAY") | ||
193 | |||
194 | # Get kernel | ||
195 | kernel_name = ('%s-%s.bin' % (d.getVar("KERNEL_IMAGETYPE"), machine)) | ||
196 | kernel = os.path.join(d.getVar("DEPLOY_DIR_IMAGE"), kernel_name) | ||
197 | |||
198 | # Get boottime | ||
199 | boottime = int(d.getVar("TEST_QEMUBOOT_TIMEOUT")) | ||
200 | |||
201 | # Get use_kvm | ||
202 | qemu_use_kvm = d.getVar("QEMU_USE_KVM") | ||
203 | if qemu_use_kvm and qemu_use_kvm == 'True' and 'x86' in machine: | ||
204 | kvm = True | ||
205 | else: | ||
206 | kvm = False | ||
207 | |||
208 | # TODO: We use the current implementatin of qemu runner because of | ||
209 | # time constrains, qemu runner really needs a refactor too. | ||
210 | target_kwargs = { 'machine' : machine, | ||
211 | 'rootfs' : rootfs, | ||
212 | 'tmpdir' : tmpdir, | ||
213 | 'dir_image' : dir_image, | ||
214 | 'display' : display, | ||
215 | 'kernel' : kernel, | ||
216 | 'boottime' : boottime, | ||
217 | 'bootlog' : bootlog, | ||
218 | 'kvm' : kvm, | ||
219 | } | ||
137 | 220 | ||
138 | # runtime use network for download projects for build | 221 | # runtime use network for download projects for build |
139 | export_proxies(d) | 222 | export_proxies(d) |
140 | 223 | ||
141 | # we need the host dumper in test context | 224 | # we need the host dumper in test context |
142 | host_dumper = HostDumper(d.getVar("testimage_dump_host", True), | 225 | host_dumper = OERuntimeTestContextExecutor.getHostDumper( |
143 | d.getVar("TESTIMAGE_DUMP_DIR", True)) | 226 | d.getVar("testimage_dump_host"), |
227 | d.getVar("TESTIMAGE_DUMP_DIR")) | ||
144 | 228 | ||
145 | # the robot dance | 229 | # the robot dance |
146 | target = get_target_controller(d) | 230 | target = OERuntimeTestContextExecutor.getTarget( |
231 | d.getVar("TEST_TARGET"), None, d.getVar("TEST_TARGET_IP"), | ||
232 | d.getVar("TEST_SERVER_IP"), **target_kwargs) | ||
147 | 233 | ||
148 | # test context | 234 | # test context |
149 | tc = ImageTestContext(d, target, host_dumper) | 235 | tc = OERuntimeTestContext(td, logger, target, host_dumper, image_packages) |
150 | 236 | ||
151 | # this is a dummy load of tests | 237 | # Load tests before starting the target |
152 | # we are doing that to find compile errors in the tests themselves | 238 | test_paths = get_runtime_paths(d) |
153 | # before booting the image | 239 | test_modules = d.getVar('TEST_SUITES') |
154 | try: | 240 | tc.loadTests(test_paths, modules=test_modules) |
155 | tc.loadTests() | 241 | |
156 | except Exception as e: | 242 | bootparams = None |
157 | import traceback | 243 | if d.getVar('VIRTUAL-RUNTIME_init_manager', '') == 'systemd': |
158 | bb.fatal("Loading tests failed:\n%s" % traceback.format_exc()) | 244 | bootparams = 'systemd.log_level=debug systemd.log_target=console' |
159 | 245 | ||
160 | tc.extract_packages() | 246 | results = None |
161 | target.deploy() | 247 | orig_sigterm_handler = signal.signal(signal.SIGTERM, sigterm_exception) |
162 | try: | 248 | try: |
163 | bootparams = None | 249 | # We need to check if runqemu ends unexpectedly |
164 | if d.getVar('VIRTUAL-RUNTIME_init_manager', '') == 'systemd': | 250 | # or if the worker send us a SIGTERM |
165 | bootparams = 'systemd.log_level=debug systemd.log_target=console' | 251 | tc.target.start(extra_bootparams=bootparams) |
166 | target.start(extra_bootparams=bootparams) | 252 | results = tc.runTests() |
167 | starttime = time.time() | 253 | except (RuntimeError, BlockingIOError) as err: |
168 | result = tc.runTests() | 254 | if isinstance(err, RuntimeError): |
169 | stoptime = time.time() | 255 | bb.error('testimage received SIGTERM, shutting down...') |
170 | if result.wasSuccessful(): | ||
171 | bb.plain("%s - Ran %d test%s in %.3fs" % (pn, result.testsRun, result.testsRun != 1 and "s" or "", stoptime - starttime)) | ||
172 | msg = "%s - OK - All required tests passed" % pn | ||
173 | skipped = len(result.skipped) | ||
174 | if skipped: | ||
175 | msg += " (skipped=%d)" % skipped | ||
176 | bb.plain(msg) | ||
177 | else: | 256 | else: |
178 | bb.fatal("%s - FAILED - check the task log and the ssh log" % pn) | 257 | bb.error('runqemu failed, shutting down...') |
179 | except BlockingIOError as err: | 258 | if results: |
180 | bb.error('runqemu failed, shutting down...') | 259 | results.stop() |
260 | results = None | ||
181 | finally: | 261 | finally: |
182 | signal.signal(signal.SIGTERM, tc.origsigtermhandler) | 262 | signal.signal(signal.SIGTERM, orig_sigterm_handler) |
183 | target.stop() | 263 | tc.target.stop() |
264 | |||
265 | # Show results (if we have them) | ||
266 | if not results: | ||
267 | bb.fatal('%s - FAILED - tests were interrupted during execution' % pn) | ||
268 | tc.logSummary(results, pn) | ||
269 | tc.logDetails() | ||
270 | if not results.wasSuccessful(): | ||
271 | bb.fatal('%s - FAILED - check the task log and the ssh log' % pn) | ||
272 | |||
273 | def get_runtime_paths(d): | ||
274 | """ | ||
275 | Returns a list of paths where runtime test must reside. | ||
276 | |||
277 | Runtime tests are expected in <LAYER_DIR>/lib/oeqa/runtime/cases/ | ||
278 | """ | ||
279 | paths = [] | ||
280 | |||
281 | for layer in d.getVar('BBLAYERS').split(): | ||
282 | path = os.path.join(layer, 'lib/oeqa/runtime/cases') | ||
283 | if os.path.isdir(path): | ||
284 | paths.append(path) | ||
285 | return paths | ||
184 | 286 | ||
185 | def test_create_extract_dirs(d): | 287 | def test_create_extract_dirs(d): |
186 | install_path = d.getVar("TEST_INSTALL_TMP_DIR") | 288 | install_path = d.getVar("TEST_INSTALL_TMP_DIR") |
@@ -193,6 +295,6 @@ def test_create_extract_dirs(d): | |||
193 | bb.utils.mkdirhier(extracted_path) | 295 | bb.utils.mkdirhier(extracted_path) |
194 | 296 | ||
195 | 297 | ||
196 | testimage_main[vardepsexclude] =+ "BB_ORIGENV" | 298 | testimage_main[vardepsexclude] += "BB_ORIGENV DATETIME" |
197 | 299 | ||
198 | inherit testsdk | 300 | inherit testsdk |