diff mbox series

[v5,5/5] oeqa/selftest/bblock: add self test for bblock tool

Message ID 20230925080452.803540-6-jstephan@baylibre.com
State New
Headers show
Series Add bblock helper scripts | expand

Commit Message

Julien Stephan Sept. 25, 2023, 8:04 a.m. UTC
it implements various combination of locking single/multiple recipe(s)/task(s)

it also tests that locked sig are architecture dependant

Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
 meta/lib/oeqa/selftest/cases/bblock.py | 201 +++++++++++++++++++++++++
 1 file changed, 201 insertions(+)
 create mode 100644 meta/lib/oeqa/selftest/cases/bblock.py
diff mbox series

Patch

diff --git a/meta/lib/oeqa/selftest/cases/bblock.py b/meta/lib/oeqa/selftest/cases/bblock.py
new file mode 100644
index 00000000000..07143c59676
--- /dev/null
+++ b/meta/lib/oeqa/selftest/cases/bblock.py
@@ -0,0 +1,201 @@ 
+#
+# Copyright (c) 2023 BayLibre, SAS
+# Author: Julien Stepahn <jstephan@baylibre.com>
+#
+# SPDX-License-Identifier: GPL-2.0-only
+#
+
+import os
+import re
+import bb.tinfoil
+
+import oeqa.utils.ftools as ftools
+from oeqa.utils.commands import runCmd, get_bb_var, get_bb_vars, bitbake
+
+from oeqa.selftest.case import OESelftestTestCase
+
+
+class BBLock(OESelftestTestCase):
+    @classmethod
+    def setUpClass(cls):
+        super(BBLock, cls).setUpClass()
+        cls.lockfile = cls.builddir + "/conf/bblock.conf"
+
+    def unlock_recipes(self, recipes=None, tasks=None):
+        cmd = "bblock -r "
+        if recipes:
+            cmd += " ".join(recipes)
+        if tasks:
+            cmd += " -t " + ",".join(tasks)
+        result = runCmd(cmd)
+
+        if recipes:
+            # ensure all signatures are removed from lockfile
+            contents = ftools.read_file(self.lockfile)
+            for recipe in recipes:
+                for task in tasks:
+                    find_in_contents = re.search(
+                        'SIGGEN_LOCKEDSIGS_.+\s\+=\s"%s:%s:.*"' % (recipe, task),
+                        contents,
+                    )
+                    self.assertFalse(
+                        find_in_contents,
+                        msg="%s:%s should not be present into bblock.conf anymore"
+                        % (recipe, task),
+                    )
+                self.assertExists(self.lockfile)
+        else:
+            self.assertNotExists(self.lockfile)
+
+    def lock_recipes(self, recipes, tasks=None):
+        cmd = "bblock " + " ".join(recipes)
+        if tasks:
+            cmd += " -t " + ",".join(tasks)
+
+        result = runCmd(cmd)
+
+        self.assertExists(self.lockfile)
+
+        # ensure all signatures are added to lockfile
+        contents = ftools.read_file(self.lockfile)
+        for recipe in recipes:
+            if tasks:
+                for task in tasks:
+                    find_in_contents = re.search(
+                        'SIGGEN_LOCKEDSIGS_.+\s\+=\s"%s:%s:.*"' % (recipe, task),
+                        contents,
+                    )
+                    self.assertTrue(
+                        find_in_contents,
+                        msg="%s:%s was not added into bblock.conf. bblock output: %s"
+                        % (recipe, task, result.output),
+                    )
+
+    def modify_tasks(self, recipes, tasks):
+        task_append = ""
+        for recipe in recipes:
+            bb_vars = get_bb_vars(["PV"], recipe)
+            recipe_pv = bb_vars["PV"]
+            recipe_append_file = recipe + "_" + recipe_pv + ".bbappend"
+
+            os.mkdir(os.path.join(self.testlayer_path, "recipes-test", recipe))
+            recipe_append_path = os.path.join(
+                self.testlayer_path, "recipes-test", recipe, recipe_append_file
+            )
+
+            for task in tasks:
+                task_append += "%s:append() {\n#modify task hash \n}\n" % task
+            ftools.write_file(recipe_append_path, task_append)
+            self.add_command_to_tearDown(
+                "rm -rf %s" % os.path.join(self.testlayer_path, "recipes-test", recipe)
+            )
+
+    def test_lock_single_recipe_single_task(self):
+        recipes = ["quilt"]
+        tasks = ["do_compile"]
+        self._run_test(recipes, tasks)
+
+    def test_lock_single_recipe_multiple_tasks(self):
+        recipes = ["quilt"]
+        tasks = ["do_compile", "do_install"]
+        self._run_test(recipes, tasks)
+
+    def test_lock_single_recipe_all_tasks(self):
+        recipes = ["quilt"]
+        self._run_test(recipes, None)
+
+    def test_lock_multiple_recipe_single_task(self):
+        recipes = ["quilt", "bc"]
+        tasks = ["do_compile"]
+        self._run_test(recipes, tasks)
+
+    def test_lock_architecture_specific(self):
+        # unlock all recipes and ensure no bblock.conf file exist
+        self.unlock_recipes()
+
+        recipes = ["quilt"]
+        tasks = ["do_compile"]
+
+        # lock quilt's do_compile task for another machine
+        if self.td["MACHINE"] == "qemux86-64":
+            machine = "qemuarm"
+        else:
+            machine = "qemux86-64"
+
+        self.write_config('MACHINE = "%s"\n' % machine)
+
+        self.lock_recipes(recipes, tasks)
+
+        self.write_config('MACHINE = "%s"\n' % self.td["MACHINE"])
+        # modify quilt's do_compile task
+        self.modify_tasks(recipes, tasks)
+
+        # build quilt using the default machine
+        # No Note/Warning should be emitted since sig is locked for another machine
+        # (quilt package is architecture dependant)
+        info_message = "NOTE: The following recipes have locked tasks: " + recipes[0]
+        warn_message = "The %s:%s sig is computed to be" % (recipes[0], tasks[0])
+        result = bitbake(recipes[0] + " -n")
+        self.assertNotIn(info_message, result.output)
+        self.assertNotIn(warn_message, result.output)
+
+        # unlock all recipes
+        self.unlock_recipes()
+
+    def _run_test(self, recipes, tasks=None):
+        # unlock all recipes and ensure no bblock.conf file exist
+        self.unlock_recipes()
+
+        # lock tasks for recipes
+        result = self.lock_recipes(recipes, tasks)
+
+        if not tasks:
+            tasks = []
+            result = bitbake("-c listtasks " + recipes[0])
+            with bb.tinfoil.Tinfoil() as tinfoil:
+                tinfoil.prepare(config_only=False, quiet=2)
+                d = tinfoil.parse_recipe(recipes[0])
+
+                for line in result.output.splitlines():
+                    if line.startswith("do_"):
+                        task = line.split()[0]
+                        if "setscene" in task:
+                            continue
+                        if d.getVarFlag(task, "nostamp"):
+                            continue
+                        tasks.append(task)
+
+        # build recipes. At this stage we should have a Note about recipes
+        # having locked task's sig, but no warning since sig still match
+        info_message = "NOTE: The following recipes have locked tasks: " + " ".join(
+            recipes
+        )
+        for recipe in recipes:
+            result = bitbake(recipe + " -n")
+            self.assertIn(info_message, result.output)
+            for task in tasks:
+                warn_message = "The %s:%s sig is computed to be" % (recipe, task)
+                self.assertNotIn(warn_message, result.output)
+
+        # modify all tasks that are locked to trigger a sig change then build the recipes
+        # at this stage we should have a Note as before, but also a Warning for all
+        # locked tasks indicating the sig mismatch
+        self.modify_tasks(recipes, tasks)
+        for recipe in recipes:
+            result = bitbake(recipe + " -n")
+            self.assertIn(info_message, result.output)
+            for task in tasks:
+                warn_message = "The %s:%s sig is computed to be" % (recipe, task)
+                self.assertIn(warn_message, result.output)
+
+        # unlock all tasks and rebuild, no more Note/Warning should remain
+        self.unlock_recipes(recipes, tasks)
+        for recipe in recipes:
+            result = bitbake(recipe + " -n")
+            self.assertNotIn(info_message, result.output)
+            for task in tasks:
+                warn_message = "The %s:%s sig is computed to be" % (recipe, task)
+                self.assertNotIn(warn_message, result.output)
+
+        # unlock all recipes
+        self.unlock_recipes()