summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oe/package_manager/__init__.py76
-rw-r--r--meta/lib/oe/patch.py14
-rw-r--r--meta/lib/oe/rootfs.py4
-rw-r--r--meta/lib/oe/sstatesig.py7
-rw-r--r--meta/lib/oe/utils.py13
-rw-r--r--meta/lib/oeqa/core/runner.py2
-rw-r--r--meta/lib/oeqa/core/target/ssh.py16
-rw-r--r--meta/lib/oeqa/runtime/cases/ssh.py4
-rw-r--r--meta/lib/oeqa/sdk/context.py12
-rw-r--r--meta/lib/oeqa/selftest/cases/devtool.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/meta_ide.py4
-rw-r--r--meta/lib/oeqa/selftest/cases/overlayfs.py41
-rw-r--r--meta/lib/oeqa/selftest/cases/reproducible.py10
-rw-r--r--meta/lib/oeqa/selftest/cases/rust.py13
-rw-r--r--meta/lib/oeqa/selftest/cases/sstatetests.py2
-rw-r--r--meta/lib/oeqa/utils/gitarchive.py4
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py11
17 files changed, 134 insertions, 101 deletions
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py
index d3b2317894..2100a97c12 100644
--- a/meta/lib/oe/package_manager/__init__.py
+++ b/meta/lib/oe/package_manager/__init__.py
@@ -365,45 +365,43 @@ class PackageManager(object, metaclass=ABCMeta):
365 for complementary_linguas in (self.d.getVar('IMAGE_LINGUAS_COMPLEMENTARY') or "").split(): 365 for complementary_linguas in (self.d.getVar('IMAGE_LINGUAS_COMPLEMENTARY') or "").split():
366 globs += (" " + complementary_linguas) % lang 366 globs += (" " + complementary_linguas) % lang
367 367
368 if globs is None: 368 if globs:
369 return 369 # we need to write the list of installed packages to a file because the
370 370 # oe-pkgdata-util reads it from a file
371 # we need to write the list of installed packages to a file because the 371 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs:
372 # oe-pkgdata-util reads it from a file 372 pkgs = self.list_installed()
373 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs: 373
374 pkgs = self.list_installed() 374 provided_pkgs = set()
375 375 for pkg in pkgs.values():
376 provided_pkgs = set() 376 provided_pkgs |= set(pkg.get('provs', []))
377 for pkg in pkgs.values(): 377
378 provided_pkgs |= set(pkg.get('provs', [])) 378 output = oe.utils.format_pkg_list(pkgs, "arch")
379 379 installed_pkgs.write(output)
380 output = oe.utils.format_pkg_list(pkgs, "arch") 380 installed_pkgs.flush()
381 installed_pkgs.write(output) 381
382 installed_pkgs.flush() 382 cmd = ["oe-pkgdata-util",
383 383 "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name,
384 cmd = ["oe-pkgdata-util", 384 globs]
385 "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name, 385 exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY')
386 globs] 386 if exclude:
387 exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY') 387 cmd.extend(['--exclude=' + '|'.join(exclude.split())])
388 if exclude: 388 try:
389 cmd.extend(['--exclude=' + '|'.join(exclude.split())]) 389 bb.note('Running %s' % cmd)
390 try: 390 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
391 bb.note('Running %s' % cmd) 391 stdout, stderr = proc.communicate()
392 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 392 if stderr: bb.note(stderr.decode("utf-8"))
393 stdout, stderr = proc.communicate() 393 complementary_pkgs = stdout.decode("utf-8")
394 if stderr: bb.note(stderr.decode("utf-8")) 394 complementary_pkgs = set(complementary_pkgs.split())
395 complementary_pkgs = stdout.decode("utf-8") 395 skip_pkgs = sorted(complementary_pkgs & provided_pkgs)
396 complementary_pkgs = set(complementary_pkgs.split()) 396 install_pkgs = sorted(complementary_pkgs - provided_pkgs)
397 skip_pkgs = sorted(complementary_pkgs & provided_pkgs) 397 bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % (
398 install_pkgs = sorted(complementary_pkgs - provided_pkgs) 398 ' '.join(install_pkgs),
399 bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % ( 399 ' '.join(skip_pkgs)))
400 ' '.join(install_pkgs), 400 self.install(install_pkgs, hard_depends_only=True)
401 ' '.join(skip_pkgs))) 401 except subprocess.CalledProcessError as e:
402 self.install(install_pkgs, hard_depends_only=True) 402 bb.fatal("Could not compute complementary packages list. Command "
403 except subprocess.CalledProcessError as e: 403 "'%s' returned %d:\n%s" %
404 bb.fatal("Could not compute complementary packages list. Command " 404 (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
405 "'%s' returned %d:\n%s" %
406 (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
407 405
408 if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1': 406 if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1':
409 target_arch = self.d.getVar('TARGET_ARCH') 407 target_arch = self.d.getVar('TARGET_ARCH')
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py
index 60a0cc8291..417333e431 100644
--- a/meta/lib/oe/patch.py
+++ b/meta/lib/oe/patch.py
@@ -462,21 +462,23 @@ class GitApplyTree(PatchTree):
462 return (tmpfile, cmd) 462 return (tmpfile, cmd)
463 463
464 @staticmethod 464 @staticmethod
465 def addNote(repo, ref, key, value=None): 465 def addNote(repo, ref, key, value=None, commituser=None, commitemail=None):
466 note = key + (": %s" % value if value else "") 466 note = key + (": %s" % value if value else "")
467 notes_ref = GitApplyTree.notes_ref 467 notes_ref = GitApplyTree.notes_ref
468 runcmd(["git", "config", "notes.rewriteMode", "ignore"], repo) 468 runcmd(["git", "config", "notes.rewriteMode", "ignore"], repo)
469 runcmd(["git", "config", "notes.displayRef", notes_ref, notes_ref], repo) 469 runcmd(["git", "config", "notes.displayRef", notes_ref, notes_ref], repo)
470 runcmd(["git", "config", "notes.rewriteRef", notes_ref, notes_ref], repo) 470 runcmd(["git", "config", "notes.rewriteRef", notes_ref, notes_ref], repo)
471 runcmd(["git", "notes", "--ref", notes_ref, "append", "-m", note, ref], repo) 471 cmd = ["git"]
472 GitApplyTree.gitCommandUserOptions(cmd, commituser, commitemail)
473 runcmd(cmd + ["notes", "--ref", notes_ref, "append", "-m", note, ref], repo)
472 474
473 @staticmethod 475 @staticmethod
474 def removeNote(repo, ref, key): 476 def removeNote(repo, ref, key, commituser=None, commitemail=None):
475 notes = GitApplyTree.getNotes(repo, ref) 477 notes = GitApplyTree.getNotes(repo, ref)
476 notes = {k: v for k, v in notes.items() if k != key and not k.startswith(key + ":")} 478 notes = {k: v for k, v in notes.items() if k != key and not k.startswith(key + ":")}
477 runcmd(["git", "notes", "--ref", GitApplyTree.notes_ref, "remove", "--ignore-missing", ref], repo) 479 runcmd(["git", "notes", "--ref", GitApplyTree.notes_ref, "remove", "--ignore-missing", ref], repo)
478 for note, value in notes.items(): 480 for note, value in notes.items():
479 GitApplyTree.addNote(repo, ref, note, value) 481 GitApplyTree.addNote(repo, ref, note, value, commituser, commitemail)
480 482
481 @staticmethod 483 @staticmethod
482 def getNotes(repo, ref): 484 def getNotes(repo, ref):
@@ -507,7 +509,7 @@ class GitApplyTree(PatchTree):
507 GitApplyTree.gitCommandUserOptions(cmd, d=d) 509 GitApplyTree.gitCommandUserOptions(cmd, d=d)
508 cmd += ["commit", "-m", subject, "--no-verify"] 510 cmd += ["commit", "-m", subject, "--no-verify"]
509 runcmd(cmd, dir) 511 runcmd(cmd, dir)
510 GitApplyTree.addNote(dir, "HEAD", GitApplyTree.ignore_commit) 512 GitApplyTree.addNote(dir, "HEAD", GitApplyTree.ignore_commit, d.getVar('PATCH_GIT_USER_NAME'), d.getVar('PATCH_GIT_USER_EMAIL'))
511 513
512 @staticmethod 514 @staticmethod
513 def extractPatches(tree, startcommits, outdir, paths=None): 515 def extractPatches(tree, startcommits, outdir, paths=None):
@@ -654,7 +656,7 @@ class GitApplyTree(PatchTree):
654 raise 656 raise
655 finally: 657 finally:
656 if patch_applied: 658 if patch_applied:
657 GitApplyTree.addNote(self.dir, "HEAD", GitApplyTree.original_patch, os.path.basename(patch['file'])) 659 GitApplyTree.addNote(self.dir, "HEAD", GitApplyTree.original_patch, os.path.basename(patch['file']), self.commituser, self.commitemail)
658 660
659 661
660class QuiltTree(PatchSet): 662class QuiltTree(PatchSet):
diff --git a/meta/lib/oe/rootfs.py b/meta/lib/oe/rootfs.py
index 8cd48f9450..5abce4ad7d 100644
--- a/meta/lib/oe/rootfs.py
+++ b/meta/lib/oe/rootfs.py
@@ -269,7 +269,11 @@ class Rootfs(object, metaclass=ABCMeta):
269 self.pm.remove(["run-postinsts"]) 269 self.pm.remove(["run-postinsts"])
270 270
271 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", 271 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
272 True, False, self.d) and \
273 not bb.utils.contains("IMAGE_FEATURES",
274 "read-only-rootfs-delayed-postinsts",
272 True, False, self.d) 275 True, False, self.d)
276
273 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE') 277 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
274 278
275 if image_rorfs or image_rorfs_force == "1": 279 if image_rorfs or image_rorfs_force == "1":
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py
index a46e5502ab..d818fce8f1 100644
--- a/meta/lib/oe/sstatesig.py
+++ b/meta/lib/oe/sstatesig.py
@@ -524,6 +524,7 @@ def OEOuthashBasic(path, sigfile, task, d):
524 if task == "package": 524 if task == "package":
525 include_timestamps = True 525 include_timestamps = True
526 include_root = False 526 include_root = False
527 source_date_epoch = float(d.getVar("SOURCE_DATE_EPOCH"))
527 hash_version = d.getVar('HASHEQUIV_HASH_VERSION') 528 hash_version = d.getVar('HASHEQUIV_HASH_VERSION')
528 extra_sigdata = d.getVar("HASHEQUIV_EXTRA_SIGDATA") 529 extra_sigdata = d.getVar("HASHEQUIV_EXTRA_SIGDATA")
529 530
@@ -615,7 +616,11 @@ def OEOuthashBasic(path, sigfile, task, d):
615 raise Exception(msg).with_traceback(e.__traceback__) 616 raise Exception(msg).with_traceback(e.__traceback__)
616 617
617 if include_timestamps: 618 if include_timestamps:
618 update_hash(" %10d" % s.st_mtime) 619 # Need to clamp to SOURCE_DATE_EPOCH
620 if s.st_mtime > source_date_epoch:
621 update_hash(" %10d" % source_date_epoch)
622 else:
623 update_hash(" %10d" % s.st_mtime)
619 624
620 update_hash(" ") 625 update_hash(" ")
621 if stat.S_ISBLK(s.st_mode) or stat.S_ISCHR(s.st_mode): 626 if stat.S_ISBLK(s.st_mode) or stat.S_ISCHR(s.st_mode):
diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
index 14a7d07ef0..c9c7a47041 100644
--- a/meta/lib/oe/utils.py
+++ b/meta/lib/oe/utils.py
@@ -482,19 +482,6 @@ def get_multilib_datastore(variant, d):
482 localdata.setVar("MLPREFIX", "") 482 localdata.setVar("MLPREFIX", "")
483 return localdata 483 return localdata
484 484
485class ImageQAFailed(Exception):
486 def __init__(self, description, name=None, logfile=None):
487 self.description = description
488 self.name = name
489 self.logfile=logfile
490
491 def __str__(self):
492 msg = 'Function failed: %s' % self.name
493 if self.description:
494 msg = msg + ' (%s)' % self.description
495
496 return msg
497
498def sh_quote(string): 485def sh_quote(string):
499 import shlex 486 import shlex
500 return shlex.quote(string) 487 return shlex.quote(string)
diff --git a/meta/lib/oeqa/core/runner.py b/meta/lib/oeqa/core/runner.py
index a86a706bd9..b683d9b80a 100644
--- a/meta/lib/oeqa/core/runner.py
+++ b/meta/lib/oeqa/core/runner.py
@@ -357,7 +357,7 @@ class OETestResultJSONHelper(object):
357 os.makedirs(write_dir, exist_ok=True) 357 os.makedirs(write_dir, exist_ok=True)
358 test_results = self._get_existing_testresults_if_available(write_dir) 358 test_results = self._get_existing_testresults_if_available(write_dir)
359 test_results[result_id] = {'configuration': configuration, 'result': test_result} 359 test_results[result_id] = {'configuration': configuration, 'result': test_result}
360 json_testresults = json.dumps(test_results, sort_keys=True, indent=4) 360 json_testresults = json.dumps(test_results, sort_keys=True, indent=1)
361 self._write_file(write_dir, self.testresult_filename, json_testresults) 361 self._write_file(write_dir, self.testresult_filename, json_testresults)
362 if has_bb: 362 if has_bb:
363 bb.utils.unlockfile(lf) 363 bb.utils.unlockfile(lf)
diff --git a/meta/lib/oeqa/core/target/ssh.py b/meta/lib/oeqa/core/target/ssh.py
index 09cdd14c75..d473469384 100644
--- a/meta/lib/oeqa/core/target/ssh.py
+++ b/meta/lib/oeqa/core/target/ssh.py
@@ -55,14 +55,14 @@ class OESSHTarget(OETarget):
55 def stop(self, **kwargs): 55 def stop(self, **kwargs):
56 pass 56 pass
57 57
58 def _run(self, command, timeout=None, ignore_status=True): 58 def _run(self, command, timeout=None, ignore_status=True, raw=False):
59 """ 59 """
60 Runs command in target using SSHProcess. 60 Runs command in target using SSHProcess.
61 """ 61 """
62 self.logger.debug("[Running]$ %s" % " ".join(command)) 62 self.logger.debug("[Running]$ %s" % " ".join(command))
63 63
64 starttime = time.time() 64 starttime = time.time()
65 status, output = SSHCall(command, self.logger, timeout) 65 status, output = SSHCall(command, self.logger, timeout, raw)
66 self.logger.debug("[Command returned '%d' after %.2f seconds]" 66 self.logger.debug("[Command returned '%d' after %.2f seconds]"
67 "" % (status, time.time() - starttime)) 67 "" % (status, time.time() - starttime))
68 68
@@ -72,7 +72,7 @@ class OESSHTarget(OETarget):
72 72
73 return (status, output) 73 return (status, output)
74 74
75 def run(self, command, timeout=None, ignore_status=True): 75 def run(self, command, timeout=None, ignore_status=True, raw=False):
76 """ 76 """
77 Runs command in target. 77 Runs command in target.
78 78
@@ -91,7 +91,7 @@ class OESSHTarget(OETarget):
91 else: 91 else:
92 processTimeout = self.timeout 92 processTimeout = self.timeout
93 93
94 status, output = self._run(sshCmd, processTimeout, ignore_status) 94 status, output = self._run(sshCmd, processTimeout, ignore_status, raw)
95 self.logger.debug('Command: %s\nStatus: %d Output: %s\n' % (command, status, output)) 95 self.logger.debug('Command: %s\nStatus: %d Output: %s\n' % (command, status, output))
96 96
97 return (status, output) 97 return (status, output)
@@ -206,7 +206,7 @@ class OESSHTarget(OETarget):
206 remoteDir = os.path.join(remotePath, tmpDir.lstrip("/")) 206 remoteDir = os.path.join(remotePath, tmpDir.lstrip("/"))
207 self.deleteDir(remoteDir) 207 self.deleteDir(remoteDir)
208 208
209def SSHCall(command, logger, timeout=None, **opts): 209def SSHCall(command, logger, timeout=None, raw=False, **opts):
210 210
211 def run(): 211 def run():
212 nonlocal output 212 nonlocal output
@@ -265,7 +265,7 @@ def SSHCall(command, logger, timeout=None, **opts):
265 else: 265 else:
266 output_raw = process.communicate()[0] 266 output_raw = process.communicate()[0]
267 267
268 output = output_raw.decode('utf-8', errors='ignore') 268 output = output_raw if raw else output_raw.decode('utf-8', errors='ignore')
269 logger.debug('Data from SSH call:\n%s' % output.rstrip()) 269 logger.debug('Data from SSH call:\n%s' % output.rstrip())
270 270
271 # timout or not, make sure process exits and is not hanging 271 # timout or not, make sure process exits and is not hanging
@@ -292,7 +292,7 @@ def SSHCall(command, logger, timeout=None, **opts):
292 292
293 options = { 293 options = {
294 "stdout": subprocess.PIPE, 294 "stdout": subprocess.PIPE,
295 "stderr": subprocess.STDOUT, 295 "stderr": subprocess.STDOUT if not raw else None,
296 "stdin": None, 296 "stdin": None,
297 "shell": False, 297 "shell": False,
298 "bufsize": -1, 298 "bufsize": -1,
@@ -320,4 +320,4 @@ def SSHCall(command, logger, timeout=None, **opts):
320 logger.debug('Something went wrong, killing SSH process') 320 logger.debug('Something went wrong, killing SSH process')
321 raise 321 raise
322 322
323 return (process.returncode, output.rstrip()) 323 return (process.returncode, output if raw else output.rstrip())
diff --git a/meta/lib/oeqa/runtime/cases/ssh.py b/meta/lib/oeqa/runtime/cases/ssh.py
index b86428002f..89d64430e5 100644
--- a/meta/lib/oeqa/runtime/cases/ssh.py
+++ b/meta/lib/oeqa/runtime/cases/ssh.py
@@ -16,8 +16,8 @@ class SSHTest(OERuntimeTestCase):
16 @OETestDepends(['ping.PingTest.test_ping']) 16 @OETestDepends(['ping.PingTest.test_ping'])
17 @OEHasPackage(['dropbear', 'openssh-sshd']) 17 @OEHasPackage(['dropbear', 'openssh-sshd'])
18 def test_ssh(self): 18 def test_ssh(self):
19 for i in range(20): 19 for i in range(5):
20 status, output = self.target.run("uname -a", timeout=5) 20 status, output = self.target.run("uname -a", timeout=30)
21 if status == 0: 21 if status == 0:
22 break 22 break
23 elif status == 255 or status == -signal.SIGTERM: 23 elif status == 255 or status == -signal.SIGTERM:
diff --git a/meta/lib/oeqa/sdk/context.py b/meta/lib/oeqa/sdk/context.py
index 01c38c24e6..77e6a98f39 100644
--- a/meta/lib/oeqa/sdk/context.py
+++ b/meta/lib/oeqa/sdk/context.py
@@ -41,11 +41,13 @@ class OESDKTestContext(OETestContext):
41 41
42 def hasTargetPackage(self, pkg, multilib=False, regex=False): 42 def hasTargetPackage(self, pkg, multilib=False, regex=False):
43 if multilib: 43 if multilib:
44 # match multilib according to sdk_env 44 stripped_sdk_env = os.path.basename(self.sdk_env)
45 mls = self.td.get('MULTILIB_VARIANTS', '').split() 45 if stripped_sdk_env.startswith('environment-setup-'):
46 for ml in mls: 46 # match multilib according to sdk_env
47 if ('ml'+ml) in self.sdk_env: 47 mls = self.td.get('MULTILIB_VARIANTS', '').split()
48 pkg = ml + '-' + pkg 48 for ml in mls:
49 if ('ml'+ml) in stripped_sdk_env:
50 pkg = ml + '-' + pkg
49 return self._hasPackage(self.target_pkg_manifest, pkg, regex=regex) 51 return self._hasPackage(self.target_pkg_manifest, pkg, regex=regex)
50 52
51class OESDKTestContextExecutor(OETestContextExecutor): 53class OESDKTestContextExecutor(OETestContextExecutor):
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index fc08906117..ee75687f01 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -2493,7 +2493,7 @@ class DevtoolIdeSdkTests(DevtoolBase):
2493 self.track_for_cleanup(tempdir) 2493 self.track_for_cleanup(tempdir)
2494 self.add_command_to_tearDown('bitbake -c clean %s' % recipe_name) 2494 self.add_command_to_tearDown('bitbake -c clean %s' % recipe_name)
2495 2495
2496 result = runCmd('devtool modify %s -x %s' % (recipe_name, tempdir)) 2496 result = runCmd('devtool modify %s -x %s --debug-build' % (recipe_name, tempdir))
2497 self.assertExists(os.path.join(tempdir, build_file), 2497 self.assertExists(os.path.join(tempdir, build_file),
2498 'Extracted source could not be found') 2498 'Extracted source could not be found')
2499 self.assertExists(os.path.join(self.workspacedir, 'conf', 2499 self.assertExists(os.path.join(self.workspacedir, 'conf',
diff --git a/meta/lib/oeqa/selftest/cases/meta_ide.py b/meta/lib/oeqa/selftest/cases/meta_ide.py
index ffe0d2604d..5a17ca52ea 100644
--- a/meta/lib/oeqa/selftest/cases/meta_ide.py
+++ b/meta/lib/oeqa/selftest/cases/meta_ide.py
@@ -20,8 +20,8 @@ class MetaIDE(OESelftestTestCase):
20 bitbake('meta-ide-support') 20 bitbake('meta-ide-support')
21 bitbake('build-sysroots -c build_native_sysroot') 21 bitbake('build-sysroots -c build_native_sysroot')
22 bitbake('build-sysroots -c build_target_sysroot') 22 bitbake('build-sysroots -c build_target_sysroot')
23 bb_vars = get_bb_vars(['MULTIMACH_TARGET_SYS', 'DEPLOY_DIR_IMAGE', 'COREBASE']) 23 bb_vars = get_bb_vars(['MACHINE_ARCH', 'TARGET_VENDOR', 'TARGET_OS', 'DEPLOY_DIR_IMAGE', 'COREBASE'])
24 cls.environment_script = 'environment-setup-%s' % bb_vars['MULTIMACH_TARGET_SYS'] 24 cls.environment_script = 'environment-setup-%s%s-%s' % (bb_vars['MACHINE_ARCH'], bb_vars['TARGET_VENDOR'], bb_vars['TARGET_OS'])
25 cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE'] 25 cls.deploydir = bb_vars['DEPLOY_DIR_IMAGE']
26 cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script) 26 cls.environment_script_path = '%s/%s' % (cls.deploydir, cls.environment_script)
27 cls.corebasedir = bb_vars['COREBASE'] 27 cls.corebasedir = bb_vars['COREBASE']
diff --git a/meta/lib/oeqa/selftest/cases/overlayfs.py b/meta/lib/oeqa/selftest/cases/overlayfs.py
index e31063567b..580fbdcb9c 100644
--- a/meta/lib/oeqa/selftest/cases/overlayfs.py
+++ b/meta/lib/oeqa/selftest/cases/overlayfs.py
@@ -5,7 +5,7 @@
5# 5#
6 6
7from oeqa.selftest.case import OESelftestTestCase 7from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import bitbake, runqemu 8from oeqa.utils.commands import bitbake, runqemu, get_bb_vars
9from oeqa.core.decorator import OETestTag 9from oeqa.core.decorator import OETestTag
10from oeqa.core.decorator.data import skipIfNotMachine 10from oeqa.core.decorator.data import skipIfNotMachine
11 11
@@ -466,6 +466,45 @@ IMAGE_INSTALL:append = " overlayfs-user"
466 line = getline_qemu(output, "Read-only file system") 466 line = getline_qemu(output, "Read-only file system")
467 self.assertTrue(line, msg=output) 467 self.assertTrue(line, msg=output)
468 468
469 @skipIfNotMachine("qemux86-64", "tests are qemux86-64 specific currently")
470 def test_postinst_on_target_for_read_only_rootfs(self):
471 """
472 Summary: The purpose of this test case is to verify that post-installation
473 on target scripts are executed even if using read-only rootfs when
474 read-only-rootfs-delayed-postinsts is set
475 Expected: The test files are created on first boot
476 """
477
478 import oe.path
479
480 vars = get_bb_vars(("IMAGE_ROOTFS", "sysconfdir"), "core-image-minimal")
481 sysconfdir = vars["sysconfdir"]
482 self.assertIsNotNone(sysconfdir)
483 # Need to use oe.path here as sysconfdir starts with /
484 targettestdir = os.path.join(sysconfdir, "postinst-test")
485
486 config = self.get_working_config()
487
488 args = {
489 'OVERLAYFS_INIT_OPTION': "",
490 'OVERLAYFS_ETC_USE_ORIG_INIT_NAME': 1,
491 'OVERLAYFS_ROOTFS_TYPE': "ext4",
492 'OVERLAYFS_ETC_CREATE_MOUNT_DIRS': 1
493 }
494
495 # read-only-rootfs is already set in get_working_config()
496 config += 'EXTRA_IMAGE_FEATURES += "read-only-rootfs-delayed-postinsts"\n'
497 config += 'CORE_IMAGE_EXTRA_INSTALL = "postinst-delayed-b"\n'
498
499 self.write_config(config.format(**args))
500
501 res = bitbake('core-image-minimal')
502
503 with runqemu('core-image-minimal', image_fstype='wic') as qemu:
504 for filename in ("rootfs", "delayed-a", "delayed-b"):
505 status, output = qemu.run_serial("test -f %s && echo found" % os.path.join(targettestdir, filename))
506 self.assertIn("found", output, "%s was not present on boot" % filename)
507
469 def get_working_config(self): 508 def get_working_config(self):
470 return """ 509 return """
471# Use systemd as init manager 510# Use systemd as init manager
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py
index 021e894012..34efa730e5 100644
--- a/meta/lib/oeqa/selftest/cases/reproducible.py
+++ b/meta/lib/oeqa/selftest/cases/reproducible.py
@@ -16,6 +16,8 @@ import os
16import datetime 16import datetime
17 17
18exclude_packages = [ 18exclude_packages = [
19 'rust-rustdoc',
20 'rust-dbg'
19 ] 21 ]
20 22
21def is_excluded(package): 23def is_excluded(package):
@@ -177,12 +179,8 @@ class ReproducibleTests(OESelftestTestCase):
177 self.sstate_targets = bb_vars['OEQA_REPRODUCIBLE_TEST_SSTATE_TARGETS'].split() 179 self.sstate_targets = bb_vars['OEQA_REPRODUCIBLE_TEST_SSTATE_TARGETS'].split()
178 180
179 self.extraresults = {} 181 self.extraresults = {}
180 self.extraresults.setdefault('reproducible.rawlogs', {})['log'] = ''
181 self.extraresults.setdefault('reproducible', {}).setdefault('files', {}) 182 self.extraresults.setdefault('reproducible', {}).setdefault('files', {})
182 183
183 def append_to_log(self, msg):
184 self.extraresults['reproducible.rawlogs']['log'] += msg
185
186 def compare_packages(self, reference_dir, test_dir, diffutils_sysroot): 184 def compare_packages(self, reference_dir, test_dir, diffutils_sysroot):
187 result = PackageCompareResults(self.oeqa_reproducible_excluded_packages) 185 result = PackageCompareResults(self.oeqa_reproducible_excluded_packages)
188 186
@@ -209,7 +207,7 @@ class ReproducibleTests(OESelftestTestCase):
209 207
210 def write_package_list(self, package_class, name, packages): 208 def write_package_list(self, package_class, name, packages):
211 self.extraresults['reproducible']['files'].setdefault(package_class, {})[name] = [ 209 self.extraresults['reproducible']['files'].setdefault(package_class, {})[name] = [
212 {'reference': p.reference, 'test': p.test} for p in packages] 210 p.reference.split("/./")[1] for p in packages]
213 211
214 def copy_file(self, source, dest): 212 def copy_file(self, source, dest):
215 bb.utils.mkdirhier(os.path.dirname(dest)) 213 bb.utils.mkdirhier(os.path.dirname(dest))
@@ -295,8 +293,6 @@ class ReproducibleTests(OESelftestTestCase):
295 293
296 self.logger.info('Reproducibility summary for %s: %s' % (c, result)) 294 self.logger.info('Reproducibility summary for %s: %s' % (c, result))
297 295
298 self.append_to_log('\n'.join("%s: %s" % (r.status, r.test) for r in result.total))
299
300 self.write_package_list(package_class, 'missing', result.missing) 296 self.write_package_list(package_class, 'missing', result.missing)
301 self.write_package_list(package_class, 'different', result.different) 297 self.write_package_list(package_class, 'different', result.different)
302 self.write_package_list(package_class, 'different_excluded', result.different_excluded) 298 self.write_package_list(package_class, 'different_excluded', result.different_excluded)
diff --git a/meta/lib/oeqa/selftest/cases/rust.py b/meta/lib/oeqa/selftest/cases/rust.py
index ad14189c6d..26f132edc4 100644
--- a/meta/lib/oeqa/selftest/cases/rust.py
+++ b/meta/lib/oeqa/selftest/cases/rust.py
@@ -3,6 +3,7 @@ import os
3import subprocess 3import subprocess
4import time 4import time
5from oeqa.core.decorator import OETestTag 5from oeqa.core.decorator import OETestTag
6from oeqa.core.decorator.data import skipIfArch
6from oeqa.core.case import OEPTestResultTestCase 7from oeqa.core.case import OEPTestResultTestCase
7from oeqa.selftest.case import OESelftestTestCase 8from oeqa.selftest.case import OESelftestTestCase
8from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu, Command 9from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars, runqemu, Command
@@ -38,15 +39,12 @@ def parse_results(filename):
38@OETestTag("toolchain-user") 39@OETestTag("toolchain-user")
39@OETestTag("runqemu") 40@OETestTag("runqemu")
40class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase): 41class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
42
43 @skipIfArch(['mips', 'mips64'])
41 def test_rust(self, *args, **kwargs): 44 def test_rust(self, *args, **kwargs):
42 # Disable Rust Oe-selftest 45 # Disable Rust Oe-selftest
43 #self.skipTest("The Rust Oe-selftest is disabled.") 46 #self.skipTest("The Rust Oe-selftest is disabled.")
44 47
45 # Skip mips32 target since it is unstable with rust tests
46 machine = get_bb_var('MACHINE')
47 if machine == "qemumips":
48 self.skipTest("The mips32 target is skipped for Rust Oe-selftest.")
49
50 # build remote-test-server before image build 48 # build remote-test-server before image build
51 recipe = "rust" 49 recipe = "rust"
52 start_time = time.time() 50 start_time = time.time()
@@ -210,9 +208,8 @@ class RustSelfTestSystemEmulated(OESelftestTestCase, OEPTestResultTestCase):
210 tmpdir = get_bb_var("TMPDIR", "rust") 208 tmpdir = get_bb_var("TMPDIR", "rust")
211 209
212 # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools. 210 # Set path for target-poky-linux-gcc, RUST_TARGET_PATH and hosttools.
213 cmd = " export PATH=%s/recipe-sysroot-native/usr/bin:$PATH;" % rustlibpath 211 cmd = "export TARGET_VENDOR=\"-poky\";"
214 cmd = cmd + " export TARGET_VENDOR=\"-poky\";" 212 cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/python3-native:%s/recipe-sysroot-native/usr/bin:%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, rustlibpath, rustlibpath, tcpath, tmpdir)
215 cmd = cmd + " export PATH=%s/recipe-sysroot-native/usr/bin/%s:%s/hosttools:$PATH;" % (rustlibpath, tcpath, tmpdir)
216 cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath 213 cmd = cmd + " export RUST_TARGET_PATH=%s/rust-targets;" % rustlibpath
217 # Trigger testing. 214 # Trigger testing.
218 cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip 215 cmd = cmd + " export TEST_DEVICE_ADDR=\"%s:12345\";" % qemu.ip
diff --git a/meta/lib/oeqa/selftest/cases/sstatetests.py b/meta/lib/oeqa/selftest/cases/sstatetests.py
index 86d6cd7464..4a2c425ac8 100644
--- a/meta/lib/oeqa/selftest/cases/sstatetests.py
+++ b/meta/lib/oeqa/selftest/cases/sstatetests.py
@@ -977,7 +977,7 @@ class SStateMirrors(SStateBase):
977 self.append_config(""" 977 self.append_config("""
978MACHINE = "{}" 978MACHINE = "{}"
979BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687" 979BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687"
980SSTATE_MIRRORS ?= "file://.* http://cdn.jsdelivr.net/yocto/sstate/all/PATH;downloadfilename=PATH" 980SSTATE_MIRRORS ?= "file://.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH"
981""".format(machine)) 981""".format(machine))
982 else: 982 else:
983 self.append_config(""" 983 self.append_config("""
diff --git a/meta/lib/oeqa/utils/gitarchive.py b/meta/lib/oeqa/utils/gitarchive.py
index 10cb267dfa..a826646059 100644
--- a/meta/lib/oeqa/utils/gitarchive.py
+++ b/meta/lib/oeqa/utils/gitarchive.py
@@ -67,7 +67,7 @@ def git_commit_data(repo, data_dir, branch, message, exclude, notes, log):
67 67
68 # Remove files that are excluded 68 # Remove files that are excluded
69 if exclude: 69 if exclude:
70 repo.run_cmd(['rm', '--cached'] + [f for f in exclude], env_update) 70 repo.run_cmd(['rm', '--cached', '--ignore-unmatch'] + [f for f in exclude], env_update)
71 71
72 tree = repo.run_cmd('write-tree', env_update) 72 tree = repo.run_cmd('write-tree', env_update)
73 73
@@ -202,6 +202,8 @@ def gitarchive(data_dir, git_dir, no_create, bare, commit_msg_subject, commit_ms
202 log.info("Pushing data to remote") 202 log.info("Pushing data to remote")
203 data_repo.run_cmd(cmd) 203 data_repo.run_cmd(cmd)
204 204
205 return tag_name
206
205# Container class for tester revisions 207# Container class for tester revisions
206TestedRev = namedtuple('TestedRev', 'commit commit_number tags') 208TestedRev = namedtuple('TestedRev', 'commit commit_number tags')
207 209
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index cda43aad8c..f1c2d2b5c9 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -519,7 +519,6 @@ class QemuRunner:
519 except Exception as e: 519 except Exception as e:
520 self.logger.warning('Extra log data exception %s' % repr(e)) 520 self.logger.warning('Extra log data exception %s' % repr(e))
521 data = None 521 data = None
522 self.thread.serial_lock.release()
523 return False 522 return False
524 523
525 with self.thread.serial_lock: 524 with self.thread.serial_lock:
@@ -822,10 +821,12 @@ class LoggingThread(threading.Thread):
822 self.logfunc(data, ".stdout") 821 self.logfunc(data, ".stdout")
823 elif self.serialsock and self.serialsock.fileno() == fd: 822 elif self.serialsock and self.serialsock.fileno() == fd:
824 if self.serial_lock.acquire(blocking=False): 823 if self.serial_lock.acquire(blocking=False):
825 data = self.recv(1024, self.serialsock) 824 try:
826 self.logger.debug("Data received serial thread %s" % data.decode('utf-8', 'replace')) 825 data = self.recv(1024, self.serialsock)
827 self.logfunc(data, ".2") 826 self.logger.debug("Data received serial thread %s" % data.decode('utf-8', 'replace'))
828 self.serial_lock.release() 827 self.logfunc(data, ".2")
828 finally:
829 self.serial_lock.release()
829 else: 830 else:
830 serial_registered = False 831 serial_registered = False
831 poll.unregister(self.serialsock.fileno()) 832 poll.unregister(self.serialsock.fileno())