[PATCH 05/10] test: py: add test for reverting globalvars after boot
Sascha Hauer
s.hauer at pengutronix.de
Fri Oct 30 03:54:03 PDT 2026
Add tests for the globalvar scope around boot entries: a failing boot
script that changes, creates and removes global.bootm.* and
global.linux.bootargs.* variables and changes global.of.overlay.path and
global.linux.bootargs_append, where the configuration has them, must
leave them as they were before, while globalvars outside the scope keep
their new values. A
second test nests boot entries like devboot does and checks that the
outer entry's variables are visible in the inner one and survive it.
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
test/py/test_boot_globalvar_scope.py | 117 +++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/test/py/test_boot_globalvar_scope.py b/test/py/test_boot_globalvar_scope.py
new file mode 100644
index 0000000000..041d38c814
--- /dev/null
+++ b/test/py/test_boot_globalvar_scope.py
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import pytest
+from .helper import devinfo, skip_disabled
+
+
+def write_bootscript(barebox, name, lines):
+ barebox.run_check(f"echo -o /env/boot/{name} '#!/bin/sh'")
+ for line in lines:
+ # Variable references must reach the script unexpanded. Neither
+ # quoting nor a backslash achieves that here, so splice in the
+ # dollar sign from a variable.
+ line = line.replace("$", "${dollar}")
+ barebox.run_check(f"dollar='$'; echo -a /env/boot/{name} \"{line}\"")
+
+
+def globals_now(barebox):
+ params = devinfo(barebox, "global")["Parameters"]
+ # devinfo prints "value (type: ...)", strip the annotation
+ return {k: v.split(" (type:")[0].strip('"') for k, v in params.items()}
+
+
+ at pytest.fixture(scope="function")
+def scope_globals(barebox, barebox_config):
+ skip_disabled(barebox_config, "CONFIG_CMD_BOOT", "CONFIG_CMD_GLOBAL",
+ "CONFIG_CMD_ECHO")
+
+ barebox.run_check("global.bootm.image=/preset/image")
+ barebox.run_check("global linux.bootargs.preset=preset=1")
+ barebox.run_check("global linux.bootargs.removed=removed=1")
+ barebox.run_check("global.bootm.appendroot=0")
+ old_user = barebox.run_check("echo ${global.user}")[0]
+
+ yield old_user
+
+ barebox.run_check(f"global.user={old_user}")
+ barebox.run("global -r linux.bootargs.preset")
+ barebox.run("global -r linux.bootargs.removed")
+ barebox.run_check("global.bootm.image=")
+
+
+def test_boot_entry_reverts_globalvars(barebox, scope_globals):
+ old_user = scope_globals
+ before = globals_now(barebox)
+
+ # boot related globalvars outside of bootm.* and linux.bootargs.*,
+ # where the configuration has them
+ others = {var: val for var, val in (("of.overlay.path", "/does/not/exist"),
+ ("linux.bootargs_append", "1"))
+ if var in before}
+
+ write_bootscript(barebox, "scope", [
+ *(f"global.{var}={val}" for var, val in others.items()),
+ "global.bootm.image=/does/not/exist",
+ "global.bootm.oftree=/does/not/exist.dtb",
+ "global.bootm.appendroot=1",
+ "global.linux.bootargs.dyn.root=root=/dev/leak",
+ "global linux.bootargs.leak=leak=1",
+ "global.linux.bootargs.preset=preset=2",
+ "global -r linux.bootargs.removed",
+ "global.user=scope-test",
+ ])
+
+ # bootm fails on the nonexistent image, so boot returns
+ barebox.run("boot scope")
+
+ after = globals_now(barebox)
+
+ # values within the boot scope are restored...
+ assert after["bootm.image"] == "/preset/image"
+ assert after["bootm.oftree"] == before["bootm.oftree"]
+ assert after["bootm.appendroot"] == "0"
+ assert after["linux.bootargs.preset"] == "preset=1"
+ for var in others:
+ assert after[var] == before[var]
+
+ # ...vars created by the boot entry are gone...
+ assert "linux.bootargs.leak" not in after
+ assert "linux.bootargs.dyn.root" not in after
+ assert "linux.bootargs.dyn.ip" not in after
+
+ # ...vars removed by the boot entry are back...
+ assert after["linux.bootargs.removed"] == "removed=1"
+
+ # ...and the loadaddrs don't come back as 0xfffffffe after a failed boot
+ assert after["bootm.image.loadaddr"] == before["bootm.image.loadaddr"]
+
+ # globalvars outside the boot scope are left alone
+ assert after["user"] == "scope-test"
+ assert old_user != "scope-test"
+
+
+ at pytest.mark.usefixtures("scope_globals")
+def test_boot_entry_scope_nests(barebox):
+ # devboot-style: an outer entry sets up bootargs that must be visible
+ # in, and survive, the inner boot entry
+ write_bootscript(barebox, "scope-inner", [
+ "global.bootm.image=/does/not/exist",
+ "echo inner-sees ${global.linux.bootargs.outer}",
+ "global.linux.bootargs.outer=outer=clobbered",
+ "global linux.bootargs.inner=inner=1",
+ ])
+ write_bootscript(barebox, "scope-outer", [
+ "global linux.bootargs.outer=outer=1",
+ "boot scope-inner",
+ "echo outer-sees ${global.linux.bootargs.outer} "
+ "inner=${global.linux.bootargs.inner}",
+ ])
+
+ stdout, _, _ = barebox.run("boot scope-outer")
+ assert "inner-sees outer=1" in stdout
+ assert "outer-sees outer=1 inner=" in stdout
+
+ after = globals_now(barebox)
+ assert "linux.bootargs.outer" not in after
+ assert "linux.bootargs.inner" not in after
+ assert after["bootm.image"] == "/preset/image"
--
2.47.3
More information about the barebox
mailing list