diff options
Diffstat (limited to 'meta/lib/oeqa/selftest')
21 files changed, 392 insertions, 62 deletions
diff --git a/meta/lib/oeqa/selftest/cases/bblayers.py b/meta/lib/oeqa/selftest/cases/bblayers.py index 7d74833f61..0b9f16eeae 100644 --- a/meta/lib/oeqa/selftest/cases/bblayers.py +++ b/meta/lib/oeqa/selftest/cases/bblayers.py @@ -46,7 +46,7 @@ class BitbakeLayers(OESelftestTestCase): bb_file = os.path.join(testoutdir, recipe_path, recipe_file) self.assertTrue(os.path.isfile(bb_file), msg = "Cannot find xcursor-transparent-theme_0.1.1.bb in the test_bitbakelayers_flatten local dir.") contents = ftools.read_file(bb_file) - find_in_contents = re.search("##### bbappended from meta-selftest #####\n(.*\n)*include test_recipe.inc", contents) + find_in_contents = re.search(r"##### bbappended from meta-selftest #####\n(.*\n)*include test_recipe.inc", contents) self.assertTrue(find_in_contents, msg = "Flattening layers did not work. bitbake-layers flatten output: %s" % result.output) def test_bitbakelayers_add_remove(self): diff --git a/meta/lib/oeqa/selftest/cases/bbtests.py b/meta/lib/oeqa/selftest/cases/bbtests.py index cfac7afcf4..d91c8ea82b 100644 --- a/meta/lib/oeqa/selftest/cases/bbtests.py +++ b/meta/lib/oeqa/selftest/cases/bbtests.py @@ -188,6 +188,10 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\" self.assertTrue(find, "No version returned for searched recipe. bitbake output: %s" % result.output) def test_prefile(self): + # Test when the prefile does not exist + result = runCmd('bitbake -r conf/prefile.conf', ignore_status=True) + self.assertEqual(1, result.status, "bitbake didn't error and should have when a specified prefile didn't exist: %s" % result.output) + # Test when the prefile exists preconf = os.path.join(self.builddir, 'conf/prefile.conf') self.track_for_cleanup(preconf) ftools.write_file(preconf ,"TEST_PREFILE=\"prefile\"") @@ -198,6 +202,10 @@ SSTATE_DIR = \"${TOPDIR}/download-selftest\" self.assertIn('localconf', result.output) def test_postfile(self): + # Test when the postfile does not exist + result = runCmd('bitbake -R conf/postfile.conf', ignore_status=True) + self.assertEqual(1, result.status, "bitbake didn't error and should have when a specified postfile didn't exist: %s" % result.output) + # Test when the postfile exists postconf = os.path.join(self.builddir, 'conf/postfile.conf') self.track_for_cleanup(postconf) ftools.write_file(postconf , "TEST_POSTFILE=\"postfile\"") @@ -350,4 +358,4 @@ INHERIT:remove = \"report-error\" self.write_config("DISTROOVERRIDES .= \":gitunpack-enable-recipe\"") result = bitbake('gitunpackoffline-fail -c fetch', ignore_status=True) - self.assertTrue("Recipe uses a floating tag/branch without a fixed SRCREV" in result.output, msg = "Recipe without PV set to SRCPV should have failed: %s" % result.output) + self.assertTrue(re.search("Recipe uses a floating tag/branch .* for repo .* without a fixed SRCREV yet doesn't call bb.fetch2.get_srcrev()", result.output), msg = "Recipe without PV set to SRCPV should have failed: %s" % result.output) diff --git a/meta/lib/oeqa/selftest/cases/cve_check.py b/meta/lib/oeqa/selftest/cases/cve_check.py index d0b2213703..22ffeffd29 100644 --- a/meta/lib/oeqa/selftest/cases/cve_check.py +++ b/meta/lib/oeqa/selftest/cases/cve_check.py @@ -48,6 +48,25 @@ class CVECheck(OESelftestTestCase): self.assertTrue( result ,msg="Failed to compare version with suffix '1.0_patch2' < '1.0_patch3'") + def test_convert_cve_version(self): + from oe.cve_check import convert_cve_version + + # Default format + self.assertEqual(convert_cve_version("8.3"), "8.3") + self.assertEqual(convert_cve_version(""), "") + + # OpenSSL format version + self.assertEqual(convert_cve_version("1.1.1t"), "1.1.1t") + + # OpenSSH format + self.assertEqual(convert_cve_version("8.3_p1"), "8.3p1") + self.assertEqual(convert_cve_version("8.3_p22"), "8.3p22") + + # Linux kernel format + self.assertEqual(convert_cve_version("6.2_rc8"), "6.2-rc8") + self.assertEqual(convert_cve_version("6.2_rc31"), "6.2-rc31") + + def test_recipe_report_json(self): config = """ INHERIT += "cve-check" diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index ddf6c0c9f8..dc0fc35062 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -8,6 +8,7 @@ import shutil import tempfile import glob import fnmatch +import unittest from oeqa.selftest.case import OESelftestTestCase from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer @@ -38,6 +39,13 @@ def setUpModule(): canonical_layerpath = os.path.realpath(canonical_layerpath) + '/' edited_layers.append(layerpath) oldmetapath = os.path.realpath(layerpath) + + # when downloading poky from tar.gz some tests will be skipped (BUG 12389) + try: + runCmd('git rev-parse --is-inside-work-tree', cwd=canonical_layerpath) + except: + raise unittest.SkipTest("devtool tests require folder to be a git repo") + result = runCmd('git rev-parse --show-toplevel', cwd=canonical_layerpath) oldreporoot = result.output.rstrip() newmetapath = os.path.join(corecopydir, os.path.relpath(oldmetapath, oldreporoot)) @@ -218,6 +226,34 @@ class DevtoolTestCase(OESelftestTestCase): filelist.append(' '.join(splitline)) return filelist + def _check_diff(self, diffoutput, addlines, removelines): + """Check output from 'git diff' matches expectation""" + remaining_addlines = addlines[:] + remaining_removelines = removelines[:] + for line in diffoutput.splitlines(): + if line.startswith('+++') or line.startswith('---'): + continue + elif line.startswith('+'): + matched = False + for item in addlines: + if re.match(item, line[1:].strip()): + matched = True + remaining_addlines.remove(item) + break + self.assertTrue(matched, 'Unexpected diff add line: %s' % line) + elif line.startswith('-'): + matched = False + for item in removelines: + if re.match(item, line[1:].strip()): + matched = True + remaining_removelines.remove(item) + break + self.assertTrue(matched, 'Unexpected diff remove line: %s' % line) + if remaining_addlines: + self.fail('Expected added lines not found: %s' % remaining_addlines) + if remaining_removelines: + self.fail('Expected removed lines not found: %s' % remaining_removelines) + class DevtoolBase(DevtoolTestCase): @@ -230,6 +266,7 @@ class DevtoolBase(DevtoolTestCase): cls.sstate_conf = 'SSTATE_DIR = "%s"\n' % cls.devtool_sstate cls.sstate_conf += ('SSTATE_MIRRORS += "file://.* file:///%s/PATH"\n' % cls.original_sstate) + cls.sstate_conf += ('BB_HASHSERVE_UPSTREAM = "hashserv.yocto.io:8687"\n') @classmethod def tearDownClass(cls): @@ -311,6 +348,38 @@ class DevtoolAddTests(DevtoolBase): bindir = bindir[1:] self.assertTrue(os.path.isfile(os.path.join(installdir, bindir, 'pv')), 'pv binary not found in D') + def test_devtool_add_binary(self): + # Create a binary package containing a known test file + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + pn = 'tst-bin' + pv = '1.0' + test_file_dir = "var/lib/%s/" % pn + test_file_name = "test_file" + test_file_content = "TEST CONTENT" + test_file_package_root = os.path.join(tempdir, pn) + test_file_dir_full = os.path.join(test_file_package_root, test_file_dir) + bb.utils.mkdirhier(test_file_dir_full) + with open(os.path.join(test_file_dir_full, test_file_name), "w") as f: + f.write(test_file_content) + bin_package_path = os.path.join(tempdir, "%s.tar.gz" % pn) + runCmd("tar czf %s -C %s ." % (bin_package_path, test_file_package_root)) + + # Test devtool add -b on the binary package + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake -c cleansstate %s' % pn) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + result = runCmd('devtool add -b %s %s' % (pn, bin_package_path)) + self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created') + + # Build the resulting recipe + result = runCmd('devtool build %s' % pn) + installdir = get_bb_var('D', pn) + self.assertTrue(installdir, 'Could not query installdir variable') + + # Check that a known file from the binary package has indeed been installed + self.assertTrue(os.path.isfile(os.path.join(installdir, test_file_dir, test_file_name)), '%s not found in D' % test_file_name) + def test_devtool_add_git_local(self): # We need dbus built so that DEPENDS recognition works bitbake('dbus') @@ -718,6 +787,7 @@ class DevtoolModifyTests(DevtoolBase): self.assertTrue(bbclassextended, 'None of these recipes are BBCLASSEXTENDed to native - need to adjust testrecipes list: %s' % ', '.join(testrecipes)) self.assertTrue(inheritnative, 'None of these recipes do "inherit native" - need to adjust testrecipes list: %s' % ', '.join(testrecipes)) + def test_devtool_modify_localfiles_only(self): # Check preconditions testrecipe = 'base-files' @@ -849,7 +919,7 @@ class DevtoolModifyTests(DevtoolBase): runCmd('git -C %s checkout %s' % (tempdir, branch)) with open(source, "rt") as f: content = f.read() - self.assertEquals(content, expected) + self.assertEqual(content, expected) check('devtool', 'This is a test for something\n') check('devtool-no-overrides', 'This is a test for something\n') check('devtool-override-qemuarm', 'This is a test for qemuarm\n') @@ -930,23 +1000,7 @@ class DevtoolUpdateTests(DevtoolBase): srcurilines[0] = 'SRC_URI = "' + srcurilines[0] srcurilines.append('"') removelines = ['SRCREV = ".*"'] + srcurilines - for line in result.output.splitlines(): - if line.startswith('+++') or line.startswith('---'): - continue - elif line.startswith('+'): - matched = False - for item in addlines: - if re.match(item, line[1:].strip()): - matched = True - break - self.assertTrue(matched, 'Unexpected diff add line: %s' % line) - elif line.startswith('-'): - matched = False - for item in removelines: - if re.match(item, line[1:].strip()): - matched = True - break - self.assertTrue(matched, 'Unexpected diff remove line: %s' % line) + self._check_diff(result.output, addlines, removelines) # Now try with auto mode runCmd('cd %s; git checkout %s %s' % (os.path.dirname(recipefile), testrecipe, os.path.basename(recipefile))) result = runCmd('devtool update-recipe %s' % testrecipe) @@ -1316,6 +1370,73 @@ class DevtoolUpdateTests(DevtoolBase): expected_status = [] self._check_repo_status(os.path.dirname(recipefile), expected_status) + def test_devtool_finish_modify_git_subdir(self): + # Check preconditions + testrecipe = 'dos2unix' + bb_vars = get_bb_vars(['SRC_URI', 'S', 'WORKDIR', 'FILE'], testrecipe) + self.assertIn('git://', bb_vars['SRC_URI'], 'This test expects the %s recipe to be a git recipe' % testrecipe) + workdir_git = '%s/git/' % bb_vars['WORKDIR'] + if not bb_vars['S'].startswith(workdir_git): + self.fail('This test expects the %s recipe to be building from a subdirectory of the git repo' % testrecipe) + subdir = bb_vars['S'].split(workdir_git, 1)[1] + # Clean up anything in the workdir/sysroot/sstate cache + bitbake('%s -c cleansstate' % testrecipe) + # Try modifying a recipe + tempdir = tempfile.mkdtemp(prefix='devtoolqa') + self.track_for_cleanup(tempdir) + self.track_for_cleanup(self.workspacedir) + self.add_command_to_tearDown('bitbake -c clean %s' % testrecipe) + self.add_command_to_tearDown('bitbake-layers remove-layer */workspace') + result = runCmd('devtool modify %s -x %s' % (testrecipe, tempdir)) + testsrcfile = os.path.join(tempdir, subdir, 'dos2unix.c') + self.assertExists(testsrcfile, 'Extracted source could not be found') + self.assertExists(os.path.join(self.workspacedir, 'conf', 'layer.conf'), 'Workspace directory not created. devtool output: %s' % result.output) + self.assertNotExists(os.path.join(tempdir, subdir, '.git'), 'Subdirectory has been initialised as a git repo') + # Check git repo + self._check_src_repo(tempdir) + # Modify file + runCmd("sed -i '1s:^:/* Add a comment */\\n:' %s" % testsrcfile) + result = runCmd('git commit -a -m "Add a comment"', cwd=tempdir) + # Now try updating original recipe + recipefile = bb_vars['FILE'] + recipedir = os.path.dirname(recipefile) + self.add_command_to_tearDown('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe)) + result = runCmd('devtool update-recipe %s' % testrecipe) + expected_status = [(' M', '.*/%s$' % os.path.basename(recipefile)), + ('??', '.*/%s/%s/$' % (testrecipe, testrecipe))] + self._check_repo_status(os.path.dirname(recipefile), expected_status) + result = runCmd('git diff %s' % os.path.basename(recipefile), cwd=os.path.dirname(recipefile)) + removelines = ['SRC_URI = "git://.*"'] + addlines = [ + 'SRC_URI = "git://.* \\\\', + 'file://0001-Add-a-comment.patch;patchdir=.. \\\\', + '"' + ] + self._check_diff(result.output, addlines, removelines) + # Put things back so we can run devtool finish on a different layer + runCmd('cd %s; rm -f %s/*.patch; git checkout .' % (recipedir, testrecipe)) + # Run devtool finish + res = re.search('recipes-.*', recipedir) + self.assertTrue(res, 'Unable to find recipe subdirectory') + recipesubdir = res[0] + self.add_command_to_tearDown('rm -rf %s' % os.path.join(self.testlayer_path, recipesubdir)) + result = runCmd('devtool finish %s meta-selftest' % testrecipe) + # Check bbappend file contents + appendfn = os.path.join(self.testlayer_path, recipesubdir, '%s_%%.bbappend' % testrecipe) + with open(appendfn, 'r') as f: + appendlines = f.readlines() + expected_appendlines = [ + 'FILESEXTRAPATHS:prepend := "${THISDIR}/${PN}:"\n', + '\n', + 'SRC_URI += "file://0001-Add-a-comment.patch;patchdir=.."\n', + '\n' + ] + self.assertEqual(appendlines, expected_appendlines) + self.assertExists(os.path.join(os.path.dirname(appendfn), testrecipe, '0001-Add-a-comment.patch')) + # Try building + bitbake('%s -c patch' % testrecipe) + + class DevtoolExtractTests(DevtoolBase): def test_devtool_extract(self): diff --git a/meta/lib/oeqa/selftest/cases/externalsrc.py b/meta/lib/oeqa/selftest/cases/externalsrc.py new file mode 100644 index 0000000000..1d800dc82c --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/externalsrc.py @@ -0,0 +1,44 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# + +import os +import shutil +import tempfile + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import get_bb_var, runCmd + +class ExternalSrc(OESelftestTestCase): + # test that srctree_hash_files does not crash + # we should be actually checking do_compile[file-checksums] but oeqa currently does not support it + # so we check only that a recipe with externalsrc can be parsed + def test_externalsrc_srctree_hash_files(self): + test_recipe = "git-submodule-test" + git_url = "git://git.yoctoproject.org/git-submodule-test" + externalsrc_dir = tempfile.TemporaryDirectory(prefix="externalsrc").name + + self.write_config( + """ +INHERIT += "externalsrc" +EXTERNALSRC:pn-%s = "%s" +""" % (test_recipe, externalsrc_dir) + ) + + # test with git without submodules + runCmd('git clone %s %s' % (git_url, externalsrc_dir)) + os.unlink(externalsrc_dir + "/.gitmodules") + open(".gitmodules", 'w').close() # local file .gitmodules in cwd should not affect externalsrc parsing + self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC") + os.unlink(".gitmodules") + + # test with git with submodules + runCmd('git checkout .gitmodules', cwd=externalsrc_dir) + runCmd('git submodule update --init --recursive', cwd=externalsrc_dir) + self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC") + + # test without git + shutil.rmtree(os.path.join(externalsrc_dir, ".git")) + self.assertEqual(get_bb_var("S", test_recipe), externalsrc_dir, msg = "S does not equal to EXTERNALSRC") diff --git a/meta/lib/oeqa/selftest/cases/fitimage.py b/meta/lib/oeqa/selftest/cases/fitimage.py index e6bfd1257e..4d820faf92 100644 --- a/meta/lib/oeqa/selftest/cases/fitimage.py +++ b/meta/lib/oeqa/selftest/cases/fitimage.py @@ -202,7 +202,7 @@ UBOOT_MKIMAGE_SIGN_ARGS = "-c 'a smart comment'" signed_sections = {} for line in result.output.splitlines(): if line.startswith((' Configuration', ' Image')): - in_signed = re.search('\((.*)\)', line).groups()[0] + in_signed = re.search(r'\((.*)\)', line).groups()[0] elif re.match('^ *', line) in (' ', ''): in_signed = None elif in_signed: @@ -521,7 +521,7 @@ UBOOT_FIT_HASH_ALG = "sha256" signed_sections = {} for line in result.output.splitlines(): if line.startswith((' Image')): - in_signed = re.search('\((.*)\)', line).groups()[0] + in_signed = re.search(r'\((.*)\)', line).groups()[0] elif re.match(' \w', line): in_signed = None elif in_signed: @@ -675,7 +675,7 @@ FIT_SIGN_INDIVIDUAL = "1" signed_sections = {} for line in result.output.splitlines(): if line.startswith((' Image')): - in_signed = re.search('\((.*)\)', line).groups()[0] + in_signed = re.search(r'\((.*)\)', line).groups()[0] elif re.match(' \w', line): in_signed = None elif in_signed: @@ -738,6 +738,7 @@ UBOOT_LOADADDRESS = "0x80000000" UBOOT_DTB_LOADADDRESS = "0x82000000" UBOOT_ARCH = "arm" UBOOT_MKIMAGE_DTCOPTS = "-I dts -O dtb -p 2000" +UBOOT_MKIMAGE_KERNEL_TYPE = "kernel" UBOOT_EXTLINUX = "0" FIT_GENERATE_KEYS = "1" KERNEL_IMAGETYPE_REPLACEMENT = "zImage" @@ -763,6 +764,7 @@ FIT_HASH_ALG = "sha256" kernel_load = str(get_bb_var('UBOOT_LOADADDRESS')) kernel_entry = str(get_bb_var('UBOOT_ENTRYPOINT')) + kernel_type = str(get_bb_var('UBOOT_MKIMAGE_KERNEL_TYPE')) kernel_compression = str(get_bb_var('FIT_KERNEL_COMP_ALG')) uboot_arch = str(get_bb_var('UBOOT_ARCH')) fit_hash_alg = str(get_bb_var('FIT_HASH_ALG')) @@ -775,7 +777,7 @@ FIT_HASH_ALG = "sha256" 'kernel-1 {', 'description = "Linux kernel";', 'data = /incbin/("linux.bin");', - 'type = "kernel";', + 'type = "' + kernel_type + '";', 'arch = "' + uboot_arch + '";', 'os = "linux";', 'compression = "' + kernel_compression + '";', diff --git a/meta/lib/oeqa/selftest/cases/glibc.py b/meta/lib/oeqa/selftest/cases/glibc.py index 6fc98e9cb4..f42593a27f 100644 --- a/meta/lib/oeqa/selftest/cases/glibc.py +++ b/meta/lib/oeqa/selftest/cases/glibc.py @@ -24,7 +24,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): features.append('TOOLCHAIN_TEST_HOST_USER = "root"') features.append('TOOLCHAIN_TEST_HOST_PORT = "22"') # force single threaded test execution - features.append('EGLIBCPARALLELISM_task-check:pn-glibc-testsuite = "PARALLELMFLAGS="-j1""') + features.append('EGLIBCPARALLELISM:task-check:pn-glibc-testsuite = "PARALLELMFLAGS="-j1""') self.write_config("\n".join(features)) bitbake("glibc-testsuite -c check") @@ -41,7 +41,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): with contextlib.ExitStack() as s: # use the base work dir, as the nfs mount, since the recipe directory may not exist tmpdir = get_bb_var("BASE_WORKDIR") - nfsport, mountport = s.enter_context(unfs_server(tmpdir)) + nfsport, mountport = s.enter_context(unfs_server(tmpdir, udp = False)) # build core-image-minimal with required packages default_installed_packages = [ @@ -61,7 +61,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): bitbake("core-image-minimal") # start runqemu - qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic")) + qemu = s.enter_context(runqemu("core-image-minimal", runqemuparams = "nographic", qemuparams = "-m 1024")) # validate that SSH is working status, _ = qemu.run("uname") @@ -70,7 +70,7 @@ class GlibcSelfTestBase(OESelftestTestCase, OEPTestResultTestCase): # setup nfs mount if qemu.run("mkdir -p \"{0}\"".format(tmpdir))[0] != 0: raise Exception("Failed to setup NFS mount directory on target") - mountcmd = "mount -o noac,nfsvers=3,port={0},udp,mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir) + mountcmd = "mount -o noac,nfsvers=3,port={0},mountport={1} \"{2}:{3}\" \"{3}\"".format(nfsport, mountport, qemu.server_ip, tmpdir) status, output = qemu.run(mountcmd) if status != 0: raise Exception("Failed to setup NFS mount on target ({})".format(repr(output))) diff --git a/meta/lib/oeqa/selftest/cases/gotoolchain.py b/meta/lib/oeqa/selftest/cases/gotoolchain.py index c809d7c9b1..978898b86f 100644 --- a/meta/lib/oeqa/selftest/cases/gotoolchain.py +++ b/meta/lib/oeqa/selftest/cases/gotoolchain.py @@ -43,12 +43,6 @@ class oeGoToolchainSelfTest(OESelftestTestCase): @classmethod def tearDownClass(cls): - # Go creates file which are readonly - for dirpath, dirnames, filenames in os.walk(cls.tmpdir_SDKQA): - for filename in filenames + dirnames: - f = os.path.join(dirpath, filename) - if not os.path.islink(f): - os.chmod(f, 0o775) shutil.rmtree(cls.tmpdir_SDKQA, ignore_errors=True) super(oeGoToolchainSelfTest, cls).tearDownClass() @@ -56,6 +50,8 @@ class oeGoToolchainSelfTest(OESelftestTestCase): cmd = "cd %s/src/%s/%s; " % (self.go_path, proj, name) cmd = cmd + ". %s; " % self.env_SDK cmd = cmd + "export GOPATH=%s; " % self.go_path + cmd = cmd + "export GOFLAGS=-modcacherw; " + cmd = cmd + "export CGO_ENABLED=1; " cmd = cmd + "${CROSS_COMPILE}go %s" % gocmd return runCmd(cmd).status diff --git a/meta/lib/oeqa/selftest/cases/git.py b/meta/lib/oeqa/selftest/cases/intercept.py index f12874dc7d..f12874dc7d 100644 --- a/meta/lib/oeqa/selftest/cases/git.py +++ b/meta/lib/oeqa/selftest/cases/intercept.py diff --git a/meta/lib/oeqa/selftest/cases/liboe.py b/meta/lib/oeqa/selftest/cases/liboe.py index afe8f8809f..da88ff480e 100644 --- a/meta/lib/oeqa/selftest/cases/liboe.py +++ b/meta/lib/oeqa/selftest/cases/liboe.py @@ -97,6 +97,6 @@ class LibOE(OESelftestTestCase): dstcnt = len(os.listdir(dst)) srccnt = len(os.listdir(src)) - self.assertEquals(dstcnt, len(testfiles), "Number of files in dst (%s) differs from number of files in src(%s)." % (dstcnt, srccnt)) + self.assertEqual(dstcnt, len(testfiles), "Number of files in dst (%s) differs from number of files in src(%s)." % (dstcnt, srccnt)) oe.path.remove(testloc) diff --git a/meta/lib/oeqa/selftest/cases/lic_checksum.py b/meta/lib/oeqa/selftest/cases/lic_checksum.py index 8f1226e6a5..bc0a2b5d8e 100644 --- a/meta/lib/oeqa/selftest/cases/lic_checksum.py +++ b/meta/lib/oeqa/selftest/cases/lic_checksum.py @@ -26,6 +26,7 @@ LIC_FILES_CHKSUM = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e" SRC_URI = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e" """ % (urllib.parse.quote(lic_path), urllib.parse.quote(lic_path))) result = bitbake(bitbake_cmd) + self.delete_recipeinc('emptytest') # Verify that changing a license file that has an absolute path causes @@ -51,5 +52,6 @@ SRC_URI = "file://%s;md5=d41d8cd98f00b204e9800998ecf8427e" f.write("data") result = bitbake(bitbake_cmd, ignore_status=True) + self.delete_recipeinc('emptytest') if error_msg not in result.output: raise AssertionError(result.output) diff --git a/meta/lib/oeqa/selftest/cases/locales.py b/meta/lib/oeqa/selftest/cases/locales.py new file mode 100644 index 0000000000..433991abf9 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/locales.py @@ -0,0 +1,45 @@ +# +# SPDX-License-Identifier: MIT +# + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.core.decorator import OETestTag +from oeqa.utils.commands import bitbake, runqemu + +class LocalesTest(OESelftestTestCase): + + @OETestTag("runqemu") + def test_locales_on(self): + """ + Summary: Test the locales are generated + Expected: 1. Check the locale exist in the locale-archive + 2. Check the locale exist for the glibc + 3. Check the locale can be generated + Product: oe-core + Author: Louis Rannou <lrannou@baylibre.com> + AutomatedBy: Louis Rannou <lrannou@baylibre.com> + """ + + features = [] + features.append('EXTRA_IMAGE_FEATURES = "empty-root-password allow-empty-password allow-root-login"') + features.append('IMAGE_INSTALL:append = " glibc-utils localedef"') + features.append('GLIBC_GENERATE_LOCALES = "en_US.UTF-8 fr_FR.UTF-8"') + features.append('IMAGE_LINGUAS:append = " en-us fr-fr"') + features.append('ENABLE_BINARY_LOCALE_GENERATION = "1"') + self.write_config("\n".join(features)) + + # Build a core-image-minimal + bitbake('core-image-minimal') + + with runqemu("core-image-minimal", ssh=False, runqemuparams='nographic') as qemu: + cmd = "locale -a" + status, output = qemu.run_serial(cmd) + # output must includes fr_FR or fr_FR.UTF-8 + self.assertEqual(status, 1, msg='locale test command failed: output: %s' % output) + self.assertIn("fr_FR", output, msg='locale -a test failed: output: %s' % output) + + cmd = "localedef --list-archive -v" + status, output = qemu.run_serial(cmd) + # output must includes fr_FR.utf8 + self.assertEqual(status, 1, msg='localedef test command failed: output: %s' % output) + self.assertIn("fr_FR.utf8", output, msg='localedef test failed: output: %s' % output) diff --git a/meta/lib/oeqa/selftest/cases/minidebuginfo.py b/meta/lib/oeqa/selftest/cases/minidebuginfo.py new file mode 100644 index 0000000000..414dad64a3 --- /dev/null +++ b/meta/lib/oeqa/selftest/cases/minidebuginfo.py @@ -0,0 +1,49 @@ +# +# Copyright OpenEmbedded Contributors +# +# SPDX-License-Identifier: MIT +# +import os +import subprocess +import tempfile +import shutil + +from oeqa.selftest.case import OESelftestTestCase +from oeqa.utils.commands import bitbake, get_bb_var, runCmd + + +class Minidebuginfo(OESelftestTestCase): + def test_minidebuginfo(self): + target_sys = get_bb_var("TARGET_SYS") + binutils = "binutils-cross-{}".format(get_bb_var("TARGET_ARCH")) + + self.write_config(""" +PACKAGE_MINIDEBUGINFO = "1" +IMAGE_FSTYPES = "tar.bz2" +""") + bitbake("core-image-minimal {}:do_addto_recipe_sysroot".format(binutils)) + + deploy_dir = get_bb_var("DEPLOY_DIR_IMAGE") + native_sysroot = get_bb_var("RECIPE_SYSROOT_NATIVE", binutils) + readelf = get_bb_var("READELF", "core-image-minimal") + + # add usr/bin/${TARGET_SYS} to PATH + env = os.environ.copy() + paths = [os.path.join(native_sysroot, "usr", "bin", target_sys)] + paths += env["PATH"].split(":") + env["PATH"] = ":".join(paths) + + # confirm that executables and shared libraries contain an ELF section + # ".gnu_debugdata" which stores minidebuginfo. + with tempfile.TemporaryDirectory(prefix = "unpackfs-") as unpackedfs: + filename = os.path.join(deploy_dir, "core-image-minimal-{}.tar.bz2".format(self.td["MACHINE"])) + shutil.unpack_archive(filename, unpackedfs) + + r = runCmd([readelf, "-W", "-S", os.path.join(unpackedfs, "bin", "busybox")], + native_sysroot = native_sysroot, env = env) + self.assertIn(".gnu_debugdata", r.output) + + r = runCmd([readelf, "-W", "-S", os.path.join(unpackedfs, "lib", "libc.so.6")], + native_sysroot = native_sysroot, env = env) + self.assertIn(".gnu_debugdata", r.output) + diff --git a/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py index 802a91a488..ae12aa0865 100644 --- a/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py +++ b/meta/lib/oeqa/selftest/cases/oelib/buildhistory.py @@ -3,6 +3,7 @@ # import os +import sys from oeqa.selftest.case import OESelftestTestCase import tempfile import operator @@ -11,15 +12,14 @@ from oeqa.utils.commands import get_bb_var class TestBlobParsing(OESelftestTestCase): def setUp(self): - import time self.repo_path = tempfile.mkdtemp(prefix='selftest-buildhistory', dir=get_bb_var('TOPDIR')) try: from git import Repo self.repo = Repo.init(self.repo_path) - except ImportError: - self.skipTest('Python module GitPython is not present') + except ImportError as e: + self.skipTest('Python module GitPython is not present (%s) (%s)' % (e, sys.path)) self.test_file = "test" self.var_map = {} @@ -28,6 +28,16 @@ class TestBlobParsing(OESelftestTestCase): import shutil shutil.rmtree(self.repo_path) + @property + def heads_default(self): + """ + Support repos defaulting to master or to main branch + """ + try: + return self.repo.heads.main + except AttributeError: + return self.repo.heads.master + def commit_vars(self, to_add={}, to_remove = [], msg="A commit message"): if len(to_add) == 0 and len(to_remove) == 0: return @@ -65,10 +75,10 @@ class TestBlobParsing(OESelftestTestCase): changesmap = { "foo-2" : ("2", "8"), "bar" : ("","4"), "bar-2" : ("","5")} self.commit_vars(to_add = { "foo" : "1", "foo-2" : "2", "foo-3" : "3" }) - blob1 = self.repo.heads.master.commit.tree.blobs[0] + blob1 = self.heads_default.commit.tree.blobs[0] self.commit_vars(to_add = { "foo-2" : "8", "bar" : "4", "bar-2" : "5" }) - blob2 = self.repo.heads.master.commit.tree.blobs[0] + blob2 = self.heads_default.commit.tree.blobs[0] change_records = compare_dict_blobs(os.path.join(self.repo_path, self.test_file), blob1, blob2, False, False) @@ -84,10 +94,10 @@ class TestBlobParsing(OESelftestTestCase): defaultmap = { x : ("default", "1") for x in ["PKG", "PKGE", "PKGV", "PKGR"]} self.commit_vars(to_add = { "foo" : "1" }) - blob1 = self.repo.heads.master.commit.tree.blobs[0] + blob1 = self.heads_default.commit.tree.blobs[0] self.commit_vars(to_add = { "PKG" : "1", "PKGE" : "1", "PKGV" : "1", "PKGR" : "1" }) - blob2 = self.repo.heads.master.commit.tree.blobs[0] + blob2 = self.heads_default.commit.tree.blobs[0] change_records = compare_dict_blobs(os.path.join(self.repo_path, self.test_file), blob1, blob2, False, False) diff --git a/meta/lib/oeqa/selftest/cases/prservice.py b/meta/lib/oeqa/selftest/cases/prservice.py index 10158ca7c2..a41812148a 100644 --- a/meta/lib/oeqa/selftest/cases/prservice.py +++ b/meta/lib/oeqa/selftest/cases/prservice.py @@ -75,7 +75,7 @@ class BitbakePrTests(OESelftestTestCase): exported_db_path = os.path.join(self.builddir, 'export.inc') export_result = runCmd("bitbake-prserv-tool export %s" % exported_db_path, ignore_status=True) self.assertEqual(export_result.status, 0, msg="PR Service database export failed: %s" % export_result.output) - self.assertTrue(os.path.exists(exported_db_path)) + self.assertTrue(os.path.exists(exported_db_path), msg="%s didn't exist, tool output %s" % (exported_db_path, export_result.output)) if replace_current_db: current_db_path = os.path.join(get_bb_var('PERSISTENT_DIR'), 'prserv.sqlite3') diff --git a/meta/lib/oeqa/selftest/cases/recipetool.py b/meta/lib/oeqa/selftest/cases/recipetool.py index 510dae6bad..a2d8d292ad 100644 --- a/meta/lib/oeqa/selftest/cases/recipetool.py +++ b/meta/lib/oeqa/selftest/cases/recipetool.py @@ -440,16 +440,18 @@ class RecipetoolCreateTests(RecipetoolBase): self._test_recipe_contents(recipefile, checkvars, inherits) def test_recipetool_create_github(self): - # Basic test to see if github URL mangling works + # Basic test to see if github URL mangling works. Deliberately use an + # older release of Meson at present so we don't need a toml parser. temprecipe = os.path.join(self.tempdir, 'recipe') os.makedirs(temprecipe) recipefile = os.path.join(temprecipe, 'meson_git.bb') - srcuri = 'https://github.com/mesonbuild/meson;rev=0.32.0' - result = runCmd(['recipetool', 'create', '-o', temprecipe, srcuri]) - self.assertTrue(os.path.isfile(recipefile)) + srcuri = 'https://github.com/mesonbuild/meson;rev=0.52.1' + cmd = ['recipetool', 'create', '-o', temprecipe, srcuri] + result = runCmd(cmd) + self.assertTrue(os.path.isfile(recipefile), msg="recipe %s not created for command %s, output %s" % (recipefile, " ".join(cmd), result.output)) checkvars = {} - checkvars['LICENSE'] = set(['Apache-2.0']) - checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https;branch=master' + checkvars['LICENSE'] = set(['Apache-2.0', "Unknown"]) + checkvars['SRC_URI'] = 'git://github.com/mesonbuild/meson;protocol=https;branch=0.52' inherits = ['setuptools3'] self._test_recipe_contents(recipefile, checkvars, inherits) @@ -473,10 +475,11 @@ class RecipetoolCreateTests(RecipetoolBase): self._test_recipe_contents(recipefile, checkvars, inherits) def test_recipetool_create_github_tarball(self): - # Basic test to ensure github URL mangling doesn't apply to release tarballs + # Basic test to ensure github URL mangling doesn't apply to release tarballs. + # Deliberately use an older release of Meson at present so we don't need a toml parser. temprecipe = os.path.join(self.tempdir, 'recipe') os.makedirs(temprecipe) - pv = '0.32.0' + pv = '0.52.1' recipefile = os.path.join(temprecipe, 'meson_%s.bb' % pv) srcuri = 'https://github.com/mesonbuild/meson/releases/download/%s/meson-%s.tar.gz' % (pv, pv) result = runCmd('recipetool create -o %s %s' % (temprecipe, srcuri)) @@ -579,7 +582,10 @@ class RecipetoolTests(RecipetoolBase): commonlicdir = get_bb_var('COMMON_LICENSE_DIR') - d = bb.tinfoil.TinfoilDataStoreConnector + class DataConnectorCopy(bb.tinfoil.TinfoilDataStoreConnector): + pass + + d = DataConnectorCopy d.getVar = Mock(return_value=commonlicdir) srctree = tempfile.mkdtemp(prefix='recipetoolqa') diff --git a/meta/lib/oeqa/selftest/cases/reproducible.py b/meta/lib/oeqa/selftest/cases/reproducible.py index 5042c11d8e..49318be43a 100644 --- a/meta/lib/oeqa/selftest/cases/reproducible.py +++ b/meta/lib/oeqa/selftest/cases/reproducible.py @@ -126,15 +126,23 @@ class DiffoscopeTests(OESelftestTestCase): class ReproducibleTests(OESelftestTestCase): # Test the reproducibility of whatever is built between sstate_targets and targets - package_classes = ['deb', 'ipk', 'rpm'] + package_classes = get_bb_var("OEQA_REPRODUCIBLE_TEST_PACKAGE") + if package_classes: + package_classes = package_classes.split() + else: + package_classes = ['deb', 'ipk', 'rpm'] # Maximum report size, in bytes max_report_size = 250 * 1024 * 1024 # targets are the things we want to test the reproducibility of - targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world'] + targets = get_bb_var("OEQA_REPRODUCIBLE_TEST_TARGET") + if targets: + targets = targets.split() + else: + targets = ['core-image-minimal', 'core-image-sato', 'core-image-full-cmdline', 'core-image-weston', 'world'] # sstate targets are things to pull from sstate to potentially cut build/debugging time - sstate_targets = [] + sstate_targets = (get_bb_var("OEQA_REPRODUCIBLE_TEST_SSTATE_TARGETS") or "").split() save_results = False if 'OEQA_DEBUGGING_SAVED_OUTPUT' in os.environ: save_results = os.environ['OEQA_DEBUGGING_SAVED_OUTPUT'] @@ -149,7 +157,7 @@ class ReproducibleTests(OESelftestTestCase): def setUpLocal(self): super().setUpLocal() - needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS'] + needed_vars = ['TOPDIR', 'TARGET_PREFIX', 'BB_NUMBER_THREADS', 'BB_HASHSERVE'] bb_vars = get_bb_vars(needed_vars) for v in needed_vars: setattr(self, v.lower(), bb_vars[v]) @@ -223,7 +231,7 @@ class ReproducibleTests(OESelftestTestCase): # mirror, forcing a complete build from scratch config += textwrap.dedent('''\ SSTATE_DIR = "${TMPDIR}/sstate" - SSTATE_MIRRORS = "" + SSTATE_MIRRORS = "file://.*/.*-native.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH file://.*/.*-cross.* http://sstate.yoctoproject.org/all/PATH;downloadfilename=PATH" ''') self.logger.info("Building %s (sstate%s allowed)..." % (name, '' if use_sstate else ' NOT')) diff --git a/meta/lib/oeqa/selftest/cases/resulttooltests.py b/meta/lib/oeqa/selftest/cases/resulttooltests.py index dac5c46801..490f3fc5cf 100644 --- a/meta/lib/oeqa/selftest/cases/resulttooltests.py +++ b/meta/lib/oeqa/selftest/cases/resulttooltests.py @@ -69,7 +69,7 @@ class ResultToolTests(OESelftestTestCase): self.assertTrue('target_result1' in results['runtime/mydistro/qemux86/image'], msg="Pair not correct:%s" % results) self.assertTrue('target_result3' in results['runtime/mydistro/qemux86-64/image'], msg="Pair not correct:%s" % results) - def test_regrresion_can_get_regression_result(self): + def test_regression_can_get_regression_result(self): base_result_data = {'result': {'test1': {'status': 'PASSED'}, 'test2': {'status': 'PASSED'}, 'test3': {'status': 'FAILED'}, diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py index 8eacde40ad..7dcdfd0ab2 100644 --- a/meta/lib/oeqa/selftest/cases/runtime_test.py +++ b/meta/lib/oeqa/selftest/cases/runtime_test.py @@ -8,7 +8,7 @@ from oeqa.core.decorator import OETestTag import os import tempfile import oe.lsb -from oeqa.core.decorator.data import skipIfNotQemu +from oeqa.core.decorator.data import skipIfNotQemu, skipIfNotMachine class TestExport(OESelftestTestCase): @@ -200,6 +200,8 @@ class TestImage(OESelftestTestCase): bitbake('core-image-full-cmdline socat') bitbake('-c testimage core-image-full-cmdline') + # https://bugzilla.yoctoproject.org/show_bug.cgi?id=14966 + @skipIfNotMachine("qemux86-64", "test needs qemux86-64") def test_testimage_virgl_gtk_sdl(self): """ Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk and SDL frontends @@ -219,6 +221,8 @@ class TestImage(OESelftestTestCase): self.skipTest('virgl isn\'t working with Centos 7') if distro and distro == 'opensuseleap-15.0': self.skipTest('virgl isn\'t working with Opensuse 15.0') + if distro and distro == 'ubuntu-18.04': + self.skipTest('virgl isn\'t working with Ubuntu 18.04') qemu_packageconfig = get_bb_var('PACKAGECONFIG', 'qemu-system-native') qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native') @@ -241,6 +245,7 @@ class TestImage(OESelftestTestCase): bitbake('core-image-minimal') bitbake('-c testimage core-image-minimal') + @skipIfNotMachine("qemux86-64", "test needs qemux86-64") def test_testimage_virgl_headless(self): """ Summary: Check host-assisted accelerate OpenGL functionality in qemu with egl-headless frontend @@ -252,7 +257,8 @@ class TestImage(OESelftestTestCase): import subprocess, os distro = oe.lsb.distro_identifier() - if distro and distro in ['debian-9', 'debian-10', 'centos-7', 'centos-8', 'ubuntu-16.04', 'ubuntu-18.04', 'almalinux-8.5', 'almalinux-8.6']: + if distro and (distro in ['debian-9', 'debian-10', 'centos-7', 'centos-8', 'ubuntu-16.04', 'ubuntu-18.04'] or + distro.startswith('almalinux') or distro.startswith('rocky')): self.skipTest('virgl headless cannot be tested with %s' %(distro)) render_hint = """If /dev/dri/renderD* is absent due to lack of suitable GPU, 'modprobe vgem' will create one suitable for mesa llvmpipe software renderer.""" @@ -263,7 +269,7 @@ class TestImage(OESelftestTestCase): except FileNotFoundError: self.fail("/dev/dri directory does not exist; no render nodes available on this machine. %s" %(render_hint)) try: - dripath = subprocess.check_output("pkg-config --variable=dridriverdir dri", shell=True) + dripath = subprocess.check_output("PATH=/bin:/usr/bin:$PATH pkg-config --variable=dridriverdir dri", shell=True) except subprocess.CalledProcessError as e: self.fail("Could not determine the path to dri drivers on the host via pkg-config.\nPlease install Mesa development files (particularly, dri.pc) on the host machine.") qemu_distrofeatures = get_bb_var('DISTRO_FEATURES', 'qemu-system-native') diff --git a/meta/lib/oeqa/selftest/cases/tinfoil.py b/meta/lib/oeqa/selftest/cases/tinfoil.py index c81d56d82b..4b261dad00 100644 --- a/meta/lib/oeqa/selftest/cases/tinfoil.py +++ b/meta/lib/oeqa/selftest/cases/tinfoil.py @@ -64,6 +64,20 @@ class TinfoilTests(OESelftestTestCase): localdata.setVar('PN', 'hello') self.assertEqual('hello', localdata.getVar('BPN')) + # The config_data API tp parse_recipe_file is used by: + # layerindex-web layerindex/update_layer.py + def test_parse_recipe_custom_data(self): + with bb.tinfoil.Tinfoil() as tinfoil: + tinfoil.prepare(config_only=False, quiet=2) + localdata = bb.data.createCopy(tinfoil.config_data) + localdata.setVar("TESTVAR", "testval") + testrecipe = 'mdadm' + best = tinfoil.find_best_provider(testrecipe) + if not best: + self.fail('Unable to find recipe providing %s' % testrecipe) + rd = tinfoil.parse_recipe_file(best[3], config_data=localdata) + self.assertEqual("testval", rd.getVar('TESTVAR')) + def test_list_recipes(self): with bb.tinfoil.Tinfoil() as tinfoil: tinfoil.prepare(config_only=False, quiet=2) diff --git a/meta/lib/oeqa/selftest/cases/wic.py b/meta/lib/oeqa/selftest/cases/wic.py index de74c07a03..49fb6fe52c 100644 --- a/meta/lib/oeqa/selftest/cases/wic.py +++ b/meta/lib/oeqa/selftest/cases/wic.py @@ -1420,7 +1420,7 @@ class ModifyTests(WicTestCase): # list directory content of the first partition result = runCmd("wic ls %s:1 -n %s" % (images[0], sysroot)) - self.assertIn('\n%s ' % kerneltype.upper(), result.output) + self.assertIn('\n%s ' % kerneltype.upper(), result.output) self.assertIn('\nEFI <DIR> ', result.output) # remove file. EFI partitions are case-insensitive so exercise that too |