blob: 2b62d2a0aa2a1c9aa7bb54491669faa802f3b09b [file] [log] [blame]
Andrew Geissler20137392023-10-12 04:59:14 -06001#
2# Copyright (c) 2023 BayLibre, SAS
3# Author: Julien Stepahn <jstephan@baylibre.com>
4#
5# SPDX-License-Identifier: GPL-2.0-only
6#
7
8import os
9import re
10import bb.tinfoil
11
12import oeqa.utils.ftools as ftools
13from oeqa.utils.commands import runCmd, get_bb_var, get_bb_vars, bitbake
14
15from oeqa.selftest.case import OESelftestTestCase
16
17
18class BBLock(OESelftestTestCase):
19 @classmethod
20 def setUpClass(cls):
21 super(BBLock, cls).setUpClass()
22 cls.lockfile = cls.builddir + "/conf/bblock.conf"
23
24 def unlock_recipes(self, recipes=None, tasks=None):
25 cmd = "bblock -r "
26 if recipes:
27 cmd += " ".join(recipes)
28 if tasks:
29 cmd += " -t " + ",".join(tasks)
30 result = runCmd(cmd)
31
32 if recipes:
33 # ensure all signatures are removed from lockfile
34 contents = ftools.read_file(self.lockfile)
35 for recipe in recipes:
36 for task in tasks:
37 find_in_contents = re.search(
38 'SIGGEN_LOCKEDSIGS_.+\s\+=\s"%s:%s:.*"' % (recipe, task),
39 contents,
40 )
41 self.assertFalse(
42 find_in_contents,
43 msg="%s:%s should not be present into bblock.conf anymore"
44 % (recipe, task),
45 )
46 self.assertExists(self.lockfile)
47 else:
48 self.assertNotExists(self.lockfile)
49
50 def lock_recipes(self, recipes, tasks=None):
51 cmd = "bblock " + " ".join(recipes)
52 if tasks:
53 cmd += " -t " + ",".join(tasks)
54
55 result = runCmd(cmd)
56
57 self.assertExists(self.lockfile)
58
59 # ensure all signatures are added to lockfile
60 contents = ftools.read_file(self.lockfile)
61 for recipe in recipes:
62 if tasks:
63 for task in tasks:
64 find_in_contents = re.search(
65 'SIGGEN_LOCKEDSIGS_.+\s\+=\s"%s:%s:.*"' % (recipe, task),
66 contents,
67 )
68 self.assertTrue(
69 find_in_contents,
70 msg="%s:%s was not added into bblock.conf. bblock output: %s"
71 % (recipe, task, result.output),
72 )
73
74 def modify_tasks(self, recipes, tasks):
75 task_append = ""
76 for recipe in recipes:
77 bb_vars = get_bb_vars(["PV"], recipe)
78 recipe_pv = bb_vars["PV"]
79 recipe_append_file = recipe + "_" + recipe_pv + ".bbappend"
80
81 os.mkdir(os.path.join(self.testlayer_path, "recipes-test", recipe))
82 recipe_append_path = os.path.join(
83 self.testlayer_path, "recipes-test", recipe, recipe_append_file
84 )
85
86 for task in tasks:
87 task_append += "%s:append() {\n#modify task hash \n}\n" % task
88 ftools.write_file(recipe_append_path, task_append)
89 self.add_command_to_tearDown(
90 "rm -rf %s" % os.path.join(self.testlayer_path, "recipes-test", recipe)
91 )
92
93 def test_lock_single_recipe_single_task(self):
94 recipes = ["quilt"]
95 tasks = ["do_compile"]
96 self._run_test(recipes, tasks)
97
98 def test_lock_single_recipe_multiple_tasks(self):
99 recipes = ["quilt"]
100 tasks = ["do_compile", "do_install"]
101 self._run_test(recipes, tasks)
102
103 def test_lock_single_recipe_all_tasks(self):
104 recipes = ["quilt"]
105 self._run_test(recipes, None)
106
107 def test_lock_multiple_recipe_single_task(self):
108 recipes = ["quilt", "bc"]
109 tasks = ["do_compile"]
110 self._run_test(recipes, tasks)
111
112 def test_lock_architecture_specific(self):
113 # unlock all recipes and ensure no bblock.conf file exist
114 self.unlock_recipes()
115
116 recipes = ["quilt"]
117 tasks = ["do_compile"]
118
119 # lock quilt's do_compile task for another machine
120 if self.td["MACHINE"] == "qemux86-64":
121 machine = "qemuarm"
122 else:
123 machine = "qemux86-64"
124
125 self.write_config('MACHINE = "%s"\n' % machine)
126
127 self.lock_recipes(recipes, tasks)
128
129 self.write_config('MACHINE = "%s"\n' % self.td["MACHINE"])
130 # modify quilt's do_compile task
131 self.modify_tasks(recipes, tasks)
132
133 # build quilt using the default machine
134 # No Note/Warning should be emitted since sig is locked for another machine
135 # (quilt package is architecture dependant)
136 info_message = "NOTE: The following recipes have locked tasks: " + recipes[0]
137 warn_message = "The %s:%s sig is computed to be" % (recipes[0], tasks[0])
138 result = bitbake(recipes[0] + " -n")
139 self.assertNotIn(info_message, result.output)
140 self.assertNotIn(warn_message, result.output)
141
142 # unlock all recipes
143 self.unlock_recipes()
144
145 def _run_test(self, recipes, tasks=None):
146 # unlock all recipes and ensure no bblock.conf file exist
147 self.unlock_recipes()
148
149 self.write_config('BB_SIGNATURE_HANDLER = "OEBasicHash"')
150
151 # lock tasks for recipes
152 result = self.lock_recipes(recipes, tasks)
153
154 if not tasks:
155 tasks = []
156 result = bitbake("-c listtasks " + recipes[0])
157 with bb.tinfoil.Tinfoil() as tinfoil:
158 tinfoil.prepare(config_only=False, quiet=2)
159 d = tinfoil.parse_recipe(recipes[0])
160
161 for line in result.output.splitlines():
162 if line.startswith("do_"):
163 task = line.split()[0]
164 if "setscene" in task:
165 continue
166 if d.getVarFlag(task, "nostamp"):
167 continue
168 tasks.append(task)
169
170 # build recipes. At this stage we should have a Note about recipes
171 # having locked task's sig, but no warning since sig still match
172 info_message = "NOTE: The following recipes have locked tasks: " + " ".join(
173 recipes
174 )
175 for recipe in recipes:
176 result = bitbake(recipe + " -n")
177 self.assertIn(info_message, result.output)
178 for task in tasks:
179 warn_message = "The %s:%s sig is computed to be" % (recipe, task)
180 self.assertNotIn(warn_message, result.output)
181
182 # modify all tasks that are locked to trigger a sig change then build the recipes
183 # at this stage we should have a Note as before, but also a Warning for all
184 # locked tasks indicating the sig mismatch
185 self.modify_tasks(recipes, tasks)
186 for recipe in recipes:
187 result = bitbake(recipe + " -n")
188 self.assertIn(info_message, result.output)
189 for task in tasks:
190 warn_message = "The %s:%s sig is computed to be" % (recipe, task)
191 self.assertIn(warn_message, result.output)
192
193 # unlock all tasks and rebuild, no more Note/Warning should remain
194 self.unlock_recipes(recipes, tasks)
195 for recipe in recipes:
196 result = bitbake(recipe + " -n")
197 self.assertNotIn(info_message, result.output)
198 for task in tasks:
199 warn_message = "The %s:%s sig is computed to be" % (recipe, task)
200 self.assertNotIn(warn_message, result.output)
201
202 # unlock all recipes
203 self.unlock_recipes()