diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/Makefile | 10 | ||||
-rw-r--r-- | test/boot/Makefile | 3 | ||||
-rw-r--r-- | test/boot/bootdev.c | 18 | ||||
-rw-r--r-- | test/boot/bootflow.c | 80 | ||||
-rw-r--r-- | test/boot/bootm.c (renamed from test/bootm.c) | 21 | ||||
-rw-r--r-- | test/cmd/Makefile | 3 | ||||
-rw-r--r-- | test/cmd/command.c | 108 | ||||
-rw-r--r-- | test/cmd/coreboot.c | 119 | ||||
-rw-r--r-- | test/cmd/hash.c | 101 | ||||
-rw-r--r-- | test/cmd_ut.c | 25 | ||||
-rw-r--r-- | test/command_ut.c | 104 | ||||
-rw-r--r-- | test/common.sh | 20 | ||||
-rw-r--r-- | test/common/Makefile | 4 | ||||
-rw-r--r-- | test/common/bloblist.c (renamed from test/bloblist.c) | 31 | ||||
-rw-r--r-- | test/common/print.c (renamed from test/print_ut.c) | 27 | ||||
-rw-r--r-- | test/dm/core.c | 22 | ||||
-rw-r--r-- | test/lib/Makefile | 8 | ||||
-rw-r--r-- | test/lib/alist.c | 253 | ||||
-rw-r--r-- | test/lib/compression.c (renamed from test/compression.c) | 39 | ||||
-rw-r--r-- | test/lib/str.c (renamed from test/str_ut.c) | 31 | ||||
-rw-r--r-- | test/lib/time.c (renamed from test/time_ut.c) | 60 | ||||
-rw-r--r-- | test/lib/unicode.c (renamed from test/unicode_ut.c) | 70 | ||||
-rw-r--r-- | test/py/conftest.py | 73 | ||||
-rw-r--r-- | test/py/tests/bootstd/flash1.img.xz | bin | 0 -> 4924 bytes | |||
-rw-r--r-- | test/py/tests/test_spi.py | 2 | ||||
-rw-r--r-- | test/py/tests/test_usb.py | 171 | ||||
-rw-r--r-- | test/py/tests/test_ut.py | 55 | ||||
-rw-r--r-- | test/py/u_boot_console_base.py | 123 | ||||
-rw-r--r-- | test/py/u_boot_console_exec_attach.py | 31 | ||||
-rw-r--r-- | test/py/u_boot_spawn.py | 44 | ||||
-rw-r--r-- | test/test-main.c | 39 | ||||
-rwxr-xr-x | test/trace/test-trace.sh | 64 |
32 files changed, 1201 insertions, 558 deletions
diff --git a/test/Makefile b/test/Makefile index 145c952d2c3..47a07d653a9 100644 --- a/test/Makefile +++ b/test/Makefile @@ -4,14 +4,8 @@ obj-y += test-main.o -ifneq ($(CONFIG_$(XPL_)BLOBLIST),) -obj-$(CONFIG_$(XPL_)CMDLINE) += bloblist.o -obj-$(CONFIG_$(XPL_)CMDLINE) += bootm.o -endif obj-$(CONFIG_$(XPL_)CMDLINE) += cmd/ obj-$(CONFIG_$(XPL_)CMDLINE) += cmd_ut.o -obj-$(CONFIG_$(XPL_)CMDLINE) += command_ut.o -obj-$(CONFIG_$(XPL_)UT_COMPRESSION) += compression.o obj-y += dm/ obj-$(CONFIG_FUZZ) += fuzz/ ifndef CONFIG_SANDBOX_VPL @@ -20,16 +14,12 @@ endif ifneq ($(CONFIG_HUSH_PARSER),) obj-$(CONFIG_$(XPL_)CMDLINE) += hush/ endif -obj-$(CONFIG_$(XPL_)CMDLINE) += print_ut.o -obj-$(CONFIG_$(XPL_)CMDLINE) += str_ut.o -obj-$(CONFIG_UT_TIME) += time_ut.o obj-y += ut.o ifeq ($(CONFIG_XPL_BUILD),) obj-y += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-y += log/ -obj-$(CONFIG_$(XPL_)UT_UNICODE) += unicode_ut.o else obj-$(CONFIG_SPL_UT_LOAD) += image/ endif diff --git a/test/boot/Makefile b/test/boot/Makefile index d8eded20d4f..63487e8d29e 100644 --- a/test/boot/Makefile +++ b/test/boot/Makefile @@ -10,6 +10,9 @@ obj-$(CONFIG_EXPO) += expo.o obj-$(CONFIG_CEDIT) += cedit.o endif +ifdef CONFIG_SANDBOX +obj-$(CONFIG_$(XPL_)CMDLINE) += bootm.o +endif obj-$(CONFIG_MEASURED_BOOT) += measurement.o ifdef CONFIG_OF_LIVE diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 369c611d924..8c44afd9297 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -221,6 +221,10 @@ static int bootdev_test_order(struct unit_test_state *uts) /* Use the environment variable to override it */ ut_assertok(env_set("boot_targets", "mmc1 mmc2 usb")); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(5, iter.num_devs); ut_asserteq_str("mmc1.bootdev", iter.dev_used[0]->name); @@ -260,7 +264,11 @@ static int bootdev_test_order(struct unit_test_state *uts) ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); ut_asserteq(2, iter.num_devs); - /* Now scan past mmc1 and make sure that the 3 USB devices show up */ + /* + * Now scan past mmc1 and make sure that the 3 USB devices show up. The + * first one has a backing file so returns success + */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); @@ -322,6 +330,10 @@ static int bootdev_test_prio(struct unit_test_state *uts) /* 3 MMC and 3 USB bootdevs: MMC should come before USB */ ut_assertok(bootflow_scan_first(NULL, NULL, &iter, 0, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(6, iter.num_devs); ut_asserteq_str("mmc2.bootdev", iter.dev_used[0]->name); @@ -339,6 +351,10 @@ static int bootdev_test_prio(struct unit_test_state *uts) bootflow_iter_uninit(&iter); ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_HUNT, &bflow)); + + /* get the usb device which has a backing file (flash1.img) */ + ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); + ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); ut_asserteq(7, iter.num_devs); ut_asserteq_str("usb_mass_storage.lun0.bootdev", diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 0d4e966892e..9397328609d 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -12,7 +12,8 @@ #include <bootstd.h> #include <cli.h> #include <dm.h> -#include <efi_default_filename.h> +#include <efi.h> +#include <efi_loader.h> #include <expo.h> #ifdef CONFIG_SANDBOX #include <asm/test.h> @@ -31,6 +32,9 @@ extern U_BOOT_DRIVER(bootmeth_android); extern U_BOOT_DRIVER(bootmeth_cros); extern U_BOOT_DRIVER(bootmeth_2script); +/* Use this as the vendor for EFI to tell the app to exit boot services */ +static u16 __efi_runtime_data test_vendor[] = u"U-Boot testing"; + static int inject_response(struct unit_test_state *uts) { /* @@ -184,8 +188,9 @@ static int bootflow_cmd_scan_e(struct unit_test_state *uts) ut_assert_nextline(" 3 efi media mmc 0 mmc1.bootdev.whole "); ut_assert_nextline(" ** No partition found, err=-2: No such file or directory"); ut_assert_nextline(" 4 extlinux ready mmc 1 mmc1.bootdev.part_1 /extlinux/extlinux.conf"); - ut_assert_nextline(" 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/" - BOOTEFI_NAME); + ut_assert_nextline( + " 5 efi fs mmc 1 mmc1.bootdev.part_1 /EFI/BOOT/%s", + efi_get_basename()); ut_assert_skip_to_line("Scanning bootdev 'mmc0.bootdev':"); ut_assert_skip_to_line( @@ -370,7 +375,7 @@ static int bootflow_iter(struct unit_test_state *uts) return 0; } -BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT); +BOOTSTD_TEST(bootflow_iter, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE); #if defined(CONFIG_SANDBOX) && defined(CONFIG_BOOTMETH_GLOBAL) /* Check using the system bootdev */ @@ -533,7 +538,7 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, order[2] = mmc_dev; - /* Enable the mmc4 node since we need a second bootflow */ + /* Enable the requested mmc node since we need a second bootflow */ root = oftree_root(oftree_default()); node = ofnode_find_subnode(root, mmc_dev); ut_assert(ofnode_valid(node)); @@ -542,7 +547,7 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev, /* Enable the script bootmeth too */ ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script), - "bootmeth_script", 0, ofnode_null(), &dev)); + "script", 0, ofnode_null(), &dev)); /* Enable the cros bootmeth if needed */ if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) { @@ -1216,3 +1221,66 @@ static int bootflow_android(struct unit_test_state *uts) return 0; } BOOTSTD_TEST(bootflow_android, UTF_CONSOLE); + +/* Test EFI bootmeth */ +static int bootflow_efi(struct unit_test_state *uts) +{ + static const char *order[] = {"mmc1", "usb", NULL}; + struct bootstd_priv *std; + struct udevice *bootstd; + const char **old_order; + + ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd)); + std = dev_get_priv(bootstd); + old_order = std->bootdev_order; + std->bootdev_order = order; + + /* disable ethernet since the hunter will run dhcp */ + test_set_eth_enable(false); + + /* make USB scan without delays */ + test_set_skip_delays(true); + + bootstd_reset_usb(); + + ut_assertok(run_command("bootflow scan", 0)); + ut_assert_skip_to_line( + "Bus usb@1: scanning bus usb@1 for devices... 5 USB Device(s) found"); + + ut_assertok(run_command("bootflow list", 0)); + + ut_assert_nextlinen("Showing all"); + ut_assert_nextlinen("Seq"); + ut_assert_nextlinen("---"); + ut_assert_nextlinen(" 0 extlinux"); + ut_assert_nextlinen( + " 1 efi ready usb_mass_ 1 usb_mass_storage.lun0.boo /EFI/BOOT/BOOTSBOX.EFI"); + ut_assert_nextlinen("---"); + ut_assert_skip_to_line("(2 bootflows, 2 valid)"); + ut_assert_console_end(); + + ut_assertok(run_command("bootflow select 1", 0)); + ut_assert_console_end(); + + systab.fw_vendor = test_vendor; + + ut_asserteq(1, run_command("bootflow boot", 0)); + ut_assert_nextline( + "** Booting bootflow 'usb_mass_storage.lun0.bootdev.part_1' with efi"); + if (IS_ENABLED(CONFIG_LOGF_FUNC)) + ut_assert_skip_to_line(" efi_run_image() Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); + else + ut_assert_skip_to_line("Booting /\\EFI\\BOOT\\BOOTSBOX.EFI"); + + /* TODO: Why the \r ? */ + ut_assert_nextline("U-Boot test app for EFI_LOADER\r"); + ut_assert_nextline("Exiting test app"); + ut_assert_nextline("Boot failed (err=-14)"); + + ut_assert_console_end(); + + ut_assertok(bootstd_test_drop_bootdev_order(uts)); + + return 0; +} +BOOTSTD_TEST(bootflow_efi, UTF_CONSOLE); diff --git a/test/bootm.c b/test/boot/bootm.c index 26c15552bf6..52b83f149cb 100644 --- a/test/bootm.c +++ b/test/boot/bootm.c @@ -26,12 +26,15 @@ static int bootm_test_nop(struct unit_test_state *uts) { char buf[BUF_SIZE]; + /* This tests relies on GD_FLG_SILENT not being set */ + gd->flags &= ~GD_FLG_SILENT; + *buf = '\0'; - ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true)); + ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_ALL)); ut_asserteq_str("", buf); strcpy(buf, "test"); - ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true)); + ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_ALL)); ut_asserteq_str("test", buf); return 0; @@ -43,23 +46,26 @@ static int bootm_test_nospace(struct unit_test_state *uts) { char buf[BUF_SIZE]; + /* This tests relies on GD_FLG_SILENT not being set */ + gd->flags &= ~GD_FLG_SILENT; + /* Zero buffer size */ *buf = '\0'; - ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 0, true)); + ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, 0, BOOTM_CL_ALL)); /* Buffer string not terminated */ memset(buf, 'a', BUF_SIZE); - ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true)); + ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_ALL)); /* Not enough space to copy string */ memset(buf, '\0', BUF_SIZE); memset(buf, 'a', BUF_SIZE / 2); - ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, true)); + ut_asserteq(-ENOSPC, bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_ALL)); /* Just enough space */ memset(buf, '\0', BUF_SIZE); memset(buf, 'a', BUF_SIZE / 2 - 1); - ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, true)); + ut_assertok(bootm_process_cmdline(buf, BUF_SIZE, BOOTM_CL_ALL)); return 0; } @@ -70,6 +76,9 @@ static int bootm_test_silent(struct unit_test_state *uts) { char buf[BUF_SIZE]; + /* This tests relies on GD_FLG_SILENT not being set */ + gd->flags &= ~GD_FLG_SILENT; + /* 'silent_linux' not set should do nothing */ env_set("silent_linux", NULL); strcpy(buf, CONSOLE_STR); diff --git a/test/cmd/Makefile b/test/cmd/Makefile index fe7a2165af2..583e7c2eec4 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -5,6 +5,7 @@ obj-y += cmd_ut_cmd.o +obj-$(CONFIG_$(XPL_)CMDLINE) += command.o ifdef CONFIG_HUSH_PARSER obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o endif @@ -15,8 +16,10 @@ obj-y += exit.o mem.o obj-$(CONFIG_X86) += cpuid.o msr.o obj-$(CONFIG_CMD_ADDRMAP) += addrmap.o obj-$(CONFIG_CMD_BDI) += bdinfo.o +obj-$(CONFIG_COREBOOT_SYSINFO) += coreboot.o obj-$(CONFIG_CMD_FDT) += fdt.o obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o +obj-$(CONFIG_CMD_HASH) += hash.o obj-$(CONFIG_CMD_HISTORY) += history.o obj-$(CONFIG_CMD_LOADM) += loadm.o obj-$(CONFIG_CMD_MEMINFO) += meminfo.o diff --git a/test/cmd/command.c b/test/cmd/command.c new file mode 100644 index 00000000000..5ec93d490ba --- /dev/null +++ b/test/cmd/command.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2012, The Chromium Authors + */ + +#define DEBUG + +#include <command.h> +#include <env.h> +#include <log.h> +#include <string.h> +#include <linux/errno.h> +#include <test/cmd.h> +#include <test/ut.h> + +static const char test_cmd[] = "setenv list 1\n setenv list ${list}2; " + "setenv list ${list}3\0" + "setenv list ${list}4"; + +static int command_test(struct unit_test_state *uts) +{ + char long_str[CONFIG_SYS_CBSIZE + 42]; + + printf("%s: Testing commands\n", __func__); + run_command("env default -f -a", 0); + + /* commands separated by \n */ + run_command_list("setenv list 1\n setenv list ${list}1", -1, 0); + ut_assert(!strcmp("11", env_get("list"))); + + /* command followed by \n and nothing else */ + run_command_list("setenv list 1${list}\n", -1, 0); + ut_assert(!strcmp("111", env_get("list"))); + + /* a command string with \0 in it. Stuff after \0 should be ignored */ + run_command("setenv list", 0); + run_command_list(test_cmd, sizeof(test_cmd), 0); + ut_assert(!strcmp("123", env_get("list"))); + + /* + * a command list where we limit execution to only the first command + * using the length parameter. + */ + run_command_list("setenv list 1\n setenv list ${list}2; " + "setenv list ${list}3", strlen("setenv list 1"), 0); + ut_assert(!strcmp("1", env_get("list"))); + + ut_asserteq(1, run_command("false", 0)); + ut_assertok(run_command("echo", 0)); + ut_asserteq(1, run_command_list("false", -1, 0)); + ut_assertok(run_command_list("echo", -1, 0)); + +#ifdef CONFIG_HUSH_PARSER + run_command("setenv foo 'setenv black 1\nsetenv adder 2'", 0); + run_command("run foo", 0); + ut_assertnonnull(env_get("black")); + ut_asserteq(0, strcmp("1", env_get("black"))); + ut_assertnonnull(env_get("adder")); + ut_asserteq(0, strcmp("2", env_get("adder"))); +#endif + + ut_assertok(run_command("", 0)); + ut_assertok(run_command(" ", 0)); + + ut_asserteq(1, run_command("'", 0)); + + /* Variadic function test-cases */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-zero-length" + ut_assertok(run_commandf("")); +#pragma GCC diagnostic pop + ut_assertok(run_commandf(" ")); + ut_asserteq(1, run_commandf("'")); + + ut_assertok(run_commandf("env %s %s", "delete -f", "list")); + /* + * Expected: "## Error: "list" not defined" + * (disabled to avoid pytest bailing out) + * + * ut_asserteq(1, run_commandf("printenv list")); + */ + + memset(long_str, 'x', sizeof(long_str)); + ut_asserteq(-ENOSPC, run_commandf("Truncation case: %s", long_str)); + + if (IS_ENABLED(CONFIG_HUSH_PARSER)) { + ut_assertok(run_commandf("env %s %s %s %s", "delete -f", + "adder", "black", "foo")); + ut_assertok(run_commandf( + "setenv foo 'setenv %s 1\nsetenv %s 2'", + "black", "adder")); + ut_assertok(run_command("run foo", 0)); + ut_assertnonnull(env_get("black")); + ut_asserteq(0, strcmp("1", env_get("black"))); + ut_assertnonnull(env_get("adder")); + ut_asserteq(0, strcmp("2", env_get("adder"))); + } + + /* Clean up before exit */ + ut_assertok(run_command("env default -f -a", 0)); + + /* put back the FDT environment */ + ut_assertok(env_set("from_fdt", "yes")); + + printf("%s: Everything went swimmingly\n", __func__); + return 0; +} +CMD_TEST(command_test, 0); diff --git a/test/cmd/coreboot.c b/test/cmd/coreboot.c new file mode 100644 index 00000000000..a99898d15c4 --- /dev/null +++ b/test/cmd/coreboot.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Test for coreboot commands + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <cedit.h> +#include <command.h> +#include <dm.h> +#include <expo.h> +#include <rtc.h> +#include <test/cedit-test.h> +#include <test/cmd.h> +#include <test/test.h> +#include <test/ut.h> +#include "../../boot/scene_internal.h" + +enum { + CSUM_LOC = 0x3f0 / 8, +}; + +/** + * test_cmd_cbsysinfo() - test the cbsysinfo command produces expected output + * + * This includes ensuring that the coreboot build has the expected options + * enabled + */ +static int test_cmd_cbsysinfo(struct unit_test_state *uts) +{ + ut_assertok(run_command("cbsysinfo", 0)); + ut_assert_nextlinen("Coreboot table at"); + + /* Make sure CMOS options are enabled */ + ut_assert_skip_to_line( + " 1c0 1 e 1 power_on_after_fail 0:Disable 1:Enable"); + ut_assert_skip_to_line("CMOS start : 1c0"); + ut_assert_nextline(" CMOS end : 1cf"); + ut_assert_nextline(" CMOS csum loc: 3f0"); + + /* Make sure the linear frame buffer is enabled */ + ut_assert_skip_to_linen("Framebuffer"); + ut_assert_nextlinen(" Phys addr"); + + ut_assert_skip_to_line("Chrome OS VPD: 00000000"); + ut_assert_nextlinen("RSDP"); + ut_assert_nextlinen("Unimpl."); + ut_assert_console_end(); + + return 0; +} +CMD_TEST(test_cmd_cbsysinfo, UTF_CONSOLE); + +/* test cbcmos command */ +static int test_cmd_cbcmos(struct unit_test_state *uts) +{ + u16 old_csum, new_csum; + struct udevice *dev; + + /* initially the checksum should be correct */ + ut_assertok(run_command("cbcmos check", 0)); + ut_assert_console_end(); + + /* make a change to the checksum */ + ut_assertok(uclass_first_device_err(UCLASS_RTC, &dev)); + ut_assertok(rtc_read16(dev, CSUM_LOC, &old_csum)); + ut_assertok(rtc_write16(dev, CSUM_LOC, old_csum + 1)); + + /* now the command should fail */ + ut_asserteq(1, run_command("cbcmos check", 0)); + ut_assert_nextline("Checksum %04x error: calculated %04x", + old_csum + 1, old_csum); + ut_assert_console_end(); + + /* now get it to fix the checksum */ + ut_assertok(run_command("cbcmos update", 0)); + ut_assert_nextline("Checksum %04x written", old_csum); + ut_assert_console_end(); + + /* check the RTC looks right */ + ut_assertok(rtc_read16(dev, CSUM_LOC, &new_csum)); + ut_asserteq(old_csum, new_csum); + ut_assert_console_end(); + + return 0; +} +CMD_TEST(test_cmd_cbcmos, UTF_CONSOLE); + +/* test 'cedit cb_load' command */ +static int test_cmd_cedit_cb_load(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct video_priv *vid_priv; + struct scene_obj_txt *txt; + struct scene *scn; + struct expo *exp; + int scn_id; + + ut_assertok(run_command("cedit cb_load", 0)); + ut_assertok(run_command("cedit read_cmos", 0)); + ut_assert_console_end(); + + exp = cur_exp; + scn_id = cedit_prepare(exp, &vid_priv, &scn); + ut_assert(scn_id > 0); + ut_assertnonnull(scn); + + /* just do a very basic test that the first menu is present */ + menu = scene_obj_find(scn, scn->highlight_id, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + txt = scene_obj_find(scn, menu->title_id, SCENEOBJT_NONE); + ut_assertnonnull(txt); + ut_asserteq_str("Boot option", expo_get_str(exp, txt->str_id)); + + return 0; +} +CMD_TEST(test_cmd_cedit_cb_load, UTF_CONSOLE); diff --git a/test/cmd/hash.c b/test/cmd/hash.c new file mode 100644 index 00000000000..2fcec9cadcd --- /dev/null +++ b/test/cmd/hash.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Tests for hash command + * + * Copyright 2024, Heinrich Schuchardt <heinrich.schuchardt@canoncal.com> + */ + +#include <command.h> +#include <dm.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +static int dm_test_cmd_hash_md5(struct unit_test_state *uts) +{ + if (!CONFIG_IS_ENABLED(MD5)) { + ut_assert(run_command("hash md5 $loadaddr 0", 0)); + + return 0; + } + + ut_assertok(run_command("hash md5 $loadaddr 0", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_asserteq_ptr(uts->actual_str, + strstr(uts->actual_str, "md5 for ")); + ut_assert(strstr(uts->actual_str, + "d41d8cd98f00b204e9800998ecf8427e")); + ut_assert_console_end(); + + ut_assertok(run_command("hash md5 $loadaddr 0 foo; echo $foo", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_asserteq_ptr(uts->actual_str, + strstr(uts->actual_str, "md5 for ")); + ut_assert(strstr(uts->actual_str, + "d41d8cd98f00b204e9800998ecf8427e")); + ut_check_console_line(uts, "d41d8cd98f00b204e9800998ecf8427e"); + + if (!CONFIG_IS_ENABLED(HASH_VERIFY)) { + ut_assert(run_command("hash -v sha256 $loadaddr 0 foo", 0)); + ut_check_console_line(uts, "hash - compute hash message digest"); + + return 0; + } + + ut_assertok(run_command("hash -v md5 $loadaddr 0 foo", 0)); + ut_assert_console_end(); + + env_set("foo", "ffffffffffffffffffffffffffffffff"); + ut_assert(run_command("hash -v md5 $loadaddr 0 foo", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_assert(strstr(uts->actual_str, "!=")); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cmd_hash_md5, UTF_CONSOLE); + +static int dm_test_cmd_hash_sha256(struct unit_test_state *uts) +{ + if (!CONFIG_IS_ENABLED(SHA256)) { + ut_assert(run_command("hash sha256 $loadaddr 0", 0)); + + return 0; + } + + ut_assertok(run_command("hash sha256 $loadaddr 0", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_asserteq_ptr(uts->actual_str, + strstr(uts->actual_str, "sha256 for ")); + ut_assert(strstr(uts->actual_str, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); + ut_assert_console_end(); + + ut_assertok(run_command("hash sha256 $loadaddr 0 foo; echo $foo", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_asserteq_ptr(uts->actual_str, + strstr(uts->actual_str, "sha256 for ")); + ut_assert(strstr(uts->actual_str, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")); + ut_check_console_line(uts, + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + + if (!CONFIG_IS_ENABLED(HASH_VERIFY)) { + ut_assert(run_command("hash -v sha256 $loadaddr 0 foo", 0)); + ut_check_console_line(uts, "hash - compute hash message digest"); + + return 0; + } + + ut_assertok(run_command("hash -v sha256 $loadaddr 0 foo", 0)); + ut_assert_console_end(); + + env_set("foo", "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + ut_assert(run_command("hash -v sha256 $loadaddr 0 foo", 0)); + console_record_readline(uts->actual_str, sizeof(uts->actual_str)); + ut_assert(strstr(uts->actual_str, "!=")); + ut_assert_console_end(); + + return 0; +} +DM_TEST(dm_test_cmd_hash_sha256, UTF_CONSOLE); diff --git a/test/cmd_ut.c b/test/cmd_ut.c index 53fddebd49d..195b7ea50ac 100644 --- a/test/cmd_ut.c +++ b/test/cmd_ut.c @@ -99,25 +99,15 @@ static struct cmd_tbl cmd_ut_sub[] = { U_BOOT_CMD_MKENT(setexpr, CONFIG_SYS_MAXARGS, 1, do_ut_setexpr, "", ""), #endif - U_BOOT_CMD_MKENT(print, CONFIG_SYS_MAXARGS, 1, do_ut_print, "", ""), -#ifdef CONFIG_UT_TIME - U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""), -#endif -#if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD) - U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""), -#endif #ifdef CONFIG_MEASURED_BOOT U_BOOT_CMD_MKENT(measurement, CONFIG_SYS_MAXARGS, 1, do_ut_measurement, "", ""), #endif #ifdef CONFIG_SANDBOX - U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression, - "", ""), U_BOOT_CMD_MKENT(bloblist, CONFIG_SYS_MAXARGS, 1, do_ut_bloblist, "", ""), U_BOOT_CMD_MKENT(bootm, CONFIG_SYS_MAXARGS, 1, do_ut_bootm, "", ""), #endif - U_BOOT_CMD_MKENT(str, CONFIG_SYS_MAXARGS, 1, do_ut_str, "", ""), #ifdef CONFIG_CMD_ADDRMAP U_BOOT_CMD_MKENT(addrmap, CONFIG_SYS_MAXARGS, 1, do_ut_addrmap, "", ""), #endif @@ -207,9 +197,7 @@ U_BOOT_LONGHELP(ut, #ifdef CONFIG_CMDLINE "\ncmd - test various commands" #endif -#ifdef CONFIG_SANDBOX - "\ncompression - compressors and bootm decompression" -#endif + "\ncommon - tests for common/ directory" #ifdef CONFIG_UT_DM "\ndm - driver model" #endif @@ -244,21 +232,10 @@ U_BOOT_LONGHELP(ut, #ifdef CONFIG_CMD_PCI_MPS "\npci_mps - PCI Express Maximum Payload Size" #endif - "\nprint - printing things to the console" "\nsetexpr - setexpr command" -#ifdef CONFIG_SANDBOX - "\nstr - basic test of string functions" -#endif #ifdef CONFIG_CMD_SEAMA "\nseama - seama command parameters loading and decoding" #endif -#ifdef CONFIG_UT_TIME - "\ntime - very basic test of time functions" -#endif -#if defined(CONFIG_UT_UNICODE) && \ - !defined(CONFIG_XPL_BUILD) && !defined(API_BUILD) - "\nunicode - Unicode functions" -#endif ); U_BOOT_CMD( diff --git a/test/command_ut.c b/test/command_ut.c deleted file mode 100644 index 2b8d28d7ae3..00000000000 --- a/test/command_ut.c +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2012, The Chromium Authors - */ - -#define DEBUG - -#include <command.h> -#include <env.h> -#include <log.h> -#include <string.h> -#include <linux/errno.h> - -static const char test_cmd[] = "setenv list 1\n setenv list ${list}2; " - "setenv list ${list}3\0" - "setenv list ${list}4"; - -static int do_ut_cmd(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - char long_str[CONFIG_SYS_CBSIZE + 42]; - - printf("%s: Testing commands\n", __func__); - run_command("env default -f -a", 0); - - /* commands separated by \n */ - run_command_list("setenv list 1\n setenv list ${list}1", -1, 0); - assert(!strcmp("11", env_get("list"))); - - /* command followed by \n and nothing else */ - run_command_list("setenv list 1${list}\n", -1, 0); - assert(!strcmp("111", env_get("list"))); - - /* a command string with \0 in it. Stuff after \0 should be ignored */ - run_command("setenv list", 0); - run_command_list(test_cmd, sizeof(test_cmd), 0); - assert(!strcmp("123", env_get("list"))); - - /* - * a command list where we limit execution to only the first command - * using the length parameter. - */ - run_command_list("setenv list 1\n setenv list ${list}2; " - "setenv list ${list}3", strlen("setenv list 1"), 0); - assert(!strcmp("1", env_get("list"))); - - assert(run_command("false", 0) == 1); - assert(run_command("echo", 0) == 0); - assert(run_command_list("false", -1, 0) == 1); - assert(run_command_list("echo", -1, 0) == 0); - -#ifdef CONFIG_HUSH_PARSER - run_command("setenv foo 'setenv black 1\nsetenv adder 2'", 0); - run_command("run foo", 0); - assert(env_get("black") != NULL); - assert(!strcmp("1", env_get("black"))); - assert(env_get("adder") != NULL); - assert(!strcmp("2", env_get("adder"))); -#endif - - assert(run_command("", 0) == 0); - assert(run_command(" ", 0) == 0); - - assert(run_command("'", 0) == 1); - - /* Variadic function test-cases */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-zero-length" - assert(run_commandf("") == 0); -#pragma GCC diagnostic pop - assert(run_commandf(" ") == 0); - assert(run_commandf("'") == 1); - - assert(run_commandf("env %s %s", "delete -f", "list") == 0); - /* Expected: "Error: "list" not defined" */ - assert(run_commandf("printenv list") == 1); - - memset(long_str, 'x', sizeof(long_str)); - assert(run_commandf("Truncation case: %s", long_str) == -ENOSPC); - - if (IS_ENABLED(CONFIG_HUSH_PARSER)) { - assert(run_commandf("env %s %s %s %s", "delete -f", "adder", - "black", "foo") == 0); - assert(run_commandf("setenv foo 'setenv %s 1\nsetenv %s 2'", - "black", "adder") == 0); - run_command("run foo", 0); - assert(env_get("black")); - assert(!strcmp("1", env_get("black"))); - assert(env_get("adder")); - assert(!strcmp("2", env_get("adder"))); - } - - /* Clean up before exit */ - run_command("env default -f -a", 0); - - printf("%s: Everything went swimmingly\n", __func__); - return 0; -} - -U_BOOT_CMD( - ut_cmd, 5, 1, do_ut_cmd, - "Very basic test of command parsers", - "" -); diff --git a/test/common.sh b/test/common.sh deleted file mode 100644 index 904d579b7bf..00000000000 --- a/test/common.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/sh - -OUTPUT_DIR=sandbox - -fail() { - echo "Test failed: $1" - if [ -n ${tmp} ]; then - rm ${tmp} - fi - exit 1 -} - -build_uboot() { - echo "Build sandbox" - OPTS="O=${OUTPUT_DIR} $1" - NUM_CPUS=$(nproc) - echo ${OPTS} - make ${OPTS} sandbox_config - make ${OPTS} -s -j${NUM_CPUS} -} diff --git a/test/common/Makefile b/test/common/Makefile index 12c65f8c951..53c4f16164d 100644 --- a/test/common/Makefile +++ b/test/common/Makefile @@ -1,6 +1,10 @@ # SPDX-License-Identifier: GPL-2.0+ obj-y += cmd_ut_common.o obj-$(CONFIG_AUTOBOOT) += test_autoboot.o +ifneq ($(CONFIG_$(XPL_)BLOBLIST),) +obj-$(CONFIG_$(XPL_)CMDLINE) += bloblist.o +endif obj-$(CONFIG_CYCLIC) += cyclic.o obj-$(CONFIG_EVENT_DYNAMIC) += event.o obj-y += cread.o +obj-$(CONFIG_$(XPL_)CMDLINE) += print.o diff --git a/test/bloblist.c b/test/common/bloblist.c index fd85c7ab79e..4bca62110a5 100644 --- a/test/bloblist.c +++ b/test/common/bloblist.c @@ -6,13 +6,10 @@ #include <bloblist.h> #include <log.h> #include <mapmem.h> -#include <asm/global_data.h> #include <test/suites.h> #include <test/test.h> #include <test/ut.h> -DECLARE_GLOBAL_DATA_PTR; - /* Declare a new bloblist test */ #define BLOBLIST_TEST(_name, _flags) \ UNIT_TEST(_name, _flags, bloblist_test) @@ -94,7 +91,7 @@ static int bloblist_test_init(struct unit_test_state *uts) return 1; } -BLOBLIST_TEST(bloblist_test_init, 0); +BLOBLIST_TEST(bloblist_test_init, UFT_BLOBLIST); static int bloblist_test_blob(struct unit_test_state *uts) { @@ -134,7 +131,7 @@ static int bloblist_test_blob(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_blob, 0); +BLOBLIST_TEST(bloblist_test_blob, UFT_BLOBLIST); /* Check bloblist_ensure_size_ret() */ static int bloblist_test_blob_ensure(struct unit_test_state *uts) @@ -168,7 +165,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_blob_ensure, 0); +BLOBLIST_TEST(bloblist_test_blob_ensure, UFT_BLOBLIST); static int bloblist_test_bad_blob(struct unit_test_state *uts) { @@ -184,7 +181,7 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_bad_blob, 0); +BLOBLIST_TEST(bloblist_test_bad_blob, UFT_BLOBLIST); static int bloblist_test_checksum(struct unit_test_state *uts) { @@ -257,7 +254,7 @@ static int bloblist_test_checksum(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_checksum, 0); +BLOBLIST_TEST(bloblist_test_checksum, UFT_BLOBLIST); /* Test the 'bloblist info' command */ static int bloblist_test_cmd_info(struct unit_test_state *uts) @@ -278,7 +275,7 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_cmd_info, UTF_CONSOLE); +BLOBLIST_TEST(bloblist_test_cmd_info, UFT_BLOBLIST | UTF_CONSOLE); /* Test the 'bloblist list' command */ static int bloblist_test_cmd_list(struct unit_test_state *uts) @@ -300,7 +297,7 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_cmd_list, UTF_CONSOLE); +BLOBLIST_TEST(bloblist_test_cmd_list, UFT_BLOBLIST | UTF_CONSOLE); /* Test alignment of bloblist blobs */ static int bloblist_test_align(struct unit_test_state *uts) @@ -358,7 +355,7 @@ static int bloblist_test_align(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_align, 0); +BLOBLIST_TEST(bloblist_test_align, UFT_BLOBLIST); /* Test relocation of a bloblist */ static int bloblist_test_reloc(struct unit_test_state *uts) @@ -392,7 +389,7 @@ static int bloblist_test_reloc(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_reloc, 0); +BLOBLIST_TEST(bloblist_test_reloc, UFT_BLOBLIST); /* Test expansion of a blob */ static int bloblist_test_grow(struct unit_test_state *uts) @@ -445,7 +442,7 @@ static int bloblist_test_grow(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_grow, 0); +BLOBLIST_TEST(bloblist_test_grow, UFT_BLOBLIST); /* Test shrinking of a blob */ static int bloblist_test_shrink(struct unit_test_state *uts) @@ -495,7 +492,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_shrink, 0); +BLOBLIST_TEST(bloblist_test_shrink, UFT_BLOBLIST); /* Test failing to adjust a blob size */ static int bloblist_test_resize_fail(struct unit_test_state *uts) @@ -530,7 +527,7 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_resize_fail, 0); +BLOBLIST_TEST(bloblist_test_resize_fail, UFT_BLOBLIST); /* Test expanding the last blob in a bloblist */ static int bloblist_test_resize_last(struct unit_test_state *uts) @@ -581,7 +578,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_resize_last, 0); +BLOBLIST_TEST(bloblist_test_resize_last, UFT_BLOBLIST); /* Check a completely full bloblist */ static int bloblist_test_blob_maxsize(struct unit_test_state *uts) @@ -604,7 +601,7 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts) return 0; } -BLOBLIST_TEST(bloblist_test_blob_maxsize, 0); +BLOBLIST_TEST(bloblist_test_blob_maxsize, UFT_BLOBLIST); int do_ut_bloblist(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/test/print_ut.c b/test/common/print.c index f5e607b21a3..f1eb9072d97 100644 --- a/test/print_ut.c +++ b/test/common/print.c @@ -11,7 +11,7 @@ #include <version_string.h> #include <stdio.h> #include <vsprintf.h> -#include <test/suites.h> +#include <test/common.h> #include <test/test.h> #include <test/ut.h> @@ -20,9 +20,6 @@ #define FAKE_BUILD_TAG "jenkins-u-boot-denx_uboot_dm-master-build-aarch64" \ "and a lot more text to come" -/* Declare a new print test */ -#define PRINT_TEST(_name, _flags) UNIT_TEST(_name, _flags, print_test) - #if CONFIG_IS_ENABLED(LIB_UUID) /* Test printing GUIDs */ static int print_guid(struct unit_test_state *uts) @@ -59,7 +56,7 @@ static int print_guid(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_guid, 0); +COMMON_TEST(print_guid, 0); #endif #if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) @@ -95,7 +92,7 @@ static int print_efi_ut(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_efi_ut, 0); +COMMON_TEST(print_efi_ut, 0); #endif static int print_printf(struct unit_test_state *uts) @@ -163,7 +160,7 @@ static int print_printf(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_printf, 0); +COMMON_TEST(print_printf, 0); static int print_display_buffer(struct unit_test_state *uts) { @@ -238,7 +235,7 @@ static int print_display_buffer(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_display_buffer, UTF_CONSOLE); +COMMON_TEST(print_display_buffer, UTF_CONSOLE); static int print_hexdump_line(struct unit_test_state *uts) { @@ -264,7 +261,7 @@ static int print_hexdump_line(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_hexdump_line, UTF_CONSOLE); +COMMON_TEST(print_hexdump_line, UTF_CONSOLE); static int print_do_hex_dump(struct unit_test_state *uts) { @@ -350,7 +347,7 @@ static int print_do_hex_dump(struct unit_test_state *uts) return 0; } -PRINT_TEST(print_do_hex_dump, UTF_CONSOLE); +COMMON_TEST(print_do_hex_dump, UTF_CONSOLE); static int snprint(struct unit_test_state *uts) { @@ -376,12 +373,4 @@ static int snprint(struct unit_test_state *uts) ut_asserteq(8, ret); return 0; } -PRINT_TEST(snprint, 0); - -int do_ut_print(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - struct unit_test *tests = UNIT_TEST_SUITE_START(print_test); - const int n_ents = UNIT_TEST_SUITE_COUNT(print_test); - - return cmd_ut_category("print", "print_", tests, n_ents, argc, argv); -} +COMMON_TEST(snprint, 0); diff --git a/test/dm/core.c b/test/dm/core.c index e0c5b9e0017..7371d3ff426 100644 --- a/test/dm/core.c +++ b/test/dm/core.c @@ -1351,3 +1351,25 @@ static int dm_test_dev_get_mem(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_dev_get_mem, UTF_SCAN_FDT); + +/* Test uclass_try_first_device() */ +static int dm_test_try_first_device(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Check that it doesn't create a device or uclass */ + ut_assertnull(uclass_find(UCLASS_TEST)); + ut_assertnull(uclass_try_first_device(UCLASS_TEST)); + ut_assertnull(uclass_try_first_device(UCLASS_TEST)); + ut_assertnull(uclass_find(UCLASS_TEST)); + + /* Create a test device */ + ut_assertok(device_bind_by_name(uts->root, false, &driver_info_manual, + &dev)); + dev = uclass_try_first_device(UCLASS_TEST); + ut_assertnonnull(dev); + ut_asserteq(UCLASS_TEST, device_get_uclass_id(dev)); + + return 0; +} +DM_TEST(dm_test_try_first_device, 0); diff --git a/test/lib/Makefile b/test/lib/Makefile index a54387a058e..f516d001747 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -2,6 +2,9 @@ # # (C) Copyright 2018 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + +obj-$(CONFIG_$(XPL_)UT_COMPRESSION) += compression.o + ifeq ($(CONFIG_XPL_BUILD),) obj-y += cmd_ut_lib.o obj-y += abuf.o @@ -11,9 +14,10 @@ obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o obj-y += hexdump.o obj-$(CONFIG_SANDBOX) += kconfig.o obj-y += lmb.o -obj-y += longjmp.o +obj-$(CONFIG_HAVE_SETJMP) += longjmp.o obj-$(CONFIG_CONSOLE_RECORD) += test_print.o obj-$(CONFIG_SSCANF) += sscanf.o +obj-$(CONFIG_$(XPL_)CMDLINE) += str.o obj-y += string.o obj-y += strlcat.o obj-$(CONFIG_ERRNO_STR) += test_errno_str.o @@ -23,6 +27,8 @@ obj-$(CONFIG_AES) += test_aes.o obj-$(CONFIG_GETOPT) += getopt.o obj-$(CONFIG_CRC8) += test_crc8.o obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o +obj-$(CONFIG_UT_TIME) += time.o +obj-$(CONFIG_$(XPL_)UT_UNICODE) += unicode.o obj-$(CONFIG_LIB_UUID) += uuid.o else obj-$(CONFIG_SANDBOX) += kconfig_spl.o diff --git a/test/lib/alist.c b/test/lib/alist.c index d41845c7e6c..0bf24578d2e 100644 --- a/test/lib/alist.c +++ b/test/lib/alist.c @@ -240,3 +240,256 @@ static int lib_test_alist_add(struct unit_test_state *uts) return 0; } LIB_TEST(lib_test_alist_add, 0); + +/* Test alist_next() */ +static int lib_test_alist_next(struct unit_test_state *uts) +{ + const struct my_struct *ptr; + struct my_struct data, *ptr2; + struct alist lst; + ulong start; + + start = ut_check_free(); + + ut_assert(alist_init_struct(&lst, struct my_struct)); + data.val = 123; + data.other_val = 0; + alist_add(&lst, data); + + data.val = 321; + alist_add(&lst, data); + + data.val = 789; + alist_add(&lst, data); + + ptr = alist_get(&lst, 0, struct my_struct); + ut_assertnonnull(ptr); + ut_asserteq(123, ptr->val); + + ptr = alist_next(&lst, ptr); + ut_assertnonnull(ptr); + ut_asserteq(321, ptr->val); + + ptr2 = (struct my_struct *)ptr; + ptr2 = alist_nextw(&lst, ptr2); + ut_assertnonnull(ptr2); + + ptr = alist_next(&lst, ptr); + ut_assertnonnull(ptr); + ut_asserteq(789, ptr->val); + ut_asserteq_ptr(ptr, ptr2); + ptr2->val = 89; + ut_asserteq(89, ptr->val); + + ptr = alist_next(&lst, ptr); + ut_assertnull(ptr); + + alist_uninit(&lst); + + /* Check for memory leaks */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_alist_next, 0); + +/* Test alist_for_each() */ +static int lib_test_alist_for_each(struct unit_test_state *uts) +{ + const struct my_struct *ptr; + struct my_struct data, *ptr2; + struct alist lst; + ulong start; + int sum; + + start = ut_check_free(); + + ut_assert(alist_init_struct(&lst, struct my_struct)); + ut_asserteq_ptr(NULL, alist_end(&lst, struct my_struct)); + + sum = 0; + alist_for_each(ptr, &lst) + sum++; + ut_asserteq(0, sum); + + alist_for_each(ptr, &lst) + sum++; + ut_asserteq(0, sum); + + /* add three items */ + data.val = 1; + data.other_val = 0; + alist_add(&lst, data); + + ptr = lst.data; + ut_asserteq_ptr(ptr + 1, alist_end(&lst, struct my_struct)); + + data.val = 2; + alist_add(&lst, data); + ut_asserteq_ptr(ptr + 2, alist_end(&lst, struct my_struct)); + + data.val = 3; + alist_add(&lst, data); + ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct)); + + /* check alist_chk_ptr() */ + ut_asserteq(true, alist_chk_ptr(&lst, ptr + 2)); + ut_asserteq(false, alist_chk_ptr(&lst, ptr + 3)); + ut_asserteq(false, alist_chk_ptr(&lst, ptr + 4)); + ut_asserteq(true, alist_chk_ptr(&lst, ptr)); + ut_asserteq(false, alist_chk_ptr(&lst, ptr - 1)); + + /* sum all items */ + sum = 0; + alist_for_each(ptr, &lst) + sum += ptr->val; + ut_asserteq(6, sum); + + /* increment all items */ + alist_for_each(ptr2, &lst) + ptr2->val += 1; + + /* sum all items again */ + sum = 0; + alist_for_each(ptr, &lst) + sum += ptr->val; + ut_asserteq(9, sum); + + ptr = lst.data; + ut_asserteq_ptr(ptr + 3, alist_end(&lst, struct my_struct)); + + /* empty the list and try again */ + alist_empty(&lst); + ut_asserteq_ptr(ptr, alist_end(&lst, struct my_struct)); + ut_assertnull(alist_get(&lst, 0, struct my_struct)); + + sum = 0; + alist_for_each(ptr, &lst) + sum += ptr->val; + ut_asserteq(0, sum); + + alist_uninit(&lst); + + /* Check for memory leaks */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_alist_for_each, 0); + +/* Test alist_empty() */ +static int lib_test_alist_empty(struct unit_test_state *uts) +{ + struct my_struct data; + struct alist lst; + ulong start; + + start = ut_check_free(); + + ut_assert(alist_init_struct(&lst, struct my_struct)); + ut_asserteq(0, lst.count); + data.val = 1; + data.other_val = 0; + alist_add(&lst, data); + ut_asserteq(1, lst.count); + ut_asserteq(4, lst.alloc); + + alist_empty(&lst); + ut_asserteq(0, lst.count); + ut_asserteq(4, lst.alloc); + ut_assertnonnull(lst.data); + ut_asserteq(sizeof(data), lst.obj_size); + + alist_uninit(&lst); + + /* Check for memory leaks */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_alist_empty, 0); + +static int lib_test_alist_filter(struct unit_test_state *uts) +{ + struct my_struct *from, *to, *ptr; + struct my_struct data; + struct alist lst; + ulong start; + int count; + + start = ut_check_free(); + + ut_assert(alist_init_struct(&lst, struct my_struct)); + data.val = 1; + data.other_val = 0; + alist_add(&lst, data); + + data.val = 2; + alist_add(&lst, data); + + data.val = 3; + alist_add(&lst, data); + ptr = lst.data; + + /* filter out all values except 2 */ + alist_for_each_filter(from, to, &lst) { + if (from->val != 2) + *to++ = *from; + } + alist_update_end(&lst, to); + + ut_asserteq(2, lst.count); + ut_assertnonnull(lst.data); + + ut_asserteq(1, alist_get(&lst, 0, struct my_struct)->val); + ut_asserteq(3, alist_get(&lst, 1, struct my_struct)->val); + ut_asserteq_ptr(ptr + 3, from); + ut_asserteq_ptr(ptr + 2, to); + + /* filter out nothing */ + alist_for_each_filter(from, to, &lst) { + if (from->val != 2) + *to++ = *from; + } + alist_update_end(&lst, to); + ut_asserteq_ptr(ptr + 2, from); + ut_asserteq_ptr(ptr + 2, to); + + ut_asserteq(2, lst.count); + ut_assertnonnull(lst.data); + + ut_asserteq(1, alist_get(&lst, 0, struct my_struct)->val); + ut_asserteq(3, alist_get(&lst, 1, struct my_struct)->val); + + /* filter out everything */ + alist_for_each_filter(from, to, &lst) { + if (from->val == 2) + *to++ = *from; + } + alist_update_end(&lst, to); + ut_asserteq_ptr(ptr + 2, from); + ut_asserteq_ptr(ptr, to); + + /* filter out everything (nop) */ + count = 0; + alist_for_each_filter(from, to, &lst) { + if (from->val == 2) + *to++ = *from; + count++; + } + alist_update_end(&lst, to); + ut_asserteq_ptr(ptr, from); + ut_asserteq_ptr(ptr, to); + ut_asserteq(0, count); + + ut_asserteq(0, lst.count); + ut_assertnonnull(lst.data); + + alist_uninit(&lst); + + /* Check for memory leaks */ + ut_assertok(ut_check_delta(start)); + + return 0; +} +LIB_TEST(lib_test_alist_filter, 0); diff --git a/test/compression.c b/test/lib/compression.c index 618a1936955..31b6e5b1eb4 100644 --- a/test/compression.c +++ b/test/lib/compression.c @@ -23,8 +23,7 @@ #include <linux/lzo.h> #include <linux/zstd.h> -#include <test/compression.h> -#include <test/suites.h> +#include <test/lib.h> #include <test/ut.h> static const char plain[] = @@ -471,40 +470,40 @@ static int compression_test_gzip(struct unit_test_state *uts) return run_test(uts, "gzip", compress_using_gzip, uncompress_using_gzip); } -COMPRESSION_TEST(compression_test_gzip, 0); +LIB_TEST(compression_test_gzip, 0); static int compression_test_bzip2(struct unit_test_state *uts) { return run_test(uts, "bzip2", compress_using_bzip2, uncompress_using_bzip2); } -COMPRESSION_TEST(compression_test_bzip2, 0); +LIB_TEST(compression_test_bzip2, 0); static int compression_test_lzma(struct unit_test_state *uts) { return run_test(uts, "lzma", compress_using_lzma, uncompress_using_lzma); } -COMPRESSION_TEST(compression_test_lzma, 0); +LIB_TEST(compression_test_lzma, 0); static int compression_test_lzo(struct unit_test_state *uts) { return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo); } -COMPRESSION_TEST(compression_test_lzo, 0); +LIB_TEST(compression_test_lzo, 0); static int compression_test_lz4(struct unit_test_state *uts) { return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4); } -COMPRESSION_TEST(compression_test_lz4, 0); +LIB_TEST(compression_test_lz4, 0); static int compression_test_zstd(struct unit_test_state *uts) { return run_test(uts, "zstd", compress_using_zstd, uncompress_using_zstd); } -COMPRESSION_TEST(compression_test_zstd, 0); +LIB_TEST(compression_test_zstd, 0); static int compress_using_none(struct unit_test_state *uts, void *in, unsigned long in_size, @@ -570,50 +569,40 @@ static int compression_test_bootm_gzip(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip); } -COMPRESSION_TEST(compression_test_bootm_gzip, 0); +LIB_TEST(compression_test_bootm_gzip, 0); static int compression_test_bootm_bzip2(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2); } -COMPRESSION_TEST(compression_test_bootm_bzip2, 0); +LIB_TEST(compression_test_bootm_bzip2, 0); static int compression_test_bootm_lzma(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma); } -COMPRESSION_TEST(compression_test_bootm_lzma, 0); +LIB_TEST(compression_test_bootm_lzma, 0); static int compression_test_bootm_lzo(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo); } -COMPRESSION_TEST(compression_test_bootm_lzo, 0); +LIB_TEST(compression_test_bootm_lzo, 0); static int compression_test_bootm_lz4(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4); } -COMPRESSION_TEST(compression_test_bootm_lz4, 0); +LIB_TEST(compression_test_bootm_lz4, 0); static int compression_test_bootm_zstd(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd); } -COMPRESSION_TEST(compression_test_bootm_zstd, 0); +LIB_TEST(compression_test_bootm_zstd, 0); static int compression_test_bootm_none(struct unit_test_state *uts) { return run_bootm_test(uts, IH_COMP_NONE, compress_using_none); } -COMPRESSION_TEST(compression_test_bootm_none, 0); - -int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) -{ - struct unit_test *tests = UNIT_TEST_SUITE_START(compression_test); - const int n_ents = UNIT_TEST_SUITE_COUNT(compression_test); - - return cmd_ut_category("compression", "compression_test_", - tests, n_ents, argc, argv); -} +LIB_TEST(compression_test_bootm_none, 0); diff --git a/test/str_ut.c b/test/lib/str.c index 96e048975d8..3cc9dfea6aa 100644 --- a/test/str_ut.c +++ b/test/lib/str.c @@ -4,7 +4,7 @@ */ #include <vsprintf.h> -#include <test/suites.h> +#include <test/lib.h> #include <test/test.h> #include <test/ut.h> @@ -19,9 +19,6 @@ static const char str5[] = "0x9876543210the last time I was deloused"; static const char str6[] = "0778octal is seldom used"; static const char str7[] = "707it is a piece of computing history"; -/* Declare a new str test */ -#define STR_TEST(_name, _flags) UNIT_TEST(_name, _flags, str_test) - static int str_upper(struct unit_test_state *uts) { char out[TEST_STR_SIZE]; @@ -58,7 +55,7 @@ static int str_upper(struct unit_test_state *uts) return 0; } -STR_TEST(str_upper, 0); +LIB_TEST(str_upper, 0); static int run_strtoul(struct unit_test_state *uts, const char *str, int base, ulong expect_val, int expect_endp_offset, bool upper) @@ -112,7 +109,7 @@ static int str_simple_strtoul(struct unit_test_state *uts) return 0; } -STR_TEST(str_simple_strtoul, 0); +LIB_TEST(str_simple_strtoul, 0); static int run_strtoull(struct unit_test_state *uts, const char *str, int base, unsigned long long expect_val, int expect_endp_offset, @@ -175,7 +172,7 @@ static int str_simple_strtoull(struct unit_test_state *uts) return 0; } -STR_TEST(str_simple_strtoull, 0); +LIB_TEST(str_simple_strtoull, 0); static int str_hextoul(struct unit_test_state *uts) { @@ -187,7 +184,7 @@ static int str_hextoul(struct unit_test_state *uts) return 0; } -STR_TEST(str_hextoul, 0); +LIB_TEST(str_hextoul, 0); static int str_dectoul(struct unit_test_state *uts) { @@ -199,7 +196,7 @@ static int str_dectoul(struct unit_test_state *uts) return 0; } -STR_TEST(str_dectoul, 0); +LIB_TEST(str_dectoul, 0); static int str_itoa(struct unit_test_state *uts) { @@ -219,7 +216,7 @@ static int str_itoa(struct unit_test_state *uts) return 0; } -STR_TEST(str_itoa, 0); +LIB_TEST(str_itoa, 0); static int str_xtoa(struct unit_test_state *uts) { @@ -239,7 +236,7 @@ static int str_xtoa(struct unit_test_state *uts) return 0; } -STR_TEST(str_xtoa, 0); +LIB_TEST(str_xtoa, 0); static int str_trailing(struct unit_test_state *uts) { @@ -271,7 +268,7 @@ static int str_trailing(struct unit_test_state *uts) return 0; } -STR_TEST(str_trailing, 0); +LIB_TEST(str_trailing, 0); static int test_str_to_list(struct unit_test_state *uts) { @@ -351,12 +348,4 @@ static int test_str_to_list(struct unit_test_state *uts) return 0; } -STR_TEST(test_str_to_list, 0); - -int do_ut_str(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - struct unit_test *tests = UNIT_TEST_SUITE_START(str_test); - const int n_ents = UNIT_TEST_SUITE_COUNT(str_test); - - return cmd_ut_category("str", "str_", tests, n_ents, argc, argv); -} +LIB_TEST(test_str_to_list, 0); diff --git a/test/time_ut.c b/test/lib/time.c index 149c4b58f4a..b99e738c500 100644 --- a/test/time_ut.c +++ b/test/lib/time.c @@ -4,12 +4,13 @@ * Written by Simon Glass <sjg@chromium.org> */ -#include <command.h> #include <errno.h> #include <time.h> #include <linux/delay.h> +#include <test/lib.h> +#include <test/ut.h> -static int test_get_timer(void) +static int test_get_timer(struct unit_test_state *uts) { ulong base, start, next, diff; int iter; @@ -21,11 +22,7 @@ static int test_get_timer(void) next = get_timer(0); } while (start == next); - if (start + 1 != next) { - printf("%s: iter=%d, start=%lu, next=%lu, expected a difference of 1\n", - __func__, iter, start, next); - return -EINVAL; - } + ut_asserteq(start + 1, next); start++; } @@ -34,16 +31,13 @@ static int test_get_timer(void) * an extra millisecond may have passed. */ diff = get_timer(base); - if (diff != iter && diff != iter + 1) { - printf("%s: expected get_timer(base) to match elapsed time: diff=%lu, expected=%d\n", - __func__, diff, iter); - return -EINVAL; - } + ut_assert(diff == iter || diff == iter + 1); return 0; } +LIB_TEST(test_get_timer, 0); -static int test_timer_get_us(void) +static int test_timer_get_us(struct unit_test_state *uts) { ulong prev, next, min = 1000000; long delta; @@ -55,11 +49,8 @@ static int test_timer_get_us(void) next = timer_get_us(); if (next != prev) { delta = next - prev; - if (delta < 0) { - printf("%s: timer_get_us() went backwards from %lu to %lu\n", - __func__, prev, next); - return -EINVAL; - } else if (delta != 0) { + ut_assert(delta >= 0); + if (delta) { if (delta < min) min = delta; prev = next; @@ -68,16 +59,13 @@ static int test_timer_get_us(void) } } - if (min != 1) { - printf("%s: Minimum microsecond delta should be 1 but is %lu\n", - __func__, min); - return -EINVAL; - } + ut_asserteq(1, min); return 0; } +LIB_TEST(test_timer_get_us, 0); -static int test_time_comparison(void) +static int test_time_comparison(struct unit_test_state *uts) { ulong start_us, end_us, delta_us; long error; @@ -92,13 +80,13 @@ static int test_time_comparison(void) error = delta_us - 1000000; printf("%s: Microsecond time for 1 second: %lu, error = %ld\n", __func__, delta_us, error); - if (abs(error) > 1000) - return -EINVAL; + ut_assert(abs(error) <= 1000); return 0; } +LIB_TEST(test_time_comparison, 0); -static int test_udelay(void) +static int test_udelay(struct unit_test_state *uts) { long error; ulong start, delta; @@ -111,22 +99,8 @@ static int test_udelay(void) error = delta - 1000; printf("%s: Delay time for 1000 udelay(1000): %lu ms, error = %ld\n", __func__, delta, error); - if (abs(error) > 100) - return -EINVAL; + ut_assert(abs(error) <= 100); return 0; } - -int do_ut_time(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - int ret = 0; - - ret |= test_get_timer(); - ret |= test_timer_get_us(); - ret |= test_time_comparison(); - ret |= test_udelay(); - - printf("Test %s\n", ret ? "failed" : "passed"); - - return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS; -} +LIB_TEST(test_udelay, 0); diff --git a/test/unicode_ut.c b/test/lib/unicode.c index 13e29c9b9e3..673470c8d2c 100644 --- a/test/unicode_ut.c +++ b/test/lib/unicode.c @@ -11,13 +11,10 @@ #include <errno.h> #include <log.h> #include <malloc.h> +#include <test/lib.h> #include <test/test.h> -#include <test/suites.h> #include <test/ut.h> -/* Linker list entry for a Unicode test */ -#define UNICODE_TEST(_name) UNIT_TEST(_name, 0, unicode_test) - /* Constants c1-c4 and d1-d4 encode the same letters */ /* Six characters translating to one utf-8 byte each. */ @@ -64,7 +61,7 @@ static int unicode_test_u16_strlen(struct unit_test_state *uts) ut_asserteq(6, u16_strlen(c4)); return 0; } -UNICODE_TEST(unicode_test_u16_strlen); +LIB_TEST(unicode_test_u16_strlen, 0); static int unicode_test_u16_strnlen(struct unit_test_state *uts) { @@ -75,7 +72,7 @@ static int unicode_test_u16_strnlen(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_u16_strnlen); +LIB_TEST(unicode_test_u16_strnlen, 0); static int unicode_test_u16_strdup(struct unit_test_state *uts) { @@ -87,7 +84,7 @@ static int unicode_test_u16_strdup(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_u16_strdup); +LIB_TEST(unicode_test_u16_strdup, 0); static int unicode_test_u16_strcpy(struct unit_test_state *uts) { @@ -100,7 +97,7 @@ static int unicode_test_u16_strcpy(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_u16_strcpy); +LIB_TEST(unicode_test_u16_strcpy, 0); /* U-Boot uses UTF-16 strings in the EFI context only. */ #if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) @@ -173,7 +170,7 @@ static int unicode_test_string16(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_string16); +LIB_TEST(unicode_test_string16, 0); #endif static int unicode_test_utf8_get(struct unit_test_state *uts) @@ -218,7 +215,7 @@ static int unicode_test_utf8_get(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_get); +LIB_TEST(unicode_test_utf8_get, 0); static int unicode_test_utf8_put(struct unit_test_state *uts) { @@ -256,7 +253,7 @@ static int unicode_test_utf8_put(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_put); +LIB_TEST(unicode_test_utf8_put, 0); static int unicode_test_utf8_utf16_strlen(struct unit_test_state *uts) { @@ -272,7 +269,7 @@ static int unicode_test_utf8_utf16_strlen(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_utf16_strlen); +LIB_TEST(unicode_test_utf8_utf16_strlen, 0); static int unicode_test_utf8_utf16_strnlen(struct unit_test_state *uts) { @@ -290,7 +287,7 @@ static int unicode_test_utf8_utf16_strnlen(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_utf16_strnlen); +LIB_TEST(unicode_test_utf8_utf16_strnlen, 0); /** * ut_u16_strcmp() - Compare to u16 strings. @@ -354,7 +351,7 @@ static int unicode_test_utf8_utf16_strcpy(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_utf16_strcpy); +LIB_TEST(unicode_test_utf8_utf16_strcpy, 0); static int unicode_test_utf8_utf16_strncpy(struct unit_test_state *uts) { @@ -398,7 +395,7 @@ static int unicode_test_utf8_utf16_strncpy(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_utf16_strncpy); +LIB_TEST(unicode_test_utf8_utf16_strncpy, 0); static int unicode_test_utf16_get(struct unit_test_state *uts) { @@ -424,7 +421,7 @@ static int unicode_test_utf16_get(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_get); +LIB_TEST(unicode_test_utf16_get, 0); static int unicode_test_utf16_put(struct unit_test_state *uts) { @@ -452,7 +449,7 @@ static int unicode_test_utf16_put(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_put); +LIB_TEST(unicode_test_utf16_put, 0); static int unicode_test_utf16_strnlen(struct unit_test_state *uts) { @@ -470,7 +467,7 @@ static int unicode_test_utf16_strnlen(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_strnlen); +LIB_TEST(unicode_test_utf16_strnlen, 0); static int unicode_test_utf16_utf8_strlen(struct unit_test_state *uts) { @@ -486,7 +483,7 @@ static int unicode_test_utf16_utf8_strlen(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_utf8_strlen); +LIB_TEST(unicode_test_utf16_utf8_strlen, 0); static int unicode_test_utf16_utf8_strnlen(struct unit_test_state *uts) { @@ -498,7 +495,7 @@ static int unicode_test_utf16_utf8_strnlen(struct unit_test_state *uts) ut_asserteq(12, utf16_utf8_strnlen(c4, 3)); return 0; } -UNICODE_TEST(unicode_test_utf16_utf8_strnlen); +LIB_TEST(unicode_test_utf16_utf8_strnlen, 0); static int unicode_test_utf16_utf8_strcpy(struct unit_test_state *uts) { @@ -543,7 +540,7 @@ static int unicode_test_utf16_utf8_strcpy(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_utf8_strcpy); +LIB_TEST(unicode_test_utf16_utf8_strcpy, 0); static int unicode_test_utf16_utf8_strncpy(struct unit_test_state *uts) { @@ -587,7 +584,7 @@ static int unicode_test_utf16_utf8_strncpy(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf16_utf8_strncpy); +LIB_TEST(unicode_test_utf16_utf8_strncpy, 0); static int unicode_test_utf_to_lower(struct unit_test_state *uts) { @@ -604,7 +601,7 @@ static int unicode_test_utf_to_lower(struct unit_test_state *uts) #endif return 0; } -UNICODE_TEST(unicode_test_utf_to_lower); +LIB_TEST(unicode_test_utf_to_lower, 0); static int unicode_test_utf_to_upper(struct unit_test_state *uts) { @@ -621,7 +618,7 @@ static int unicode_test_utf_to_upper(struct unit_test_state *uts) #endif return 0; } -UNICODE_TEST(unicode_test_utf_to_upper); +LIB_TEST(unicode_test_utf_to_upper, 0); static int unicode_test_u16_strcasecmp(struct unit_test_state *uts) { @@ -646,7 +643,7 @@ static int unicode_test_u16_strcasecmp(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_u16_strcasecmp); +LIB_TEST(unicode_test_u16_strcasecmp, 0); static int unicode_test_u16_strncmp(struct unit_test_state *uts) { @@ -659,7 +656,7 @@ static int unicode_test_u16_strncmp(struct unit_test_state *uts) ut_assert(u16_strcmp(u"deghi", u"abcdef") > 0); return 0; } -UNICODE_TEST(unicode_test_u16_strncmp); +LIB_TEST(unicode_test_u16_strncmp, 0); static int unicode_test_u16_strsize(struct unit_test_state *uts) { @@ -669,7 +666,7 @@ static int unicode_test_u16_strsize(struct unit_test_state *uts) ut_asserteq_64(u16_strsize(c4), 14); return 0; } -UNICODE_TEST(unicode_test_u16_strsize); +LIB_TEST(unicode_test_u16_strsize, 0); static int unicode_test_utf_to_cp(struct unit_test_state *uts) { @@ -698,7 +695,7 @@ static int unicode_test_utf_to_cp(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf_to_cp); +LIB_TEST(unicode_test_utf_to_cp, 0); static void utf8_to_cp437_stream_helper(const char *in, char *out) { @@ -729,7 +726,7 @@ static int unicode_test_utf8_to_cp437_stream(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_to_cp437_stream); +LIB_TEST(unicode_test_utf8_to_cp437_stream, 0); static void utf8_to_utf32_stream_helper(const char *in, s32 *out) { @@ -778,7 +775,7 @@ static int unicode_test_utf8_to_utf32_stream(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_utf8_to_utf32_stream); +LIB_TEST(unicode_test_utf8_to_utf32_stream, 0); #ifdef CONFIG_EFI_LOADER static int unicode_test_efi_create_indexed_name(struct unit_test_state *uts) @@ -795,7 +792,7 @@ static int unicode_test_efi_create_indexed_name(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_efi_create_indexed_name); +LIB_TEST(unicode_test_efi_create_indexed_name, 0); #endif static int unicode_test_u16_strlcat(struct unit_test_state *uts) @@ -846,13 +843,4 @@ static int unicode_test_u16_strlcat(struct unit_test_state *uts) return 0; } -UNICODE_TEST(unicode_test_u16_strlcat); - -int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) -{ - struct unit_test *tests = UNIT_TEST_SUITE_START(unicode_test); - const int n_ents = UNIT_TEST_SUITE_COUNT(unicode_test); - - return cmd_ut_category("Unicode", "unicode_test_", - tests, n_ents, argc, argv); -} +LIB_TEST(unicode_test_u16_strlcat, 0); diff --git a/test/py/conftest.py b/test/py/conftest.py index 46a410cf268..d9f074f3817 100644 --- a/test/py/conftest.py +++ b/test/py/conftest.py @@ -23,6 +23,7 @@ from pathlib import Path import pytest import re from _pytest.runner import runtestprotocol +import subprocess import sys from u_boot_spawn import BootFail, Timeout, Unexpected, handle_exception @@ -65,12 +66,16 @@ def pytest_addoption(parser): parser.addoption('--build-dir', default=None, help='U-Boot build directory (O=)') + parser.addoption('--build-dir-extra', default=None, + help='U-Boot build directory for extra build (O=)') parser.addoption('--result-dir', default=None, help='U-Boot test result/tmp directory') parser.addoption('--persistent-data-dir', default=None, help='U-Boot test persistent generated data directory') parser.addoption('--board-type', '--bd', '-B', default='sandbox', help='U-Boot board type') + parser.addoption('--board-type-extra', '--bde', default='sandbox', + help='U-Boot extra board type') parser.addoption('--board-identity', '--id', default='na', help='U-Boot board identity/instance') parser.addoption('--build', default=False, action='store_true', @@ -80,6 +85,9 @@ def pytest_addoption(parser): parser.addoption('--gdbserver', default=None, help='Run sandbox under gdbserver. The argument is the channel '+ 'over which gdbserver should communicate, e.g. localhost:1234') + parser.addoption('--role', help='U-Boot board role (for Labgrid-sjg)') + parser.addoption('--use-running-system', default=False, action='store_true', + help="Assume that U-Boot is ready and don't wait for a prompt") def run_build(config, source_dir, build_dir, board_type, log): """run_build: Build U-Boot @@ -125,26 +133,71 @@ def get_details(config): Returns: tuple: str: Board type (U-Boot build name) + str: Extra board type (where two U-Boot builds are needed) str: Identity for the lab board str: Build directory + str: Extra build directory (where two U-Boot builds are needed) str: Source directory """ - board_type = config.getoption('board_type') - board_identity = config.getoption('board_identity') + role = config.getoption('role') + + # Get a few provided parameters build_dir = config.getoption('build_dir') + build_dir_extra = config.getoption('build_dir_extra') + if role: + # When using a role, build_dir and build_dir_extra are normally not set, + # since they are picked up from Labgrid-sjg via the u-boot-test-getrole + # script + board_identity = role + cmd = ['u-boot-test-getrole', role, '--configure'] + env = os.environ.copy() + if build_dir: + env['U_BOOT_BUILD_DIR'] = build_dir + if build_dir_extra: + env['U_BOOT_BUILD_DIR_EXTRA'] = build_dir_extra + proc = subprocess.run(cmd, capture_output=True, encoding='utf-8', + env=env) + if proc.returncode: + raise ValueError(proc.stderr) + # For debugging + # print('conftest: lab:', proc.stdout) + vals = {} + for line in proc.stdout.splitlines(): + item, value = line.split(' ', maxsplit=1) + k = item.split(':')[-1] + vals[k] = value + # For debugging + # print('conftest: lab info:', vals) + + # Read the build directories here, in case none were provided in the + # command-line arguments + (board_type, board_type_extra, default_build_dir, + default_build_dir_extra, source_dir) = (vals['board'], + vals['board_extra'], vals['build_dir'], vals['build_dir_extra'], + vals['source_dir']) + else: + board_type = config.getoption('board_type') + board_type_extra = config.getoption('board_type_extra') + board_identity = config.getoption('board_identity') + + source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR)) + default_build_dir = source_dir + '/build-' + board_type + default_build_dir_extra = source_dir + '/build-' + board_type_extra - source_dir = os.path.dirname(os.path.dirname(TEST_PY_DIR)) - default_build_dir = source_dir + '/build-' + board_type + # Use the provided command-line arguments if present, else fall back to if not build_dir: build_dir = default_build_dir + if not build_dir_extra: + build_dir_extra = default_build_dir_extra - return board_type, board_identity, build_dir, source_dir + return (board_type, board_type_extra, board_identity, build_dir, + build_dir_extra, source_dir) def pytest_xdist_setupnodes(config, specs): """Clear out any 'done' file from a previous build""" global build_done_file - build_dir = get_details(config)[2] + build_dir = get_details(config)[3] build_done_file = Path(build_dir) / 'build.done' if build_done_file.exists(): @@ -184,7 +237,8 @@ def pytest_configure(config): global console global ubconfig - board_type, board_identity, build_dir, source_dir = get_details(config) + (board_type, board_type_extra, board_identity, build_dir, build_dir_extra, + source_dir) = get_details(config) board_type_filename = board_type.replace('-', '_') board_identity_filename = board_identity.replace('-', '_') @@ -249,20 +303,25 @@ def pytest_configure(config): ubconfig.test_py_dir = TEST_PY_DIR ubconfig.source_dir = source_dir ubconfig.build_dir = build_dir + ubconfig.build_dir_extra = build_dir_extra ubconfig.result_dir = result_dir ubconfig.persistent_data_dir = persistent_data_dir ubconfig.board_type = board_type + ubconfig.board_type_extra = board_type_extra ubconfig.board_identity = board_identity ubconfig.gdbserver = gdbserver + ubconfig.use_running_system = config.getoption('use_running_system') ubconfig.dtb = build_dir + '/arch/sandbox/dts/test.dtb' ubconfig.connection_ok = True env_vars = ( 'board_type', + 'board_type_extra', 'board_identity', 'source_dir', 'test_py_dir', 'build_dir', + 'build_dir_extra', 'result_dir', 'persistent_data_dir', ) diff --git a/test/py/tests/bootstd/flash1.img.xz b/test/py/tests/bootstd/flash1.img.xz Binary files differnew file mode 100644 index 00000000000..29b78c62a9b --- /dev/null +++ b/test/py/tests/bootstd/flash1.img.xz diff --git a/test/py/tests/test_spi.py b/test/py/tests/test_spi.py index caca9303271..44e54738dd0 100644 --- a/test/py/tests/test_spi.py +++ b/test/py/tests/test_spi.py @@ -695,7 +695,7 @@ def test_spi_negative(u_boot_console): # Read to relocation address output = u_boot_console.run_command('bdinfo') - m = re.search('relocaddr\s*= (.+)', output) + m = re.search(r'relocaddr\s*= (.+)', output) res_area = int(m.group(1), 16) start = 0 diff --git a/test/py/tests/test_usb.py b/test/py/tests/test_usb.py index fb3d20f0826..2397fd3c2e7 100644 --- a/test/py/tests/test_usb.py +++ b/test/py/tests/test_usb.py @@ -288,6 +288,47 @@ def test_usb_fatls_fatinfo(u_boot_console): if not part_detect: pytest.skip('No %s partition detected' % fs.upper()) +def usb_fatload_fatwrite(u_boot_console, fs, x, part): + addr = u_boot_utils.find_ram_base(u_boot_console) + size = random.randint(4, 1 * 1024 * 1024) + output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) + m = re.search('==> (.+?)', output) + if not m: + pytest.fail('CRC32 failed') + expected_crc32 = m.group(1) + + file = '%s_%d' % ('uboot_test', size) + output = u_boot_console.run_command( + '%swrite usb %d:%s %x %s %x' % (fs, x, part, addr, file, size) + ) + assert 'Unable to write' not in output + assert 'Error' not in output + assert 'overflow' not in output + expected_text = '%d bytes written' % size + assert expected_text in output + + alignment = int( + u_boot_console.config.buildconfig.get( + 'config_sys_cacheline_size', 128 + ) + ) + offset = random.randrange(alignment, 1024, alignment) + output = u_boot_console.run_command( + '%sload usb %d:%s %x %s' % (fs, x, part, addr + offset, file) + ) + assert 'Invalid FAT entry' not in output + assert 'Unable to read file' not in output + assert 'Misaligned buffer address' not in output + expected_text = '%d bytes read' % size + assert expected_text in output + + output = u_boot_console.run_command( + 'crc32 %x $filesize' % (addr + offset) + ) + assert expected_crc32 in output + + return file, size, expected_crc32 + @pytest.mark.buildconfigspec('cmd_usb') @pytest.mark.buildconfigspec('cmd_fat') @pytest.mark.buildconfigspec('cmd_memory') @@ -309,49 +350,11 @@ def test_usb_fatload_fatwrite(u_boot_console): for part in partitions: part_detect = 1 - addr = u_boot_utils.find_ram_base(u_boot_console) - size = random.randint(4, 1 * 1024 * 1024) - output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) - m = re.search('==> (.+?)', output) - if not m: - pytest.fail('CRC32 failed') - expected_crc32 = m.group(1) - - file = '%s_%d' % ('uboot_test', size) - output = u_boot_console.run_command( - '%swrite usb %d:%s %x %s %x' % (fs, x, part, addr, file, size) - ) - assert 'Unable to write' not in output - assert 'Error' not in output - assert 'overflow' not in output - expected_text = '%d bytes written' % size - assert expected_text in output - - alignment = int( - u_boot_console.config.buildconfig.get( - 'config_sys_cacheline_size', 128 - ) - ) - offset = random.randrange(alignment, 1024, alignment) - output = u_boot_console.run_command( - '%sload usb %d:%s %x %s' % (fs, x, part, addr + offset, file) - ) - assert 'Invalid FAT entry' not in output - assert 'Unable to read file' not in output - assert 'Misaligned buffer address' not in output - expected_text = '%d bytes read' % size - assert expected_text in output - - output = u_boot_console.run_command( - 'crc32 %x $filesize' % (addr + offset) - ) - assert expected_crc32 in output + usb_fatload_fatwrite(u_boot_console, fs, x, part) if not part_detect: pytest.skip('No %s partition detected' % fs.upper()) - return file, size - @pytest.mark.buildconfigspec('cmd_usb') @pytest.mark.buildconfigspec('cmd_ext4') def test_usb_ext4ls(u_boot_console): @@ -380,9 +383,42 @@ def test_usb_ext4ls(u_boot_console): if not part_detect: pytest.skip('No %s partition detected' % fs.upper()) +def usb_ext4load_ext4write(u_boot_console, fs, x, part): + addr = u_boot_utils.find_ram_base(u_boot_console) + size = random.randint(4, 1 * 1024 * 1024) + output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) + m = re.search('==> (.+?)', output) + if not m: + pytest.fail('CRC32 failed') + expected_crc32 = m.group(1) + file = '%s_%d' % ('uboot_test', size) + + output = u_boot_console.run_command( + '%swrite usb %d:%s %x /%s %x' % (fs, x, part, addr, file, size) + ) + assert 'Unable to write' not in output + assert 'Error' not in output + assert 'overflow' not in output + expected_text = '%d bytes written' % size + assert expected_text in output + + offset = random.randrange(128, 1024, 128) + output = u_boot_console.run_command( + '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file) + ) + expected_text = '%d bytes read' % size + assert expected_text in output + + output = u_boot_console.run_command( + 'crc32 %x $filesize' % (addr + offset) + ) + assert expected_crc32 in output + + return file, size, expected_crc32 + @pytest.mark.buildconfigspec('cmd_usb') @pytest.mark.buildconfigspec('cmd_ext4') -@pytest.mark.buildconfigspec('ext4_write') +@pytest.mark.buildconfigspec('cmd_ext4_write') @pytest.mark.buildconfigspec('cmd_memory') def test_usb_ext4load_ext4write(u_boot_console): devices, controllers, storage_device = test_usb_part(u_boot_console) @@ -402,41 +438,11 @@ def test_usb_ext4load_ext4write(u_boot_console): for part in partitions: part_detect = 1 - addr = u_boot_utils.find_ram_base(u_boot_console) - size = random.randint(4, 1 * 1024 * 1024) - output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) - m = re.search('==> (.+?)', output) - if not m: - pytest.fail('CRC32 failed') - expected_crc32 = m.group(1) - file = '%s_%d' % ('uboot_test', size) - - output = u_boot_console.run_command( - '%swrite usb %d:%s %x /%s %x' % (fs, x, part, addr, file, size) - ) - assert 'Unable to write' not in output - assert 'Error' not in output - assert 'overflow' not in output - expected_text = '%d bytes written' % size - assert expected_text in output - - offset = random.randrange(128, 1024, 128) - output = u_boot_console.run_command( - '%sload usb %d:%s %x /%s' % (fs, x, part, addr + offset, file) - ) - expected_text = '%d bytes read' % size - assert expected_text in output - - output = u_boot_console.run_command( - 'crc32 %x $filesize' % (addr + offset) - ) - assert expected_crc32 in output + usb_ext4load_ext4write(u_boot_console, fs, x, part) if not part_detect: pytest.skip('No %s partition detected' % fs.upper()) - return file, size - @pytest.mark.buildconfigspec('cmd_usb') @pytest.mark.buildconfigspec('cmd_ext2') def test_usb_ext2ls(u_boot_console): @@ -469,11 +475,10 @@ def test_usb_ext2ls(u_boot_console): @pytest.mark.buildconfigspec('cmd_usb') @pytest.mark.buildconfigspec('cmd_ext2') @pytest.mark.buildconfigspec('cmd_ext4') -@pytest.mark.buildconfigspec('ext4_write') +@pytest.mark.buildconfigspec('cmd_ext4_write') @pytest.mark.buildconfigspec('cmd_memory') def test_usb_ext2load(u_boot_console): devices, controllers, storage_device = test_usb_part(u_boot_console) - file, size = test_usb_ext4load_ext4write(u_boot_console) if not devices: pytest.skip('No devices detected') @@ -491,12 +496,9 @@ def test_usb_ext2load(u_boot_console): for part in partitions: part_detect = 1 + file, size, expected_crc32 = \ + usb_ext4load_ext4write(u_boot_console, 'ext4', x, part) addr = u_boot_utils.find_ram_base(u_boot_console) - output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) - m = re.search('==> (.+?)', output) - if not m: - pytest.fail('CRC32 failed') - expected_crc32 = m.group(1) offset = random.randrange(128, 1024, 128) output = u_boot_console.run_command( @@ -543,6 +545,7 @@ def test_usb_ls(u_boot_console): pytest.skip('No partition detected') @pytest.mark.buildconfigspec('cmd_usb') +@pytest.mark.buildconfigspec('cmd_ext4_write') @pytest.mark.buildconfigspec('cmd_fs_generic') def test_usb_load(u_boot_console): devices, controllers, storage_device = test_usb_part(u_boot_console) @@ -565,15 +568,11 @@ def test_usb_load(u_boot_console): addr = u_boot_utils.find_ram_base(u_boot_console) if fs == 'fat': - file, size = test_usb_fatload_fatwrite(u_boot_console) + file, size, expected_crc32 = \ + usb_fatload_fatwrite(u_boot_console, fs, x, part) elif fs == 'ext4': - file, size = test_usb_ext4load_ext4write(u_boot_console) - - output = u_boot_console.run_command('crc32 %x %x' % (addr, size)) - m = re.search('==> (.+?)', output) - if not m: - pytest.fail('CRC32 failed') - expected_crc32 = m.group(1) + file, size, expected_crc32 = \ + usb_ext4load_ext4write(u_boot_console, fs, x, part) offset = random.randrange(128, 1024, 128) output = u_boot_console.run_command( diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 39aa1035e34..6d44191976b 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -28,21 +28,22 @@ def mkdir_cond(dirname): if not os.path.exists(dirname): os.mkdir(dirname) -def setup_image(cons, mmc_dev, part_type, second_part=False): +def setup_image(cons, devnum, part_type, second_part=False, basename='mmc'): """Create a 20MB disk image with a single partition Args: cons (ConsoleBase): Console to use - mmc_dev (int): MMC device number to use, e.g. 1 + devnum (int): Device number to use, e.g. 1 part_type (int): Partition type, e.g. 0xc for FAT32 second_part (bool): True to contain a small second partition + basename (str): Base name to use in the filename, e.g. 'mmc' Returns: tuple: str: Filename of MMC image str: Directory name of 'mnt' directory """ - fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img') + fname = os.path.join(cons.config.source_dir, f'{basename}{devnum}.img') mnt = os.path.join(cons.config.persistent_data_dir, 'mnt') mkdir_cond(mnt) @@ -78,16 +79,17 @@ def mount_image(cons, fname, mnt, fstype): u_boot_utils.run_and_log(cons, f'sudo chown {getpass.getuser()} {mnt}') return loop -def copy_prepared_image(cons, mmc_dev, fname): +def copy_prepared_image(cons, devnum, fname, basename='mmc'): """Use a prepared image since we cannot create one Args: cons (ConsoleBase): Console touse - mmc_dev (int): MMC device number + devnum (int): device number fname (str): Filename of MMC image + basename (str): Base name to use in the filename, e.g. 'mmc' """ infname = os.path.join(cons.config.source_dir, - f'test/py/tests/bootstd/mmc{mmc_dev}.img.xz') + f'test/py/tests/bootstd/{basename}{devnum}.img.xz') u_boot_utils.run_and_log(cons, ['sh', '-c', f'xz -dc {infname} >{fname}']) def setup_bootmenu_image(cons): @@ -208,8 +210,6 @@ booti ${kernel_addr_r} ${ramdisk_addr_r} ${fdt_addr_r} cons, f'echo here {kernel} {symlink}') os.symlink(kernel, symlink) - u_boot_utils.run_and_log( - cons, f'mkimage -C none -A arm -T script -d {cmd_fname} {scr_fname}') complete = True except ValueError as exc: @@ -549,6 +549,44 @@ def test_ut_dm_init(u_boot_console): with open(fn, 'wb') as fh: fh.write(data) + +def setup_efi_image(cons): + """Create a 20MB disk image with an EFI app on it""" + devnum = 1 + basename = 'flash' + fname, mnt = setup_image(cons, devnum, 0xc, second_part=True, + basename=basename) + + loop = None + mounted = False + complete = False + try: + loop = mount_image(cons, fname, mnt, 'ext4') + mounted = True + efi_dir = os.path.join(mnt, 'EFI') + mkdir_cond(efi_dir) + bootdir = os.path.join(efi_dir, 'BOOT') + mkdir_cond(bootdir) + efi_src = os.path.join(cons.config.build_dir, + f'lib/efi_loader/testapp.efi') + efi_dst = os.path.join(bootdir, 'BOOTSBOX.EFI') + with open(efi_src, 'rb') as inf: + with open(efi_dst, 'wb') as outf: + outf.write(inf.read()) + complete = True + except ValueError as exc: + print(f'Falled to create image, failing back to prepared copy: {exc}') + + finally: + if mounted: + u_boot_utils.run_and_log(cons, 'sudo umount --lazy %s' % mnt) + if loop: + u_boot_utils.run_and_log(cons, 'sudo losetup -d %s' % loop) + + if not complete: + copy_prepared_image(cons, devnum, fname, basename) + + @pytest.mark.buildconfigspec('cmd_bootflow') @pytest.mark.buildconfigspec('sandbox') def test_ut_dm_init_bootstd(u_boot_console): @@ -559,6 +597,7 @@ def test_ut_dm_init_bootstd(u_boot_console): setup_cedit_file(u_boot_console) setup_cros_image(u_boot_console) setup_android_image(u_boot_console) + setup_efi_image(u_boot_console) # Restart so that the new mmc1.img is picked up u_boot_console.restart_uboot() diff --git a/test/py/u_boot_console_base.py b/test/py/u_boot_console_base.py index d8d0bdf9fd4..fa9cd57b04b 100644 --- a/test/py/u_boot_console_base.py +++ b/test/py/u_boot_console_base.py @@ -23,12 +23,22 @@ pattern_stop_autoboot_prompt = re.compile('Hit any key to stop autoboot: ') pattern_unknown_command = re.compile('Unknown command \'.*\' - try \'help\'') pattern_error_notification = re.compile('## Error: ') pattern_error_please_reset = re.compile('### ERROR ### Please RESET the board ###') +pattern_ready_prompt = re.compile('{lab ready in (.*)s: (.*)}') +pattern_lab_mode = re.compile('{lab mode.*}') PAT_ID = 0 PAT_RE = 1 # Timeout before expecting the console to be ready (in milliseconds) -TIMEOUT_MS = 30000 +TIMEOUT_MS = 30000 # Standard timeout +TIMEOUT_CMD_MS = 10000 # Command-echo timeout + +# Timeout for board preparation in lab mode. This needs to be enough to build +# U-Boot, write it to the board and then boot the board. Since this process is +# under the control of another program (e.g. Labgrid), it will failure sooner +# if something goes way. So use a very long timeout here to cover all possible +# situations. +TIMEOUT_PREPARE_MS = 3 * 60 * 1000 bad_pattern_defs = ( ('spl_signon', pattern_u_boot_spl_signon), @@ -142,6 +152,7 @@ class ConsoleBase(object): self.at_prompt = False self.at_prompt_logevt = None + self.lab_mode = False def get_spawn(self): # This is not called, ssubclass must define this. @@ -172,43 +183,75 @@ class ConsoleBase(object): """ if self.p: - self.p.close() + self.log.start_section('Stopping U-Boot') + close_type = self.p.close() + self.log.info(f'Close type: {close_type}') + self.log.end_section('Stopping U-Boot') self.logstream.close() + def set_lab_mode(self): + """Select lab mode + + This tells us that we will get a 'lab ready' message when the board is + ready for use. We don't need to look for signon messages. + """ + self.log.info(f'test.py: Lab mode is active') + self.p.timeout = TIMEOUT_PREPARE_MS + self.lab_mode = True + def wait_for_boot_prompt(self, loop_num = 1): """Wait for the boot up until command prompt. This is for internal use only. """ try: + self.log.info('Waiting for U-Boot to be ready') bcfg = self.config.buildconfig config_spl_serial = bcfg.get('config_spl_serial', 'n') == 'y' env_spl_skipped = self.config.env.get('env__spl_skipped', False) env_spl_banner_times = self.config.env.get('env__spl_banner_times', 1) - while loop_num > 0: + while not self.lab_mode and loop_num > 0: loop_num -= 1 while config_spl_serial and not env_spl_skipped and env_spl_banner_times > 0: - m = self.p.expect([pattern_u_boot_spl_signon] + - self.bad_patterns) - if m != 0: + m = self.p.expect([pattern_u_boot_spl_signon, + pattern_lab_mode] + self.bad_patterns) + if m == 1: + self.set_lab_mode() + break + elif m != 0: raise BootFail('Bad pattern found on SPL console: ' + - self.bad_pattern_ids[m - 1]) + self.bad_pattern_ids[m - 1]) env_spl_banner_times -= 1 - m = self.p.expect([pattern_u_boot_main_signon] + self.bad_patterns) - if m != 0: - raise BootFail('Bad pattern found on console: ' + - self.bad_pattern_ids[m - 1]) - self.u_boot_version_string = self.p.after + if not self.lab_mode: + m = self.p.expect([pattern_u_boot_main_signon, + pattern_lab_mode] + self.bad_patterns) + if m == 1: + self.set_lab_mode() + elif m != 0: + raise BootFail('Bad pattern found on console: ' + + self.bad_pattern_ids[m - 1]) + if not self.lab_mode: + self.u_boot_version_string = self.p.after while True: - m = self.p.expect([self.prompt_compiled, + m = self.p.expect([self.prompt_compiled, pattern_ready_prompt, pattern_stop_autoboot_prompt] + self.bad_patterns) if m == 0: + self.log.info(f'Found ready prompt {m}') break - if m == 1: + elif m == 1: + m = pattern_ready_prompt.search(self.p.after) + self.u_boot_version_string = m.group(2) + self.log.info(f'Lab: Board is ready') + self.p.timeout = TIMEOUT_MS + break + if m == 2: + self.log.info(f'Found autoboot prompt {m}') self.p.send(' ') continue - raise BootFail('Bad pattern found on console: ' + - self.bad_pattern_ids[m - 2]) + if not self.lab_mode: + raise BootFail('Missing prompt / ready message on console: ' + + self.bad_pattern_ids[m - 3]) + self.log.info(f'U-Boot is ready') finally: self.log.timestamp() @@ -261,22 +304,28 @@ class ConsoleBase(object): try: self.at_prompt = False + if not self.p: + raise BootFail( + f"Lab failure: Connection lost when sending command '{cmd}'") + if send_nl: cmd += '\n' - while cmd: - # Limit max outstanding data, so UART FIFOs don't overflow - chunk = cmd[:self.max_fifo_fill] - cmd = cmd[self.max_fifo_fill:] - self.p.send(chunk) - if not wait_for_echo: - continue - chunk = re.escape(chunk) - chunk = chunk.replace('\\\n', '[\r\n]') - m = self.p.expect([chunk] + self.bad_patterns) - if m != 0: - self.at_prompt = False - raise BootFail('Bad pattern found on console: ' + - self.bad_pattern_ids[m - 1]) + rem = cmd # Remaining to be sent + with self.temporary_timeout(TIMEOUT_CMD_MS): + while rem: + # Limit max outstanding data, so UART FIFOs don't overflow + chunk = rem[:self.max_fifo_fill] + rem = rem[self.max_fifo_fill:] + self.p.send(chunk) + if not wait_for_echo: + continue + chunk = re.escape(chunk) + chunk = chunk.replace('\\\n', '[\r\n]') + m = self.p.expect([chunk] + self.bad_patterns) + if m != 0: + self.at_prompt = False + raise BootFail(f"Failed to get echo on console (cmd '{cmd}':rem '{rem}'): " + + self.bad_pattern_ids[m - 1]) if not wait_for_prompt: return if wait_for_reboot: @@ -440,11 +489,17 @@ class ConsoleBase(object): if not self.config.gdbserver: self.p.timeout = TIMEOUT_MS self.p.logfile_read = self.logstream - if expect_reset: - loop_num = 2 + if self.config.use_running_system: + # Send an empty command to set up the 'expect' logic. This has + # the side effect of ensuring that there was no partial command + # line entered + self.run_command(' ') else: - loop_num = 1 - self.wait_for_boot_prompt(loop_num = loop_num) + if expect_reset: + loop_num = 2 + else: + loop_num = 1 + self.wait_for_boot_prompt(loop_num = loop_num) self.at_prompt = True self.at_prompt_logevt = self.logstream.logfile.cur_evt except Exception as ex: diff --git a/test/py/u_boot_console_exec_attach.py b/test/py/u_boot_console_exec_attach.py index 8dd8cc1230c..8b253b4451d 100644 --- a/test/py/u_boot_console_exec_attach.py +++ b/test/py/u_boot_console_exec_attach.py @@ -59,14 +59,27 @@ class ConsoleExecAttach(ConsoleBase): args = [self.config.board_type, self.config.board_identity] s = Spawn(['u-boot-test-console'] + args) - try: - self.log.action('Resetting board') - cmd = ['u-boot-test-reset'] + args - runner = self.log.get_runner(cmd[0], sys.stdout) - runner.run(cmd) - runner.close() - except: - s.close() - raise + if self.config.use_running_system: + self.log.action('Connecting to board without reset') + else: + try: + self.log.action('Resetting board') + cmd = ['u-boot-test-reset'] + args + runner = self.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + runner.close() + except: + s.close() + raise return s + + def close(self): + super().close() + + self.log.action('Releasing board') + args = [self.config.board_type, self.config.board_identity] + cmd = ['u-boot-test-release'] + args + runner = self.log.get_runner(cmd[0], sys.stdout) + runner.run(cmd) + runner.close() diff --git a/test/py/u_boot_spawn.py b/test/py/u_boot_spawn.py index 24d369035e5..c703454389d 100644 --- a/test/py/u_boot_spawn.py +++ b/test/py/u_boot_spawn.py @@ -5,15 +5,21 @@ Logic to spawn a sub-process and interact with its stdio. """ +import io import os import re import pty import pytest import signal import select +import sys +import termios import time import traceback +# Character to send (twice) to exit the terminal +EXIT_CHAR = 0x1d # FS (Ctrl + ]) + class Timeout(Exception): """An exception sub-class that indicates that a timeout occurred.""" @@ -115,11 +121,30 @@ class Spawn: finally: os._exit(255) + old = None try: + isatty = False + try: + isatty = os.isatty(sys.stdout.fileno()) + + # with --capture=tee-sys we cannot call fileno() + except io.UnsupportedOperation as exc: + pass + if isatty: + new = termios.tcgetattr(self.fd) + old = new + new[3] = new[3] & ~(termios.ICANON | termios.ISIG) + new[3] = new[3] & ~termios.ECHO + new[6][termios.VMIN] = 0 + new[6][termios.VTIME] = 0 + termios.tcsetattr(self.fd, termios.TCSANOW, new) + self.poll = select.poll() self.poll.register(self.fd, select.POLLIN | select.POLLPRI | select.POLLERR | select.POLLHUP | select.POLLNVAL) except: + if old: + termios.tcsetattr(self.fd, termios.TCSANOW, old) self.close() raise @@ -289,15 +314,28 @@ class Spawn: None. Returns: - Nothing. + str: Type of closure completed """ - + # For Labgrid-sjg, ask it is exit gracefully, so it can transition the + # board to the final state (like 'off') before exiting. + if os.environ.get('USE_LABGRID_SJG'): + self.send(chr(EXIT_CHAR) * 2) + + # Wait about 10 seconds for Labgrid to close and power off the board + for _ in range(100): + if not self.isalive(): + return 'normal' + time.sleep(0.1) + + # That didn't work, so try closing the PTY os.close(self.fd) for _ in range(100): if not self.isalive(): - break + return 'break' time.sleep(0.1) + return 'timeout' + def get_expect_output(self): """Return the output read by expect() diff --git a/test/test-main.c b/test/test-main.c index da5b07ce00b..8d764892fa6 100644 --- a/test/test-main.c +++ b/test/test-main.c @@ -4,6 +4,8 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_TEST + #include <blk.h> #include <console.h> #include <cyclic.h> @@ -240,15 +242,22 @@ static bool test_matches(const char *prefix, const char *test_name, * ut_list_has_dm_tests() - Check if a list of tests has driver model ones * * @tests: List of tests to run - * @count: Number of tests to ru + * @count: Number of tests to run + * @prefix: String prefix for the tests. Any tests that have this prefix will be + * printed without the prefix, so that it is easier to see the unique part + * of the test name. If NULL, no prefix processing is done + * @select_name: Name of a single test being run (from the list provided). If + * NULL all tests are being run * Return: true if any of the tests have the UTF_DM flag */ -static bool ut_list_has_dm_tests(struct unit_test *tests, int count) +static bool ut_list_has_dm_tests(struct unit_test *tests, int count, + const char *prefix, const char *select_name) { struct unit_test *test; for (test = tests; test < tests + count; test++) { - if (test->flags & UTF_DM) + if (test_matches(prefix, test->name, select_name) && + (test->flags & UTF_DM)) return true; } @@ -379,6 +388,12 @@ static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) return -EAGAIN; } } + if (test->flags & UFT_BLOBLIST) { + log_debug("save bloblist %p\n", gd_bloblist()); + uts->old_bloblist = gd_bloblist(); + gd_set_bloblist(NULL); + } + ut_silence_console(uts); return 0; @@ -402,6 +417,11 @@ static int test_post_run(struct unit_test_state *uts, struct unit_test *test) free(uts->of_other); uts->of_other = NULL; + if (test->flags & UFT_BLOBLIST) { + gd_set_bloblist(uts->old_bloblist); + log_debug("restore bloblist %p\n", gd_bloblist()); + } + blkcache_free(); return 0; @@ -550,6 +570,9 @@ static int ut_run_test_live_flat(struct unit_test_state *uts, * @count: Number of tests to run * @select_name: Name of a single test to run (from the list provided). If NULL * then all tests are run + * @test_insert: String describing a test to run after n other tests run, in the + * format n:name where n is the number of tests to run before this one and + * name is the name of the test to run * Return: 0 if all tests passed, -ENOENT if test @select_name was not found, * -EBADF if any failed */ @@ -594,14 +617,14 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, */ len = strlen(test_name); if (len < 6 || strcmp(test_name + len - 6, "_norun")) { - printf("Test %s is manual so must have a name ending in _norun\n", + printf("Test '%s' is manual so must have a name ending in _norun\n", test_name); uts->fail_count++; return -EBADF; } if (!uts->force_run) { if (select_name) { - printf("Test %s skipped as it is manual (use -f to run it)\n", + printf("Test '%s' skipped as it is manual (use -f to run it)\n", test_name); } continue; @@ -612,7 +635,7 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, if (one && upto == pos) { ret = ut_run_test_live_flat(uts, one); if (uts->fail_count != old_fail_count) { - printf("Test %s failed %d times (position %d)\n", + printf("Test '%s' failed %d times (position %d)\n", one->name, uts->fail_count - old_fail_count, pos); } @@ -622,7 +645,7 @@ static int ut_run_tests(struct unit_test_state *uts, const char *prefix, for (i = 0; i < uts->runs_per_test; i++) ret = ut_run_test_live_flat(uts, test); if (uts->fail_count != old_fail_count) { - printf("Test %s failed %d times\n", select_name, + printf("Test '%s' failed %d times\n", test_name, uts->fail_count - old_fail_count); } found++; @@ -646,7 +669,7 @@ int ut_run_list(const char *category, const char *prefix, int ret; if (!CONFIG_IS_ENABLED(OF_PLATDATA) && - ut_list_has_dm_tests(tests, count)) { + ut_list_has_dm_tests(tests, count, prefix, select_name)) { has_dm_tests = true; /* * If we have no device tree, or it only has a root node, then diff --git a/test/trace/test-trace.sh b/test/trace/test-trace.sh deleted file mode 100755 index 5130b2bf017..00000000000 --- a/test/trace/test-trace.sh +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0+ -# Copyright (c) 2013 The Chromium OS Authors. -# - -# Simple test script for tracing with sandbox - -TRACE_OPT="FTRACE=1" - -BASE="$(dirname $0)/.." -. $BASE/common.sh - -run_trace() { - echo "Run trace" - ./${OUTPUT_DIR}/u-boot <<END -trace stats -hash sha256 0 10000 -trace pause -trace stats -hash sha256 0 10000 -trace stats -trace resume -hash sha256 0 10000 -trace pause -trace stats -reset -END -} - -check_results() { - echo "Check results" - - # Expect sha256 to run 3 times, so we see the string 6 times - if [ $(grep -c sha256 ${tmp}) -ne 6 ]; then - fail "sha256 error" - fi - - # 4 sets of results (output of 'trace stats') - if [ $(grep -c "traced function calls" ${tmp}) -ne 4 ]; then - fail "trace output error" - fi - - # Check trace counts. We expect to see an increase in the number of - # traced function calls between each 'trace stats' command, except - # between calls 2 and 3, where tracing is paused. - # This code gets the sign of the difference between each number and - # its predecessor. - counts="$(tr -d ',\r' <${tmp} | awk \ - '/traced function calls/ { diff = $1 - upto; upto = $1; \ - printf "%d ", diff < 0 ? -1 : (diff > 0 ? 1 : 0)}')" - - if [ "${counts}" != "1 1 0 1 " ]; then - fail "trace collection error: ${counts}" - fi -} - -echo "Simple trace test / sanity check using sandbox" -echo -tmp="$(tempfile)" -build_uboot "${TRACE_OPT}" -run_trace >${tmp} -check_results ${tmp} -rm ${tmp} -echo "Test passed" |