1# 2# BitBake Tests for runqueue task processing 3# 4# Copyright (C) 2019 Richard Purdie 5# 6# SPDX-License-Identifier: GPL-2.0-only 7# 8 9import unittest 10import os 11import tempfile 12import subprocess 13import sys 14import time 15 16# 17# TODO: 18# Add tests on task ordering (X happens before Y after Z) 19# 20 21class RunQueueTests(unittest.TestCase): 22 23 alltasks = ['package', 'fetch', 'unpack', 'patch', 'prepare_recipe_sysroot', 'configure', 24 'compile', 'install', 'packagedata', 'package_qa', 'package_write_rpm', 'package_write_ipk', 25 'populate_sysroot', 'build'] 26 a1_sstatevalid = "a1:do_package a1:do_package_qa a1:do_packagedata a1:do_package_write_ipk a1:do_package_write_rpm a1:do_populate_lic a1:do_populate_sysroot" 27 b1_sstatevalid = "b1:do_package b1:do_package_qa b1:do_packagedata b1:do_package_write_ipk b1:do_package_write_rpm b1:do_populate_lic b1:do_populate_sysroot" 28 29 def run_bitbakecmd(self, cmd, builddir, sstatevalid="", slowtasks="", extraenv=None, cleanup=False): 30 env = os.environ.copy() 31 env["BBPATH"] = os.path.realpath(os.path.join(os.path.dirname(__file__), "runqueue-tests")) 32 env["BB_ENV_EXTRAWHITE"] = "SSTATEVALID SLOWTASKS" 33 env["SSTATEVALID"] = sstatevalid 34 env["SLOWTASKS"] = slowtasks 35 if extraenv: 36 for k in extraenv: 37 env[k] = extraenv[k] 38 env["BB_ENV_EXTRAWHITE"] = env["BB_ENV_EXTRAWHITE"] + " " + k 39 try: 40 output = subprocess.check_output(cmd, env=env, stderr=subprocess.STDOUT,universal_newlines=True, cwd=builddir) 41 print(output) 42 except subprocess.CalledProcessError as e: 43 self.fail("Command %s failed with %s" % (cmd, e.output)) 44 tasks = [] 45 tasklog = builddir + "/task.log" 46 if os.path.exists(tasklog): 47 with open(tasklog, "r") as f: 48 tasks = [line.rstrip() for line in f] 49 if cleanup: 50 os.remove(tasklog) 51 return tasks 52 53 def test_no_setscenevalid(self): 54 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 55 cmd = ["bitbake", "a1"] 56 sstatevalid = "" 57 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 58 expected = ['a1:' + x for x in self.alltasks] 59 self.assertEqual(set(tasks), set(expected)) 60 61 def test_single_setscenevalid(self): 62 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 63 cmd = ["bitbake", "a1"] 64 sstatevalid = "a1:do_package" 65 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 66 expected = ['a1:package_setscene', 'a1:fetch', 'a1:unpack', 'a1:patch', 'a1:prepare_recipe_sysroot', 'a1:configure', 67 'a1:compile', 'a1:install', 'a1:packagedata', 'a1:package_qa', 'a1:package_write_rpm', 'a1:package_write_ipk', 68 'a1:populate_sysroot', 'a1:build'] 69 self.assertEqual(set(tasks), set(expected)) 70 71 def test_intermediate_setscenevalid(self): 72 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 73 cmd = ["bitbake", "a1"] 74 sstatevalid = "a1:do_package a1:do_populate_sysroot" 75 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 76 expected = ['a1:package_setscene', 'a1:packagedata', 'a1:package_qa', 'a1:package_write_rpm', 'a1:package_write_ipk', 77 'a1:populate_sysroot_setscene', 'a1:build'] 78 self.assertEqual(set(tasks), set(expected)) 79 80 def test_intermediate_notcovered(self): 81 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 82 cmd = ["bitbake", "a1"] 83 sstatevalid = "a1:do_package_qa a1:do_packagedata a1:do_package_write_ipk a1:do_package_write_rpm a1:do_populate_lic a1:do_populate_sysroot" 84 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 85 expected = ['a1:package_write_ipk_setscene', 'a1:package_write_rpm_setscene', 'a1:packagedata_setscene', 86 'a1:package_qa_setscene', 'a1:build', 'a1:populate_sysroot_setscene'] 87 self.assertEqual(set(tasks), set(expected)) 88 89 def test_all_setscenevalid(self): 90 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 91 cmd = ["bitbake", "a1"] 92 sstatevalid = self.a1_sstatevalid 93 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 94 expected = ['a1:package_write_ipk_setscene', 'a1:package_write_rpm_setscene', 'a1:packagedata_setscene', 95 'a1:package_qa_setscene', 'a1:build', 'a1:populate_sysroot_setscene'] 96 self.assertEqual(set(tasks), set(expected)) 97 98 def test_no_settasks(self): 99 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 100 cmd = ["bitbake", "a1", "-c", "patch"] 101 sstatevalid = self.a1_sstatevalid 102 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 103 expected = ['a1:fetch', 'a1:unpack', 'a1:patch'] 104 self.assertEqual(set(tasks), set(expected)) 105 106 def test_mix_covered_notcovered(self): 107 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 108 cmd = ["bitbake", "a1:do_patch", "a1:do_populate_sysroot"] 109 sstatevalid = self.a1_sstatevalid 110 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 111 expected = ['a1:fetch', 'a1:unpack', 'a1:patch', 'a1:populate_sysroot_setscene'] 112 self.assertEqual(set(tasks), set(expected)) 113 114 115 # Test targets with intermediate setscene tasks alongside a target with no intermediate setscene tasks 116 def test_mixed_direct_tasks_setscene_tasks(self): 117 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 118 cmd = ["bitbake", "c1:do_patch", "a1"] 119 sstatevalid = self.a1_sstatevalid 120 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 121 expected = ['c1:fetch', 'c1:unpack', 'c1:patch', 'a1:package_write_ipk_setscene', 'a1:package_write_rpm_setscene', 'a1:packagedata_setscene', 122 'a1:package_qa_setscene', 'a1:build', 'a1:populate_sysroot_setscene'] 123 self.assertEqual(set(tasks), set(expected)) 124 125 # This test slows down the execution of do_package_setscene until after other real tasks have 126 # started running which tests for a bug where tasks were being lost from the buildable list of real 127 # tasks if they weren't in tasks_covered or tasks_notcovered 128 def test_slow_setscene(self): 129 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 130 cmd = ["bitbake", "a1"] 131 sstatevalid = "a1:do_package" 132 slowtasks = "a1:package_setscene" 133 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, slowtasks) 134 expected = ['a1:package_setscene', 'a1:fetch', 'a1:unpack', 'a1:patch', 'a1:prepare_recipe_sysroot', 'a1:configure', 135 'a1:compile', 'a1:install', 'a1:packagedata', 'a1:package_qa', 'a1:package_write_rpm', 'a1:package_write_ipk', 136 'a1:populate_sysroot', 'a1:build'] 137 self.assertEqual(set(tasks), set(expected)) 138 139 def test_setscenewhitelist(self): 140 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 141 cmd = ["bitbake", "a1"] 142 extraenv = { 143 "BB_SETSCENE_ENFORCE" : "1", 144 "BB_SETSCENE_ENFORCE_WHITELIST" : "a1:do_package_write_rpm a1:do_build" 145 } 146 sstatevalid = "a1:do_package a1:do_package_qa a1:do_packagedata a1:do_package_write_ipk a1:do_populate_lic a1:do_populate_sysroot" 147 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv) 148 expected = ['a1:packagedata_setscene', 'a1:package_qa_setscene', 'a1:package_write_ipk_setscene', 149 'a1:populate_sysroot_setscene', 'a1:package_setscene'] 150 self.assertEqual(set(tasks), set(expected)) 151 152 # Tests for problems with dependencies between setscene tasks 153 def test_no_setscenevalid_harddeps(self): 154 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 155 cmd = ["bitbake", "d1"] 156 sstatevalid = "" 157 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 158 expected = ['a1:package', 'a1:fetch', 'a1:unpack', 'a1:patch', 'a1:prepare_recipe_sysroot', 'a1:configure', 159 'a1:compile', 'a1:install', 'a1:packagedata', 'a1:package_write_rpm', 'a1:package_write_ipk', 160 'a1:populate_sysroot', 'd1:package', 'd1:fetch', 'd1:unpack', 'd1:patch', 'd1:prepare_recipe_sysroot', 'd1:configure', 161 'd1:compile', 'd1:install', 'd1:packagedata', 'd1:package_qa', 'd1:package_write_rpm', 'd1:package_write_ipk', 162 'd1:populate_sysroot', 'd1:build'] 163 self.assertEqual(set(tasks), set(expected)) 164 165 def test_no_setscenevalid_withdeps(self): 166 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 167 cmd = ["bitbake", "b1"] 168 sstatevalid = "" 169 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 170 expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] 171 expected.remove('a1:build') 172 expected.remove('a1:package_qa') 173 self.assertEqual(set(tasks), set(expected)) 174 175 def test_single_a1_setscenevalid_withdeps(self): 176 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 177 cmd = ["bitbake", "b1"] 178 sstatevalid = "a1:do_package" 179 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 180 expected = ['a1:package_setscene', 'a1:fetch', 'a1:unpack', 'a1:patch', 'a1:prepare_recipe_sysroot', 'a1:configure', 181 'a1:compile', 'a1:install', 'a1:packagedata', 'a1:package_write_rpm', 'a1:package_write_ipk', 182 'a1:populate_sysroot'] + ['b1:' + x for x in self.alltasks] 183 self.assertEqual(set(tasks), set(expected)) 184 185 def test_single_b1_setscenevalid_withdeps(self): 186 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 187 cmd = ["bitbake", "b1"] 188 sstatevalid = "b1:do_package" 189 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 190 expected = ['a1:package', 'a1:fetch', 'a1:unpack', 'a1:patch', 'a1:prepare_recipe_sysroot', 'a1:configure', 191 'a1:compile', 'a1:install', 'a1:packagedata', 'a1:package_write_rpm', 'a1:package_write_ipk', 192 'a1:populate_sysroot', 'b1:package_setscene'] + ['b1:' + x for x in self.alltasks] 193 expected.remove('b1:package') 194 self.assertEqual(set(tasks), set(expected)) 195 196 def test_intermediate_setscenevalid_withdeps(self): 197 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 198 cmd = ["bitbake", "b1"] 199 sstatevalid = "a1:do_package a1:do_populate_sysroot b1:do_package" 200 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 201 expected = ['a1:package_setscene', 'a1:packagedata', 'a1:package_write_rpm', 'a1:package_write_ipk', 202 'a1:populate_sysroot_setscene', 'b1:package_setscene'] + ['b1:' + x for x in self.alltasks] 203 expected.remove('b1:package') 204 self.assertEqual(set(tasks), set(expected)) 205 206 def test_all_setscenevalid_withdeps(self): 207 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 208 cmd = ["bitbake", "b1"] 209 sstatevalid = self.a1_sstatevalid + " " + self.b1_sstatevalid 210 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid) 211 expected = ['a1:package_write_ipk_setscene', 'a1:package_write_rpm_setscene', 'a1:packagedata_setscene', 212 'b1:build', 'a1:populate_sysroot_setscene', 'b1:package_write_ipk_setscene', 'b1:package_write_rpm_setscene', 213 'b1:packagedata_setscene', 'b1:package_qa_setscene', 'b1:populate_sysroot_setscene'] 214 self.assertEqual(set(tasks), set(expected)) 215 216 def test_multiconfig_setscene_optimise(self): 217 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 218 extraenv = { 219 "BBMULTICONFIG" : "mc1 mc2", 220 "BB_SIGNATURE_HANDLER" : "basic" 221 } 222 cmd = ["bitbake", "b1", "mc:mc1:b1", "mc:mc2:b1"] 223 setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', 224 'populate_sysroot_setscene', 'package_qa_setscene'] 225 sstatevalid = "" 226 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv) 227 expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + \ 228 ['mc1:b1:' + x for x in setscenetasks] + ['mc1:a1:' + x for x in setscenetasks] + \ 229 ['mc2:b1:' + x for x in setscenetasks] + ['mc2:a1:' + x for x in setscenetasks] + \ 230 ['mc1:b1:build', 'mc2:b1:build'] 231 for x in ['mc1:a1:package_qa_setscene', 'mc2:a1:package_qa_setscene', 'a1:build', 'a1:package_qa']: 232 expected.remove(x) 233 self.assertEqual(set(tasks), set(expected)) 234 235 236 @unittest.skipIf(sys.version_info < (3, 5, 0), 'Python 3.5 or later required') 237 def test_hashserv_single(self): 238 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 239 extraenv = { 240 "BB_HASHSERVE" : "auto", 241 "BB_SIGNATURE_HANDLER" : "TestEquivHash" 242 } 243 cmd = ["bitbake", "a1", "b1"] 244 setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', 245 'populate_sysroot_setscene', 'package_qa_setscene'] 246 sstatevalid = "" 247 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 248 expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] 249 self.assertEqual(set(tasks), set(expected)) 250 cmd = ["bitbake", "a1", "-c", "install", "-f"] 251 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 252 expected = ['a1:install'] 253 self.assertEqual(set(tasks), set(expected)) 254 cmd = ["bitbake", "a1", "b1"] 255 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 256 expected = ['a1:populate_sysroot', 'a1:package', 'a1:package_write_rpm_setscene', 'a1:packagedata_setscene', 257 'a1:package_write_ipk_setscene', 'a1:package_qa_setscene', 'a1:build'] 258 self.assertEqual(set(tasks), set(expected)) 259 260 self.shutdown(tempdir) 261 262 @unittest.skipIf(sys.version_info < (3, 5, 0), 'Python 3.5 or later required') 263 def test_hashserv_double(self): 264 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 265 extraenv = { 266 "BB_HASHSERVE" : "auto", 267 "BB_SIGNATURE_HANDLER" : "TestEquivHash" 268 } 269 cmd = ["bitbake", "a1", "b1", "e1"] 270 setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', 271 'populate_sysroot_setscene', 'package_qa_setscene'] 272 sstatevalid = "" 273 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 274 expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + ['e1:' + x for x in self.alltasks] 275 self.assertEqual(set(tasks), set(expected)) 276 cmd = ["bitbake", "a1", "b1", "-c", "install", "-fn"] 277 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 278 cmd = ["bitbake", "e1"] 279 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 280 expected = ['a1:package', 'a1:install', 'b1:package', 'b1:install', 'a1:populate_sysroot', 'b1:populate_sysroot', 281 'a1:package_write_ipk_setscene', 'b1:packagedata_setscene', 'b1:package_write_rpm_setscene', 282 'a1:package_write_rpm_setscene', 'b1:package_write_ipk_setscene', 'a1:packagedata_setscene'] 283 self.assertEqual(set(tasks), set(expected)) 284 285 self.shutdown(tempdir) 286 287 @unittest.skipIf(sys.version_info < (3, 5, 0), 'Python 3.5 or later required') 288 def test_hashserv_multiple_setscene(self): 289 # Runs e1:do_package_setscene twice 290 with tempfile.TemporaryDirectory(prefix="runqueuetest") as tempdir: 291 extraenv = { 292 "BB_HASHSERVE" : "auto", 293 "BB_SIGNATURE_HANDLER" : "TestEquivHash" 294 } 295 cmd = ["bitbake", "a1", "b1", "e1"] 296 setscenetasks = ['package_write_ipk_setscene', 'package_write_rpm_setscene', 'packagedata_setscene', 297 'populate_sysroot_setscene', 'package_qa_setscene'] 298 sstatevalid = "" 299 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 300 expected = ['a1:' + x for x in self.alltasks] + ['b1:' + x for x in self.alltasks] + ['e1:' + x for x in self.alltasks] 301 self.assertEqual(set(tasks), set(expected)) 302 cmd = ["bitbake", "a1", "b1", "-c", "install", "-fn"] 303 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True) 304 cmd = ["bitbake", "e1"] 305 sstatevalid = "e1:do_package" 306 tasks = self.run_bitbakecmd(cmd, tempdir, sstatevalid, extraenv=extraenv, cleanup=True, slowtasks="a1:populate_sysroot b1:populate_sysroot") 307 expected = ['a1:package', 'a1:install', 'b1:package', 'b1:install', 'a1:populate_sysroot', 'b1:populate_sysroot', 308 'a1:package_write_ipk_setscene', 'b1:packagedata_setscene', 'b1:package_write_rpm_setscene', 309 'a1:package_write_rpm_setscene', 'b1:package_write_ipk_setscene', 'a1:packagedata_setscene', 310 'e1:package_setscene'] 311 self.assertEqual(set(tasks), set(expected)) 312 for i in expected: 313 self.assertEqual(tasks.count(i), 1, "%s not in task list once" % i) 314 315 self.shutdown(tempdir) 316 317 def shutdown(self, tempdir): 318 # Wait for the hashserve socket to disappear else we'll see races with the tempdir cleanup 319 while os.path.exists(tempdir + "/hashserve.sock"): 320 time.sleep(0.5) 321 322 323