diff options
Diffstat (limited to 'meta/lib')
25 files changed, 268 insertions, 45 deletions
diff --git a/meta/lib/oe/copy_buildsystem.py b/meta/lib/oe/copy_buildsystem.py index 31a84f5b06..d97bf9d1b9 100644 --- a/meta/lib/oe/copy_buildsystem.py +++ b/meta/lib/oe/copy_buildsystem.py | |||
@@ -20,7 +20,7 @@ def _smart_copy(src, dest): | |||
20 | mode = os.stat(src).st_mode | 20 | mode = os.stat(src).st_mode |
21 | if stat.S_ISDIR(mode): | 21 | if stat.S_ISDIR(mode): |
22 | bb.utils.mkdirhier(dest) | 22 | bb.utils.mkdirhier(dest) |
23 | cmd = "tar --exclude='.git' --xattrs --xattrs-include='*' -chf - -C %s -p . \ | 23 | cmd = "tar --exclude='.git' --exclude='__pycache__' --xattrs --xattrs-include='*' -chf - -C %s -p . \ |
24 | | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dest) | 24 | | tar --xattrs --xattrs-include='*' -xf - -C %s" % (src, dest) |
25 | subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) | 25 | subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT) |
26 | else: | 26 | else: |
@@ -259,7 +259,7 @@ def create_locked_sstate_cache(lockedsigs, input_sstate_cache, output_sstate_cac | |||
259 | bb.note('Generating sstate-cache...') | 259 | bb.note('Generating sstate-cache...') |
260 | 260 | ||
261 | nativelsbstring = d.getVar('NATIVELSBSTRING') | 261 | nativelsbstring = d.getVar('NATIVELSBSTRING') |
262 | bb.process.run("gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or '')) | 262 | bb.process.run("PYTHONDONTWRITEBYTECODE=1 gen-lockedsig-cache %s %s %s %s %s" % (lockedsigs, input_sstate_cache, output_sstate_cache, nativelsbstring, filterfile or '')) |
263 | if fixedlsbstring and nativelsbstring != fixedlsbstring: | 263 | if fixedlsbstring and nativelsbstring != fixedlsbstring: |
264 | nativedir = output_sstate_cache + '/' + nativelsbstring | 264 | nativedir = output_sstate_cache + '/' + nativelsbstring |
265 | if os.path.isdir(nativedir): | 265 | if os.path.isdir(nativedir): |
@@ -286,7 +286,7 @@ def check_sstate_task_list(d, targets, filteroutfile, cmdprefix='', cwd=None, lo | |||
286 | logparam = '-l %s' % logfile | 286 | logparam = '-l %s' % logfile |
287 | else: | 287 | else: |
288 | logparam = '' | 288 | logparam = '' |
289 | cmd = "%sBB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam) | 289 | cmd = "%sPYTHONDONTWRITEBYTECODE=1 BB_SETSCENE_ENFORCE=1 PSEUDO_DISABLED=1 oe-check-sstate %s -s -o %s %s" % (cmdprefix, targets, filteroutfile, logparam) |
290 | env = dict(d.getVar('BB_ORIGENV', False)) | 290 | env = dict(d.getVar('BB_ORIGENV', False)) |
291 | env.pop('BUILDDIR', '') | 291 | env.pop('BUILDDIR', '') |
292 | env.pop('BBPATH', '') | 292 | env.pop('BBPATH', '') |
diff --git a/meta/lib/oe/cve_check.py b/meta/lib/oe/cve_check.py new file mode 100644 index 0000000000..a1d7c292af --- /dev/null +++ b/meta/lib/oe/cve_check.py | |||
@@ -0,0 +1,65 @@ | |||
1 | import collections | ||
2 | import re | ||
3 | import itertools | ||
4 | import functools | ||
5 | |||
6 | _Version = collections.namedtuple( | ||
7 | "_Version", ["release", "patch_l", "pre_l", "pre_v"] | ||
8 | ) | ||
9 | |||
10 | @functools.total_ordering | ||
11 | class Version(): | ||
12 | |||
13 | def __init__(self, version, suffix=None): | ||
14 | |||
15 | suffixes = ["alphabetical", "patch"] | ||
16 | |||
17 | if str(suffix) == "alphabetical": | ||
18 | version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(?P<patch_l>[a-z]))?(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?""" | ||
19 | elif str(suffix) == "patch": | ||
20 | version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<patch>[-_\.]?(p|patch)(?P<patch_l>[0-9]+))?(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?""" | ||
21 | else: | ||
22 | version_pattern = r"""r?v?(?:(?P<release>[0-9]+(?:[-\.][0-9]+)*)(?P<pre>[-_\.]?(?P<pre_l>(rc|alpha|beta|pre|preview|dev))[-_\.]?(?P<pre_v>[0-9]+)?)?)(.*)?""" | ||
23 | regex = re.compile(r"^\s*" + version_pattern + r"\s*$", re.VERBOSE | re.IGNORECASE) | ||
24 | |||
25 | match = regex.search(version) | ||
26 | if not match: | ||
27 | raise Exception("Invalid version: '{0}'".format(version)) | ||
28 | |||
29 | self._version = _Version( | ||
30 | release=tuple(int(i) for i in match.group("release").replace("-",".").split(".")), | ||
31 | patch_l=match.group("patch_l") if str(suffix) in suffixes and match.group("patch_l") else "", | ||
32 | pre_l=match.group("pre_l"), | ||
33 | pre_v=match.group("pre_v") | ||
34 | ) | ||
35 | |||
36 | self._key = _cmpkey( | ||
37 | self._version.release, | ||
38 | self._version.patch_l, | ||
39 | self._version.pre_l, | ||
40 | self._version.pre_v | ||
41 | ) | ||
42 | |||
43 | def __eq__(self, other): | ||
44 | if not isinstance(other, Version): | ||
45 | return NotImplemented | ||
46 | return self._key == other._key | ||
47 | |||
48 | def __gt__(self, other): | ||
49 | if not isinstance(other, Version): | ||
50 | return NotImplemented | ||
51 | return self._key > other._key | ||
52 | |||
53 | def _cmpkey(release, patch_l, pre_l, pre_v): | ||
54 | # remove leading 0 | ||
55 | _release = tuple( | ||
56 | reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release)))) | ||
57 | ) | ||
58 | |||
59 | _patch = patch_l.upper() | ||
60 | |||
61 | if pre_l is None and pre_v is None: | ||
62 | _pre = float('inf') | ||
63 | else: | ||
64 | _pre = float(pre_v) if pre_v else float('-inf') | ||
65 | return _release, _patch, _pre | ||
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py index 42225a3b2e..26f9f82aaa 100644 --- a/meta/lib/oe/package_manager/__init__.py +++ b/meta/lib/oe/package_manager/__init__.py | |||
@@ -189,7 +189,7 @@ class PackageManager(object, metaclass=ABCMeta): | |||
189 | bb.utils.remove(self.intercepts_dir, True) | 189 | bb.utils.remove(self.intercepts_dir, True) |
190 | bb.utils.mkdirhier(self.intercepts_dir) | 190 | bb.utils.mkdirhier(self.intercepts_dir) |
191 | for intercept in postinst_intercepts: | 191 | for intercept in postinst_intercepts: |
192 | bb.utils.copyfile(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept))) | 192 | shutil.copy(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept))) |
193 | 193 | ||
194 | @abstractmethod | 194 | @abstractmethod |
195 | def _handle_intercept_failure(self, failed_script): | 195 | def _handle_intercept_failure(self, failed_script): |
diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py index 26157f591a..0f9b27f831 100644 --- a/meta/lib/oe/package_manager/deb/__init__.py +++ b/meta/lib/oe/package_manager/deb/__init__.py | |||
@@ -312,6 +312,12 @@ class DpkgPM(OpkgDpkgPM): | |||
312 | if not pkgs: | 312 | if not pkgs: |
313 | return | 313 | return |
314 | 314 | ||
315 | os.environ['D'] = self.target_rootfs | ||
316 | os.environ['OFFLINE_ROOT'] = self.target_rootfs | ||
317 | os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
318 | os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs | ||
319 | os.environ['INTERCEPT_DIR'] = self.intercepts_dir | ||
320 | |||
315 | if with_dependencies: | 321 | if with_dependencies: |
316 | os.environ['APT_CONFIG'] = self.apt_conf_file | 322 | os.environ['APT_CONFIG'] = self.apt_conf_file |
317 | cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkgs)) | 323 | cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkgs)) |
diff --git a/meta/lib/oe/package_manager/deb/sdk.py b/meta/lib/oe/package_manager/deb/sdk.py index b25eb70b00..76548b06f0 100644 --- a/meta/lib/oe/package_manager/deb/sdk.py +++ b/meta/lib/oe/package_manager/deb/sdk.py | |||
@@ -65,6 +65,8 @@ class DpkgSdk(Sdk): | |||
65 | 65 | ||
66 | self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) | 66 | self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) |
67 | 67 | ||
68 | self.target_pm.run_pre_post_installs() | ||
69 | |||
68 | self.target_pm.run_intercepts(populate_sdk='target') | 70 | self.target_pm.run_intercepts(populate_sdk='target') |
69 | 71 | ||
70 | execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) | 72 | execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) |
@@ -78,6 +80,8 @@ class DpkgSdk(Sdk): | |||
78 | self._populate_sysroot(self.host_pm, self.host_manifest) | 80 | self._populate_sysroot(self.host_pm, self.host_manifest) |
79 | self.install_locales(self.host_pm) | 81 | self.install_locales(self.host_pm) |
80 | 82 | ||
83 | self.host_pm.run_pre_post_installs() | ||
84 | |||
81 | self.host_pm.run_intercepts(populate_sdk='host') | 85 | self.host_pm.run_intercepts(populate_sdk='host') |
82 | 86 | ||
83 | execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) | 87 | execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) |
diff --git a/meta/lib/oe/patch.py b/meta/lib/oe/patch.py index 40755fbb03..8ad70f53f1 100644 --- a/meta/lib/oe/patch.py +++ b/meta/lib/oe/patch.py | |||
@@ -38,15 +38,19 @@ def runcmd(args, dir = None): | |||
38 | args = [ pipes.quote(str(arg)) for arg in args ] | 38 | args = [ pipes.quote(str(arg)) for arg in args ] |
39 | cmd = " ".join(args) | 39 | cmd = " ".join(args) |
40 | # print("cmd: %s" % cmd) | 40 | # print("cmd: %s" % cmd) |
41 | (exitstatus, output) = subprocess.getstatusoutput(cmd) | 41 | proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) |
42 | stdout, stderr = proc.communicate() | ||
43 | stdout = stdout.decode('utf-8') | ||
44 | stderr = stderr.decode('utf-8') | ||
45 | exitstatus = proc.returncode | ||
42 | if exitstatus != 0: | 46 | if exitstatus != 0: |
43 | raise CmdError(cmd, exitstatus >> 8, output) | 47 | raise CmdError(cmd, exitstatus >> 8, "stdout: %s\nstderr: %s" % (stdout, stderr)) |
44 | if " fuzz " in output and "Hunk " in output: | 48 | if " fuzz " in stdout and "Hunk " in stdout: |
45 | # Drop patch fuzz info with header and footer to log file so | 49 | # Drop patch fuzz info with header and footer to log file so |
46 | # insane.bbclass can handle to throw error/warning | 50 | # insane.bbclass can handle to throw error/warning |
47 | bb.note("--- Patch fuzz start ---\n%s\n--- Patch fuzz end ---" % format(output)) | 51 | bb.note("--- Patch fuzz start ---\n%s\n--- Patch fuzz end ---" % format(stdout)) |
48 | 52 | ||
49 | return output | 53 | return stdout |
50 | 54 | ||
51 | finally: | 55 | finally: |
52 | if dir: | 56 | if dir: |
diff --git a/meta/lib/oe/path.py b/meta/lib/oe/path.py index 082972457b..c8d8ad05b9 100644 --- a/meta/lib/oe/path.py +++ b/meta/lib/oe/path.py | |||
@@ -320,3 +320,24 @@ def which_wild(pathname, path=None, mode=os.F_OK, *, reverse=False, candidates=F | |||
320 | 320 | ||
321 | return files | 321 | return files |
322 | 322 | ||
323 | def canonicalize(paths, sep=','): | ||
324 | """Given a string with paths (separated by commas by default), expand | ||
325 | each path using os.path.realpath() and return the resulting paths as a | ||
326 | string (separated using the same separator a the original string). | ||
327 | """ | ||
328 | # Ignore paths containing "$" as they are assumed to be unexpanded bitbake | ||
329 | # variables. Normally they would be ignored, e.g., when passing the paths | ||
330 | # through the shell they would expand to empty strings. However, when they | ||
331 | # are passed through os.path.realpath(), it will cause them to be prefixed | ||
332 | # with the absolute path to the current directory and thus not be empty | ||
333 | # anymore. | ||
334 | # | ||
335 | # Also maintain trailing slashes, as the paths may actually be used as | ||
336 | # prefixes in sting compares later on, where the slashes then are important. | ||
337 | canonical_paths = [] | ||
338 | for path in (paths or '').split(sep): | ||
339 | if '$' not in path: | ||
340 | trailing_slash = path.endswith('/') and '/' or '' | ||
341 | canonical_paths.append(os.path.realpath(path) + trailing_slash) | ||
342 | |||
343 | return sep.join(canonical_paths) | ||
diff --git a/meta/lib/oe/prservice.py b/meta/lib/oe/prservice.py index 2d3c9c7e50..fcdbe66c19 100644 --- a/meta/lib/oe/prservice.py +++ b/meta/lib/oe/prservice.py | |||
@@ -3,10 +3,6 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | def prserv_make_conn(d, check = False): | 5 | def prserv_make_conn(d, check = False): |
6 | # Otherwise this fails when called from recipes which e.g. inherit python3native (which sets _PYTHON_SYSCONFIGDATA_NAME) with: | ||
7 | # No module named '_sysconfigdata' | ||
8 | if '_PYTHON_SYSCONFIGDATA_NAME' in os.environ: | ||
9 | del os.environ['_PYTHON_SYSCONFIGDATA_NAME'] | ||
10 | import prserv.serv | 6 | import prserv.serv |
11 | host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f]) | 7 | host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f]) |
12 | try: | 8 | try: |
diff --git a/meta/lib/oe/recipeutils.py b/meta/lib/oe/recipeutils.py index ef69ef207f..407d168894 100644 --- a/meta/lib/oe/recipeutils.py +++ b/meta/lib/oe/recipeutils.py | |||
@@ -409,7 +409,7 @@ def copy_recipe_files(d, tgt_dir, whole_dir=False, download=True, all_variants=F | |||
409 | fetch.download() | 409 | fetch.download() |
410 | for pth in fetch.localpaths(): | 410 | for pth in fetch.localpaths(): |
411 | if pth not in localpaths: | 411 | if pth not in localpaths: |
412 | localpaths.append(pth) | 412 | localpaths.append(os.path.abspath(pth)) |
413 | uri_values.append(srcuri) | 413 | uri_values.append(srcuri) |
414 | 414 | ||
415 | fetch_urls(d) | 415 | fetch_urls(d) |
diff --git a/meta/lib/oe/reproducible.py b/meta/lib/oe/reproducible.py index 421bb12f54..0fb02ccdb0 100644 --- a/meta/lib/oe/reproducible.py +++ b/meta/lib/oe/reproducible.py | |||
@@ -47,7 +47,7 @@ def find_git_folder(d, sourcedir): | |||
47 | return None | 47 | return None |
48 | 48 | ||
49 | def get_source_date_epoch_from_git(d, sourcedir): | 49 | def get_source_date_epoch_from_git(d, sourcedir): |
50 | if not "git://" in d.getVar('SRC_URI'): | 50 | if not "git://" in d.getVar('SRC_URI') and not "gitsm://" in d.getVar('SRC_URI'): |
51 | return None | 51 | return None |
52 | 52 | ||
53 | gitpath = find_git_folder(d, sourcedir) | 53 | gitpath = find_git_folder(d, sourcedir) |
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py index 64fb84ec92..31a6140984 100644 --- a/meta/lib/oe/sstatesig.py +++ b/meta/lib/oe/sstatesig.py | |||
@@ -439,7 +439,7 @@ def find_sstate_manifest(taskdata, taskdata2, taskname, d, multilibcache): | |||
439 | d2 = multilibcache[variant] | 439 | d2 = multilibcache[variant] |
440 | 440 | ||
441 | if taskdata.endswith("-native"): | 441 | if taskdata.endswith("-native"): |
442 | pkgarchs = ["${BUILD_ARCH}"] | 442 | pkgarchs = ["${BUILD_ARCH}", "${BUILD_ARCH}_${ORIGNATIVELSBSTRING}"] |
443 | elif taskdata.startswith("nativesdk-"): | 443 | elif taskdata.startswith("nativesdk-"): |
444 | pkgarchs = ["${SDK_ARCH}_${SDK_OS}", "allarch"] | 444 | pkgarchs = ["${SDK_ARCH}_${SDK_OS}", "allarch"] |
445 | elif "-cross-canadian" in taskdata: | 445 | elif "-cross-canadian" in taskdata: |
@@ -557,9 +557,11 @@ def OEOuthashBasic(path, sigfile, task, d): | |||
557 | try: | 557 | try: |
558 | update_hash(" %10s" % pwd.getpwuid(s.st_uid).pw_name) | 558 | update_hash(" %10s" % pwd.getpwuid(s.st_uid).pw_name) |
559 | update_hash(" %10s" % grp.getgrgid(s.st_gid).gr_name) | 559 | update_hash(" %10s" % grp.getgrgid(s.st_gid).gr_name) |
560 | except KeyError: | 560 | except KeyError as e: |
561 | bb.warn("KeyError in %s" % path) | 561 | bb.warn("KeyError in %s" % path) |
562 | raise | 562 | msg = ("KeyError: %s\nPath %s is owned by uid %d, gid %d, which doesn't match " |
563 | "any user/group on target. This may be due to host contamination." % (e, path, s.st_uid, s.st_gid)) | ||
564 | raise Exception(msg).with_traceback(e.__traceback__) | ||
563 | 565 | ||
564 | if include_timestamps: | 566 | if include_timestamps: |
565 | update_hash(" %10d" % s.st_mtime) | 567 | update_hash(" %10d" % s.st_mtime) |
diff --git a/meta/lib/oe/terminal.py b/meta/lib/oe/terminal.py index eb10a6e33e..2ac39df9e1 100644 --- a/meta/lib/oe/terminal.py +++ b/meta/lib/oe/terminal.py | |||
@@ -163,7 +163,12 @@ class Tmux(Terminal): | |||
163 | # devshells, if it's already there, add a new window to it. | 163 | # devshells, if it's already there, add a new window to it. |
164 | window_name = 'devshell-%i' % os.getpid() | 164 | window_name = 'devshell-%i' % os.getpid() |
165 | 165 | ||
166 | self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"'.format(window_name) | 166 | self.command = 'tmux new -c "{{cwd}}" -d -s {0} -n {0} "{{command}}"' |
167 | if not check_tmux_version('1.9'): | ||
168 | # `tmux new-session -c` was added in 1.9; | ||
169 | # older versions fail with that flag | ||
170 | self.command = 'tmux new -d -s {0} -n {0} "{{command}}"' | ||
171 | self.command = self.command.format(window_name) | ||
167 | Terminal.__init__(self, sh_cmd, title, env, d) | 172 | Terminal.__init__(self, sh_cmd, title, env, d) |
168 | 173 | ||
169 | attach_cmd = 'tmux att -t {0}'.format(window_name) | 174 | attach_cmd = 'tmux att -t {0}'.format(window_name) |
@@ -253,13 +258,18 @@ def spawn(name, sh_cmd, title=None, env=None, d=None): | |||
253 | except OSError: | 258 | except OSError: |
254 | return | 259 | return |
255 | 260 | ||
261 | def check_tmux_version(desired): | ||
262 | vernum = check_terminal_version("tmux") | ||
263 | if vernum and LooseVersion(vernum) < desired: | ||
264 | return False | ||
265 | return vernum | ||
266 | |||
256 | def check_tmux_pane_size(tmux): | 267 | def check_tmux_pane_size(tmux): |
257 | import subprocess as sub | 268 | import subprocess as sub |
258 | # On older tmux versions (<1.9), return false. The reason | 269 | # On older tmux versions (<1.9), return false. The reason |
259 | # is that there is no easy way to get the height of the active panel | 270 | # is that there is no easy way to get the height of the active panel |
260 | # on current window without nested formats (available from version 1.9) | 271 | # on current window without nested formats (available from version 1.9) |
261 | vernum = check_terminal_version("tmux") | 272 | if not check_tmux_version('1.9'): |
262 | if vernum and LooseVersion(vernum) < '1.9': | ||
263 | return False | 273 | return False |
264 | try: | 274 | try: |
265 | p = sub.Popen('%s list-panes -F "#{?pane_active,#{pane_height},}"' % tmux, | 275 | p = sub.Popen('%s list-panes -F "#{?pane_active,#{pane_height},}"' % tmux, |
diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py index 468c76f30f..9a2187e36f 100644 --- a/meta/lib/oe/utils.py +++ b/meta/lib/oe/utils.py | |||
@@ -193,7 +193,7 @@ def parallel_make(d, makeinst=False): | |||
193 | 193 | ||
194 | return int(v) | 194 | return int(v) |
195 | 195 | ||
196 | return None | 196 | return '' |
197 | 197 | ||
198 | def parallel_make_argument(d, fmt, limit=None, makeinst=False): | 198 | def parallel_make_argument(d, fmt, limit=None, makeinst=False): |
199 | """ | 199 | """ |
diff --git a/meta/lib/oeqa/manual/oe-core.json b/meta/lib/oeqa/manual/oe-core.json index fb47c5ec36..4ad524d89b 100644 --- a/meta/lib/oeqa/manual/oe-core.json +++ b/meta/lib/oeqa/manual/oe-core.json | |||
@@ -80,7 +80,7 @@ | |||
80 | "expected_results": "" | 80 | "expected_results": "" |
81 | }, | 81 | }, |
82 | "7": { | 82 | "7": { |
83 | "action": "Run command:./configure && make ", | 83 | "action": "Run command:./configure ${CONFIGUREOPTS} && make ", |
84 | "expected_results": "Verify that \"matchbox-desktop\" binary file was created successfully under \"src/\" directory " | 84 | "expected_results": "Verify that \"matchbox-desktop\" binary file was created successfully under \"src/\" directory " |
85 | }, | 85 | }, |
86 | "8": { | 86 | "8": { |
diff --git a/meta/lib/oeqa/runtime/cases/df.py b/meta/lib/oeqa/runtime/cases/df.py index 89fd0fb901..bb155c9cf9 100644 --- a/meta/lib/oeqa/runtime/cases/df.py +++ b/meta/lib/oeqa/runtime/cases/df.py | |||
@@ -4,12 +4,14 @@ | |||
4 | 4 | ||
5 | from oeqa.runtime.case import OERuntimeTestCase | 5 | from oeqa.runtime.case import OERuntimeTestCase |
6 | from oeqa.core.decorator.depends import OETestDepends | 6 | from oeqa.core.decorator.depends import OETestDepends |
7 | from oeqa.core.decorator.data import skipIfDataVar, skipIfInDataVar | ||
7 | from oeqa.runtime.decorator.package import OEHasPackage | 8 | from oeqa.runtime.decorator.package import OEHasPackage |
8 | 9 | ||
9 | class DfTest(OERuntimeTestCase): | 10 | class DfTest(OERuntimeTestCase): |
10 | 11 | ||
11 | @OETestDepends(['ssh.SSHTest.test_ssh']) | 12 | @OETestDepends(['ssh.SSHTest.test_ssh']) |
12 | @OEHasPackage(['coreutils', 'busybox']) | 13 | @OEHasPackage(['coreutils', 'busybox']) |
14 | @skipIfInDataVar('IMAGE_FEATURES', 'read-only-rootfs', 'Test case df requires a writable rootfs') | ||
13 | def test_df(self): | 15 | def test_df(self): |
14 | cmd = "df -P / | sed -n '2p' | awk '{print $4}'" | 16 | cmd = "df -P / | sed -n '2p' | awk '{print $4}'" |
15 | (status,output) = self.target.run(cmd) | 17 | (status,output) = self.target.run(cmd) |
diff --git a/meta/lib/oeqa/runtime/cases/pam.py b/meta/lib/oeqa/runtime/cases/pam.py index 271a1943e3..a482ded945 100644 --- a/meta/lib/oeqa/runtime/cases/pam.py +++ b/meta/lib/oeqa/runtime/cases/pam.py | |||
@@ -8,11 +8,14 @@ | |||
8 | from oeqa.runtime.case import OERuntimeTestCase | 8 | from oeqa.runtime.case import OERuntimeTestCase |
9 | from oeqa.core.decorator.depends import OETestDepends | 9 | from oeqa.core.decorator.depends import OETestDepends |
10 | from oeqa.core.decorator.data import skipIfNotFeature | 10 | from oeqa.core.decorator.data import skipIfNotFeature |
11 | from oeqa.runtime.decorator.package import OEHasPackage | ||
11 | 12 | ||
12 | class PamBasicTest(OERuntimeTestCase): | 13 | class PamBasicTest(OERuntimeTestCase): |
13 | 14 | ||
14 | @skipIfNotFeature('pam', 'Test requires pam to be in DISTRO_FEATURES') | 15 | @skipIfNotFeature('pam', 'Test requires pam to be in DISTRO_FEATURES') |
15 | @OETestDepends(['ssh.SSHTest.test_ssh']) | 16 | @OETestDepends(['ssh.SSHTest.test_ssh']) |
17 | @OEHasPackage(['shadow']) | ||
18 | @OEHasPackage(['shadow-base']) | ||
16 | def test_pam(self): | 19 | def test_pam(self): |
17 | status, output = self.target.run('login --help') | 20 | status, output = self.target.run('login --help') |
18 | msg = ('login command does not work as expected. ' | 21 | msg = ('login command does not work as expected. ' |
diff --git a/meta/lib/oeqa/selftest/cases/buildoptions.py b/meta/lib/oeqa/selftest/cases/buildoptions.py index e91f0bd18f..b1b9ea7e55 100644 --- a/meta/lib/oeqa/selftest/cases/buildoptions.py +++ b/meta/lib/oeqa/selftest/cases/buildoptions.py | |||
@@ -57,15 +57,15 @@ class ImageOptionsTests(OESelftestTestCase): | |||
57 | class DiskMonTest(OESelftestTestCase): | 57 | class DiskMonTest(OESelftestTestCase): |
58 | 58 | ||
59 | def test_stoptask_behavior(self): | 59 | def test_stoptask_behavior(self): |
60 | self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"') | 60 | self.write_config('BB_DISKMON_DIRS = "STOPTASKS,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') |
61 | res = bitbake("delay -c delay", ignore_status = True) | 61 | res = bitbake("delay -c delay", ignore_status = True) |
62 | self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output) | 62 | self.assertTrue('ERROR: No new tasks can be executed since the disk space monitor action is "STOPTASKS"!' in res.output, msg = "Tasks should have stopped. Disk monitor is set to STOPTASK: %s" % res.output) |
63 | self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) | 63 | self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) |
64 | self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"') | 64 | self.write_config('BB_DISKMON_DIRS = "ABORT,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') |
65 | res = bitbake("delay -c delay", ignore_status = True) | 65 | res = bitbake("delay -c delay", ignore_status = True) |
66 | self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output) | 66 | self.assertTrue('ERROR: Immediately abort since the disk space monitor action is "ABORT"!' in res.output, "Tasks should have been aborted immediatelly. Disk monitor is set to ABORT: %s" % res.output) |
67 | self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) | 67 | self.assertEqual(res.status, 1, msg = "bitbake reported exit code %s. It should have been 1. Bitbake output: %s" % (str(res.status), res.output)) |
68 | self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"') | 68 | self.write_config('BB_DISKMON_DIRS = "WARN,${TMPDIR},100000G,100K"\nBB_HEARTBEAT_EVENT = "1"') |
69 | res = bitbake("delay -c delay") | 69 | res = bitbake("delay -c delay") |
70 | self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output) | 70 | self.assertTrue('WARNING: The free space' in res.output, msg = "A warning should have been displayed for disk monitor is set to WARN: %s" %res.output) |
71 | 71 | ||
diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py new file mode 100644 index 0000000000..d1947baffc --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/cve_check.py | |||
@@ -0,0 +1,44 @@ | |||
1 | from oe.cve_check import Version | ||
2 | from oeqa.selftest.case import OESelftestTestCase | ||
3 | |||
4 | class CVECheck(OESelftestTestCase): | ||
5 | |||
6 | def test_version_compare(self): | ||
7 | result = Version("100") > Version("99") | ||
8 | self.assertTrue( result, msg="Failed to compare version '100' > '99'") | ||
9 | result = Version("2.3.1") > Version("2.2.3") | ||
10 | self.assertTrue( result, msg="Failed to compare version '2.3.1' > '2.2.3'") | ||
11 | result = Version("2021-01-21") > Version("2020-12-25") | ||
12 | self.assertTrue( result, msg="Failed to compare version '2021-01-21' > '2020-12-25'") | ||
13 | result = Version("1.2-20200910") < Version("1.2-20200920") | ||
14 | self.assertTrue( result, msg="Failed to compare version '1.2-20200910' < '1.2-20200920'") | ||
15 | |||
16 | result = Version("1.0") >= Version("1.0beta") | ||
17 | self.assertTrue( result, msg="Failed to compare version '1.0' >= '1.0beta'") | ||
18 | result = Version("1.0-rc2") > Version("1.0-rc1") | ||
19 | self.assertTrue( result, msg="Failed to compare version '1.0-rc2' > '1.0-rc1'") | ||
20 | result = Version("1.0.alpha1") < Version("1.0") | ||
21 | self.assertTrue( result, msg="Failed to compare version '1.0.alpha1' < '1.0'") | ||
22 | result = Version("1.0_dev") <= Version("1.0") | ||
23 | self.assertTrue( result, msg="Failed to compare version '1.0_dev' <= '1.0'") | ||
24 | |||
25 | # ignore "p1" and "p2", so these should be equal | ||
26 | result = Version("1.0p2") == Version("1.0p1") | ||
27 | self.assertTrue( result ,msg="Failed to compare version '1.0p2' to '1.0p1'") | ||
28 | # ignore the "b" and "r" | ||
29 | result = Version("1.0b") == Version("1.0r") | ||
30 | self.assertTrue( result ,msg="Failed to compare version '1.0b' to '1.0r'") | ||
31 | |||
32 | # consider the trailing alphabet as patched level when comparing | ||
33 | result = Version("1.0b","alphabetical") < Version("1.0r","alphabetical") | ||
34 | self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' < '1.0r'") | ||
35 | result = Version("1.0b","alphabetical") > Version("1.0","alphabetical") | ||
36 | self.assertTrue( result ,msg="Failed to compare version with suffix '1.0b' > '1.0'") | ||
37 | |||
38 | # consider the trailing "p" and "patch" as patched released when comparing | ||
39 | result = Version("1.0","patch") < Version("1.0p1","patch") | ||
40 | self.assertTrue( result ,msg="Failed to compare version with suffix '1.0' < '1.0p1'") | ||
41 | result = Version("1.0p2","patch") > Version("1.0p1","patch") | ||
42 | self.assertTrue( result ,msg="Failed to compare version with suffix '1.0p2' > '1.0p1'") | ||
43 | result = Version("1.0_patch2","patch") < Version("1.0_patch3","patch") | ||
44 | self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'") | ||
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index d3d2e04c20..4eba23890f 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py | |||
@@ -57,7 +57,7 @@ def setUpModule(): | |||
57 | if relpth.endswith('/'): | 57 | if relpth.endswith('/'): |
58 | destdir = os.path.join(corecopydir, relpth) | 58 | destdir = os.path.join(corecopydir, relpth) |
59 | # avoid race condition by not copying .pyc files YPBZ#13421,13803 | 59 | # avoid race condition by not copying .pyc files YPBZ#13421,13803 |
60 | shutil.copytree(pth, destdir, ignore=ignore_patterns('*.pyc', '__pycache__')) | 60 | shutil.copytree(pth, destdir, ignore=shutil.ignore_patterns('*.pyc', '__pycache__')) |
61 | else: | 61 | else: |
62 | destdir = os.path.join(corecopydir, os.path.dirname(relpth)) | 62 | destdir = os.path.join(corecopydir, os.path.dirname(relpth)) |
63 | bb.utils.mkdirhier(destdir) | 63 | bb.utils.mkdirhier(destdir) |
@@ -269,7 +269,7 @@ class DevtoolAddTests(DevtoolBase): | |||
269 | self.track_for_cleanup(tempdir) | 269 | self.track_for_cleanup(tempdir) |
270 | pn = 'pv' | 270 | pn = 'pv' |
271 | pv = '1.5.3' | 271 | pv = '1.5.3' |
272 | url = 'http://www.ivarch.com/programs/sources/pv-1.5.3.tar.bz2' | 272 | url = 'http://downloads.yoctoproject.org/mirror/sources/pv-1.5.3.tar.bz2' |
273 | result = runCmd('wget %s' % url, cwd=tempdir) | 273 | result = runCmd('wget %s' % url, cwd=tempdir) |
274 | result = runCmd('tar xfv %s' % os.path.basename(url), cwd=tempdir) | 274 | result = runCmd('tar xfv %s' % os.path.basename(url), cwd=tempdir) |
275 | srcdir = os.path.join(tempdir, '%s-%s' % (pn, pv)) | 275 | srcdir = os.path.join(tempdir, '%s-%s' % (pn, pv)) |
diff --git a/meta/lib/oeqa/selftest/cases/pseudo.py b/meta/lib/oeqa/selftest/cases/pseudo.py new file mode 100644 index 0000000000..33593d5ce9 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/pseudo.py | |||
@@ -0,0 +1,27 @@ | |||
1 | # | ||
2 | # SPDX-License-Identifier: MIT | ||
3 | # | ||
4 | |||
5 | import glob | ||
6 | import os | ||
7 | import shutil | ||
8 | from oeqa.utils.commands import bitbake, get_test_layer | ||
9 | from oeqa.selftest.case import OESelftestTestCase | ||
10 | |||
11 | class Pseudo(OESelftestTestCase): | ||
12 | |||
13 | def test_pseudo_pyc_creation(self): | ||
14 | self.write_config("") | ||
15 | |||
16 | metaselftestpath = get_test_layer() | ||
17 | pycache_path = os.path.join(metaselftestpath, 'lib/__pycache__') | ||
18 | if os.path.exists(pycache_path): | ||
19 | shutil.rmtree(pycache_path) | ||
20 | |||
21 | bitbake('pseudo-pyc-test -c install') | ||
22 | |||
23 | test1_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test1.*.pyc'))) | ||
24 | self.assertTrue(test1_pyc_present, 'test1 pyc file missing, should be created outside of pseudo context.') | ||
25 | |||
26 | test2_pyc_present = len(glob.glob(os.path.join(pycache_path, 'pseudo_pyc_test2.*.pyc'))) | ||
27 | self.assertFalse(test2_pyc_present, 'test2 pyc file present, should not be created in pseudo context.') | ||
diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py index a7ef336143..cd7be7d436 100644 --- a/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/meta/lib/oeqa/selftest/cases/reproducible.py | |||
@@ -68,7 +68,7 @@ def compare_file(reference, test, diffutils_sysroot): | |||
68 | result.status = MISSING | 68 | result.status = MISSING |
69 | return result | 69 | return result |
70 | 70 | ||
71 | r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True) | 71 | r = runCmd(['cmp', '--quiet', reference, test], native_sysroot=diffutils_sysroot, ignore_status=True, sync=False) |
72 | 72 | ||
73 | if r.status: | 73 | if r.status: |
74 | result.status = DIFFERENT | 74 | result.status = DIFFERENT |
@@ -184,9 +184,10 @@ class ReproducibleTests(OESelftestTestCase): | |||
184 | # mirror, forcing a complete build from scratch | 184 | # mirror, forcing a complete build from scratch |
185 | config += textwrap.dedent('''\ | 185 | config += textwrap.dedent('''\ |
186 | SSTATE_DIR = "${TMPDIR}/sstate" | 186 | SSTATE_DIR = "${TMPDIR}/sstate" |
187 | SSTATE_MIRROR = "" | 187 | SSTATE_MIRRORS = "" |
188 | ''') | 188 | ''') |
189 | 189 | ||
190 | self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT')) | ||
190 | self.write_config(config) | 191 | self.write_config(config) |
191 | d = get_bb_vars(capture_vars) | 192 | d = get_bb_vars(capture_vars) |
192 | bitbake(' '.join(self.images)) | 193 | bitbake(' '.join(self.images)) |
@@ -213,6 +214,7 @@ class ReproducibleTests(OESelftestTestCase): | |||
213 | self.logger.info('Non-reproducible packages will be copied to %s', save_dir) | 214 | self.logger.info('Non-reproducible packages will be copied to %s', save_dir) |
214 | 215 | ||
215 | vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) | 216 | vars_A = self.do_test_build('reproducibleA', self.build_from_sstate) |
217 | |||
216 | vars_B = self.do_test_build('reproducibleB', False) | 218 | vars_B = self.do_test_build('reproducibleB', False) |
217 | 219 | ||
218 | # NOTE: The temp directories from the reproducible build are purposely | 220 | # NOTE: The temp directories from the reproducible build are purposely |
@@ -227,6 +229,7 @@ class ReproducibleTests(OESelftestTestCase): | |||
227 | deploy_A = vars_A['DEPLOY_DIR_' + c.upper()] | 229 | deploy_A = vars_A['DEPLOY_DIR_' + c.upper()] |
228 | deploy_B = vars_B['DEPLOY_DIR_' + c.upper()] | 230 | deploy_B = vars_B['DEPLOY_DIR_' + c.upper()] |
229 | 231 | ||
232 | self.logger.info('Checking %s packages for differences...' % c) | ||
230 | result = self.compare_packages(deploy_A, deploy_B, diffutils_sysroot) | 233 | result = self.compare_packages(deploy_A, deploy_B, diffutils_sysroot) |
231 | 234 | ||
232 | self.logger.info('Reproducibility summary for %s: %s' % (c, result)) | 235 | self.logger.info('Reproducibility summary for %s: %s' % (c, result)) |
diff --git a/meta/lib/oeqa/selftest/cases/tinfoil.py b/meta/lib/oeqa/selftest/cases/tinfoil.py index 206168ed00..a51c6048d3 100644 --- a/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/meta/lib/oeqa/selftest/cases/tinfoil.py | |||
@@ -100,9 +100,11 @@ class TinfoilTests(OESelftestTestCase): | |||
100 | eventreceived = False | 100 | eventreceived = False |
101 | commandcomplete = False | 101 | commandcomplete = False |
102 | start = time.time() | 102 | start = time.time() |
103 | # Wait for 10s in total so we'd detect spurious heartbeat events for example | 103 | # Wait for maximum 60s in total so we'd detect spurious heartbeat events for example |
104 | # The test is IO load sensitive too | 104 | # The test is IO load sensitive too |
105 | while time.time() - start < 10: | 105 | while (not (eventreceived == True and commandcomplete == True) |
106 | and (time.time() - start < 60)): | ||
107 | # if we received both events (on let's say a good day), we are done | ||
106 | event = tinfoil.wait_event(1) | 108 | event = tinfoil.wait_event(1) |
107 | if event: | 109 | if event: |
108 | if isinstance(event, bb.command.CommandCompleted): | 110 | if isinstance(event, bb.command.CommandCompleted): |
diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index 714637ec1e..39c6828f59 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py | |||
@@ -318,6 +318,7 @@ class Wic(WicTestCase): | |||
318 | "--image-name=core-image-minimal " | 318 | "--image-name=core-image-minimal " |
319 | "-D -o %s" % self.resultdir) | 319 | "-D -o %s" % self.resultdir) |
320 | self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) | 320 | self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) |
321 | self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*"))) | ||
321 | 322 | ||
322 | def test_debug_long(self): | 323 | def test_debug_long(self): |
323 | """Test --debug option""" | 324 | """Test --debug option""" |
@@ -325,6 +326,7 @@ class Wic(WicTestCase): | |||
325 | "--image-name=core-image-minimal " | 326 | "--image-name=core-image-minimal " |
326 | "--debug -o %s" % self.resultdir) | 327 | "--debug -o %s" % self.resultdir) |
327 | self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) | 328 | self.assertEqual(1, len(glob(self.resultdir + "wictestdisk-*.direct"))) |
329 | self.assertEqual(1, len(glob(self.resultdir + "tmp.wic*"))) | ||
328 | 330 | ||
329 | def test_skip_build_check_short(self): | 331 | def test_skip_build_check_short(self): |
330 | """Test -s option""" | 332 | """Test -s option""" |
@@ -588,6 +590,9 @@ part / --source rootfs --fstype=ext4 --include-path %s --include-path core-imag | |||
588 | def test_permissions(self): | 590 | def test_permissions(self): |
589 | """Test permissions are respected""" | 591 | """Test permissions are respected""" |
590 | 592 | ||
593 | # prepare wicenv and rootfs | ||
594 | bitbake('core-image-minimal core-image-minimal-mtdutils -c do_rootfs_wicenv') | ||
595 | |||
591 | oldpath = os.environ['PATH'] | 596 | oldpath = os.environ['PATH'] |
592 | os.environ['PATH'] = get_bb_var("PATH", "wic-tools") | 597 | os.environ['PATH'] = get_bb_var("PATH", "wic-tools") |
593 | 598 | ||
@@ -621,6 +626,19 @@ part /etc --source rootfs --fstype=ext4 --change-directory=etc | |||
621 | res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) | 626 | res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) |
622 | self.assertEqual(True, files_own_by_root(res.output)) | 627 | self.assertEqual(True, files_own_by_root(res.output)) |
623 | 628 | ||
629 | config = 'IMAGE_FSTYPES += "wic"\nWKS_FILE = "%s"\n' % wks_file | ||
630 | self.append_config(config) | ||
631 | bitbake('core-image-minimal') | ||
632 | tmpdir = os.path.join(get_bb_var('WORKDIR', 'core-image-minimal'),'build-wic') | ||
633 | |||
634 | # check each partition for permission | ||
635 | for part in glob(os.path.join(tmpdir, 'temp-*.direct.p*')): | ||
636 | res = runCmd("debugfs -R 'ls -p' %s 2>/dev/null" % (part)) | ||
637 | self.assertTrue(files_own_by_root(res.output) | ||
638 | ,msg='Files permission incorrect using wks set "%s"' % test) | ||
639 | |||
640 | # clean config and result directory for next cases | ||
641 | self.remove_config(config) | ||
624 | rmtree(self.resultdir, ignore_errors=True) | 642 | rmtree(self.resultdir, ignore_errors=True) |
625 | 643 | ||
626 | finally: | 644 | finally: |
@@ -961,14 +979,18 @@ class Wic2(WicTestCase): | |||
961 | @only_for_arch(['i586', 'i686', 'x86_64']) | 979 | @only_for_arch(['i586', 'i686', 'x86_64']) |
962 | def test_rawcopy_plugin_qemu(self): | 980 | def test_rawcopy_plugin_qemu(self): |
963 | """Test rawcopy plugin in qemu""" | 981 | """Test rawcopy plugin in qemu""" |
964 | # build ext4 and wic images | 982 | # build ext4 and then use it for a wic image |
965 | for fstype in ("ext4", "wic"): | 983 | config = 'IMAGE_FSTYPES = "ext4"\n' |
966 | config = 'IMAGE_FSTYPES = "%s"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' % fstype | 984 | self.append_config(config) |
967 | self.append_config(config) | 985 | self.assertEqual(0, bitbake('core-image-minimal').status) |
968 | self.assertEqual(0, bitbake('core-image-minimal').status) | 986 | self.remove_config(config) |
969 | self.remove_config(config) | ||
970 | 987 | ||
971 | with runqemu('core-image-minimal', ssh=False, image_fstype='wic') as qemu: | 988 | config = 'IMAGE_FSTYPES = "wic"\nWKS_FILE = "test_rawcopy_plugin.wks.in"\n' |
989 | self.append_config(config) | ||
990 | self.assertEqual(0, bitbake('core-image-minimal-mtdutils').status) | ||
991 | self.remove_config(config) | ||
992 | |||
993 | with runqemu('core-image-minimal-mtdutils', ssh=False, image_fstype='wic') as qemu: | ||
972 | cmd = "grep sda. /proc/partitions |wc -l" | 994 | cmd = "grep sda. /proc/partitions |wc -l" |
973 | status, output = qemu.run_serial(cmd) | 995 | status, output = qemu.run_serial(cmd) |
974 | self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) | 996 | self.assertEqual(1, status, 'Failed to run command "%s": %s' % (cmd, output)) |
diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py index dd3609c1d6..1659926975 100644 --- a/meta/lib/oeqa/selftest/context.py +++ b/meta/lib/oeqa/selftest/context.py | |||
@@ -34,7 +34,7 @@ class NonConcurrentTestSuite(unittest.TestSuite): | |||
34 | (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite) | 34 | (builddir, newbuilddir) = self.setupfunc("-st", None, self.suite) |
35 | ret = super().run(result) | 35 | ret = super().run(result) |
36 | os.chdir(builddir) | 36 | os.chdir(builddir) |
37 | if newbuilddir and ret.wasSuccessful(): | 37 | if newbuilddir and ret.wasSuccessful() and self.removefunc: |
38 | self.removefunc(newbuilddir) | 38 | self.removefunc(newbuilddir) |
39 | 39 | ||
40 | def removebuilddir(d): | 40 | def removebuilddir(d): |
@@ -54,7 +54,7 @@ def removebuilddir(d): | |||
54 | bb.utils.prunedir(d, ionice=True) | 54 | bb.utils.prunedir(d, ionice=True) |
55 | 55 | ||
56 | class OESelftestTestContext(OETestContext): | 56 | class OESelftestTestContext(OETestContext): |
57 | def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None): | 57 | def __init__(self, td=None, logger=None, machines=None, config_paths=None, newbuilddir=None, keep_builddir=None): |
58 | super(OESelftestTestContext, self).__init__(td, logger) | 58 | super(OESelftestTestContext, self).__init__(td, logger) |
59 | 59 | ||
60 | self.machines = machines | 60 | self.machines = machines |
@@ -62,6 +62,11 @@ class OESelftestTestContext(OETestContext): | |||
62 | self.config_paths = config_paths | 62 | self.config_paths = config_paths |
63 | self.newbuilddir = newbuilddir | 63 | self.newbuilddir = newbuilddir |
64 | 64 | ||
65 | if keep_builddir: | ||
66 | self.removebuilddir = None | ||
67 | else: | ||
68 | self.removebuilddir = removebuilddir | ||
69 | |||
65 | def setup_builddir(self, suffix, selftestdir, suite): | 70 | def setup_builddir(self, suffix, selftestdir, suite): |
66 | builddir = os.environ['BUILDDIR'] | 71 | builddir = os.environ['BUILDDIR'] |
67 | if not selftestdir: | 72 | if not selftestdir: |
@@ -119,9 +124,9 @@ class OESelftestTestContext(OETestContext): | |||
119 | if processes: | 124 | if processes: |
120 | from oeqa.core.utils.concurrencytest import ConcurrentTestSuite | 125 | from oeqa.core.utils.concurrencytest import ConcurrentTestSuite |
121 | 126 | ||
122 | return ConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) | 127 | return ConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir) |
123 | else: | 128 | else: |
124 | return NonConcurrentTestSuite(suites, processes, self.setup_builddir, removebuilddir) | 129 | return NonConcurrentTestSuite(suites, processes, self.setup_builddir, self.removebuilddir) |
125 | 130 | ||
126 | def runTests(self, processes=None, machine=None, skips=[]): | 131 | def runTests(self, processes=None, machine=None, skips=[]): |
127 | if machine: | 132 | if machine: |
@@ -179,6 +184,9 @@ class OESelftestTestContextExecutor(OETestContextExecutor): | |||
179 | action='append', default=None, | 184 | action='append', default=None, |
180 | help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)') | 185 | help='Exclude all (unhidden) tests that match any of the specified tag(s). (exclude applies before select)') |
181 | 186 | ||
187 | parser.add_argument('-K', '--keep-builddir', action='store_true', | ||
188 | help='Keep the test build directory even if all tests pass') | ||
189 | |||
182 | parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.') | 190 | parser.add_argument('-B', '--newbuilddir', help='New build directory to use for tests.') |
183 | parser.add_argument('-v', '--verbose', action='store_true') | 191 | parser.add_argument('-v', '--verbose', action='store_true') |
184 | parser.set_defaults(func=self.run) | 192 | parser.set_defaults(func=self.run) |
@@ -236,6 +244,7 @@ class OESelftestTestContextExecutor(OETestContextExecutor): | |||
236 | self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf") | 244 | self.tc_kwargs['init']['config_paths']['localconf'] = os.path.join(builddir, "conf/local.conf") |
237 | self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf") | 245 | self.tc_kwargs['init']['config_paths']['bblayers'] = os.path.join(builddir, "conf/bblayers.conf") |
238 | self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir | 246 | self.tc_kwargs['init']['newbuilddir'] = args.newbuilddir |
247 | self.tc_kwargs['init']['keep_builddir'] = args.keep_builddir | ||
239 | 248 | ||
240 | def tag_filter(tags): | 249 | def tag_filter(tags): |
241 | if args.exclude_tags: | 250 | if args.exclude_tags: |
diff --git a/meta/lib/oeqa/utils/commands.py b/meta/lib/oeqa/utils/commands.py index 8059cbce3e..a71c16ab14 100644 --- a/meta/lib/oeqa/utils/commands.py +++ b/meta/lib/oeqa/utils/commands.py | |||
@@ -125,11 +125,11 @@ class Command(object): | |||
125 | 125 | ||
126 | def stop(self): | 126 | def stop(self): |
127 | for thread in self.threads: | 127 | for thread in self.threads: |
128 | if thread.isAlive(): | 128 | if thread.is_alive(): |
129 | self.process.terminate() | 129 | self.process.terminate() |
130 | # let's give it more time to terminate gracefully before killing it | 130 | # let's give it more time to terminate gracefully before killing it |
131 | thread.join(5) | 131 | thread.join(5) |
132 | if thread.isAlive(): | 132 | if thread.is_alive(): |
133 | self.process.kill() | 133 | self.process.kill() |
134 | thread.join() | 134 | thread.join() |
135 | 135 | ||
@@ -188,7 +188,10 @@ def runCmd(command, ignore_status=False, timeout=None, assert_error=True, sync=T | |||
188 | # call sync around the tests to ensure the IO queue doesn't get too large, taking any IO | 188 | # call sync around the tests to ensure the IO queue doesn't get too large, taking any IO |
189 | # hit here rather than in bitbake shutdown. | 189 | # hit here rather than in bitbake shutdown. |
190 | if sync: | 190 | if sync: |
191 | p = os.environ['PATH'] | ||
192 | os.environ['PATH'] = "/usr/bin:/bin:/usr/sbin:/sbin:" + p | ||
191 | os.system("sync") | 193 | os.system("sync") |
194 | os.environ['PATH'] = p | ||
192 | 195 | ||
193 | result.command = command | 196 | result.command = command |
194 | result.status = cmd.status | 197 | result.status = cmd.status |