summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/testimage.bbclass186
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
77TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}" 77TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}"
78TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'ipk', 'opkg-utils-native:do_populate_sysroot', '', d)}" 78TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'ipk', 'opkg-utils-native:do_populate_sysroot', '', d)}"
79TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'deb', 'apt-native:do_populate_sysroot', '', d)}" 79TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'deb', 'apt-native:do_populate_sysroot', '', d)}"
80TESTIMAGEDEPENDS += "${@bb.utils.contains('IMAGE_PKGTYPE', 'rpm', 'python-smartpm-native:do_populate_sysroot', '', d)}"
80 81
81 82
82TESTIMAGELOCK = "${TMPDIR}/testimage.lock" 83TESTIMAGELOCK = "${TMPDIR}/testimage.lock"
@@ -112,6 +113,9 @@ testimage_dump_host () {
112} 113}
113 114
114python do_testimage() { 115python 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"
120do_testimage[depends] += "${TESTIMAGEDEPENDS}" 124do_testimage[depends] += "${TESTIMAGEDEPENDS}"
121do_testimage[lockfiles] += "${TESTIMAGELOCK}" 125do_testimage[lockfiles] += "${TESTIMAGELOCK}"
122 126
127def 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
123def testimage_main(d): 134def 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
273def 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
185def test_create_extract_dirs(d): 287def 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
196testimage_main[vardepsexclude] =+ "BB_ORIGENV" 298testimage_main[vardepsexclude] += "BB_ORIGENV DATETIME"
197 299
198inherit testsdk 300inherit testsdk