blob: 6906b21237402940c1e03280355ed92d42cb319b [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001import datetime
2import unittest
3import os
4import re
5import shutil
6
7import oeqa.utils.ftools as ftools
8from oeqa.selftest.base import oeSelfTest
9from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_test_layer
10from oeqa.selftest.sstate import SStateBase
11from oeqa.utils.decorators import testcase
12
13class SStateTests(SStateBase):
14
15 # Test sstate files creation and their location
16 def run_test_sstate_creation(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True, should_pass=True):
17 self.config_sstate(temp_sstate_location)
18
19 if self.temp_sstate_location:
20 bitbake(['-cclean'] + targets)
21 else:
22 bitbake(['-ccleansstate'] + targets)
23
24 bitbake(targets)
25 file_tracker = self.search_sstate('|'.join(map(str, targets)), distro_specific, distro_nonspecific)
26 if should_pass:
27 self.assertTrue(file_tracker , msg="Could not find sstate files for: %s" % ', '.join(map(str, targets)))
28 else:
29 self.assertTrue(not file_tracker , msg="Found sstate files in the wrong place for: %s" % ', '.join(map(str, targets)))
30
31 @testcase(975)
32 def test_sstate_creation_distro_specific_pass(self):
33 targetarch = get_bb_var('TUNE_ARCH')
34 self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
35
36 @testcase(975)
37 def test_sstate_creation_distro_specific_fail(self):
38 targetarch = get_bb_var('TUNE_ARCH')
39 self.run_test_sstate_creation(['binutils-cross-'+ targetarch, 'binutils-native'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True, should_pass=False)
40
41 @testcase(976)
42 def test_sstate_creation_distro_nonspecific_pass(self):
43 self.run_test_sstate_creation(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
44
45 @testcase(976)
46 def test_sstate_creation_distro_nonspecific_fail(self):
47 self.run_test_sstate_creation(['glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True, should_pass=False)
48
49
50 # Test the sstate files deletion part of the do_cleansstate task
51 def run_test_cleansstate_task(self, targets, distro_specific=True, distro_nonspecific=True, temp_sstate_location=True):
52 self.config_sstate(temp_sstate_location)
53
54 bitbake(['-ccleansstate'] + targets)
55
56 bitbake(targets)
57 tgz_created = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific)
58 self.assertTrue(tgz_created, msg="Could not find sstate .tgz files for: %s" % ', '.join(map(str, targets)))
59
60 siginfo_created = self.search_sstate('|'.join(map(str, [s + '.*?\.siginfo$' for s in targets])), distro_specific, distro_nonspecific)
61 self.assertTrue(siginfo_created, msg="Could not find sstate .siginfo files for: %s" % ', '.join(map(str, targets)))
62
63 bitbake(['-ccleansstate'] + targets)
64 tgz_removed = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific, distro_nonspecific)
65 self.assertTrue(not tgz_removed, msg="do_cleansstate didn't remove .tgz sstate files for: %s" % ', '.join(map(str, targets)))
66
67 @testcase(977)
68 def test_cleansstate_task_distro_specific_nonspecific(self):
69 targetarch = get_bb_var('TUNE_ARCH')
70 self.run_test_cleansstate_task(['binutils-cross-' + targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=True, temp_sstate_location=True)
71
72 @testcase(977)
73 def test_cleansstate_task_distro_nonspecific(self):
74 self.run_test_cleansstate_task(['glibc-initial'], distro_specific=False, distro_nonspecific=True, temp_sstate_location=True)
75
76 @testcase(977)
77 def test_cleansstate_task_distro_specific(self):
78 targetarch = get_bb_var('TUNE_ARCH')
79 self.run_test_cleansstate_task(['binutils-cross-'+ targetarch, 'binutils-native', 'glibc-initial'], distro_specific=True, distro_nonspecific=False, temp_sstate_location=True)
80
81
82 # Test rebuilding of distro-specific sstate files
83 def run_test_rebuild_distro_specific_sstate(self, targets, temp_sstate_location=True):
84 self.config_sstate(temp_sstate_location)
85
86 bitbake(['-ccleansstate'] + targets)
87
88 bitbake(targets)
89 self.assertTrue(self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=False, distro_nonspecific=True) == [], msg="Found distro non-specific sstate for: %s" % ', '.join(map(str, targets)))
90 file_tracker_1 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
91 self.assertTrue(len(file_tracker_1) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets)))
92
93 self.track_for_cleanup(self.distro_specific_sstate + "_old")
94 shutil.copytree(self.distro_specific_sstate, self.distro_specific_sstate + "_old")
95 shutil.rmtree(self.distro_specific_sstate)
96
97 bitbake(['-cclean'] + targets)
98 bitbake(targets)
99 file_tracker_2 = self.search_sstate('|'.join(map(str, [s + '.*?\.tgz$' for s in targets])), distro_specific=True, distro_nonspecific=False)
100 self.assertTrue(len(file_tracker_2) >= len(targets), msg = "Not all sstate files ware created for: %s" % ', '.join(map(str, targets)))
101
102 not_recreated = [x for x in file_tracker_1 if x not in file_tracker_2]
103 self.assertTrue(not_recreated == [], msg="The following sstate files ware not recreated: %s" % ', '.join(map(str, not_recreated)))
104
105 created_once = [x for x in file_tracker_2 if x not in file_tracker_1]
106 self.assertTrue(created_once == [], msg="The following sstate files ware created only in the second run: %s" % ', '.join(map(str, created_once)))
107
108 @testcase(175)
109 def test_rebuild_distro_specific_sstate_cross_native_targets(self):
110 targetarch = get_bb_var('TUNE_ARCH')
111 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch, 'binutils-native'], temp_sstate_location=True)
112
113 @testcase(175)
114 def test_rebuild_distro_specific_sstate_cross_target(self):
115 targetarch = get_bb_var('TUNE_ARCH')
116 self.run_test_rebuild_distro_specific_sstate(['binutils-cross-' + targetarch], temp_sstate_location=True)
117
118 @testcase(175)
119 def test_rebuild_distro_specific_sstate_native_target(self):
120 self.run_test_rebuild_distro_specific_sstate(['binutils-native'], temp_sstate_location=True)
121
122
123 # Test the sstate-cache-management script. Each element in the global_config list is used with the corresponding element in the target_config list
124 # 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)
125 def run_test_sstate_cache_management_script(self, target, global_config=[''], target_config=[''], ignore_patterns=[]):
126 self.assertTrue(global_config)
127 self.assertTrue(target_config)
128 self.assertTrue(len(global_config) == len(target_config), msg='Lists global_config and target_config should have the same number of elements')
129 self.config_sstate(temp_sstate_location=True, add_local_mirrors=[self.sstate_path])
130
131 # If buildhistory is enabled, we need to disable version-going-backwards QA checks for this test. It may report errors otherwise.
132 if ('buildhistory' in get_bb_var('USER_CLASSES')) or ('buildhistory' in get_bb_var('INHERIT')):
133 remove_errors_config = 'ERROR_QA_remove = "version-going-backwards"'
134 self.append_config(remove_errors_config)
135
136 # For not this only checks if random sstate tasks are handled correctly as a group.
137 # In the future we should add control over what tasks we check for.
138
139 sstate_archs_list = []
140 expected_remaining_sstate = []
141 for idx in range(len(target_config)):
142 self.append_config(global_config[idx])
143 self.append_recipeinc(target, target_config[idx])
144 sstate_arch = get_bb_var('SSTATE_PKGARCH', target)
145 if not sstate_arch in sstate_archs_list:
146 sstate_archs_list.append(sstate_arch)
147 if target_config[idx] == target_config[-1]:
148 target_sstate_before_build = self.search_sstate(target + '.*?\.tgz$')
149 bitbake("-cclean %s" % target)
150 result = bitbake(target, ignore_status=True)
151 if target_config[idx] == target_config[-1]:
152 target_sstate_after_build = self.search_sstate(target + '.*?\.tgz$')
153 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)]
154 self.remove_config(global_config[idx])
155 self.remove_recipeinc(target, target_config[idx])
156 self.assertEqual(result.status, 0, msg = "build of %s failed with %s" % (target, result.output))
157
158 runCmd("sstate-cache-management.sh -y --cache-dir=%s --remove-duplicated --extra-archs=%s" % (self.sstate_path, ','.join(map(str, sstate_archs_list))))
159 actual_remaining_sstate = [x for x in self.search_sstate(target + '.*?\.tgz$') if not any(pattern in x for pattern in ignore_patterns)]
160
161 actual_not_expected = [x for x in actual_remaining_sstate if x not in expected_remaining_sstate]
162 self.assertFalse(actual_not_expected, msg="Files should have been removed but ware not: %s" % ', '.join(map(str, actual_not_expected)))
163 expected_not_actual = [x for x in expected_remaining_sstate if x not in actual_remaining_sstate]
164 self.assertFalse(expected_not_actual, msg="Extra files ware removed: %s" ', '.join(map(str, expected_not_actual)))
165
166 @testcase(973)
167 def test_sstate_cache_management_script_using_pr_1(self):
168 global_config = []
169 target_config = []
170 global_config.append('')
171 target_config.append('PR = "0"')
172 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
173
174 @testcase(978)
175 def test_sstate_cache_management_script_using_pr_2(self):
176 global_config = []
177 target_config = []
178 global_config.append('')
179 target_config.append('PR = "0"')
180 global_config.append('')
181 target_config.append('PR = "1"')
182 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
183
184 @testcase(979)
185 def test_sstate_cache_management_script_using_pr_3(self):
186 global_config = []
187 target_config = []
188 global_config.append('MACHINE = "qemux86-64"')
189 target_config.append('PR = "0"')
190 global_config.append(global_config[0])
191 target_config.append('PR = "1"')
192 global_config.append('MACHINE = "qemux86"')
193 target_config.append('PR = "1"')
194 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
195
196 @testcase(974)
197 def test_sstate_cache_management_script_using_machine(self):
198 global_config = []
199 target_config = []
200 global_config.append('MACHINE = "qemux86-64"')
201 target_config.append('')
202 global_config.append('MACHINE = "qemux86"')
203 target_config.append('')
204 self.run_test_sstate_cache_management_script('m4', global_config, target_config, ignore_patterns=['populate_lic'])
205
206 @testcase(1270)
207 def test_sstate_32_64_same_hash(self):
208 """
209 The sstate checksums for both native and target should not vary whether
210 they're built on a 32 or 64 bit system. Rather than requiring two different
211 build machines and running a builds, override the variables calling uname()
212 manually and check using bitbake -S.
213 """
214
215 topdir = get_bb_var('TOPDIR')
216 targetvendor = get_bb_var('TARGET_VENDOR')
217 self.write_config("""
218TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
219BUILD_ARCH = \"x86_64\"
220BUILD_OS = \"linux\"
221""")
222 self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
223 bitbake("core-image-sato -S none")
224 self.write_config("""
225TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
226BUILD_ARCH = \"i686\"
227BUILD_OS = \"linux\"
228""")
229 self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
230 bitbake("core-image-sato -S none")
231
232 def get_files(d):
233 f = []
234 for root, dirs, files in os.walk(d):
235 f.extend(os.path.join(root, name) for name in files)
236 return f
237 files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
238 files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
239 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash").replace("i686-linux", "x86_64-linux").replace("i686" + targetvendor + "-linux", "x86_64" + targetvendor + "-linux", ) for x in files2]
240 self.assertItemsEqual(files1, files2)
241
242
243 @testcase(1271)
244 def test_sstate_nativelsbstring_same_hash(self):
245 """
246 The sstate checksums should be independent of whichever NATIVELSBSTRING is
247 detected. Rather than requiring two different build machines and running
248 builds, override the variables manually and check using bitbake -S.
249 """
250
251 topdir = get_bb_var('TOPDIR')
252 self.write_config("""
253TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
254NATIVELSBSTRING = \"DistroA\"
255""")
256 self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
257 bitbake("core-image-sato -S none")
258 self.write_config("""
259TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
260NATIVELSBSTRING = \"DistroB\"
261""")
262 self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
263 bitbake("core-image-sato -S none")
264
265 def get_files(d):
266 f = []
267 for root, dirs, files in os.walk(d):
268 f.extend(os.path.join(root, name) for name in files)
269 return f
270 files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/")
271 files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/")
272 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
273 self.assertItemsEqual(files1, files2)
274
275 def test_sstate_allarch_samesigs(self):
276 """
277 The sstate checksums off allarch packages should be independent of whichever
278 MACHINE is set. Check this using bitbake -S.
279 """
280
281 topdir = get_bb_var('TOPDIR')
282 targetos = get_bb_var('TARGET_OS')
283 targetvendor = get_bb_var('TARGET_VENDOR')
284 self.write_config("""
285TMPDIR = \"${TOPDIR}/tmp-sstatesamehash\"
286MACHINE = \"qemux86\"
287""")
288 self.track_for_cleanup(topdir + "/tmp-sstatesamehash")
289 bitbake("world -S none")
290 self.write_config("""
291TMPDIR = \"${TOPDIR}/tmp-sstatesamehash2\"
292MACHINE = \"qemuarm\"
293""")
294 self.track_for_cleanup(topdir + "/tmp-sstatesamehash2")
295 bitbake("world -S none")
296
297 def get_files(d):
298 f = []
299 for root, dirs, files in os.walk(d):
300 for name in files:
301 if "do_build" not in name:
302 f.append(os.path.join(root, name))
303 return f
304 files1 = get_files(topdir + "/tmp-sstatesamehash/stamps/all" + targetvendor + "-" + targetos)
305 files2 = get_files(topdir + "/tmp-sstatesamehash2/stamps/all" + targetvendor + "-" + targetos)
306 files2 = [x.replace("tmp-sstatesamehash2", "tmp-sstatesamehash") for x in files2]
307 self.maxDiff = None
308 self.assertItemsEqual(files1, files2)