blob: e978313c61f6dd8950af903d722fd32245a233f1 [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 -05007import os
8import shutil
9import glob
10import subprocess
Brad Bishop316dfdd2018-06-25 12:45:53 -040011import tempfile
Andrew Geisslerfc113ea2023-03-31 09:59:46 -050012import datetime
13import re
Brad Bishopd7bf8c12018-02-25 22:55:05 -050014
Andrew Geisslerfc113ea2023-03-31 09:59:46 -050015from oeqa.utils.commands import runCmd, bitbake, get_bb_var, create_temp_layer, get_bb_vars
16from oeqa.selftest.case import OESelftestTestCase
17
Andrew Geissler595f6302022-01-24 19:11:47 +000018import oe
Brad Bishopd7bf8c12018-02-25 22:55:05 -050019import bb.siggen
20
Andrew Geisslerfc113ea2023-03-31 09:59:46 -050021class SStateBase(OESelftestTestCase):
22
23 def setUpLocal(self):
24 super(SStateBase, self).setUpLocal()
25 self.temp_sstate_location = None
26 needed_vars = ['SSTATE_DIR', 'NATIVELSBSTRING', 'TCLIBC', 'TUNE_ARCH',
27 'TOPDIR', 'TARGET_VENDOR', 'TARGET_OS']
28 bb_vars = get_bb_vars(needed_vars)
29 self.sstate_path = bb_vars['SSTATE_DIR']
30 self.hostdistro = bb_vars['NATIVELSBSTRING']
31 self.tclibc = bb_vars['TCLIBC']
32 self.tune_arch = bb_vars['TUNE_ARCH']
33 self.topdir = bb_vars['TOPDIR']
34 self.target_vendor = bb_vars['TARGET_VENDOR']
35 self.target_os = bb_vars['TARGET_OS']
36 self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
37
38 # Creates a special sstate configuration with the option to add sstate mirrors
39 def config_sstate(self, temp_sstate_location=False, add_local_mirrors=[]):
40 self.temp_sstate_location = temp_sstate_location
41
42 if self.temp_sstate_location:
43 temp_sstate_path = os.path.join(self.builddir, "temp_sstate_%s" % datetime.datetime.now().strftime('%Y%m%d%H%M%S'))
44 config_temp_sstate = "SSTATE_DIR = \"%s\"" % temp_sstate_path
45 self.append_config(config_temp_sstate)
46 self.track_for_cleanup(temp_sstate_path)
47 bb_vars = get_bb_vars(['SSTATE_DIR', 'NATIVELSBSTRING'])
48 self.sstate_path = bb_vars['SSTATE_DIR']
49 self.hostdistro = bb_vars['NATIVELSBSTRING']
50 self.distro_specific_sstate = os.path.join(self.sstate_path, self.hostdistro)
51
52 if add_local_mirrors:
53 config_set_sstate_if_not_set = 'SSTATE_MIRRORS ?= ""'
54 self.append_config(config_set_sstate_if_not_set)
55 for local_mirror in add_local_mirrors:
56 self.assertFalse(os.path.join(local_mirror) == os.path.join(self.sstate_path), msg='Cannot add the current sstate path as a sstate mirror')
57 config_sstate_mirror = "SSTATE_MIRRORS += \"file://.* file:///%s/PATH\"" % local_mirror
58 self.append_config(config_sstate_mirror)
59
60 # Returns a list containing sstate files
61 def search_sstate(self, filename_regex, distro_specific=True, distro_nonspecific=True):
62 result = []
63 for root, dirs, files in os.walk(self.sstate_path):
64 if distro_specific and re.search(r"%s/%s/[a-z0-9]{2}/[a-z0-9]{2}$" % (self.sstate_path, self.hostdistro), root):
65 for f in files:
66 if re.search(filename_regex, f):
67 result.append(f)
68 if distro_nonspecific and re.search(r"%s/[a-z0-9]{2}/[a-z0-9]{2}$" % self.sstate_path, root):
69 for f in files:
70 if re.search(filename_regex, f):
71 result.append(f)
72 return result
73
74 # Test sstate files creation and their location
75 def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True):
76 self.config_sstate(temp_sstate_location, [self.sstate_path])
77
78 if self.temp_sstate_location:
79 bitbake(['-cclean'] + targets)
80 else:
81 bitbake(['-ccleansstate'] + targets)
82
83 bitbake(targets)
84 file_tracker = []
85 results = self.search_sstate('|'.join(map(str, targets)), distro_specific, distro_nonspecific)
86 if distro_nonspecific:
87 for r in results:
88 if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo", "_fetch.tar.zst.siginfo", "_unpack.tar.zst.siginfo", "_patch.tar.zst.siginfo")):
89 continue
90 file_tracker.append(r)
91 else:
92 file_tracker = results
93
94 if should_pass:
95 self.assertTrue(file_tracker , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
96 else:
97 self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s (found %s)" % (', '.join(map(str, targets)), str(file_tracker)))
98
99 # Test the sstate files deletion part of the do_cleansstate task
100 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
101 self.config_sstate(temp_sstate_location, [self.sstate_path])
102
103 bitbake(['-ccleansstate'] + targets)
104
105 bitbake(targets)
106 archives_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific, distro_nonspecific)
107 self.assertTrue(archives_created, msg="Could not find sstate .tar.zst files for: %s (%s)" % (', '.join(map(str, targets)), str(archives_created)))
108
109 siginfo_created = self.search_sstate('|'.join(map(str, [s + r'.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific)
110 self.assertTrue(siginfo_created, msg="Could not find sstate .siginfo files for: %s (%s)" % (', '.join(map(str, targets)), str(siginfo_created)))
111
112 bitbake(['-ccleansstate'] + targets)
113 archives_removed = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific, distro_nonspecific)
114 self.assertTrue(not archives_removed, msg="do_cleansstate didn't remove .tar.zst sstate files for: %s (%s)" % (', '.join(map(str, targets)), str(archives_removed)))
115
116 # Test rebuilding of distro-specific sstate files
117 def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True):
118 self.config_sstate(temp_sstate_location, [self.sstate_path])
119
120 bitbake(['-ccleansstate'] + targets)
121
122 bitbake(targets)
123 results = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=False, distro_nonspecific=True)
124 filtered_results = []
125 for r in results:
126 if r.endswith(("_populate_lic.tar.zst", "_populate_lic.tar.zst.siginfo")):
127 continue
128 filtered_results.append(r)
129 self.assertTrue(filtered_results == [], msg="Found distro non-specific sstate for: %s (%s)" % (', '.join(map(str, targets)), str(filtered_results)))
130 file_tracker_1 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=True, distro_nonspecific=False)
131 self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
132
133 self.track_for_cleanup(self.distro_specific_sstate + "_old")
134 shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old")
135 shutil.rmtree(self.distro_specific_sstate)
136
137 bitbake(['-cclean'] + targets)
138 bitbake(targets)
139 file_tracker_2 = self.search_sstate('|'.join(map(str, [s + r'.*?\.tar.zst$' for s in targets])), distro_specific=True, distro_nonspecific=False)
140 self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files were created for: %s" % ', '.join(map(str, targets)))
141
142 not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2]
143 self.assertTrue(not_recreated == [], msg="The following sstate files were not recreated: %s" % ', '.join(map(str, not_recreated)))
144
145 created_once = [x for x in file_tracker_2 if x not in file_tracker_1]
146 self.assertTrue(created_once == [], msg="The following sstate files were created only in the second run: %s" % ', '.join(map(str, created_once)))
147
148 def sstate_common_samesigs(self, configA, configB, allarch=False):
149
150 self.write_config(configA)
151 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
152 bitbake("world meta-toolchain -S none")
153 self.write_config(configB)
154 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
155 bitbake("world meta-toolchain -S none")
156
157 def get_files(d, result):
158 for root, dirs, files in os.walk(d):
159 for name in files:
160 if "meta-environment" in root or "cross-canadian" in root:
161 continue
162 if "do_build" not in name:
163 # 1.4.1+gitAUTOINC+302fca9f4c-r0.do_package_write_ipk.sigdata.f3a2a38697da743f0dbed8b56aafcf79
164 (_, task, _, shash) = name.rsplit(".", 3)
165 result[os.path.join(os.path.basename(root), task)] = shash
166
167 files1 = {}
168 files2 = {}
169 subdirs = sorted(glob.glob(self.topdir + "/tmp-sstatesamehash/stamps/*-nativesdk*-linux"))
170 if allarch:
171 subdirs.extend(sorted(glob.glob(self.topdir + "/tmp-sstatesamehash/stamps/all-*-linux")))
172
173 for subdir in subdirs:
174 nativesdkdir = os.path.basename(subdir)
175 get_files(self.topdir + "/tmp-sstatesamehash/stamps/" + nativesdkdir, files1)
176 get_files(self.topdir + "/tmp-sstatesamehash2/stamps/" + nativesdkdir, files2)
177
178 self.maxDiff = None
179 self.assertEqual(files1, files2)
180
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500181class SStateTests(SStateBase):
Brad Bishop316dfdd2018-06-25 12:45:53 -0400182 def test_autorev_sstate_works(self):
183 # Test that a git repository which changes is correctly handled by SRCREV = ${AUTOREV}
184 # when PV does not contain SRCPV
185
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500186 tempdir = tempfile.mkdtemp(prefix='sstate_autorev')
187 tempdldir = tempfile.mkdtemp(prefix='sstate_autorev_dldir')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400188 self.track_for_cleanup(tempdir)
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500189 self.track_for_cleanup(tempdldir)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400190 create_temp_layer(tempdir, 'selftestrecipetool')
191 self.add_command_to_tearDown('bitbake-layers remove-layer %s' % tempdir)
Andrew Geisslerb7d28612020-07-24 16:15:54 -0500192 self.append_config("DL_DIR = \"%s\"" % tempdldir)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400193 runCmd('bitbake-layers add-layer %s' % tempdir)
194
195 # Use dbus-wait as a local git repo we can add a commit between two builds in
196 pn = 'dbus-wait'
197 srcrev = '6cc6077a36fe2648a5f993fe7c16c9632f946517'
198 url = 'git://git.yoctoproject.org/dbus-wait'
199 result = runCmd('git clone %s noname' % url, cwd=tempdir)
200 srcdir = os.path.join(tempdir, 'noname')
201 result = runCmd('git reset --hard %s' % srcrev, cwd=srcdir)
202 self.assertTrue(os.path.isfile(os.path.join(srcdir, 'configure.ac')), 'Unable to find configure script in source directory')
203
204 recipefile = os.path.join(tempdir, "recipes-test", "dbus-wait-test", 'dbus-wait-test_git.bb')
205 os.makedirs(os.path.dirname(recipefile))
Andrew Geissler595f6302022-01-24 19:11:47 +0000206 srcuri = 'git://' + srcdir + ';protocol=file;branch=master'
Brad Bishop316dfdd2018-06-25 12:45:53 -0400207 result = runCmd(['recipetool', 'create', '-o', recipefile, srcuri])
208 self.assertTrue(os.path.isfile(recipefile), 'recipetool did not create recipe file; output:\n%s' % result.output)
209
210 with open(recipefile, 'a') as f:
211 f.write('SRCREV = "${AUTOREV}"\n')
212 f.write('PV = "1.0"\n')
213
214 bitbake("dbus-wait-test -c fetch")
215 with open(os.path.join(srcdir, "bar.txt"), "w") as f:
216 f.write("foo")
217 result = runCmd('git add bar.txt; git commit -asm "add bar"', cwd=srcdir)
218 bitbake("dbus-wait-test -c unpack")
219
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500220class SStateCreation(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500221 def test_sstate_creation_distro_specific_pass(self):
222 self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
223
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500224 def test_sstate_creation_distro_specific_fail(self):
225 self.run_test_sstate_creation(['binutils-cross-'+ self.tune_arch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
226
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500227 def test_sstate_creation_distro_nonspecific_pass(self):
228 self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
229
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500230 def test_sstate_creation_distro_nonspecific_fail(self):
231 self.run_test_sstate_creation(['linux-libc-headers'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False)
232
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500233class SStateCleanup(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500234 def test_cleansstate_task_distro_specific_nonspecific(self):
235 targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native']
236 targets.append('linux-libc-headers')
237 self.run_test_cleansstate_task(targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True)
238
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500239 def test_cleansstate_task_distro_nonspecific(self):
240 self.run_test_cleansstate_task(['linux-libc-headers'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
241
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500242 def test_cleansstate_task_distro_specific(self):
243 targets = ['binutils-cross-'+ self.tune_arch, 'binutils-native']
244 targets.append('linux-libc-headers')
245 self.run_test_cleansstate_task(targets, distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
246
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500247class SStateDistroTests(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500248 def test_rebuild_distro_specific_sstate_cross_native_targets(self):
249 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch, 'binutils-native'], temp_sstate_location=True)
250
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500251 def test_rebuild_distro_specific_sstate_cross_target(self):
252 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + self.tune_arch], temp_sstate_location=True)
253
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500254 def test_rebuild_distro_specific_sstate_native_target(self):
255 self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True)
256
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500257class SStateCacheManagement(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500258 # Test the sstate-cache-management script. Each element in the global_config list is used with the corresponding element in the target_config list
259 # global_config elements are expected to not generate any sstate files that would be removed by sstate-cache-management.sh (such as changing the value of MACHINE)
260 def run_test_sstate_cache_management_script(self, target, global_config=[''], target_config=[''], ignore_patterns=[]):
261 self.assertTrue(global_config)
262 self.assertTrue(target_config)
263 self.assertTrue(len(global_config) == len(target_config), msg='Lists global_config and target_config should have the same number of elements')
264 self.config_sstate(temp_sstate_location=True, add_local_mirrors=[self.sstate_path])
265
266 # If buildhistory is enabled, we need to disable version-going-backwards
267 # QA checks for this test. It may report errors otherwise.
Patrick Williams213cb262021-08-07 19:21:33 -0500268 self.append_config('ERROR_QA:remove = "version-going-backwards"')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500269
Andrew Geissler7e0e3c02022-02-25 20:34:39 +0000270 # For now this only checks if random sstate tasks are handled correctly as a group.
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500271 # In the future we should add control over what tasks we check for.
272
273 sstate_archs_list = []
274 expected_remaining_sstate = []
275 for idx in range(len(target_config)):
276 self.append_config(global_config[idx])
277 self.append_recipeinc(target, target_config[idx])
278 sstate_arch = get_bb_var('SSTATE_PKGARCH', target)
279 if not sstate_arch in sstate_archs_list:
280 sstate_archs_list.append(sstate_arch)
281 if target_config[idx] == target_config[-1]:
Andrew Geisslereff27472021-10-29 15:35:00 -0500282 target_sstate_before_build = self.search_sstate(target + r'.*?\.tar.zst$')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500283 bitbake("-cclean %s" % target)
284 result = bitbake(target, ignore_status=True)
285 if target_config[idx] == target_config[-1]:
Andrew Geisslereff27472021-10-29 15:35:00 -0500286 target_sstate_after_build = self.search_sstate(target + r'.*?\.tar.zst$')
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500287 expected_remaining_sstate += [x for x in target_sstate_after_build if x not in target_sstate_before_build if not any(pattern in x for pattern in ignore_patterns)]
288 self.remove_config(global_config[idx])
289 self.remove_recipeinc(target, target_config[idx])
290 self.assertEqual(result.status, 0, msg = "build of %s failed with %s" % (target, result.output))
291
292 runCmd("sstate-cache-management.sh -y --cache-dir=%s --remove-duplicated --extra-archs=%s" % (self.sstate_path, ','.join(map(str, sstate_archs_list))))
Andrew Geisslereff27472021-10-29 15:35:00 -0500293 actual_remaining_sstate = [x for x in self.search_sstate(target + r'.*?\.tar.zst$') if not any(pattern in x for pattern in ignore_patterns)]
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500294
295 actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate]
Andrew Geisslereff27472021-10-29 15:35:00 -0500296 self.assertFalse(actual_not_expected, msg="Files should have been removed but were not: %s" % ', '.join(map(str, actual_not_expected)))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500297 expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate]
Andrew Geisslereff27472021-10-29 15:35:00 -0500298 self.assertFalse(expected_not_actual, msg="Extra files were removed: %s" ', '.join(map(str, expected_not_actual)))
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500299
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500300 def test_sstate_cache_management_script_using_pr_1(self):
301 global_config = []
302 target_config = []
303 global_config.append('')
304 target_config.append('PR = "0"')
305 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
306
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500307 def test_sstate_cache_management_script_using_pr_2(self):
308 global_config = []
309 target_config = []
310 global_config.append('')
311 target_config.append('PR = "0"')
312 global_config.append('')
313 target_config.append('PR = "1"')
314 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
315
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500316 def test_sstate_cache_management_script_using_pr_3(self):
317 global_config = []
318 target_config = []
319 global_config.append('MACHINE = "qemux86-64"')
320 target_config.append('PR = "0"')
321 global_config.append(global_config[0])
322 target_config.append('PR = "1"')
323 global_config.append('MACHINE = "qemux86"')
324 target_config.append('PR = "1"')
325 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
326
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500327 def test_sstate_cache_management_script_using_machine(self):
328 global_config = []
329 target_config = []
330 global_config.append('MACHINE = "qemux86-64"')
331 target_config.append('')
332 global_config.append('MACHINE = "qemux86"')
333 target_config.append('')
334 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
335
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500336class SStateHashSameSigs(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500337 def test_sstate_32_64_same_hash(self):
338 """
339 The sstate checksums for both native and target should not vary whether
340 they're built on a 32 or 64 bit system. Rather than requiring two different
341 build machines and running a builds, override the variables calling uname()
342 manually and check using bitbake -S.
343 """
344
345 self.write_config("""
346MACHINE = "qemux86"
347TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800348TCLIBCAPPEND = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500349BUILD_ARCH = "x86_64"
350BUILD_OS = "linux"
351SDKMACHINE = "x86_64"
352PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500353BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500354""")
355 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500356 bitbake("core-image-weston -S none")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500357 self.write_config("""
358MACHINE = "qemux86"
359TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800360TCLIBCAPPEND = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500361BUILD_ARCH = "i686"
362BUILD_OS = "linux"
363SDKMACHINE = "i686"
364PACKAGE_CLASSES = "package_rpm package_ipk package_deb"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500365BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500366""")
367 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500368 bitbake("core-image-weston -S none")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500369
370 def get_files(d):
371 f = []
372 for root, dirs, files in os.walk(d):
Andrew Geisslerc926e172021-05-07 16:11:35 -0500373 if "core-image-weston" in root:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500374 # SDKMACHINE changing will change
375 # do_rootfs/do_testimage/do_build stamps of images which
376 # is safe to ignore.
377 continue
378 f.extend(os.path.join(root, name) for name in files)
379 return f
380 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
381 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
382 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash").replace("i686-linux", "x86_64-linux").replace("i686" + self.target_vendor + "-linux", "x86_64" + self.target_vendor + "-linux", ) for x in files2]
383 self.maxDiff = None
384 self.assertCountEqual(files1, files2)
385
386
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500387 def test_sstate_nativelsbstring_same_hash(self):
388 """
389 The sstate checksums should be independent of whichever NATIVELSBSTRING is
390 detected. Rather than requiring two different build machines and running
391 builds, override the variables manually and check using bitbake -S.
392 """
393
394 self.write_config("""
395TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800396TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500397NATIVELSBSTRING = \"DistroA\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500398BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500399""")
400 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500401 bitbake("core-image-weston -S none")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500402 self.write_config("""
403TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800404TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500405NATIVELSBSTRING = \"DistroB\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500406BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500407""")
408 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500409 bitbake("core-image-weston -S none")
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500410
411 def get_files(d):
412 f = []
413 for root, dirs, files in os.walk(d):
414 f.extend(os.path.join(root, name) for name in files)
415 return f
416 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
417 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
418 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
419 self.maxDiff = None
420 self.assertCountEqual(files1, files2)
421
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500422class SStateHashSameSigs2(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500423 def test_sstate_allarch_samesigs(self):
424 """
425 The sstate checksums of allarch packages should be independent of whichever
426 MACHINE is set. Check this using bitbake -S.
427 Also, rather than duplicate the test, check nativesdk stamps are the same between
428 the two MACHINE values.
429 """
430
431 configA = """
432TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800433TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500434MACHINE = \"qemux86-64\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500435BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500436"""
Andrew Geissler595f6302022-01-24 19:11:47 +0000437 #OLDEST_KERNEL is arch specific so set to a different value here for testing
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500438 configB = """
439TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800440TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500441MACHINE = \"qemuarm\"
Andrew Geissler595f6302022-01-24 19:11:47 +0000442OLDEST_KERNEL = \"3.3.0\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500443BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500444"""
Andrew Geissler595f6302022-01-24 19:11:47 +0000445 self.sstate_common_samesigs(configA, configB, allarch=True)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500446
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800447 def test_sstate_nativesdk_samesigs_multilib(self):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500448 """
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800449 check nativesdk stamps are the same between the two MACHINE values.
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500450 """
451
452 configA = """
453TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800454TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500455MACHINE = \"qemux86-64\"
456require conf/multilib.conf
457MULTILIBS = \"multilib:lib32\"
Patrick Williams213cb262021-08-07 19:21:33 -0500458DEFAULTTUNE:virtclass-multilib-lib32 = \"x86\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500459BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500460"""
461 configB = """
462TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800463TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500464MACHINE = \"qemuarm\"
465require conf/multilib.conf
466MULTILIBS = \"\"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500467BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500468"""
Andrew Geissler595f6302022-01-24 19:11:47 +0000469 self.sstate_common_samesigs(configA, configB)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500470
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500471class SStateHashSameSigs3(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500472 def test_sstate_sametune_samesigs(self):
473 """
474 The sstate checksums of two identical machines (using the same tune) should be the
475 same, apart from changes within the machine specific stamps directory. We use the
476 qemux86copy machine to test this. Also include multilibs in the test.
477 """
478
479 self.write_config("""
480TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800481TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500482MACHINE = \"qemux86\"
483require conf/multilib.conf
484MULTILIBS = "multilib:lib32"
Patrick Williams213cb262021-08-07 19:21:33 -0500485DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500486BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500487""")
488 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
489 bitbake("world meta-toolchain -S none")
490 self.write_config("""
491TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800492TCLIBCAPPEND = \"\"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500493MACHINE = \"qemux86copy\"
494require conf/multilib.conf
495MULTILIBS = "multilib:lib32"
Patrick Williams213cb262021-08-07 19:21:33 -0500496DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500497BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500498""")
499 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
500 bitbake("world meta-toolchain -S none")
501
502 def get_files(d):
503 f = []
504 for root, dirs, files in os.walk(d):
505 for name in files:
Patrick Williamsdb4c27e2022-08-05 08:10:29 -0500506 if "meta-environment" in root or "cross-canadian" in root or 'meta-ide-support' in root:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500507 continue
508 if "qemux86copy-" in root or "qemux86-" in root:
509 continue
510 if "do_build" not in name and "do_populate_sdk" not in name:
511 f.append(os.path.join(root, name))
512 return f
513 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
514 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
515 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
516 self.maxDiff = None
517 self.assertCountEqual(files1, files2)
518
519
Andrew Geissler82c905d2020-04-13 13:39:40 -0500520 def test_sstate_multilib_or_not_native_samesigs(self):
521 """The sstate checksums of two native recipes (and their dependencies)
522 where the target is using multilib in one but not the other
523 should be the same. We use the qemux86copy machine to test
524 this.
525 """
526
527 self.write_config("""
528TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
529TCLIBCAPPEND = \"\"
530MACHINE = \"qemux86\"
531require conf/multilib.conf
532MULTILIBS = "multilib:lib32"
Patrick Williams213cb262021-08-07 19:21:33 -0500533DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
Andrew Geissler82c905d2020-04-13 13:39:40 -0500534BB_SIGNATURE_HANDLER = "OEBasicHash"
535""")
536 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
537 bitbake("binutils-native -S none")
538 self.write_config("""
539TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
540TCLIBCAPPEND = \"\"
541MACHINE = \"qemux86copy\"
542BB_SIGNATURE_HANDLER = "OEBasicHash"
543""")
544 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
545 bitbake("binutils-native -S none")
546
547 def get_files(d):
548 f = []
549 for root, dirs, files in os.walk(d):
550 for name in files:
551 f.append(os.path.join(root, name))
552 return f
553 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
554 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
555 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
556 self.maxDiff = None
557 self.assertCountEqual(files1, files2)
558
Andrew Geisslerfc113ea2023-03-31 09:59:46 -0500559class SStateHashSameSigs4(SStateBase):
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500560 def test_sstate_noop_samesigs(self):
561 """
562 The sstate checksums of two builds with these variables changed or
563 classes inherits should be the same.
564 """
565
566 self.write_config("""
567TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800568TCLIBCAPPEND = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500569BB_NUMBER_THREADS = "${@oe.utils.cpu_count()}"
570PARALLEL_MAKE = "-j 1"
571DL_DIR = "${TOPDIR}/download1"
572TIME = "111111"
573DATE = "20161111"
Patrick Williams213cb262021-08-07 19:21:33 -0500574INHERIT:remove = "buildstats-summary buildhistory uninative"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500575http_proxy = ""
Brad Bishop6dbb3162019-11-25 09:41:34 -0500576BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500577""")
578 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
579 self.track_for_cleanup(self.topdir + "/download1")
580 bitbake("world meta-toolchain -S none")
581 self.write_config("""
582TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800583TCLIBCAPPEND = ""
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500584BB_NUMBER_THREADS = "${@oe.utils.cpu_count()+1}"
585PARALLEL_MAKE = "-j 2"
586DL_DIR = "${TOPDIR}/download2"
587TIME = "222222"
588DATE = "20161212"
589# Always remove uninative as we're changing proxies
Patrick Williams213cb262021-08-07 19:21:33 -0500590INHERIT:remove = "uninative"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500591INHERIT += "buildstats-summary buildhistory"
592http_proxy = "http://example.com/"
Brad Bishop6dbb3162019-11-25 09:41:34 -0500593BB_SIGNATURE_HANDLER = "OEBasicHash"
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500594""")
595 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
596 self.track_for_cleanup(self.topdir + "/download2")
597 bitbake("world meta-toolchain -S none")
598
599 def get_files(d):
600 f = {}
601 for root, dirs, files in os.walk(d):
602 for name in files:
603 name, shash = name.rsplit('.', 1)
604 # Extract just the machine and recipe name
605 base = os.sep.join(root.rsplit(os.sep, 2)[-2:] + [name])
606 f[base] = shash
607 return f
608
609 def compare_sigfiles(files, files1, files2, compare=False):
610 for k in files:
611 if k in files1 and k in files2:
612 print("%s differs:" % k)
613 if compare:
614 sigdatafile1 = self.topdir + "/tmp-sstatesamehash/stamps/" + k + "." + files1[k]
615 sigdatafile2 = self.topdir + "/tmp-sstatesamehash2/stamps/" + k + "." + files2[k]
616 output = bb.siggen.compare_sigfiles(sigdatafile1, sigdatafile2)
617 if output:
618 print('\n'.join(output))
619 elif k in files1 and k not in files2:
620 print("%s in files1" % k)
621 elif k not in files1 and k in files2:
622 print("%s in files2" % k)
623 else:
624 assert "shouldn't reach here"
625
626 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps/")
627 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps/")
628 # Remove items that are identical in both sets
629 for k,v in files1.items() & files2.items():
630 del files1[k]
631 del files2[k]
632 if not files1 and not files2:
633 # No changes, so we're done
634 return
635
636 files = list(files1.keys() | files2.keys())
637 # this is an expensive computation, thus just compare the first 'max_sigfiles_to_compare' k files
638 max_sigfiles_to_compare = 20
639 first, rest = files[:max_sigfiles_to_compare], files[max_sigfiles_to_compare:]
Brad Bishop316dfdd2018-06-25 12:45:53 -0400640 compare_sigfiles(first, files1, files2, compare=True)
641 compare_sigfiles(rest, files1, files2, compare=False)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500642
643 self.fail("sstate hashes not identical.")
Andrew Geissler595f6302022-01-24 19:11:47 +0000644
645 def test_sstate_movelayer_samesigs(self):
646 """
647 The sstate checksums of two builds with the same oe-core layer in two
648 different locations should be the same.
649 """
650 core_layer = os.path.join(
651 self.tc.td["COREBASE"], 'meta')
652 copy_layer_1 = self.topdir + "/meta-copy1/meta"
653 copy_layer_2 = self.topdir + "/meta-copy2/meta"
654
655 oe.path.copytree(core_layer, copy_layer_1)
Andrew Geissler615f2f12022-07-15 14:00:58 -0500656 os.symlink(os.path.dirname(core_layer) + "/scripts", self.topdir + "/meta-copy1/scripts")
Andrew Geissler595f6302022-01-24 19:11:47 +0000657 self.write_config("""
658TMPDIR = "${TOPDIR}/tmp-sstatesamehash"
659""")
660 bblayers_conf = 'BBLAYERS += "%s"\nBBLAYERS:remove = "%s"' % (copy_layer_1, core_layer)
661 self.write_bblayers_config(bblayers_conf)
662 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash")
663 bitbake("bash -S none")
664
665 oe.path.copytree(core_layer, copy_layer_2)
Andrew Geissler615f2f12022-07-15 14:00:58 -0500666 os.symlink(os.path.dirname(core_layer) + "/scripts", self.topdir + "/meta-copy2/scripts")
Andrew Geissler595f6302022-01-24 19:11:47 +0000667 self.write_config("""
668TMPDIR = "${TOPDIR}/tmp-sstatesamehash2"
669""")
670 bblayers_conf = 'BBLAYERS += "%s"\nBBLAYERS:remove = "%s"' % (copy_layer_2, core_layer)
671 self.write_bblayers_config(bblayers_conf)
672 self.track_for_cleanup(self.topdir + "/tmp-sstatesamehash2")
673 bitbake("bash -S none")
674
675 def get_files(d):
676 f = []
677 for root, dirs, files in os.walk(d):
678 for name in files:
679 f.append(os.path.join(root, name))
680 return f
681 files1 = get_files(self.topdir + "/tmp-sstatesamehash/stamps")
682 files2 = get_files(self.topdir + "/tmp-sstatesamehash2/stamps")
683 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
684 self.maxDiff = None
685 self.assertCountEqual(files1, files2)
686