From: Frieder Schrempf <[email protected]>

Add a test that boots the same RAUC bootflow twice and checks that each
attempt uses up a try and that the boot script is only listed once
afterwards. Before the boot script of a failed attempt was freed, every
attempt added another copy of it.

The boot script of the RAUC test image now runs a command set by the
test, which lets it fail, as a successful boot script frees the private
data of the bootflow, so it cannot be booted again.

Booting saves the environment, which sandbox keeps nowhere by default.
Set CONFIG_ENV_FAT_DEVICE_AND_PART to the first partition of mmc10,
which has a FAT filesystem, and select it during the test. No other
test uses the FAT environment.

Assisted-by: LLM
Suggested-by: Simon Glass <[email protected]>
Signed-off-by: Frieder Schrempf <[email protected]>
---
Changes in v2:
- New patch (Simon)
---
 configs/sandbox_defconfig |  1 +
 test/boot/bootflow.c      | 84 +++++++++++++++++++++++++++++++++++++++++++++++
 test/py/tests/test_ut.py  |  4 +--
 3 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index a3fa5246082..289fbcf2d34 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -166,6 +166,7 @@ CONFIG_ENV_IS_IN_SPI_FLASH=y
 CONFIG_ENV_SECT_SIZE_AUTO=y
 CONFIG_ENV_REDUNDANT=y
 CONFIG_ENV_REDUNDANT_UPGRADE=y
+CONFIG_ENV_FAT_DEVICE_AND_PART="a:1"
 CONFIG_ENV_EXT4_INTERFACE="host"
 CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
 CONFIG_ENV_IMPORT_FDT=y
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index d2d4edb0add..20c371d984c 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -1734,6 +1734,90 @@ static int bootflow_rauc(struct unit_test_state *uts)
 }
 BOOTSTD_TEST(bootflow_rauc, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
 
+/**
+ * bootflow_rauc_run_env_fat() - Run RAUC checks with the environment on FAT
+ *
+ * Booting a RAUC bootflow saves the environment, so this selects the FAT
+ * environment, which is on the first partition of mmc10, while running @check
+ * on mmc10.
+ *
+ * @uts: Unit test state
+ * @check: Checks to run with the RAUC bootmeth
+ * Returns 0 on success, -EAGAIN if not supported, other -ve on failure
+ */
+static int bootflow_rauc_run_env_fat(struct unit_test_state *uts,
+                                    int (*check)(struct unit_test_state *uts))
+{
+       int ret;
+
+       if (!CONFIG_IS_ENABLED(BOOTMETH_RAUC) ||
+           !IS_ENABLED(CONFIG_ENV_IS_IN_FAT) ||
+           !IS_ENABLED(CONFIG_CMD_NVEDIT_SELECT))
+               return -EAGAIN;
+
+       ut_assertok(run_command("env select FAT", 0));
+       ut_assert_nextline("Select Environment on FAT: OK");
+
+       ret = bootflow_rauc_run(uts, "mmc10", check);
+       run_command("env select nowhere", 0);
+       if (ret)
+               return ret;
+       ut_assert_nextline("Select Environment on nowhere: OK");
+       ut_assert_console_end();
+
+       return 0;
+}
+
+/* Boot the selected RAUC bootflow, which saves the environment first */
+static int bootflow_rauc_boot(struct unit_test_state *uts)
+{
+       ut_asserteq(1, run_command("bootflow boot", 0));
+       ut_assert_nextline("** Booting bootflow 'mmc10.bootdev.whole' with 
rauc");
+       ut_assert_nextline("Saving Environment to FAT... OK");
+
+       return 0;
+}
+
+static int bootflow_rauc_boot_twice_check(struct unit_test_state *uts)
+{
+       /* Start with the default tries, also when running a second time */
+       ut_assertok(env_set("BOOT_A_LEFT", NULL));
+       ut_assertok(env_set("BOOT_B_LEFT", NULL));
+
+       /* Let the boot script fail, so that the bootflow can be booted again */
+       ut_assertok(env_set("rauc_test_script", "false"));
+
+       ut_assertok(run_command("bootflow scan", 0));
+       ut_assertok(run_command("bootflow select 0", 0));
+       ut_assertok(bootflow_rauc_boot(uts));
+       ut_assert_skip_to_line("Boot failed (err=1)");
+       ut_assert_console_end();
+       ut_asserteq_str("2", env_get("BOOT_A_LEFT"));
+
+       /* The second attempt loads the boot script again, but only once */
+       ut_assertok(bootflow_rauc_boot(uts));
+       ut_assert_skip_to_line("Boot failed (err=1)");
+       ut_assert_console_end();
+       ut_asserteq_str("1", env_get("BOOT_A_LEFT"));
+
+       ut_assertok(run_command("bootstd images", 0));
+       ut_assert_skip_to_line("(1 image)");
+       ut_assert_console_end();
+
+       ut_assertok(env_set("BOOT_A_LEFT", NULL));
+       ut_assertok(env_set("BOOT_B_LEFT", NULL));
+       ut_assertok(env_set("rauc_test_script", NULL));
+
+       return 0;
+}
+
+/* Test booting the same RAUC bootflow twice after a failed boot */
+static int bootflow_rauc_boot_twice(struct unit_test_state *uts)
+{
+       return bootflow_rauc_run_env_fat(uts, bootflow_rauc_boot_twice_check);
+}
+BOOTSTD_TEST(bootflow_rauc_boot_twice, UTF_CONSOLE | UTF_DM | UTF_SCAN_FDT);
+
 /*
  * Test the BLS bootmeth against entries that live below a '/boot/' prefix,
  * so that they are only found via the second bootstd prefix. The Fedora
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index a33f188d984..36d0f14973d 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -590,8 +590,8 @@ def setup_rauc_image(ubman):
     boot = FsHelper(ubman.config, 'fat32', 8, 'rauc_boot')
     boot.setup()
 
-    # Generate boot script
-    script = '# dummy boot script'
+    # Generate boot script, which runs a command set by the test
+    script = 'run rauc_test_script'
     cmd_fname = os.path.join(boot.srcdir, 'boot.cmd')
     scr_fname = os.path.join(boot.srcdir, 'boot.scr')
     with open(cmd_fname, 'w', encoding='ascii') as outf:

-- 
2.56.0

Reply via email to