blob: 1aa6c03f8adb6dff6368edd6e1fc845ad5752653 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Patrick Williams92b42cb2022-09-03 06:53:57 -05002# Copyright OpenEmbedded Contributors
3#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: MIT
5#
6
Brad Bishopd7bf8c12018-02-25 22:55:05 -05007from oeqa.selftest.case import OESelftestTestCase
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08008from oeqa.utils.commands import bitbake, get_bb_vars, get_bb_var, runqemu
Brad Bishopd7bf8c12018-02-25 22:55:05 -05009import subprocess, os
10import oe.path
Brad Bishop15ae2502019-06-18 21:44:24 -040011import re
Brad Bishopd7bf8c12018-02-25 22:55:05 -050012
13class VersionOrdering(OESelftestTestCase):
14 # version1, version2, sort order
15 tests = (
16 ("1.0", "1.0", 0),
17 ("1.0", "2.0", -1),
18 ("2.0", "1.0", 1),
19 ("2.0-rc", "2.0", 1),
20 ("2.0~rc", "2.0", -1),
21 ("1.2rc2", "1.2.0", -1)
22 )
23
24 @classmethod
25 def setUpClass(cls):
26 super().setUpClass()
27
28 # Build the tools we need and populate a sysroot
29 bitbake("dpkg-native opkg-native rpm-native python3-native")
30 bitbake("build-sysroots -c build_native_sysroot")
31
32 # Get the paths so we can point into the sysroot correctly
33 vars = get_bb_vars(["STAGING_DIR", "BUILD_ARCH", "bindir_native", "libdir_native"])
34 cls.staging = oe.path.join(vars["STAGING_DIR"], vars["BUILD_ARCH"])
35 cls.bindir = oe.path.join(cls.staging, vars["bindir_native"])
36 cls.libdir = oe.path.join(cls.staging, vars["libdir_native"])
37
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080038 def setUpLocal(self):
Brad Bishopd7bf8c12018-02-25 22:55:05 -050039 # Just for convenience
40 self.staging = type(self).staging
41 self.bindir = type(self).bindir
42 self.libdir = type(self).libdir
43
Brad Bishopd7bf8c12018-02-25 22:55:05 -050044 def test_dpkg(self):
45 for ver1, ver2, sort in self.tests:
46 op = { -1: "<<", 0: "=", 1: ">>" }[sort]
47 status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
48 self.assertEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
49
50 # Now do it again but with incorrect operations
51 op = { -1: ">>", 0: ">>", 1: "<<" }[sort]
52 status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
53 self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
54
55 # Now do it again but with incorrect operations
56 op = { -1: "=", 0: "<<", 1: "=" }[sort]
57 status = subprocess.call((oe.path.join(self.bindir, "dpkg"), "--compare-versions", ver1, op, ver2))
58 self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
59
Brad Bishopd7bf8c12018-02-25 22:55:05 -050060 def test_opkg(self):
61 for ver1, ver2, sort in self.tests:
62 op = { -1: "<<", 0: "=", 1: ">>" }[sort]
63 status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
64 self.assertEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
65
66 # Now do it again but with incorrect operations
67 op = { -1: ">>", 0: ">>", 1: "<<" }[sort]
68 status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
69 self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
70
71 # Now do it again but with incorrect operations
72 op = { -1: "=", 0: "<<", 1: "=" }[sort]
73 status = subprocess.call((oe.path.join(self.bindir, "opkg"), "compare-versions", ver1, op, ver2))
74 self.assertNotEqual(status, 0, "%s %s %s failed" % (ver1, op, ver2))
75
Brad Bishopd7bf8c12018-02-25 22:55:05 -050076 def test_rpm(self):
77 # Need to tell the Python bindings where to find its configuration
78 env = os.environ.copy()
79 env["RPM_CONFIGDIR"] = oe.path.join(self.libdir, "rpm")
80
81 for ver1, ver2, sort in self.tests:
82 # The only way to test rpm is via the Python module, so we need to
83 # execute python3-native. labelCompare returns -1/0/1 (like strcmp)
84 # so add 100 and use that as the exit code.
85 command = (oe.path.join(self.bindir, "python3-native", "python3"), "-c",
86 "import sys, rpm; v1=(None, \"%s\", None); v2=(None, \"%s\", None); sys.exit(rpm.labelCompare(v1, v2) + 100)" % (ver1, ver2))
87 status = subprocess.call(command, env=env)
88 self.assertIn(status, (99, 100, 101))
89 self.assertEqual(status - 100, sort, "%s %s (%d) failed" % (ver1, ver2, sort))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080090
91class PackageTests(OESelftestTestCase):
Andrew Geisslerfc113ea2023-03-31 09:59:46 -050092 # Verify that a recipe cannot rename a package into an existing one
93 def test_package_name_conflict(self):
94 res = bitbake("packagenameconflict", ignore_status=True)
95 self.assertNotEqual(res.status, 0)
96 err = "package name already exists"
97 self.assertTrue(err in res.output)
98
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080099 # Verify that a recipe which sets up hardlink files has those preserved into split packages
100 # Also test file sparseness is preserved
101 def test_preserve_sparse_hardlinks(self):
102 bitbake("selftest-hardlink -c package")
103
104 dest = get_bb_var('PKGDEST', 'selftest-hardlink')
105 bindir = get_bb_var('bindir', 'selftest-hardlink')
106
107 def checkfiles():
108 # Recipe creates 4 hardlinked files, there is a copy in package/ and a copy in packages-split/
109 # so expect 8 in total.
110 self.assertEqual(os.stat(dest + "/selftest-hardlink" + bindir + "/hello1").st_nlink, 8)
111
112 # Test a sparse file remains sparse
113 sparsestat = os.stat(dest + "/selftest-hardlink" + bindir + "/sparsetest")
114 self.assertEqual(sparsestat.st_blocks, 0)
115 self.assertEqual(sparsestat.st_size, 1048576)
116
117 checkfiles()
118
119 # Clean and reinstall so its now definitely from sstate, then retest.
120 bitbake("selftest-hardlink -c clean")
121 bitbake("selftest-hardlink -c package")
122
123 checkfiles()
124
125 # Verify gdb to read symbols from separated debug hardlink file correctly
126 def test_gdb_hardlink_debug(self):
Patrick Williams213cb262021-08-07 19:21:33 -0500127 features = 'IMAGE_INSTALL:append = " selftest-hardlink"\n'
128 features += 'IMAGE_INSTALL:append = " selftest-hardlink-dbg"\n'
129 features += 'IMAGE_INSTALL:append = " selftest-hardlink-gdb"\n'
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800130 self.write_config(features)
131 bitbake("core-image-minimal")
132
133 def gdbtest(qemu, binary):
134 """
135 Check that gdb ``binary`` to read symbols from separated debug file
136 """
137 self.logger.info("gdbtest %s" % binary)
138 status, output = qemu.run_serial('/usr/bin/gdb.sh %s' % binary, timeout=60)
139 for l in output.split('\n'):
140 # Check debugging symbols exists
141 if '(no debugging symbols found)' in l:
142 self.logger.error("No debugging symbols found. GDB result:\n%s" % output)
143 return False
144
Patrick Williams7784c422022-11-17 07:29:11 -0600145 # Check debugging symbols works correctly. Don't look for a
146 # source file as optimisation can put the breakpoint inside
147 # stdio.h.
148 elif "Breakpoint 1 at" in l:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800149 return True
150
Brad Bishop19323692019-04-05 15:28:33 -0400151 self.logger.error("GDB result:\n%d: %s", status, output)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800152 return False
153
154 with runqemu('core-image-minimal') as qemu:
155 for binary in ['/usr/bin/hello1',
156 '/usr/bin/hello2',
157 '/usr/libexec/hello3',
158 '/usr/libexec/hello4']:
159 if not gdbtest(qemu, binary):
160 self.fail('GDB %s failed' % binary)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500161
162 def test_preserve_ownership(self):
Patrick Williams213cb262021-08-07 19:21:33 -0500163 features = 'IMAGE_INSTALL:append = " selftest-chown"\n'
Andrew Geissler82c905d2020-04-13 13:39:40 -0500164 self.write_config(features)
165 bitbake("core-image-minimal")
166
Patrick Williams7784c422022-11-17 07:29:11 -0600167 def check_ownership(qemu, expected_gid, expected_uid, path):
Andrew Geissler82c905d2020-04-13 13:39:40 -0500168 self.logger.info("Check ownership of %s", path)
Patrick Williams7784c422022-11-17 07:29:11 -0600169 status, output = qemu.run_serial('stat -c "%U %G" ' + path)
170 self.assertEqual(status, 1, "stat failed: " + output)
171 try:
172 uid, gid = output.split()
173 self.assertEqual(uid, expected_uid)
174 self.assertEqual(gid, expected_gid)
175 except ValueError:
176 self.fail("Cannot parse output: " + output)
Andrew Geissler82c905d2020-04-13 13:39:40 -0500177
Patrick Williams7784c422022-11-17 07:29:11 -0600178 sysconfdir = get_bb_var('sysconfdir', 'selftest-chown')
Andrew Geissler82c905d2020-04-13 13:39:40 -0500179 with runqemu('core-image-minimal') as qemu:
180 for path in [ sysconfdir + "/selftest-chown/file",
181 sysconfdir + "/selftest-chown/dir",
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600182 sysconfdir + "/selftest-chown/symlink",
183 sysconfdir + "/selftest-chown/fifotest/fifo"]:
Patrick Williams7784c422022-11-17 07:29:11 -0600184 check_ownership(qemu, "test", "test", path)