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