[PATCH 23/28] bootmethod: Add tests for bootmethod and bootflow

Simon Glass sjg at chromium.org
Thu Aug 19 05:45:56 CEST 2021


Add a set of combined tests for these two commands.

Expand the sandbox console-recording limit so that these can work.

These tests rely on a filesystem script which is not yet added to the
Python tests. It is included here as a shell script.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 MAINTAINERS               |   1 +
 configs/sandbox_defconfig |   2 +-
 include/test/suites.h     |   2 +
 test/Makefile             |   1 +
 test/boot/Makefile        |   5 +
 test/boot/bootmethod.c    | 271 ++++++++++++++++++++++++++++++++++++++
 test/cmd_ut.c             |   4 +
 try.sh                    | 131 ++++++++++++++++++
 8 files changed, 416 insertions(+), 1 deletion(-)
 create mode 100644 test/boot/Makefile
 create mode 100644 test/boot/bootmethod.c
 create mode 100755 try.sh

diff --git a/MAINTAINERS b/MAINTAINERS
index 367193358b7..2f74f7dbb19 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -639,6 +639,7 @@ F:	cmd/bootflow.c
 F:	cmd/bootmethod.c
 F:	include/bootmethod.h
 F:	include/distro.h
+F:	test/boot/bootmethod.c
 
 BTRFS
 M:	Marek Behun <marek.behun at nic.cz>
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 952d430304c..31a8d6a1d90 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -26,7 +26,7 @@ CONFIG_AUTOBOOT_NEVER_TIMEOUT=y
 CONFIG_AUTOBOOT_STOP_STR_ENABLE=y
 CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9"
 CONFIG_CONSOLE_RECORD=y
-CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x2000
 CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_LOG=y
 CONFIG_DISPLAY_BOARDINFO_LATE=y
diff --git a/include/test/suites.h b/include/test/suites.h
index d35cd83a4eb..c36aa568e78 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -29,6 +29,8 @@ int cmd_ut_category(const char *name, const char *prefix,
 int do_ut_addrmap(struct cmd_tbl *cmdtp, int flag, int argc,
 		  char *const argv[]);
 int do_ut_bootm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_bootmethod(struct cmd_tbl *cmdtp, int flag, int argc,
+		     char *const argv[]);
 int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc,
 		   char *const argv[]);
 int do_ut_common(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/test/Makefile b/test/Makefile
index b3b2902e2e7..abd605a4351 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o
 obj-y += ut.o
 
 ifeq ($(CONFIG_SPL_BUILD),)
+obj-$(CONFIG_UNIT_TEST) += boot/
 obj-$(CONFIG_UNIT_TEST) += common/
 obj-$(CONFIG_UNIT_TEST) += lib/
 obj-y += log/
diff --git a/test/boot/Makefile b/test/boot/Makefile
new file mode 100644
index 00000000000..bb1599b9c0d
--- /dev/null
+++ b/test/boot/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright 2021 Google LLC
+
+obj-$(CONFIG_BOOTMETHOD) += bootmethod.o
diff --git a/test/boot/bootmethod.c b/test/boot/bootmethod.c
new file mode 100644
index 00000000000..4467625c0fd
--- /dev/null
+++ b/test/boot/bootmethod.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg at chromium.org>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <bootmethod.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+/* Declare a new bootmethod test */
+#define BOOTMETHOD_TEST(_name, _flags) \
+		UNIT_TEST(_name, _flags, bootmethod_test)
+
+/* Check 'bootmethod list' command */
+static int bootmethod_test_cmd_list(struct unit_test_state *uts)
+{
+	int probed;
+
+	console_record_reset_enable();
+	for (probed = 0; probed < 2; probed++) {
+		int probe_ch = probed ? '+' : ' ';
+
+		ut_assertok(run_command(probed ? "bootmethod list -p" :
+			"bootmethod list", 0));
+		ut_assert_nextline("Seq  Probed  Status  Uclass    Name");
+		ut_assert_nextlinen("---");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 0, probe_ch, "OK",
+				   "mmc", "mmc2.bootmethod");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 1, probe_ch, "OK",
+				   "mmc", "mmc1.bootmethod");
+		ut_assert_nextline("%3x   [ %c ]  %6s  %-8s  %s", 2, probe_ch, "OK",
+				   "mmc", "mmc0.bootmethod");
+		ut_assert_nextlinen("---");
+		ut_assert_nextline("(3 devices)");
+		ut_assert_console_end();
+	}
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_list, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootmethod select' and 'info' commands */
+static int bootmethod_test_cmd_select(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_asserteq(1, run_command("bootmethod info", 0));
+	ut_assert_nextlinen("Please use");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootmethod select 0", 0));
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootmethod info", 0));
+	ut_assert_nextline("Name:      mmc2.bootmethod");
+	ut_assert_nextline("Uclass:    mmc");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_select, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan/list' commands */
+static int bootmethod_test_cmd_bootflow(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in bootmethod 'mmc0.bootmethod'");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(21 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing bootflows for bootmethod 'mmc0.bootmethod'");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan/list' commands using all bootmethods */
+static int bootmethod_test_cmd_bootflow_glob(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -l", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootmethods");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':");
+	ut_assert_nextline("Scanning bootmethod 'mmc1.bootmethod':");
+	ut_assert_nextline("Scanning bootmethod 'mmc0.bootmethod':");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextline("No more bootmethods");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing all bootflows");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(1 bootflow, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_glob,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -e' */
+static int bootmethod_test_cmd_bootflow_scan_e(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -ale", 0));
+	ut_assert_nextline("Scanning for bootflows in all bootmethods");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("Scanning bootmethod 'mmc2.bootmethod':");
+	ut_assert_nextline("  0  distro-boot  media   mmc          0  mmc2.bootmethod.part_1    <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-93");
+	ut_assert_nextline("  1  distro-boot  media   mmc          0  mmc2.bootmethod.part_2    <NULL>");
+
+	ut_assert_skip_to_line("Scanning bootmethod 'mmc1.bootmethod':");
+	ut_assert_skip_to_line("Scanning bootmethod 'mmc0.bootmethod':");
+	ut_assert_nextline(" 28  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_nextline(" 29  distro-boot  media   mmc          0  mmc0.bootmethod.part_2    <NULL>");
+	ut_assert_skip_to_line(" 3b  distro-boot  media   mmc          0  mmc0.bootmethod.part_14   <NULL>");
+	ut_assert_nextline("     ** No partition found, err=-2");
+	ut_assert_nextline("No more bootmethods");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(60 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow list", 0));
+	ut_assert_nextline("Showing all bootflows");
+	ut_assert_nextline("Seq  Type         State   Uclass    Part  Name                      Filename");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("  0  distro-boot  media   mmc          0  mmc2.bootmethod.part_1    <NULL>");
+	ut_assert_skip_to_line(" 28  distro-boot  loaded  mmc          1  mmc0.bootmethod.part_1    extlinux/extlinux.conf");
+	ut_assert_skip_to_line(" 3b  distro-boot  media   mmc          0  mmc0.bootmethod.part_14   <NULL>");
+	ut_assert_nextlinen("---");
+	ut_assert_nextline("(60 bootflows, 1 valid)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_e,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow info' */
+static int bootmethod_test_cmd_bootflow_info(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow select 0", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow info", 0));
+	ut_assert_nextline("Name:      mmc0.bootmethod.part_1");
+	ut_assert_nextline("Device:    mmc0.bootmethod");
+	ut_assert_nextline("Block dev: mmc0.blk");
+	ut_assert_nextline("Sequence:  0");
+	ut_assert_nextline("Type:      distro-boot");
+	ut_assert_nextline("State:     loaded");
+	ut_assert_nextline("Partition: 1");
+	ut_assert_nextline("Subdir:    (none)");
+	ut_assert_nextline("Filename:  extlinux/extlinux.conf");
+	ut_assert_nextlinen("Buffer:    ");
+	ut_assert_nextline("Size:      237 (567 bytes)");
+	ut_assert_nextline("Error:     0");
+	ut_assert_console_end();
+
+	ut_assertok(run_command("bootflow info -d", 0));
+	ut_assert_nextline("Name:      mmc0.bootmethod.part_1");
+	ut_assert_skip_to_line("Error:     0");
+	ut_assert_nextline("Contents:");
+	ut_assert_nextline("%s", "");
+	ut_assert_nextline("# extlinux.conf generated by appliance-creator");
+	ut_assert_skip_to_line("initrd /initramfs-5.3.7-301.fc31.armv7hl.img");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_info,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow scan -b' to boot the first available bootmethod */
+static int bootmethod_test_cmd_bootflow_scan_boot(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan -b", 0));
+	ut_assert_nextline("** Booting bootflow 'mmc0.bootmethod.part_1'");
+	ut_assert_nextline("Ignoring unknown command: ui");
+
+	/*
+	 * We expect it to get through to boot although sandbox always returns
+	 * -EFAULT as it cannot actually boot the kernel
+	 */
+	ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
+	ut_assert_nextline("Boot failed (err=-14)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_scan_boot,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check 'bootflow boot' to boot a selected bootflow */
+static int bootmethod_test_cmd_bootflow_boot(struct unit_test_state *uts)
+{
+	console_record_reset_enable();
+	ut_assertok(run_command("bootmethod select 2", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow scan", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow select 0", 0));
+	ut_assert_console_end();
+	ut_assertok(run_command("bootflow boot", 0));
+	ut_assert_nextline("** Booting bootflow 'mmc0.bootmethod.part_1'");
+	ut_assert_nextline("Ignoring unknown command: ui");
+
+	/*
+	 * We expect it to get through to boot although sandbox always returns
+	 * -EFAULT as it cannot actually boot the kernel
+	 */
+	ut_assert_skip_to_line("sandbox: continuing, as we cannot run Linux");
+	ut_assert_nextline("Boot failed (err=-14)");
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_cmd_bootflow_boot,
+		UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+/* Check we can get a bootmethod */
+static int bootmethod_test_get(struct unit_test_state *uts)
+{
+	struct bootmethod_iter iter;
+	struct bootflow bflow;
+
+	ut_assertok(bootmethod_scan_first_bootflow(&iter, 0, &bflow));
+
+	return 0;
+}
+BOOTMETHOD_TEST(bootmethod_test_get, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+
+int do_ut_bootmethod(struct cmd_tbl *cmdtp, int flag, int argc,
+		     char *const argv[])
+{
+	struct unit_test *tests = UNIT_TEST_SUITE_START(bootmethod_test);
+	const int n_ents = UNIT_TEST_SUITE_COUNT(bootmethod_test);
+
+	return cmd_ut_category("bootmethod", "bootmethod_test_",
+			       tests, n_ents, argc, argv);
+}
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 90b260f72d6..c71f5575a04 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -28,6 +28,10 @@ int cmd_ut_category(const char *name, const char *prefix,
 
 static struct cmd_tbl cmd_ut_sub[] = {
 	U_BOOT_CMD_MKENT(all, CONFIG_SYS_MAXARGS, 1, do_ut_all, "", ""),
+#ifdef CONFIG_BOOTMETHOD
+	U_BOOT_CMD_MKENT(bootmethod, CONFIG_SYS_MAXARGS, 1, do_ut_bootmethod,
+			 "", ""),
+#endif
 	U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""),
 #if defined(CONFIG_UT_DM)
 	U_BOOT_CMD_MKENT(dm, CONFIG_SYS_MAXARGS, 1, do_ut_dm, "", ""),
diff --git a/try.sh b/try.sh
new file mode 100755
index 00000000000..14519c3144c
--- /dev/null
+++ b/try.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+
+set -e
+
+file=mmc.img
+mnt=/mnt/x
+fat=/mnt/y
+dstdir=$fat/extlinux
+
+vmlinux=vmlinuz-5.3.7-301.fc31.armv7hl
+initrd=initramfs-5.3.7-301.fc31.armv7hl.img
+dtb=dtb-5.3.7-301.fc31.armv7hl/sandbox.dtb
+
+old() {
+	mkfs.vfat $file
+	sudo mount -o loop $file $mnt
+	#sudo cp /tmp/b/efi-x86_payload64/u-boot-payload.efi /mnt/x
+	#sudo cp /tmp/efi64/startup.nsh  $mnt
+	#sudo cp /tmp/efi64/vmlinuz $mnt
+	echo >>/tmp/extlinux.conf <<EOF
+ui menu.c32
+
+menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options.
+menu title Arch Boot Options.
+menu hidden
+
+timeout 50
+
+default Arch
+
+label Arch
+    kernel /zImage
+    append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8
+    fdtdir /dtbs
+    initrd /initramfs-linux.img
+EOF
+	sudo cp /tmp/extlinux.conf $mnt
+	ls $mnt
+	sudo umount $mnt
+}
+
+
+fat_setup() {
+	echo 'type=c' | sudo sfdisk $file
+	#sudo kpartx -a $file
+	loop=$(sudo losetup --show -f -P $file)
+	echo "Mounted to $loop"
+	fatpart="${loop}p1"
+ 	sudo mkfs.vfat $fatpart
+	sudo mount -o loop ${fatpart} $fat
+}
+
+
+fat_finish() {
+	sudo mkdir -p $dstdir
+	sudo cp /tmp/extlinux.conf $dstdir
+
+	echo "vmlinux" | gzip >/tmp/inf
+	mkimage -f auto -d /tmp/inf /tmp/$vmlinux
+
+	sudo cp /tmp/$vmlinux $fat
+
+	echo "initd" >/tmp/$initrd
+	sudo cp /tmp/$initrd $fat
+
+	dtb_dir="$(dirname /tmp/$dtb)"
+	mkdir -p $dtb_dir
+	echo "/dts-v1/; / {};" | dtc >/tmp/$dtb
+	sudo cp -r $dtb_dir $fat
+
+	ls $dstdir
+
+	sudo umount $fat
+
+	losetup -d $loop
+}
+
+
+new() {
+	fat_setup
+	cat >/tmp/extlinux.conf << EOF
+ui menu.c32
+
+menu autoboot Arch Boot. Automatic boot in # second{,s}. Press a key for options.
+menu title Arch Boot Options.
+menu hidden
+
+timeout 50
+
+default Arch
+
+label Arch
+    kernel /zImage
+    append root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait consoleblank=0 no_console_suspend=1 console=ttymxc0,115200n8
+    fdtdir /dtbs
+    initrd /initramfs-linux.img
+EOF
+	fat_finish
+}
+
+
+fedora31() {
+	fat_setup
+	cat >/tmp/extlinux.conf << EOF
+# extlinux.conf generated by appliance-creator
+ui menu.c32
+menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options.
+menu title Fedora-Workstation-armhfp-31-1.9 Boot Options.
+menu hidden
+timeout 20
+totaltimeout 600
+
+label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
+	kernel /$vmlinux
+	append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
+	fdtdir /dtb-5.3.7-301.fc31.armv7hl/
+	initrd /$initrd
+EOF
+	fat_finish
+}
+
+# Remove old devices
+for dev in $(losetup |grep $file | awk '{print $1}'); do
+	echo "Remove $dev"
+	losetup -d $dev
+done
+
+qemu-img create $file 20M
+#old
+#new
+fedora31
-- 
2.33.0.rc1.237.g0d66db33f3-goog



More information about the U-Boot mailing list