summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Kconfig6
-rw-r--r--test/Makefile5
-rw-r--r--test/bloblist.c105
-rw-r--r--test/boot/bootflow.c102
-rw-r--r--test/cmd/Makefile3
-rw-r--r--test/cmd/bdinfo.c107
-rw-r--r--test/cmd/cmd_ut_cmd.c20
-rw-r--r--test/cmd/fdt.c8
-rw-r--r--test/cmd/font.c6
-rw-r--r--test/cmd/mem_copy.c168
-rw-r--r--test/cmd_ut.c16
-rw-r--r--test/common/event.c3
-rw-r--r--test/dm/acpi.c138
-rw-r--r--test/dm/clk_ccf.c22
-rw-r--r--test/dm/scmi.c94
-rw-r--r--test/dm/spmi.c4
-rwxr-xr-xtest/fs/fs-test.sh118
-rw-r--r--test/hush/Makefile10
-rw-r--r--test/hush/cmd_ut_hush.c19
-rw-r--r--test/hush/dollar.c225
-rw-r--r--test/hush/if.c316
-rw-r--r--test/hush/list.c139
-rw-r--r--test/hush/loop.c90
-rw-r--r--test/image/spl_load_fs.c2
-rw-r--r--test/lib/lmb.c36
-rw-r--r--test/print_ut.c8
-rw-r--r--test/py/requirements.txt8
-rw-r--r--test/py/tests/fs_helper.py11
-rw-r--r--test/py/tests/test_bootstage.py67
-rw-r--r--test/py/tests/test_cleanup_build.py5
-rwxr-xr-xtest/py/tests/test_fit.py14
-rw-r--r--test/py/tests/test_fs/conftest.py54
-rw-r--r--test/py/tests/test_fs/test_fs_fat.py25
-rw-r--r--test/py/tests/test_gpio.py90
-rw-r--r--test/py/tests/test_hush_if_test.py197
-rw-r--r--test/py/tests/test_i2c.py116
-rw-r--r--test/py/tests/test_mdio.py79
-rw-r--r--test/py/tests/test_memtest.py68
-rw-r--r--test/py/tests/test_mii.py92
-rw-r--r--test/py/tests/test_mmc.py671
-rw-r--r--test/py/tests/test_net.py73
-rw-r--r--test/py/tests/test_scsi.py92
-rw-r--r--test/py/tests/test_smbios.py41
-rw-r--r--test/py/tests/test_trace.py32
-rw-r--r--test/py/tests/test_usb.py626
-rw-r--r--test/py/tests/test_ut.py9
-rw-r--r--test/py/tests/test_vboot.py6
-rw-r--r--test/py/tests/test_zynq_secure.py190
-rw-r--r--test/py/tests/test_zynqmp_rpu.py208
-rw-r--r--test/py/tests/test_zynqmp_secure.py104
-rw-r--r--test/unicode_ut.c11
-rw-r--r--test/ut.c27
52 files changed, 4282 insertions, 404 deletions
diff --git a/test/Kconfig b/test/Kconfig
index c3db727c58e..e2ec0994a2e 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -32,6 +32,7 @@ if UT_LIB
config UT_LIB_ASN1
bool "Unit test for asn1 compiler and decoder function"
+ depends on SANDBOX
default y
imply ASYMMETRIC_KEY_TYPE
imply ASYMMETRIC_PUBLIC_KEY_SUBTYPE
@@ -64,6 +65,11 @@ config UT_LIB_RSA
endif
+config UT_BOOTSTD
+ bool "Unit tests for standard boot"
+ depends on UNIT_TEST && BOOTSTD && SANDBOX
+ default y
+
config UT_COMPRESSION
bool "Unit test for compression"
depends on UNIT_TEST
diff --git a/test/Makefile b/test/Makefile
index 8e1fed2c28b..ed312cd0a48 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -17,13 +17,16 @@ obj-$(CONFIG_FUZZ) += fuzz/
ifndef CONFIG_SANDBOX_VPL
obj-$(CONFIG_UNIT_TEST) += lib/
endif
+ifneq ($(CONFIG_HUSH_PARSER),)
+obj-$(CONFIG_$(SPL_)CMDLINE) += hush/
+endif
obj-$(CONFIG_$(SPL_)CMDLINE) += print_ut.o
obj-$(CONFIG_$(SPL_)CMDLINE) += str_ut.o
obj-$(CONFIG_UT_TIME) += time_ut.o
obj-y += ut.o
ifeq ($(CONFIG_SPL_BUILD),)
-obj-$(CONFIG_UNIT_TEST) += boot/
+obj-y += boot/
obj-$(CONFIG_UNIT_TEST) += common/
obj-y += log/
obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o
diff --git a/test/bloblist.c b/test/bloblist.c
index 720be7e244f..17d9dd03d07 100644
--- a/test/bloblist.c
+++ b/test/bloblist.c
@@ -72,15 +72,15 @@ static int bloblist_test_init(struct unit_test_state *uts)
hdr = clear_bloblist();
ut_asserteq(-ENOENT, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_asserteq_ptr(NULL, bloblist_check_magic(TEST_ADDR));
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_asserteq_ptr(hdr, bloblist_check_magic(TEST_ADDR));
hdr->version++;
ut_asserteq(-EPROTONOSUPPORT, bloblist_check(TEST_ADDR,
TEST_BLOBLIST_SIZE));
- ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0x10, 0));
- ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0));
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_asserteq(-ENOSPC, bloblist_new(TEST_ADDR, 0xc, 0, 0));
+ ut_asserteq(-EFAULT, bloblist_new(1, TEST_BLOBLIST_SIZE, 0, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
ut_assertok(bloblist_finish());
@@ -106,8 +106,9 @@ static int bloblist_test_blob(struct unit_test_state *uts)
/* At the start there should be no records */
hdr = clear_bloblist();
ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
- ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_size());
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
+ ut_asserteq(sizeof(struct bloblist_hdr), bloblist_get_size());
+ ut_asserteq(TEST_BLOBLIST_SIZE, bloblist_get_total_size());
ut_asserteq(TEST_ADDR, bloblist_get_base());
ut_asserteq(map_to_sysmem(hdr), TEST_ADDR);
@@ -144,7 +145,7 @@ static int bloblist_test_blob_ensure(struct unit_test_state *uts)
/* At the start there should be no records */
clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
/* Test with an empty bloblist */
size = TEST_SIZE;
@@ -176,7 +177,7 @@ static int bloblist_test_bad_blob(struct unit_test_state *uts)
void *data;
hdr = clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = hdr + 1;
data += sizeof(struct bloblist_rec);
ut_asserteq_addr(data, bloblist_ensure(TEST_TAG, TEST_SIZE));
@@ -192,7 +193,7 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
char *data, *data2;
hdr = clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_assertok(bloblist_finish());
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@@ -205,9 +206,9 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->flags++;
- hdr->size--;
+ hdr->total_size--;
ut_asserteq(-EFBIG, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
- hdr->size++;
+ hdr->total_size++;
hdr->spare++;
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@@ -217,6 +218,10 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
hdr->chksum--;
+ hdr->align_log2++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ hdr->align_log2--;
+
/* Make sure the checksum changes when we add blobs */
data = bloblist_add(TEST_TAG, TEST_SIZE, 0);
ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
@@ -237,12 +242,18 @@ static int bloblist_test_checksum(struct unit_test_state *uts)
*data2 -= 1;
/*
- * Changing data outside the range of valid data should not affect
- * the checksum.
+ * Changing data outside the range of valid data should affect the
+ * checksum.
*/
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
data[TEST_SIZE]++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ data[TEST_SIZE]--;
+ ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+
data2[TEST_SIZE2]++;
+ ut_asserteq(-EIO, bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
+ data[TEST_SIZE]--;
ut_assertok(bloblist_check(TEST_ADDR, TEST_BLOBLIST_SIZE));
return 0;
@@ -256,7 +267,7 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
char *data, *data2;
hdr = clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = bloblist_ensure(TEST_TAG, TEST_SIZE);
data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
@@ -264,10 +275,10 @@ static int bloblist_test_cmd_info(struct unit_test_state *uts)
ut_silence_console(uts);
console_record_reset();
run_command("bloblist info", 0);
- ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
- ut_assert_nextline("size: 400 1 KiB");
- ut_assert_nextline("alloced: 70 112 Bytes");
- ut_assert_nextline("free: 390 912 Bytes");
+ ut_assert_nextline("base: %lx", (ulong)map_to_sysmem(hdr));
+ ut_assert_nextline("total size: 400 1 KiB");
+ ut_assert_nextline("used size: 50 80 Bytes");
+ ut_assert_nextline("free: 3b0 944 Bytes");
ut_assert_console_end();
ut_unsilence_console(uts);
@@ -282,7 +293,7 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts)
char *data, *data2;
hdr = clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
data = bloblist_ensure(TEST_TAG, TEST_SIZE);
data2 = bloblist_ensure(TEST_TAG2, TEST_SIZE2);
@@ -291,9 +302,9 @@ static int bloblist_test_cmd_list(struct unit_test_state *uts)
console_record_reset();
run_command("bloblist list", 0);
ut_assert_nextline("Address Size Tag Name");
- ut_assert_nextline("%08lx %8x 8000 SPL hand-off",
+ ut_assert_nextline("%08lx %8x fff000 SPL hand-off",
(ulong)map_to_sysmem(data), TEST_SIZE);
- ut_assert_nextline("%08lx %8x 106 Chrome OS vboot context",
+ ut_assert_nextline("%08lx %8x 202 Chrome OS vboot context",
(ulong)map_to_sysmem(data2), TEST_SIZE2);
ut_assert_console_end();
ut_unsilence_console(uts);
@@ -312,7 +323,7 @@ static int bloblist_test_align(struct unit_test_state *uts)
/* At the start there should be no records */
hdr = clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
ut_assertnull(bloblist_find(TEST_TAG, TEST_BLOBLIST_SIZE));
/* Check the default alignment */
@@ -325,18 +336,18 @@ static int bloblist_test_align(struct unit_test_state *uts)
data = bloblist_add(i, size, 0);
ut_assertnonnull(data);
addr = map_to_sysmem(data);
- ut_asserteq(0, addr & (BLOBLIST_ALIGN - 1));
+ ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN - 1));
/* Only the bytes in the blob data should be zeroed */
for (j = 0; j < size; j++)
ut_asserteq(0, data[j]);
- for (; j < BLOBLIST_ALIGN; j++)
+ for (; j < BLOBLIST_BLOB_ALIGN; j++)
ut_asserteq(ERASE_BYTE, data[j]);
}
/* Check larger alignment */
for (i = 0; i < 3; i++) {
- int align = 32 << i;
+ int align = 5 - i;
data = bloblist_add(3 + i, i * 4, align);
ut_assertnonnull(data);
@@ -345,16 +356,16 @@ static int bloblist_test_align(struct unit_test_state *uts)
}
/* Check alignment with an bloblist starting on a smaller alignment */
- hdr = map_sysmem(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE);
+ hdr = map_sysmem(TEST_ADDR + BLOBLIST_BLOB_ALIGN, TEST_BLOBLIST_SIZE);
memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
memset(hdr, '\0', sizeof(*hdr));
ut_assertok(bloblist_new(TEST_ADDR + BLOBLIST_ALIGN, TEST_BLOBLIST_SIZE,
- 0));
+ 0, 0));
- data = bloblist_add(1, 5, BLOBLIST_ALIGN * 2);
+ data = bloblist_add(1, 5, BLOBLIST_ALIGN_LOG2 + 1);
ut_assertnonnull(data);
addr = map_to_sysmem(data);
- ut_asserteq(0, addr & (BLOBLIST_ALIGN * 2 - 1));
+ ut_asserteq(0, addr & (BLOBLIST_BLOB_ALIGN * 2 - 1));
return 0;
}
@@ -370,7 +381,7 @@ static int bloblist_test_reloc(struct unit_test_state *uts)
ulong new_addr;
ulong new_size;
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
old_ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Add one blob and then one that won't fit */
@@ -409,7 +420,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
memset(hdr, ERASE_BYTE, TEST_BLOBLIST_SIZE);
/* Create two blobs */
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1);
ut_assertok(check_zero(blob1, small_size));
@@ -421,7 +432,7 @@ static int bloblist_test_grow(struct unit_test_state *uts)
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2,
- hdr->alloced);
+ hdr->used_size);
/* Resize the first one */
ut_assertok(bloblist_resize(TEST_TAG, small_size + 4));
@@ -442,8 +453,8 @@ static int bloblist_test_grow(struct unit_test_state *uts)
hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2 +
- BLOBLIST_ALIGN,
- hdr->alloced);
+ BLOBLIST_BLOB_ALIGN,
+ hdr->used_size);
return 0;
}
@@ -461,7 +472,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Create two blobs */
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1);
strcpy(blob1, test1_str);
@@ -473,7 +484,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2,
- hdr->alloced);
+ hdr->used_size);
/* Resize the first one */
new_size = small_size - BLOBLIST_ALIGN - 4;
@@ -493,7 +504,7 @@ static int bloblist_test_shrink(struct unit_test_state *uts)
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2 -
BLOBLIST_ALIGN,
- hdr->alloced);
+ hdr->used_size);
return 0;
}
@@ -511,7 +522,7 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
ptr = map_sysmem(TEST_ADDR, TEST_BLOBLIST_SIZE);
/* Create two blobs */
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1);
@@ -521,12 +532,12 @@ static int bloblist_test_resize_fail(struct unit_test_state *uts)
hdr = ptr;
ut_asserteq(sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2,
- hdr->alloced);
+ hdr->used_size);
/* Resize the first one, to check the boundary conditions */
ut_asserteq(-EINVAL, bloblist_resize(TEST_TAG, -1));
- new_size = small_size + (hdr->size - hdr->alloced);
+ new_size = small_size + (hdr->total_size - hdr->used_size);
ut_asserteq(-ENOSPC, bloblist_resize(TEST_TAG, new_size + 1));
ut_assertok(bloblist_resize(TEST_TAG, new_size));
@@ -548,7 +559,7 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
hdr = ptr;
/* Create two blobs */
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
blob1 = bloblist_add(TEST_TAG, small_size, 0);
ut_assertnonnull(blob1);
@@ -558,9 +569,9 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
/* Check the byte after the last blob */
alloced_val = sizeof(struct bloblist_hdr) +
sizeof(struct bloblist_rec) * 2 + small_size * 2;
- ut_asserteq(alloced_val, hdr->alloced);
+ ut_asserteq(alloced_val, hdr->used_size);
ut_asserteq_ptr((void *)hdr + alloced_val, blob2 + small_size);
- ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
+ ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
/* Resize the second one, checking nothing changes */
ut_asserteq(0, bloblist_resize(TEST_TAG2, small_size + 4));
@@ -577,9 +588,9 @@ static int bloblist_test_resize_last(struct unit_test_state *uts)
ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + alloced_val + 4));
/* Check that the new top of the allocated blobs has not been touched */
- alloced_val += BLOBLIST_ALIGN;
- ut_asserteq(alloced_val, hdr->alloced);
- ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->alloced));
+ alloced_val += BLOBLIST_BLOB_ALIGN;
+ ut_asserteq(alloced_val, hdr->used_size);
+ ut_asserteq((u8)ERASE_BYTE, *((u8 *)hdr + hdr->used_size));
return 0;
}
@@ -593,7 +604,7 @@ static int bloblist_test_blob_maxsize(struct unit_test_state *uts)
/* At the start there should be no records */
clear_bloblist();
- ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0));
+ ut_assertok(bloblist_new(TEST_ADDR, TEST_BLOBLIST_SIZE, 0, 0));
/* Add a blob that takes up all space */
size = TEST_BLOBLIST_SIZE - sizeof(struct bloblist_hdr) -
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index b97c566f000..fa54dde661c 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -374,7 +374,7 @@ static int bootflow_system(struct unit_test_state *uts)
{
struct udevice *bootstd, *dev;
- if (!IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR))
+ if (!IS_ENABLED(CONFIG_EFI_BOOTMGR))
return -EAGAIN;
ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
ut_assertok(device_bind(bootstd, DM_DRIVER_GET(bootmeth_efi_mgr),
@@ -637,6 +637,102 @@ static int bootflow_cmd_menu(struct unit_test_state *uts)
}
BOOTSTD_TEST(bootflow_cmd_menu, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
+/* Check 'bootflow scan -m' to select a bootflow using a menu */
+static int bootflow_scan_menu(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+ const char **old_order, **new_order;
+ char prev[3];
+
+ /* get access to the current bootflow */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
+
+ /* Add keypresses to move to and select the second one in the list */
+ prev[0] = CTL_CH('n');
+ prev[1] = '\r';
+ prev[2] = '\0';
+ ut_asserteq(2, console_in_puts(prev));
+
+ ut_assertok(run_command("bootflow scan -lm", 0));
+ new_order = std->bootdev_order;
+ std->bootdev_order = old_order;
+
+ ut_assert_skip_to_line("No more bootdevs");
+ ut_assert_nextlinen("--");
+ ut_assert_nextline("(2 bootflows, 2 valid)");
+
+ ut_assert_nextline("Selected: Armbian");
+ ut_assertnonnull(std->cur_bootflow);
+ ut_assert_console_end();
+
+ /* Check not selecting anything */
+ prev[0] = '\e';
+ prev[1] = '\0';
+ ut_asserteq(1, console_in_puts(prev));
+
+ std->bootdev_order = new_order; /* Blue Monday */
+ ut_assertok(run_command("bootflow scan -lm", 0));
+ std->bootdev_order = old_order;
+
+ ut_assertnull(std->cur_bootflow);
+ ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+ ut_assert_nextline("Nothing chosen");
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_scan_menu,
+ UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
+/* Check 'bootflow scan -mb' to select and boot a bootflow using a menu */
+static int bootflow_scan_menu_boot(struct unit_test_state *uts)
+{
+ struct bootstd_priv *std;
+ const char **old_order;
+ char prev[3];
+
+ /* get access to the current bootflow */
+ ut_assertok(bootstd_get_priv(&std));
+
+ ut_assertok(prep_mmc_bootdev(uts, "mmc4", false, &old_order));
+
+ /* Add keypresses to move to and select the second one in the list */
+ prev[0] = CTL_CH('n');
+ prev[1] = '\r';
+ prev[2] = '\0';
+ ut_asserteq(2, console_in_puts(prev));
+
+ ut_assertok(run_command("bootflow scan -lmb", 0));
+ std->bootdev_order = old_order;
+
+ ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+
+ ut_assert_nextline("Selected: Armbian");
+
+ if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ /*
+ * With old hush, despite booti failing to boot, i.e. returning
+ * CMD_RET_FAILURE, run_command() returns 0 which leads bootflow_boot(), as
+ * we are using bootmeth_script here, to return -EFAULT.
+ */
+ ut_assert_skip_to_line("Boot failed (err=-14)");
+ } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * While with modern one, run_command() propagates CMD_RET_FAILURE returned
+ * by booti, so we get 1 here.
+ */
+ ut_assert_skip_to_line("Boot failed (err=1)");
+ }
+ ut_assertnonnull(std->cur_bootflow);
+ ut_assert_console_end();
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_scan_menu_boot,
+ UT_TESTF_DM | UT_TESTF_SCAN_FDT | UT_TESTF_CONSOLE_REC);
+
/* Check searching for a single bootdev using the hunters */
static int bootflow_cmd_hunt_single(struct unit_test_state *uts)
{
@@ -1013,6 +1109,10 @@ static int bootflow_cmdline(struct unit_test_state *uts)
ut_asserteq(0, run_command("bootflow cmdline get mary", 0));
ut_assert_nextline_empty();
+ ut_asserteq(0, run_command("bootflow cmdline set mary abc", 0));
+ ut_asserteq(0, run_command("bootflow cmdline set mary", 0));
+ ut_assert_nextline_empty();
+
ut_assert_console_end();
return 0;
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index e296ba1192b..478ef4c6f05 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -3,6 +3,8 @@
# Copyright (c) 2013 Google, Inc
# Copyright 2022-2023 Arm Limited and/or its affiliates <open-source-office@arm.com>
+obj-y += cmd_ut_cmd.o
+
ifdef CONFIG_HUSH_PARSER
obj-$(CONFIG_CONSOLE_RECORD) += test_echo.o
endif
@@ -17,6 +19,7 @@ obj-$(CONFIG_CONSOLE_TRUETYPE) += font.o
obj-$(CONFIG_CMD_HISTORY) += history.o
obj-$(CONFIG_CMD_LOADM) += loadm.o
obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+obj-$(CONFIG_CMD_MEMORY) += mem_copy.o
ifdef CONFIG_CMD_PCI
obj-$(CONFIG_CMD_PCI_MPS) += pci_mps.o
endif
diff --git a/test/cmd/bdinfo.c b/test/cmd/bdinfo.c
index 8c09281cac0..4977d01f62d 100644
--- a/test/cmd/bdinfo.c
+++ b/test/cmd/bdinfo.c
@@ -114,6 +114,18 @@ static int lmb_test_dump_region(struct unit_test_state *uts,
end = base + size - 1;
flags = rgn->region[i].flags;
+ /*
+ * this entry includes the stack (get_sp()) on many platforms
+ * so will different each time lmb_init_and_reserve() is called.
+ * We could instead have the bdinfo command put its lmb region
+ * in a known location, so we can check it directly, rather than
+ * calling lmb_init_and_reserve() to create a new (and hopefully
+ * identical one). But for now this seems good enough.
+ */
+ if (!IS_ENABLED(CONFIG_SANDBOX) && i == 3) {
+ ut_assert_nextlinen(" %s[%d]\t[", name, i);
+ continue;
+ }
ut_assert_nextline(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: %x",
name, i, base, end, size, flags);
}
@@ -124,23 +136,17 @@ static int lmb_test_dump_region(struct unit_test_state *uts,
static int lmb_test_dump_all(struct unit_test_state *uts, struct lmb *lmb)
{
ut_assert_nextline("lmb_dump_all:");
- lmb_test_dump_region(uts, &lmb->memory, "memory");
- lmb_test_dump_region(uts, &lmb->reserved, "reserved");
+ ut_assertok(lmb_test_dump_region(uts, &lmb->memory, "memory"));
+ ut_assertok(lmb_test_dump_region(uts, &lmb->reserved, "reserved"));
return 0;
}
-static int bdinfo_test_move(struct unit_test_state *uts)
+static int bdinfo_check_mem(struct unit_test_state *uts)
{
struct bd_info *bd = gd->bd;
int i;
- /* Test moving the working BDINFO to a new location */
- ut_assertok(console_record_reset_enable());
- ut_assertok(run_commandf("bdinfo"));
-
- ut_assertok(test_num_l(uts, "boot_params", 0));
-
for (i = 0; i < CONFIG_NR_DRAM_BANKS; ++i) {
if (bd->bi_dram[i].size) {
ut_assertok(test_num_l(uts, "DRAM bank", i));
@@ -151,6 +157,15 @@ static int bdinfo_test_move(struct unit_test_state *uts)
}
}
+ return 0;
+}
+
+static int bdinfo_test_all(struct unit_test_state *uts)
+{
+ ut_assertok(test_num_l(uts, "boot_params", 0));
+
+ ut_assertok(bdinfo_check_mem(uts));
+
/* CONFIG_SYS_HAS_SRAM testing not supported */
ut_assertok(test_num_l(uts, "flashstart", 0));
ut_assertok(test_num_l(uts, "flashsize", 0));
@@ -176,7 +191,7 @@ static int bdinfo_test_move(struct unit_test_state *uts)
ut_assertok(test_num_l(uts, "fdt_size", (ulong)gd->fdt_size));
if (IS_ENABLED(CONFIG_VIDEO))
- test_video_info(uts);
+ ut_assertok(test_video_info(uts));
/* The gd->multi_dtb_fit may not be available, hence, #if below. */
#if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
@@ -187,7 +202,7 @@ static int bdinfo_test_move(struct unit_test_state *uts)
struct lmb lmb;
lmb_init_and_reserve(&lmb, gd->bd, (void *)gd->fdt_blob);
- lmb_test_dump_all(uts, &lmb);
+ ut_assertok(lmb_test_dump_all(uts, &lmb));
if (IS_ENABLED(CONFIG_OF_REAL))
ut_assert_nextline("devicetree = %s", fdtdec_get_srcname());
}
@@ -212,12 +227,80 @@ static int bdinfo_test_move(struct unit_test_state *uts)
ut_assertok(test_num_l(uts, "malloc base", gd_malloc_start()));
}
+ if (IS_ENABLED(CONFIG_X86))
+ ut_check_skip_to_linen(uts, " high end =");
+
+ return 0;
+}
+
+static int bdinfo_test_full(struct unit_test_state *uts)
+{
+ /* Test BDINFO full print */
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("bdinfo"));
+ ut_assertok(bdinfo_test_all(uts));
+ ut_assertok(run_commandf("bdinfo -a"));
+ ut_assertok(bdinfo_test_all(uts));
+ ut_assertok(ut_check_console_end(uts));
+
+ return 0;
+}
+
+BDINFO_TEST(bdinfo_test_full, UT_TESTF_CONSOLE_REC);
+
+static int bdinfo_test_help(struct unit_test_state *uts)
+{
+ /* Test BDINFO unknown option help text print */
+ ut_assertok(console_record_reset_enable());
+ if (!CONFIG_IS_ENABLED(GETOPT)) {
+ ut_asserteq(0, run_commandf("bdinfo -h"));
+ ut_assertok(bdinfo_test_all(uts));
+ } else {
+ ut_asserteq(1, run_commandf("bdinfo -h"));
+ ut_assert_nextlinen("bdinfo: invalid option -- h");
+ ut_assert_nextlinen("bdinfo - print Board Info structure");
+ ut_assert_nextline_empty();
+ ut_assert_nextlinen("Usage:");
+ ut_assert_nextlinen("bdinfo");
+ }
+ ut_assertok(ut_check_console_end(uts));
+
+ return 0;
+}
+
+BDINFO_TEST(bdinfo_test_help, UT_TESTF_CONSOLE_REC);
+
+static int bdinfo_test_memory(struct unit_test_state *uts)
+{
+ /* Test BDINFO memory layout only print */
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("bdinfo -m"));
+ if (!CONFIG_IS_ENABLED(GETOPT))
+ ut_assertok(bdinfo_test_all(uts));
+ else
+ ut_assertok(bdinfo_check_mem(uts));
+ ut_assertok(ut_check_console_end(uts));
+
+ return 0;
+}
+
+BDINFO_TEST(bdinfo_test_memory, UT_TESTF_CONSOLE_REC);
+
+static int bdinfo_test_eth(struct unit_test_state *uts)
+{
+ /* Test BDINFO ethernet settings only print */
+ ut_assertok(console_record_reset_enable());
+ ut_assertok(run_commandf("bdinfo -e"));
+ if (!CONFIG_IS_ENABLED(GETOPT))
+ ut_assertok(bdinfo_test_all(uts));
+ else if (IS_ENABLED(CONFIG_CMD_NET))
+ ut_assertok(test_eth(uts));
ut_assertok(ut_check_console_end(uts));
return 0;
}
-BDINFO_TEST(bdinfo_test_move, UT_TESTF_CONSOLE_REC);
+BDINFO_TEST(bdinfo_test_eth, UT_TESTF_CONSOLE_REC);
int do_ut_bdinfo(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
diff --git a/test/cmd/cmd_ut_cmd.c b/test/cmd/cmd_ut_cmd.c
new file mode 100644
index 00000000000..e77fa1c7f01
--- /dev/null
+++ b/test/cmd/cmd_ut_cmd.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2023 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Unit tests for command functions
+ */
+
+#include <command.h>
+#include <test/cmd.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+int do_ut_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(cmd_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(cmd_test);
+
+ return cmd_ut_category("cmd", "cmd_test_", tests, n_ents, argc, argv);
+}
diff --git a/test/cmd/fdt.c b/test/cmd/fdt.c
index 1f103a1d7eb..54708552175 100644
--- a/test/cmd/fdt.c
+++ b/test/cmd/fdt.c
@@ -160,7 +160,13 @@ static int fdt_test_addr(struct unit_test_state *uts)
set_working_fdt_addr(0);
ut_assert_nextline("Working FDT set to 0");
ut_asserteq(CMD_RET_FAILURE, run_command("fdt addr", 0));
- ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
+
+ /*
+ * sandbox fails the check for !blob since the 0 pointer is mapped to
+ * memory somewhere other than at 0x0
+ */
+ if (IS_ENABLED(CONFIG_SANDBOX))
+ ut_assert_nextline("libfdt fdt_check_header(): FDT_ERR_BADMAGIC");
ut_assertok(ut_check_console_end(uts));
/* Set up a working FDT and try again */
diff --git a/test/cmd/font.c b/test/cmd/font.c
index 40682e5ce49..1fe05c1ead5 100644
--- a/test/cmd/font.c
+++ b/test/cmd/font.c
@@ -30,13 +30,17 @@ static int font_test_base(struct unit_test_state *uts)
ut_assertok(console_record_reset_enable());
ut_assertok(run_command("font list", 0));
ut_assert_nextline("nimbus_sans_l_regular");
- ut_assert_nextline("cantoraone_regular");
+ if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
+ ut_assert_nextline("cantoraone_regular");
ut_assertok(ut_check_console_end(uts));
ut_assertok(vidconsole_get_font_size(dev, &name, &size));
ut_asserteq_str("nimbus_sans_l_regular", name);
ut_asserteq(18, size);
+ if (!IS_ENABLED(CONFIG_CONSOLE_TRUETYPE_CANTORAONE))
+ return 0;
+
max_metrics = 1;
if (IS_ENABLED(CONFIG_CONSOLE_TRUETYPE))
max_metrics = IF_ENABLED_INT(CONFIG_CONSOLE_TRUETYPE,
diff --git a/test/cmd/mem_copy.c b/test/cmd/mem_copy.c
new file mode 100644
index 00000000000..1ba0cebbbe0
--- /dev/null
+++ b/test/cmd/mem_copy.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Tests for memory 'cp' command
+ */
+
+#include <command.h>
+#include <console.h>
+#include <mapmem.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+#define BUF_SIZE 256
+
+/* Declare a new mem test */
+#define MEM_TEST(_name) UNIT_TEST(_name, 0, mem_test)
+
+struct param {
+ int d, s, count;
+};
+
+static int do_test(struct unit_test_state *uts,
+ const char *suffix, int d, int s, int count)
+{
+ const long addr = 0x1000;
+ u8 shadow[BUF_SIZE];
+ u8 *buf;
+ int i, w, bytes;
+
+ buf = map_sysmem(addr, BUF_SIZE);
+
+ /* Fill with distinct bytes. */
+ for (i = 0; i < BUF_SIZE; ++i)
+ buf[i] = shadow[i] = i;
+
+ /* Parameter sanity checking. */
+ w = cmd_get_data_size(suffix, 4);
+ ut_assert(w == 1 || w == 2 || w == 4 || (MEM_SUPPORT_64BIT_DATA && w == 8));
+
+ bytes = count * w;
+ ut_assert(d < BUF_SIZE);
+ ut_assert(d + bytes <= BUF_SIZE);
+ ut_assert(s < BUF_SIZE);
+ ut_assert(s + bytes <= BUF_SIZE);
+
+ /* This is exactly what we expect to happen to "buf" */
+ memmove(shadow + d, shadow + s, bytes);
+
+ run_commandf("cp%s 0x%lx 0x%lx 0x%x", suffix, addr + s, addr + d, count);
+
+ ut_asserteq(0, memcmp(buf, shadow, BUF_SIZE));
+
+ unmap_sysmem(buf);
+
+ return 0;
+}
+
+static int mem_test_cp_b(struct unit_test_state *uts)
+{
+ static const struct param tests[] = {
+ { 0, 128, 128 },
+ { 128, 0, 128 },
+ { 0, 16, 32 },
+ { 16, 0, 32 },
+ { 60, 100, 100 },
+ { 100, 60, 100 },
+ { 123, 54, 96 },
+ { 54, 123, 96 },
+ };
+ const struct param *p;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ p = &tests[i];
+ ret = do_test(uts, ".b", p->d, p->s, p->count);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+MEM_TEST(mem_test_cp_b);
+
+static int mem_test_cp_w(struct unit_test_state *uts)
+{
+ static const struct param tests[] = {
+ { 0, 128, 64 },
+ { 128, 0, 64 },
+ { 0, 16, 16 },
+ { 16, 0, 16 },
+ { 60, 100, 50 },
+ { 100, 60, 50 },
+ { 123, 54, 48 },
+ { 54, 123, 48 },
+ };
+ const struct param *p;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ p = &tests[i];
+ ret = do_test(uts, ".w", p->d, p->s, p->count);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+MEM_TEST(mem_test_cp_w);
+
+static int mem_test_cp_l(struct unit_test_state *uts)
+{
+ static const struct param tests[] = {
+ { 0, 128, 32 },
+ { 128, 0, 32 },
+ { 0, 16, 8 },
+ { 16, 0, 8 },
+ { 60, 100, 25 },
+ { 100, 60, 25 },
+ { 123, 54, 24 },
+ { 54, 123, 24 },
+ };
+ const struct param *p;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ p = &tests[i];
+ ret = do_test(uts, ".l", p->d, p->s, p->count);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ p = &tests[i];
+ ret = do_test(uts, "", p->d, p->s, p->count);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+MEM_TEST(mem_test_cp_l);
+
+#if MEM_SUPPORT_64BIT_DATA
+static int mem_test_cp_q(struct unit_test_state *uts)
+{
+ static const struct param tests[] = {
+ { 0, 128, 16 },
+ { 128, 0, 16 },
+ { 0, 16, 8 },
+ { 16, 0, 8 },
+ { 60, 100, 15 },
+ { 100, 60, 15 },
+ { 123, 54, 12 },
+ { 54, 123, 12 },
+ };
+ const struct param *p;
+ int ret, i;
+
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ p = &tests[i];
+ ret = do_test(uts, ".q", p->d, p->s, p->count);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+MEM_TEST(mem_test_cp_q);
+#endif
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 2d5b80f992e..0677ce0cd17 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -45,7 +45,7 @@ int cmd_ut_category(const char *name, const char *prefix,
}
ret = ut_run_list(name, prefix, tests, n_ents,
- argc > 1 ? argv[1] : NULL, runs_per_text, force_run,
+ cmd_arg1(argc, argv), runs_per_text, force_run,
test_insert);
return ret ? CMD_RET_FAILURE : 0;
@@ -57,10 +57,13 @@ static struct cmd_tbl cmd_ut_sub[] = {
#ifdef CONFIG_CMD_BDI
U_BOOT_CMD_MKENT(bdinfo, CONFIG_SYS_MAXARGS, 1, do_ut_bdinfo, "", ""),
#endif
-#ifdef CONFIG_BOOTSTD
+#ifdef CONFIG_UT_BOOTSTD
U_BOOT_CMD_MKENT(bootstd, CONFIG_SYS_MAXARGS, 1, do_ut_bootstd,
"", ""),
#endif
+#ifdef CONFIG_CMDLINE
+ U_BOOT_CMD_MKENT(cmd, CONFIG_SYS_MAXARGS, 1, do_ut_cmd, "", ""),
+#endif
U_BOOT_CMD_MKENT(common, CONFIG_SYS_MAXARGS, 1, do_ut_common, "", ""),
#if defined(CONFIG_UT_DM)
U_BOOT_CMD_MKENT(dm, CONFIG_SYS_MAXARGS, 1, do_ut_dm, "", ""),
@@ -118,6 +121,9 @@ static struct cmd_tbl cmd_ut_sub[] = {
#ifdef CONFIG_CMD_ADDRMAP
U_BOOT_CMD_MKENT(addrmap, CONFIG_SYS_MAXARGS, 1, do_ut_addrmap, "", ""),
#endif
+#if CONFIG_IS_ENABLED(HUSH_PARSER)
+ U_BOOT_CMD_MKENT(hush, CONFIG_SYS_MAXARGS, 1, do_ut_hush, "", ""),
+#endif
#ifdef CONFIG_CMD_LOADM
U_BOOT_CMD_MKENT(loadm, CONFIG_SYS_MAXARGS, 1, do_ut_loadm, "", ""),
#endif
@@ -195,6 +201,9 @@ U_BOOT_LONGHELP(ut,
#ifdef CONFIG_BOOTSTD
"\nbootstd - standard boot implementation"
#endif
+#ifdef CONFIG_CMDLINE
+ "\ncmd - test various commands"
+#endif
#ifdef CONFIG_SANDBOX
"\ncompression - compressors and bootm decompression"
#endif
@@ -210,6 +219,9 @@ U_BOOT_LONGHELP(ut,
#ifdef CONFIG_CONSOLE_TRUETYPE
"\nfont - font command"
#endif
+#if CONFIG_IS_ENABLED(HUSH_PARSER)
+ "\nhush - Test hush behavior"
+#endif
#ifdef CONFIG_CMD_LOADM
"\nloadm - loadm command parameters and loading memory blob"
#endif
diff --git a/test/common/event.c b/test/common/event.c
index c0912a3437b..b462694fc3b 100644
--- a/test/common/event.c
+++ b/test/common/event.c
@@ -92,6 +92,9 @@ static int test_event_probe(struct unit_test_state *uts)
struct test_state state;
struct udevice *dev;
+ if (!IS_ENABLED(SANDBOX))
+ return -EAGAIN;
+
state.val = 0;
ut_assertok(event_register("pre", EVT_DM_PRE_PROBE, h_probe, &state));
ut_assertok(event_register("post", EVT_DM_POST_PROBE, h_probe, &state));
diff --git a/test/dm/acpi.c b/test/dm/acpi.c
index 5997bda649b..c53ebcdb1c1 100644
--- a/test/dm/acpi.c
+++ b/test/dm/acpi.c
@@ -291,8 +291,8 @@ static int dm_test_acpi_write_tables(struct unit_test_state *uts)
/* Check that the pointers were added correctly */
for (i = 0; i < 3; i++) {
- ut_asserteq(map_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
- ut_asserteq(map_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
+ ut_asserteq(nomap_to_sysmem(dmar + i), ctx.rsdt->entry[i]);
+ ut_asserteq(nomap_to_sysmem(dmar + i), ctx.xsdt->entry[i]);
}
ut_asserteq(0, ctx.rsdt->entry[3]);
ut_asserteq(0, ctx.xsdt->entry[3]);
@@ -330,7 +330,7 @@ static int dm_test_acpi_basic(struct unit_test_state *uts)
DM_TEST(dm_test_acpi_basic, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test setup_ctx_and_base_tables */
-static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
+static int dm_test_acpi_ctx_and_base_tables(struct unit_test_state *uts)
{
struct acpi_rsdp *rsdp;
struct acpi_rsdt *rsdt;
@@ -371,12 +371,12 @@ static int dm_test_setup_ctx_and_base_tables(struct unit_test_state *uts)
end = PTR_ALIGN((void *)xsdt + sizeof(*xsdt), 64);
ut_asserteq_ptr(end, ctx.current);
- ut_asserteq(map_to_sysmem(rsdt), rsdp->rsdt_address);
- ut_asserteq(map_to_sysmem(xsdt), rsdp->xsdt_address);
+ ut_asserteq(nomap_to_sysmem(rsdt), rsdp->rsdt_address);
+ ut_asserteq(nomap_to_sysmem(xsdt), rsdp->xsdt_address);
return 0;
}
-DM_TEST(dm_test_setup_ctx_and_base_tables,
+DM_TEST(dm_test_acpi_ctx_and_base_tables,
UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/* Test 'acpi list' command */
@@ -395,26 +395,26 @@ static int dm_test_acpi_cmd_list(struct unit_test_state *uts)
console_record_reset();
run_command("acpi list", 0);
- ut_assert_nextline("Name Base Size Detail");
- ut_assert_nextline("---- -------- ----- ------");
- ut_assert_nextline("RSDP %08lx %5zx v02 U-BOOT", addr,
+ ut_assert_nextline("Name Base Size Detail");
+ ut_assert_nextline("---- ---------------- ----- ----------------------------");
+ ut_assert_nextline("RSDP %16lx %5zx v02 U-BOOT", addr,
sizeof(struct acpi_rsdp));
addr = ALIGN(addr + sizeof(struct acpi_rsdp), 16);
- ut_assert_nextline("RSDT %08lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
+ ut_assert_nextline("RSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_table_header) +
3 * sizeof(u32), OEM_REVISION);
addr = ALIGN(addr + sizeof(struct acpi_rsdt), 16);
- ut_assert_nextline("XSDT %08lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
+ ut_assert_nextline("XSDT %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_table_header) +
3 * sizeof(u64), OEM_REVISION);
addr = ALIGN(addr + sizeof(struct acpi_xsdt), 64);
- ut_assert_nextline("DMAR %08lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_dmar), OEM_REVISION);
addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
- ut_assert_nextline("DMAR %08lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_dmar), OEM_REVISION);
addr = ALIGN(addr + sizeof(struct acpi_dmar), 16);
- ut_assert_nextline("DMAR %08lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
+ ut_assert_nextline("DMAR %16lx %5zx v01 U-BOOT U-BOOTBL %x INTL 0",
addr, sizeof(struct acpi_dmar), OEM_REVISION);
ut_assert_console_end();
@@ -445,8 +445,8 @@ static int dm_test_acpi_cmd_dump(struct unit_test_state *uts)
/* Now a real table */
console_record_reset();
run_command("acpi dump dmar", 0);
- addr = ALIGN(map_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
- ut_assert_nextline("DMAR @ %08lx", addr);
+ addr = ALIGN(nomap_to_sysmem(ctx.xsdt) + sizeof(struct acpi_xsdt), 64);
+ ut_assert_nextline("DMAR @ %16lx", addr);
ut_assert_nextlines_are_dump(0x30);
ut_assert_console_end();
@@ -651,3 +651,109 @@ static int dm_test_acpi_cmd_set(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_acpi_cmd_set, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+
+/**
+ * dm_test_write_test_table() - create test ACPI table
+ *
+ * Create an ACPI table TSTn, where n is given by @index.
+ *
+ * @ctx: ACPI table writing context
+ * @index: table index
+ * Return: generated table
+ */
+static struct acpi_table_header
+*dm_test_write_test_table(struct acpi_ctx *ctx, int index)
+{
+ struct acpi_table_header *tbl = ctx->current;
+ char signature[5];
+
+ snprintf(signature, sizeof(signature), "TST%1d", index);
+ memset(tbl, 0, sizeof(*tbl));
+ acpi_fill_header(tbl, signature);
+ acpi_inc(ctx, sizeof(struct acpi_table_header));
+ tbl->length = (u8 *)ctx->current - (u8 *)tbl;
+ tbl->checksum = table_compute_checksum(tbl, tbl->length);
+ acpi_add_table(ctx, tbl);
+
+ return tbl;
+}
+
+/* Test acpi_find_table() */
+static int dm_test_acpi_find_table(struct unit_test_state *uts)
+{
+ struct acpi_ctx ctx;
+ ulong acpi_start, addr;
+ void *buf;
+ struct acpi_table_header *table, *table1, *table2, *table3;
+ struct acpi_rsdp *rsdp;
+ ulong rsdt;
+ ulong xsdt;
+
+ /* Keep reference to original ACPI tables */
+ acpi_start = gd_acpi_start();
+
+ /* Setup new ACPI tables */
+ buf = memalign(16, BUF_SIZE);
+ ut_assertnonnull(buf);
+ addr = map_to_sysmem(buf);
+ ut_assertok(setup_ctx_and_base_tables(uts, &ctx, addr));
+ table3 = dm_test_write_test_table(&ctx, 3);
+ table1 = dm_test_write_test_table(&ctx, 1);
+ table2 = dm_test_write_test_table(&ctx, 2);
+
+ /* Retrieve RSDP, RSDT, XSDT */
+ rsdp = map_sysmem(gd_acpi_start(), 0);
+ ut_assertnonnull(rsdp);
+ rsdt = rsdp->rsdt_address;
+ ut_assert(rsdt);
+ xsdt = rsdp->xsdt_address;
+ ut_assert(xsdt);
+
+ /* Find with both RSDT and XSDT */
+ table = acpi_find_table("TST1");
+ ut_asserteq_ptr(table1, table);
+ ut_asserteq_strn("TST1", table->signature);
+ table = acpi_find_table("TST2");
+ ut_asserteq_ptr(table2, table);
+ ut_asserteq_strn("TST2", table->signature);
+ table = acpi_find_table("TST3");
+ ut_asserteq_ptr(table3, table);
+ ut_asserteq_strn("TST3", table->signature);
+
+ /* Find with XSDT only */
+ rsdp->rsdt_address = 0;
+ table = acpi_find_table("TST1");
+ ut_asserteq_ptr(table1, table);
+ table = acpi_find_table("TST2");
+ ut_asserteq_ptr(table2, table);
+ table = acpi_find_table("TST3");
+ ut_asserteq_ptr(table3, table);
+ rsdp->rsdt_address = rsdt;
+
+ /* Find with RSDT only */
+ rsdp->xsdt_address = 0;
+ table = acpi_find_table("TST1");
+ ut_asserteq_ptr(table1, table);
+ table = acpi_find_table("TST2");
+ ut_asserteq_ptr(table2, table);
+ table = acpi_find_table("TST3");
+ ut_asserteq_ptr(table3, table);
+ rsdp->xsdt_address = xsdt;
+
+ /* Restore previous ACPI tables */
+ gd_set_acpi_start(acpi_start);
+ free(buf);
+
+ return 0;
+}
+DM_TEST(dm_test_acpi_find_table, 0);
+
+/* Test offsets in RSDT, XSDT */
+static int dm_test_acpi_offsets(struct unit_test_state *uts)
+{
+ ut_asserteq(36, offsetof(struct acpi_rsdt, entry));
+ ut_asserteq(36, offsetof(struct acpi_xsdt, entry));
+
+ return 0;
+}
+DM_TEST(dm_test_acpi_offsets, 0);
diff --git a/test/dm/clk_ccf.c b/test/dm/clk_ccf.c
index e4ebb93cdad..61dad8d8527 100644
--- a/test/dm/clk_ccf.c
+++ b/test/dm/clk_ccf.c
@@ -19,16 +19,18 @@
static int dm_test_clk_ccf(struct unit_test_state *uts)
{
struct clk *clk, *pclk;
- struct udevice *dev;
+ struct udevice *dev, *test_dev;
long long rate;
int ret;
#if CONFIG_IS_ENABLED(CLK_CCF)
+ struct clk clk_ccf;
const char *clkname;
int clkid, i;
#endif
/* Get the device using the clk device */
ut_assertok(uclass_get_device_by_name(UCLASS_CLK, "clk-ccf", &dev));
+ ut_assertok(uclass_get_device_by_name(UCLASS_MISC, "clk-test", &test_dev));
/* Test for clk_get_by_id() */
ret = clk_get_by_id(SANDBOX_CLK_ECSPI_ROOT, &clk);
@@ -63,6 +65,9 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
rate = clk_get_parent_rate(clk);
ut_asserteq(rate, 60000000);
+ rate = clk_set_rate(clk, 60000000);
+ ut_asserteq(rate, -ENOSYS);
+
rate = clk_get_rate(clk);
ut_asserteq(rate, 60000000);
@@ -87,6 +92,9 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
ut_asserteq_str("pll3_80m", pclk->dev->name);
ut_asserteq(CLK_SET_RATE_PARENT, pclk->flags);
+ rate = clk_set_rate(clk, 80000000);
+ ut_asserteq(rate, -ENOSYS);
+
rate = clk_get_rate(clk);
ut_asserteq(rate, 80000000);
@@ -108,13 +116,23 @@ static int dm_test_clk_ccf(struct unit_test_state *uts)
rate = clk_get_rate(clk);
ut_asserteq(rate, 60000000);
+ rate = clk_set_rate(clk, 60000000);
+ ut_asserteq(rate, 60000000);
+
#if CONFIG_IS_ENABLED(CLK_CCF)
/* Test clk tree enable/disable */
+
+ ret = clk_get_by_index(test_dev, SANDBOX_CLK_TEST_ID_I2C_ROOT, &clk_ccf);
+ ut_assertok(ret);
+ ut_asserteq_str("clk-ccf", clk_ccf.dev->name);
+ ut_asserteq(clk_ccf.id, SANDBOX_CLK_I2C_ROOT);
+
ret = clk_get_by_id(SANDBOX_CLK_I2C_ROOT, &clk);
ut_assertok(ret);
ut_asserteq_str("i2c_root", clk->dev->name);
+ ut_asserteq(clk->id, SANDBOX_CLK_I2C_ROOT);
- ret = clk_enable(clk);
+ ret = clk_enable(&clk_ccf);
ut_assertok(ret);
ret = sandbox_clk_enable_count(clk);
diff --git a/test/dm/scmi.c b/test/dm/scmi.c
index da45314f2e4..adf36ffaab1 100644
--- a/test/dm/scmi.c
+++ b/test/dm/scmi.c
@@ -19,10 +19,10 @@
#include <scmi_agent.h>
#include <scmi_agent-uclass.h>
#include <scmi_protocols.h>
+#include <vsprintf.h>
#include <asm/scmi_test.h>
#include <dm/device-internal.h>
#include <dm/test.h>
-#include <linux/kconfig.h>
#include <power/regulator.h>
#include <test/ut.h>
@@ -206,6 +206,86 @@ static int dm_test_scmi_base(struct unit_test_state *uts)
DM_TEST(dm_test_scmi_base, UT_TESTF_SCAN_FDT);
+static int dm_test_scmi_cmd(struct unit_test_state *uts)
+{
+ struct udevice *agent_dev;
+ int num_proto = 0;
+ char cmd_out[30];
+
+ if (!CONFIG_IS_ENABLED(CMD_SCMI))
+ return -EAGAIN;
+
+ /* preparation */
+ ut_assertok(uclass_get_device_by_name(UCLASS_SCMI_AGENT, "scmi",
+ &agent_dev));
+ ut_assertnonnull(agent_dev);
+
+ /*
+ * Estimate the number of provided protocols.
+ * This estimation is correct as far as a corresponding
+ * protocol support is added to sandbox fake serer.
+ */
+ if (CONFIG_IS_ENABLED(POWER_DOMAIN))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(RESET_SCMI))
+ num_proto++;
+ if (CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ num_proto++;
+
+ /* scmi info */
+ ut_assertok(run_command("scmi info", 0));
+
+ ut_assert_nextline("SCMI device: scmi");
+ snprintf(cmd_out, 30, " protocol version: 0x%x",
+ SCMI_BASE_PROTOCOL_VERSION);
+ ut_assert_nextline(cmd_out);
+ ut_assert_nextline(" # of agents: 2");
+ ut_assert_nextline(" 0: platform");
+ ut_assert_nextline(" > 1: OSPM");
+ snprintf(cmd_out, 30, " # of protocols: %d", num_proto);
+ ut_assert_nextline(cmd_out);
+ if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN))
+ ut_assert_nextline(" Power domain management");
+ if (CONFIG_IS_ENABLED(CLK_SCMI))
+ ut_assert_nextline(" Clock management");
+ if (CONFIG_IS_ENABLED(RESET_SCMI))
+ ut_assert_nextline(" Reset domain management");
+ if (CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ ut_assert_nextline(" Voltage domain management");
+ ut_assert_nextline(" vendor: U-Boot");
+ ut_assert_nextline(" sub vendor: Sandbox");
+ ut_assert_nextline(" impl version: 0x1");
+
+ ut_assert_console_end();
+
+ /* scmi perm_dev */
+ ut_assertok(run_command("scmi perm_dev 1 0 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_dev 1 0 0", 0));
+ ut_assert_nextline("Denying access to device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi perm_proto */
+ ut_assertok(run_command("scmi perm_proto 1 0 14 1", 0));
+ ut_assert_console_end();
+
+ ut_assert(run_command("scmi perm_proto 1 0 14 0", 0));
+ ut_assert_nextline("Denying access to protocol:0x14 on device:0 failed (-13)");
+ ut_assert_console_end();
+
+ /* scmi reset */
+ ut_assert(run_command("scmi reset 1 1", 0));
+ ut_assert_nextline("Reset failed (-13)");
+ ut_assert_console_end();
+
+ return 0;
+}
+
+DM_TEST(dm_test_scmi_cmd, UT_TESTF_SCAN_FDT);
+
static int dm_test_scmi_power_domains(struct unit_test_state *uts)
{
struct sandbox_scmi_agent *agent;
@@ -217,6 +297,9 @@ static int dm_test_scmi_power_domains(struct unit_test_state *uts)
u8 *name;
int ret;
+ if (!CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN))
+ return -EAGAIN;
+
/* preparation */
ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
ut_assertnonnull(agent);
@@ -317,6 +400,9 @@ static int dm_test_scmi_clocks(struct unit_test_state *uts)
int ret_dev;
int ret;
+ if (!CONFIG_IS_ENABLED(CLK_SCMI))
+ return -EAGAIN;
+
ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
@@ -382,6 +468,9 @@ static int dm_test_scmi_resets(struct unit_test_state *uts)
struct udevice *agent_dev, *reset_dev, *dev = NULL;
int ret;
+ if (!CONFIG_IS_ENABLED(RESET_SCMI))
+ return -EAGAIN;
+
ret = load_sandbox_scmi_test_devices(uts, &agent, &dev);
if (ret)
return ret;
@@ -418,6 +507,9 @@ static int dm_test_scmi_voltage_domains(struct unit_test_state *uts)
struct udevice *dev;
struct udevice *regul0_dev;
+ if (!CONFIG_IS_ENABLED(DM_REGULATOR_SCMI))
+ return -EAGAIN;
+
ut_assertok(load_sandbox_scmi_test_devices(uts, &agent, &dev));
scmi_devices = sandbox_scmi_devices_ctx(dev);
diff --git a/test/dm/spmi.c b/test/dm/spmi.c
index 9cc284b98cb..97bb0eb30fc 100644
--- a/test/dm/spmi.c
+++ b/test/dm/spmi.c
@@ -81,7 +81,7 @@ static int dm_test_spmi_access_peripheral(struct unit_test_state *uts)
int offset_count;
/* Get second pin of PMIC GPIO */
- ut_assertok(gpio_lookup_name("spmi1", &dev, &offset, &gpio));
+ ut_assertok(gpio_lookup_name("pmic1", &dev, &offset, &gpio));
/* Check if PMIC is parent */
ut_asserteq(device_get_uclass_id(dev->parent), UCLASS_PMIC);
@@ -92,7 +92,7 @@ static int dm_test_spmi_access_peripheral(struct unit_test_state *uts)
name = gpio_get_bank_info(dev, &offset_count);
/* Check bank name */
- ut_asserteq_str("spmi", name);
+ ut_asserteq_str("pmic", name);
/* Check pin count */
ut_asserteq(4, offset_count);
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index dec2634de37..257b50fd063 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -23,7 +23,7 @@
# --------------------------------------------
# pre-requisite binaries list.
-PREREQ_BINS="md5sum mkfs mount umount dd fallocate mkdir"
+PREREQ_BINS="sha256sum mkfs mount umount dd fallocate mkdir"
# All generated output files from this test will be in $OUT_DIR
# Hence everything is sandboxed.
@@ -44,9 +44,9 @@ SMALL_FILE="1MB.file"
# $BIG_FILE is the name of the 2.5GB file in the file system image
BIG_FILE="2.5GB.file"
-# $MD5_FILE will have the expected md5s when we do the test
+# $HASH_FILE will have the expected hashes when we do the test
# They shall have a suffix which represents their file system (ext4/fat16/...)
-MD5_FILE="${OUT_DIR}/md5s.list"
+HASH_FILE="${OUT_DIR}/hash.list"
# $OUT shall be the prefix of the test output. Their suffix will be .out
OUT="${OUT_DIR}/fs-test"
@@ -103,7 +103,7 @@ function compile_sandbox() {
# Clean out all generated files other than the file system images
# We save time by not deleting and recreating the file system images
function prepare_env() {
- rm -f ${MD5_FILE}.* ${OUT}.*
+ rm -f ${HASH_FILE}.* ${OUT}.*
mkdir -p ${OUT_DIR}
}
@@ -254,14 +254,14 @@ setenv filesize
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
printenv filesize
# Test Case 4b - Read full 1MB of small file
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# Test Case 5a - First 1MB of big file
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x0
printenv filesize
# Test Case 5b - First 1MB of big file
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# fails for ext as no offset support
@@ -269,7 +269,7 @@ setenv filesize
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x9C300000
printenv filesize
# Test Case 6b - Last 1MB of big file
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# fails for ext as no offset support
@@ -277,7 +277,7 @@ setenv filesize
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF00000
printenv filesize
# Test Case 7b - One from the last 1MB chunk of 2GB
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# fails for ext as no offset support
@@ -285,7 +285,7 @@ setenv filesize
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x80000000
printenv filesize
# Test Case 8b - One from the start 1MB chunk from 2GB
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# fails for ext as no offset support
@@ -293,7 +293,7 @@ setenv filesize
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_BIG $length 0x7FF80000
printenv filesize
# Test Case 9b - One 1MB chunk crossing the 2GB boundary
-md5sum $addr \$filesize
+hash sha256 $addr \$filesize
setenv filesize
# Generic failure case
@@ -309,8 +309,8 @@ ${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}$FILE_WRITE \$filesize
mw.b $addr 00 100
${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_WRITE
-# Test Case 11b - Check md5 of written to is same as the one read from
-md5sum $addr \$filesize
+# Test Case 11b - Check hash of written to is same as the one read from
+hash sha256 $addr \$filesize
setenv filesize
#
@@ -327,13 +327,13 @@ ${PREFIX}load host${SUFFIX} $addr ${FPATH}$FILE_SMALL
${PREFIX}${WRITE} host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2 \$filesize
mw.b $addr 00 100
${PREFIX}load host${SUFFIX} $addr ${FPATH}./${FILE_WRITE}2
-# Test Case 13b - Check md5 of written to is same as the one read from
-md5sum $addr \$filesize
+# Test Case 13b - Check hash of written to is same as the one read from
+hash sha256 $addr \$filesize
setenv filesize
mw.b $addr 00 100
${PREFIX}load host${SUFFIX} $addr ${FPATH}${FILE_WRITE}2
-# Test Case 13c - Check md5 of written to is same as the one read from
-md5sum $addr \$filesize
+# Test Case 13c - Check hash of written to is same as the one read from
+ hasheshash sha256 $addr \$filesize
setenv filesize
#
reset
@@ -342,7 +342,7 @@ EOF
}
# 1st argument is the name of the image file.
-# 2nd argument is the file where we generate the md5s of the files
+# 2nd argument is the file where we generate the hashes of the files
# generated with the appropriate start and length that we use to test.
# It creates the necessary files in the image to test.
# $GB2p5 is the path of the big file (2.5 GB)
@@ -380,29 +380,29 @@ function create_files() {
sudo rm -f "${MB1}.w"
sudo rm -f "${MB1}.w2"
- # Generate the md5sums of reads that we will test against small file
- dd if="${MB1}" bs=1M skip=0 count=1 2> /dev/null | md5sum > "$2"
+ # Generate the hashes of reads that we will test against small file
+ dd if="${MB1}" bs=1M skip=0 count=1 2> /dev/null | sha256sum > "$2"
- # Generate the md5sums of reads that we will test against big file
+ # Generate the hashes of reads that we will test against big file
# One from beginning of file.
dd if="${GB2p5}" bs=1M skip=0 count=1 \
- 2> /dev/null | md5sum >> "$2"
+ 2> /dev/null | sha256sum >> "$2"
# One from end of file.
dd if="${GB2p5}" bs=1M skip=2499 count=1 \
- 2> /dev/null | md5sum >> "$2"
+ 2> /dev/null | sha256sum >> "$2"
# One from the last 1MB chunk of 2GB
dd if="${GB2p5}" bs=1M skip=2047 count=1 \
- 2> /dev/null | md5sum >> "$2"
+ 2> /dev/null | sha256sum >> "$2"
# One from the start 1MB chunk from 2GB
dd if="${GB2p5}" bs=1M skip=2048 count=1 \
- 2> /dev/null | md5sum >> "$2"
+ 2> /dev/null | sha256sum >> "$2"
# One 1MB chunk crossing the 2GB boundary
dd if="${GB2p5}" bs=512K skip=4095 count=2 \
- 2> /dev/null | md5sum >> "$2"
+ 2> /dev/null | sha256sum >> "$2"
sync
sudo umount "$MOUNT_DIR"
@@ -422,35 +422,35 @@ function pass_fail() {
fi
}
-# 1st parameter is the string which leads to an md5 generation
+# 1st parameter is the string which leads to an hash generation
# 2nd parameter is the file we grep, for that string
-# 3rd parameter is the name of the file which has md5s in it
-# 4th parameter is the line # in the md5 file that we match it against
-# This function checks if the md5 of the file in the sandbox matches
+# 3rd parameter is the name of the file which has hashes in it
+# 4th parameter is the line # in the hash file that we match against
+# This function checks if the hash of the file in the sandbox matches
# that calculated while generating the file
# 5th parameter is the string to print with the result
-check_md5() {
- # md5sum in u-boot has output of form:
- # md5 for 01000008 ... 01100007 ==> <md5>
- # the 7th field is the actual md5
- md5_src=`grep -A2 "$1" "$2" | grep "md5 for" | tr -d '\r'`
- md5_src=($md5_src)
- md5_src=${md5_src[6]}
-
- # The md5 list, each line is of the form:
- # - <md5>
- # the 2nd field is the actual md5
- md5_dst=`sed -n $4p $3`
- md5_dst=($md5_dst)
- md5_dst=${md5_dst[0]}
+check_hash() {
+ # hash cmd output in u-boot has output of form:
+ # sha256 for 01000008 ... 01100007 ==> <hash>
+ # the 7th field is the actual hash
+ hash_src=`grep -A2 "$1" "$2" | grep "sha256 for" | tr -d '\r'`
+ hash_src=($hash_src)
+ hash_src=${hash_src[6]}
+
+ # The hash list, each line is of the form:
+ # - <hash>
+ # the 2nd field is the actual hash
+ hash_dst=`sed -n $4p $3`
+ hash_dst=($hash_dst)
+ hash_dst=${hash_dst[0]}
# For a pass they should match.
- [ "$md5_src" = "$md5_dst" ]
+ [ "$hash_src" = "$hash_dst" ]
pass_fail "$5"
}
# 1st parameter is the name of the output file to check
-# 2nd parameter is the name of the file containing the md5 expected
+# 2nd parameter is the name of the file containing the expected hash
# 3rd parameter is the name of the small file
# 4th parameter is the name of the big file
# 5th paramter is the name of the written file
@@ -483,34 +483,34 @@ function check_results() {
# Check read full mb of 1MB.file
grep -A4 "Test Case 4a " "$1" | grep -q "filesize=100000"
pass_fail "TC4: load of $3 size"
- check_md5 "Test Case 4b " "$1" "$2" 1 "TC4: load from $3"
+ check_hash "Test Case 4b " "$1" "$2" 1 "TC4: load from $3"
# Check first mb of 2.5GB.file
grep -A4 "Test Case 5a " "$1" | grep -q "filesize=100000"
pass_fail "TC5: load of 1st MB from $4 size"
- check_md5 "Test Case 5b " "$1" "$2" 2 "TC5: load of 1st MB from $4"
+ check_hash "Test Case 5b " "$1" "$2" 2 "TC5: load of 1st MB from $4"
# Check last mb of 2.5GB.file
grep -A4 "Test Case 6a " "$1" | grep -q "filesize=100000"
pass_fail "TC6: load of last MB from $4 size"
- check_md5 "Test Case 6b " "$1" "$2" 3 "TC6: load of last MB from $4"
+ check_hash "Test Case 6b " "$1" "$2" 3 "TC6: load of last MB from $4"
# Check last 1mb chunk of 2gb from 2.5GB file
grep -A4 "Test Case 7a " "$1" | grep -q "filesize=100000"
pass_fail "TC7: load of last 1mb chunk of 2GB from $4 size"
- check_md5 "Test Case 7b " "$1" "$2" 4 \
+ check_hash "Test Case 7b " "$1" "$2" 4 \
"TC7: load of last 1mb chunk of 2GB from $4"
# Check first 1mb chunk after 2gb from 2.5GB file
grep -A4 "Test Case 8a " "$1" | grep -q "filesize=100000"
pass_fail "TC8: load 1st MB chunk after 2GB from $4 size"
- check_md5 "Test Case 8b " "$1" "$2" 5 \
+ check_hash "Test Case 8b " "$1" "$2" 5 \
"TC8: load 1st MB chunk after 2GB from $4"
# Check 1mb chunk crossing the 2gb boundary from 2.5GB file
grep -A4 "Test Case 9a " "$1" | grep -q "filesize=100000"
pass_fail "TC9: load 1MB chunk crossing 2GB boundary from $4 size"
- check_md5 "Test Case 9b " "$1" "$2" 6 \
+ check_hash "Test Case 9b " "$1" "$2" 6 \
"TC9: load 1MB chunk crossing 2GB boundary from $4"
# Check 2mb chunk from the last 1MB of 2.5GB file loads 1MB
@@ -520,7 +520,7 @@ function check_results() {
# Check 1mb chunk write
grep -A2 "Test Case 11a " "$1" | grep -q '1048576 bytes written'
pass_fail "TC11: 1MB write to $3.w - write succeeded"
- check_md5 "Test Case 11b " "$1" "$2" 1 \
+ check_hash "Test Case 11b " "$1" "$2" 1 \
"TC11: 1MB write to $3.w - content verified"
# Check lookup of 'dot' directory
@@ -530,9 +530,9 @@ function check_results() {
# Check directory traversal
grep -A2 "Test Case 13a " "$1" | grep -q '1048576 bytes written'
pass_fail "TC13: 1MB write to ./$3.w2 - write succeeded"
- check_md5 "Test Case 13b " "$1" "$2" 1 \
+ check_hash "Test Case 13b " "$1" "$2" 1 \
"TC13: 1MB read from ./$3.w2 - content verified"
- check_md5 "Test Case 13c " "$1" "$2" 1 \
+ check_hash "Test Case 13c " "$1" "$2" 1 \
"TC13: 1MB read from $3.w2 - content verified"
echo "** End $1"
@@ -543,7 +543,7 @@ function check_results() {
# be performed.
function test_fs_nonfs() {
echo "Creating files in $fs image if not already present."
- create_files $IMAGE $MD5_FILE_FS
+ create_files $IMAGE $HASH_FILE_FS
OUT_FILE="${OUT}.$1.${fs}.out"
test_image $IMAGE $fs $SMALL_FILE $BIG_FILE $1 "" \
@@ -552,7 +552,7 @@ function test_fs_nonfs() {
grep -v -e "File System is consistent\|update journal finished" \
-e "reading .*\.file\|writing .*\.file.w" \
< ${OUT_FILE} > ${OUT_FILE}_clean
- check_results ${OUT_FILE}_clean $MD5_FILE_FS $SMALL_FILE \
+ check_results ${OUT_FILE}_clean $HASH_FILE_FS $SMALL_FILE \
$BIG_FILE
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
TOTAL_PASS=$((TOTAL_PASS + PASS))
@@ -580,12 +580,12 @@ for fs in ext4 fat16 fat32; do
echo "Creating $fs image if not already present."
IMAGE=${IMG}.${fs}.img
- MD5_FILE_FS="${MD5_FILE}.${fs}"
+ HASH_FILE_FS="${HASH_FILE}.${fs}"
create_image $IMAGE $fs
# host commands test
echo "Creating files in $fs image if not already present."
- create_files $IMAGE $MD5_FILE_FS
+ create_files $IMAGE $HASH_FILE_FS
# Lets mount the image and test host hostfs commands
mkdir -p "$MOUNT_DIR"
@@ -606,7 +606,7 @@ for fs in ext4 fat16 fat32; do
sudo umount "$MOUNT_DIR"
rmdir "$MOUNT_DIR"
- check_results $OUT_FILE $MD5_FILE_FS $SMALL_FILE $BIG_FILE
+ check_results $OUT_FILE $HASH_FILE_FS $SMALL_FILE $BIG_FILE
TOTAL_FAIL=$((TOTAL_FAIL + FAIL))
TOTAL_PASS=$((TOTAL_PASS + PASS))
echo "Summary: PASS: $PASS FAIL: $FAIL"
diff --git a/test/hush/Makefile b/test/hush/Makefile
new file mode 100644
index 00000000000..a2d98815e50
--- /dev/null
+++ b/test/hush/Makefile
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# (C) Copyright 2021
+# Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+
+obj-y += cmd_ut_hush.o
+obj-y += if.o
+obj-y += dollar.o
+obj-y += list.o
+obj-y += loop.o
diff --git a/test/hush/cmd_ut_hush.c b/test/hush/cmd_ut_hush.c
new file mode 100644
index 00000000000..abad44f3216
--- /dev/null
+++ b/test/hush/cmd_ut_hush.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021
+ * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+ */
+
+#include <command.h>
+#include <test/hush.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+int do_ut_hush(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct unit_test *tests = UNIT_TEST_SUITE_START(hush_test);
+ const int n_ents = UNIT_TEST_SUITE_COUNT(hush_test);
+
+ return cmd_ut_category("hush", "hush_test_",
+ tests, n_ents, argc, argv);
+}
diff --git a/test/hush/dollar.c b/test/hush/dollar.c
new file mode 100644
index 00000000000..4caa07c192a
--- /dev/null
+++ b/test/hush/dollar.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021
+ * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+ */
+
+#include <command.h>
+#include <env_attr.h>
+#include <test/hush.h>
+#include <test/ut.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int hush_test_simple_dollar(struct unit_test_state *uts)
+{
+ console_record_reset_enable();
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline_empty();
+ ut_assert_console_end();
+
+ ut_assertok(run_command("echo ${dollar_foo}", 0));
+ ut_assert_nextline_empty();
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_foo=bar", 0));
+
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("echo ${dollar_foo}", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_foo=\\$bar", 0));
+
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline("$bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_foo='$bar'", 0));
+
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline("$bar");
+ ut_assert_console_end();
+
+ ut_asserteq(1, run_command("dollar_foo=bar quux", 0));
+ /* Next line contains error message */
+ ut_assert_skipline();
+ ut_assert_console_end();
+
+ ut_asserteq(1, run_command("dollar_foo='bar quux", 0));
+ /* Next line contains error message */
+ ut_assert_skipline();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * For some strange reasons, the console is not empty after
+ * running above command.
+ * So, we reset it to not have side effects for other tests.
+ */
+ console_record_reset_enable();
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_assert_console_end();
+ }
+
+ ut_asserteq(1, run_command("dollar_foo=bar quux\"", 0));
+ /* Two next lines contain error message */
+ ut_assert_skipline();
+ ut_assert_skipline();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* See above comments. */
+ console_record_reset_enable();
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_assert_console_end();
+ }
+
+ ut_assertok(run_command("dollar_foo='bar \"quux'", 0));
+
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ /*
+ * This one is buggy.
+ * ut_assert_nextline("bar \"quux");
+ * ut_assert_console_end();
+ *
+ * So, let's reset output:
+ */
+ console_record_reset_enable();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * Old parser returns an error because it waits for closing
+ * '\'', but this behavior is wrong as the '\'' is surrounded by
+ * '"', so no need to wait for a closing one.
+ */
+ ut_assertok(run_command("dollar_foo=\"bar 'quux\"", 0));
+
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline("bar 'quux");
+ ut_assert_console_end();
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_asserteq(1, run_command("dollar_foo=\"bar 'quux\"", 0));
+ /* Next line contains error message */
+ ut_assert_skipline();
+ ut_assert_console_end();
+ }
+
+ ut_assertok(run_command("dollar_foo='bar quux'", 0));
+ ut_assertok(run_command("echo $dollar_foo", 0));
+ ut_assert_nextline("bar quux");
+ ut_assert_console_end();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* Reset local variable. */
+ ut_assertok(run_command("dollar_foo=", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ puts("Beware: this test set local variable dollar_foo and it cannot be unset!");
+ }
+
+ return 0;
+}
+HUSH_TEST(hush_test_simple_dollar, 0);
+
+static int hush_test_env_dollar(struct unit_test_state *uts)
+{
+ env_set("env_foo", "bar");
+ console_record_reset_enable();
+
+ ut_assertok(run_command("echo $env_foo", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("echo ${env_foo}", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ /* Environment variables have priority over local variable */
+ ut_assertok(run_command("env_foo=quux", 0));
+ ut_assertok(run_command("echo ${env_foo}", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ /* Clean up setting the variable */
+ env_set("env_foo", NULL);
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* Reset local variable. */
+ ut_assertok(run_command("env_foo=", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ puts("Beware: this test set local variable env_foo and it cannot be unset!");
+ }
+
+ return 0;
+}
+HUSH_TEST(hush_test_env_dollar, 0);
+
+static int hush_test_command_dollar(struct unit_test_state *uts)
+{
+ console_record_reset_enable();
+
+ ut_assertok(run_command("dollar_bar=\"echo bar\"", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("${dollar_bar}", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_bar=\"echo\nbar\"", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_bar='echo bar\n'", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_bar='echo bar\\n'", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * This difference seems to come from a bug solved in Busybox
+ * hush.
+ * Behavior of hush 2021 is coherent with bash and other shells.
+ */
+ ut_assert_nextline("bar\\n");
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_assert_nextline("barn");
+ }
+
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_bar='echo $bar'", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+ ut_assert_nextline("$bar");
+ ut_assert_console_end();
+
+ ut_assertok(run_command("dollar_quux=quux", 0));
+ ut_assertok(run_command("dollar_bar=\"echo $dollar_quux\"", 0));
+
+ ut_assertok(run_command("$dollar_bar", 0));
+ ut_assert_nextline("quux");
+ ut_assert_console_end();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* Reset local variables. */
+ ut_assertok(run_command("dollar_bar=", 0));
+ ut_assertok(run_command("dollar_quux=", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ puts("Beware: this test sets local variable dollar_bar and dollar_quux and they cannot be unset!");
+ }
+
+ return 0;
+}
+HUSH_TEST(hush_test_command_dollar, 0);
diff --git a/test/hush/if.c b/test/hush/if.c
new file mode 100644
index 00000000000..8939b7a6c86
--- /dev/null
+++ b/test/hush/if.c
@@ -0,0 +1,316 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021
+ * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+ */
+
+#include <command.h>
+#include <env_attr.h>
+#include <vsprintf.h>
+#include <test/hush.h>
+#include <test/ut.h>
+
+/*
+ * All tests will execute the following:
+ * if condition_to_test; then
+ * true
+ * else
+ * false
+ * fi
+ * If condition is true, command returns 1, 0 otherwise.
+ */
+const char *if_format = "if %s; then true; else false; fi";
+
+static int hush_test_if_base(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "true");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "false");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_base, 0);
+
+static int hush_test_if_basic_operators(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test aaa = aaa");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa = bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa != bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa != aaa");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa < bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test bbb < aaa");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test bbb > aaa");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa > bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -eq 123");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -eq 456");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -ne 456");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -ne 123");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -lt 456");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -lt 123");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 456 -lt 123");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -le 456");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -le 123");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 456 -le 123");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 456 -gt 123");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -gt 123");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -gt 456");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 456 -ge 123");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -ge 123");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 123 -ge 456");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_basic_operators, 0);
+
+static int hush_test_if_octal(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test 010 -eq 010");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 010 -eq 011");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 010 -ne 011");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 010 -ne 010");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_octal, 0);
+
+static int hush_test_if_hexadecimal(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -gt 0x2000001");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -gt 0x2000000");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -gt 0x1ffffff");
+ ut_assertok(run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_hexadecimal, 0);
+
+static int hush_test_if_mixed(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test 010 -eq 10");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 010 -ne 10");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0xa -eq 10");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0xa -eq 012");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 2000000 -gt 0x1ffffff");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -gt 1ffffff");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -lt 1ffffff");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -eq 2000000");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test 0x2000000 -ne 2000000");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -z \"\"");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -z \"aaa\"");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -n \"aaa\"");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -n \"\"");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_mixed, 0);
+
+static int hush_test_if_inverted(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test ! aaa = aaa");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! aaa = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! ! aaa = aaa");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! ! aaa = bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_inverted, 0);
+
+static int hush_test_if_binary(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test aaa != aaa -o bbb != bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa != aaa -o bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa = aaa -o bbb != bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa = aaa -o bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa != aaa -a bbb != bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa != aaa -a bbb = bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa = aaa -a bbb != bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test aaa = aaa -a bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_binary, 0);
+
+static int hush_test_if_inverted_binary(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ sprintf(if_formatted, if_format, "test ! aaa != aaa -o ! bbb != bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! aaa != aaa -o ! bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! aaa = aaa -o ! bbb != bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! aaa = aaa -o ! bbb = bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format,
+ "test ! ! aaa != aaa -o ! ! bbb != bbb");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format,
+ "test ! ! aaa != aaa -o ! ! bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format,
+ "test ! ! aaa = aaa -o ! ! bbb != bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test ! ! aaa = aaa -o ! ! bbb = bbb");
+ ut_assertok(run_command(if_formatted, 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_inverted_binary, 0);
+
+static int hush_test_if_z_operator(struct unit_test_state *uts)
+{
+ char if_formatted[128];
+
+ /* Deal with environment variable used during test. */
+ env_set("ut_var_nonexistent", NULL);
+ env_set("ut_var_exists", "1");
+ env_set("ut_var_unset", "1");
+
+ sprintf(if_formatted, if_format, "test -z \"$ut_var_nonexistent\"");
+ ut_assertok(run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -z \"$ut_var_exists\"");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ sprintf(if_formatted, if_format, "test -z \"$ut_var_unset\"");
+ ut_asserteq(1, run_command(if_formatted, 0));
+
+ env_set("ut_var_unset", NULL);
+ sprintf(if_formatted, if_format, "test -z \"$ut_var_unset\"");
+ ut_assertok(run_command(if_formatted, 0));
+
+ /* Clear the set environment variable. */
+ env_set("ut_var_exists", NULL);
+
+ return 0;
+}
+HUSH_TEST(hush_test_if_z_operator, 0);
diff --git a/test/hush/list.c b/test/hush/list.c
new file mode 100644
index 00000000000..210823db2f5
--- /dev/null
+++ b/test/hush/list.c
@@ -0,0 +1,139 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021
+ * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+ */
+
+#include <command.h>
+#include <env_attr.h>
+#include <test/hush.h>
+#include <test/ut.h>
+#include <asm/global_data.h>
+
+static int hush_test_semicolon(struct unit_test_state *uts)
+{
+ /* A; B = B truth table. */
+ ut_asserteq(1, run_command("false; false", 0));
+ ut_assertok(run_command("false; true", 0));
+ ut_assertok(run_command("true; true", 0));
+ ut_asserteq(1, run_command("true; false", 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_semicolon, 0);
+
+static int hush_test_and(struct unit_test_state *uts)
+{
+ /* A && B truth table. */
+ ut_asserteq(1, run_command("false && false", 0));
+ ut_asserteq(1, run_command("false && true", 0));
+ ut_assertok(run_command("true && true", 0));
+ ut_asserteq(1, run_command("true && false", 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_and, 0);
+
+static int hush_test_or(struct unit_test_state *uts)
+{
+ /* A || B truth table. */
+ ut_asserteq(1, run_command("false || false", 0));
+ ut_assertok(run_command("false || true", 0));
+ ut_assertok(run_command("true || true", 0));
+ ut_assertok(run_command("true || false", 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_or, 0);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int hush_test_and_or(struct unit_test_state *uts)
+{
+ /* A && B || C truth table. */
+ ut_asserteq(1, run_command("false && false || false", 0));
+
+ if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_asserteq(1, run_command("false && false || true", 0));
+ } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * This difference seems to come from a bug solved in Busybox
+ * hush.
+ *
+ * Indeed, the following expression can be seen like this:
+ * (false && false) || true
+ * So, (false && false) returns 1, the second false is not
+ * executed, and true is executed because of ||.
+ */
+ ut_assertok(run_command("false && false || true", 0));
+ }
+
+ if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_asserteq(1, run_command("false && true || true", 0));
+ } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * This difference seems to come from a bug solved in Busybox
+ * hush.
+ *
+ * Indeed, the following expression can be seen like this:
+ * (false && true) || true
+ * So, (false && true) returns 1, the true is not executed, and
+ * true is executed because of ||.
+ */
+ ut_assertok(run_command("false && true || true", 0));
+ }
+
+ ut_asserteq(1, run_command("false && true || false", 0));
+ ut_assertok(run_command("true && true || false", 0));
+ ut_asserteq(1, run_command("true && false || false", 0));
+ ut_assertok(run_command("true && false || true", 0));
+ ut_assertok(run_command("true && true || true", 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_and_or, 0);
+
+static int hush_test_or_and(struct unit_test_state *uts)
+{
+ /* A || B && C truth table. */
+ ut_asserteq(1, run_command("false || false && false", 0));
+ ut_asserteq(1, run_command("false || false && true", 0));
+ ut_assertok(run_command("false || true && true", 0));
+ ut_asserteq(1, run_command("false || true && false", 0));
+
+ if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_assertok(run_command("true || true && false", 0));
+ } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * This difference seems to come from a bug solved in Busybox
+ * hush.
+ *
+ * Indeed, the following expression can be seen like this:
+ * (true || true) && false
+ * So, (true || true) returns 0, the second true is not
+ * executed, and then false is executed because of &&.
+ */
+ ut_asserteq(1, run_command("true || true && false", 0));
+ }
+
+ if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ ut_assertok(run_command("true || false && false", 0));
+ } else if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * This difference seems to come from a bug solved in Busybox
+ * hush.
+ *
+ * Indeed, the following expression can be seen like this:
+ * (true || false) && false
+ * So, (true || false) returns 0, the false is not executed, and
+ * then false is executed because of &&.
+ */
+ ut_asserteq(1, run_command("true || false && false", 0));
+ }
+
+ ut_assertok(run_command("true || false && true", 0));
+ ut_assertok(run_command("true || true && true", 0));
+
+ return 0;
+}
+HUSH_TEST(hush_test_or_and, 0);
diff --git a/test/hush/loop.c b/test/hush/loop.c
new file mode 100644
index 00000000000..d734abf136d
--- /dev/null
+++ b/test/hush/loop.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2021
+ * Francis Laniel, Amarula Solutions, francis.laniel@amarulasolutions.com
+ */
+
+#include <command.h>
+#include <env_attr.h>
+#include <test/hush.h>
+#include <test/ut.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int hush_test_for(struct unit_test_state *uts)
+{
+ console_record_reset_enable();
+
+ ut_assertok(run_command("for loop_i in foo bar quux quux; do echo $loop_i; done", 0));
+ ut_assert_nextline("foo");
+ ut_assert_nextline("bar");
+ ut_assert_nextline("quux");
+ ut_assert_nextline("quux");
+ ut_assert_console_end();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* Reset local variable. */
+ ut_assertok(run_command("loop_i=", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ puts("Beware: this test set local variable loop_i and it cannot be unset!");
+ }
+
+ return 0;
+}
+HUSH_TEST(hush_test_for, 0);
+
+static int hush_test_while(struct unit_test_state *uts)
+{
+ console_record_reset_enable();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /*
+ * Hush 2021 always returns 0 from while loop...
+ * You can see code snippet near this line to have a better
+ * understanding:
+ * debug_printf_exec(": while expr is false: breaking (exitcode:EXIT_SUCCESS)\n");
+ */
+ ut_assertok(run_command("while test -z \"$loop_foo\"; do echo bar; loop_foo=quux; done", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ /*
+ * Exit status is that of test, so 1 since test is false to quit
+ * the loop.
+ */
+ ut_asserteq(1, run_command("while test -z \"$loop_foo\"; do echo bar; loop_foo=quux; done", 0));
+ }
+ ut_assert_nextline("bar");
+ ut_assert_console_end();
+
+ if (gd->flags & GD_FLG_HUSH_MODERN_PARSER) {
+ /* Reset local variable. */
+ ut_assertok(run_command("loop_foo=", 0));
+ } else if (gd->flags & GD_FLG_HUSH_OLD_PARSER) {
+ puts("Beware: this test set local variable loop_foo and it cannot be unset!");
+ }
+
+ return 0;
+}
+HUSH_TEST(hush_test_while, 0);
+
+static int hush_test_until(struct unit_test_state *uts)
+{
+ console_record_reset_enable();
+ env_set("loop_bar", "bar");
+
+ /*
+ * WARNING We have to use environment variable because it is not possible
+ * resetting local variable.
+ */
+ ut_assertok(run_command("until test -z \"$loop_bar\"; do echo quux; setenv loop_bar; done", 0));
+ ut_assert_nextline("quux");
+ ut_assert_console_end();
+
+ /*
+ * Loop normally resets foo environment variable, but we reset it here in
+ * case the test failed.
+ */
+ env_set("loop_bar", NULL);
+ return 0;
+}
+HUSH_TEST(hush_test_until, 0);
diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c
index 5f1de5486f4..a89189e1124 100644
--- a/test/image/spl_load_fs.c
+++ b/test/image/spl_load_fs.c
@@ -220,7 +220,7 @@ static size_t create_fat(void *dst, size_t size, const char *filename,
bs->root_cluster = cpu_to_le32(root_sector);
vi->ext_boot_sign = 0x29;
- memcpy(vi->fs_type, FAT32_SIGN, sizeof(vi->fs_type));
+ memcpy(vi->fs_type, "FAT32 ", sizeof(vi->fs_type));
memcpy(dst + 0x1fe, "\x55\xAA", 2);
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 15c68ce3961..7e4368de22e 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -9,6 +9,7 @@
#include <log.h>
#include <malloc.h>
#include <dm/test.h>
+#include <test/lib.h>
#include <test/test.h>
#include <test/ut.h>
@@ -205,8 +206,7 @@ static int lib_test_lmb_simple(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_multi_alloc_512mb(uts, 0xE0000000);
}
-
-DM_TEST(lib_test_lmb_simple, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_simple, 0);
/* Create two memory regions with one reserved region and allocate */
static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
@@ -221,8 +221,7 @@ static int lib_test_lmb_simple_x2(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 3.5GiB and 1 GiB */
return test_multi_alloc_512mb_x2(uts, 0xE0000000, 0x40000000);
}
-
-DM_TEST(lib_test_lmb_simple_x2, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_simple_x2, 0);
/* Simulate 512 MiB RAM, allocate some blocks that fit/don't fit */
static int test_bigblock(struct unit_test_state *uts, const phys_addr_t ram)
@@ -288,8 +287,7 @@ static int lib_test_lmb_big(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_bigblock(uts, 0xE0000000);
}
-
-DM_TEST(lib_test_lmb_big, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_big, 0);
/* Simulate 512 MiB RAM, allocate a block without previous reservation */
static int test_noreserved(struct unit_test_state *uts, const phys_addr_t ram,
@@ -364,7 +362,7 @@ static int lib_test_lmb_noreserved(struct unit_test_state *uts)
return test_noreserved(uts, 0xE0000000, 4, 1);
}
-DM_TEST(lib_test_lmb_noreserved, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_noreserved, 0);
static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
{
@@ -378,8 +376,8 @@ static int lib_test_lmb_unaligned_size(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_noreserved(uts, 0xE0000000, 5, 8);
}
+LIB_TEST(lib_test_lmb_unaligned_size, 0);
-DM_TEST(lib_test_lmb_unaligned_size, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
/*
* Simulate a RAM that starts at 0 and allocate down to address 0, which must
* fail as '0' means failure for the lmb_alloc functions.
@@ -421,8 +419,7 @@ static int lib_test_lmb_at_0(struct unit_test_state *uts)
return 0;
}
-
-DM_TEST(lib_test_lmb_at_0, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_at_0, 0);
/* Check that calling lmb_reserve with overlapping regions fails. */
static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
@@ -470,9 +467,7 @@ static int lib_test_lmb_overlapping_reserve(struct unit_test_state *uts)
0, 0, 0, 0);
return 0;
}
-
-DM_TEST(lib_test_lmb_overlapping_reserve,
- UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_overlapping_reserve, 0);
/*
* Simulate 512 MiB RAM, reserve 3 blocks, allocate addresses in between.
@@ -601,8 +596,7 @@ static int lib_test_lmb_alloc_addr(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_alloc_addr(uts, 0xE0000000);
}
-
-DM_TEST(lib_test_lmb_alloc_addr, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_alloc_addr, 0);
/* Simulate 512 MiB RAM, reserve 3 blocks, check addresses in between */
static int test_get_unreserved_size(struct unit_test_state *uts,
@@ -672,9 +666,7 @@ static int lib_test_lmb_get_free_size(struct unit_test_state *uts)
/* simulate 512 MiB RAM beginning at 1.5GiB */
return test_get_unreserved_size(uts, 0xE0000000);
}
-
-DM_TEST(lib_test_lmb_get_free_size,
- UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_get_free_size, 0);
#ifdef CONFIG_LMB_USE_MAX_REGIONS
static int lib_test_lmb_max_regions(struct unit_test_state *uts)
@@ -743,11 +735,9 @@ static int lib_test_lmb_max_regions(struct unit_test_state *uts)
return 0;
}
+LIB_TEST(lib_test_lmb_max_regions, 0);
#endif
-DM_TEST(lib_test_lmb_max_regions,
- UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
-
static int lib_test_lmb_flags(struct unit_test_state *uts)
{
const phys_addr_t ram = 0x40000000;
@@ -833,6 +823,4 @@ static int lib_test_lmb_flags(struct unit_test_state *uts)
return 0;
}
-
-DM_TEST(lib_test_lmb_flags,
- UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
+LIB_TEST(lib_test_lmb_flags, 0);
diff --git a/test/print_ut.c b/test/print_ut.c
index b26f6281b01..bb844d2542b 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -170,6 +170,10 @@ static int print_display_buffer(struct unit_test_state *uts)
u8 *buf;
int i;
+ /* This test requires writable memory at zero */
+ if (IS_ENABLED(CONFIG_X86))
+ return -EAGAIN;
+
buf = map_sysmem(0, BUF_SIZE);
memset(buf, '\0', BUF_SIZE);
for (i = 0; i < 0x11; i++)
@@ -275,6 +279,10 @@ static int print_do_hex_dump(struct unit_test_state *uts)
u8 *buf;
int i;
+ /* This test requires writable memory at zero */
+ if (IS_ENABLED(CONFIG_X86))
+ return -EAGAIN;
+
buf = map_sysmem(0, BUF_SIZE);
memset(buf, '\0', BUF_SIZE);
for (i = 0; i < 0x11; i++)
diff --git a/test/py/requirements.txt b/test/py/requirements.txt
index f7e76bdb918..0f67c3c6194 100644
--- a/test/py/requirements.txt
+++ b/test/py/requirements.txt
@@ -8,13 +8,13 @@ fixtures==3.0.0
importlib-metadata==0.23
linecache2==1.0.0
more-itertools==7.2.0
-packaging==21.3
+packaging==23.2
pbr==5.4.3
pluggy==0.13.0
-py==1.10.0
-pycryptodomex==3.9.8
+py==1.11.0
+pycryptodomex==3.19.1
pyelftools==0.27
-pygit2==1.9.2
+pygit2==1.13.3
pyparsing==3.0.7
pytest==6.2.5
pytest-xdist==2.5.0
diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py
index 9882ddb1daa..380f4c4dca3 100644
--- a/test/py/tests/fs_helper.py
+++ b/test/py/tests/fs_helper.py
@@ -9,7 +9,7 @@ import re
import os
from subprocess import call, check_call, check_output, CalledProcessError
-def mk_fs(config, fs_type, size, prefix):
+def mk_fs(config, fs_type, size, prefix, size_gran = 0x100000):
"""Create a file system volume
Args:
@@ -17,6 +17,7 @@ def mk_fs(config, fs_type, size, prefix):
fs_type (str): File system type, e.g. 'ext4'
size (int): Size of file system in bytes
prefix (str): Prefix string of volume's file name
+ size_gran (int): Size granularity of file system image in bytes
Raises:
CalledProcessError: if any error occurs when creating the filesystem
@@ -24,7 +25,9 @@ def mk_fs(config, fs_type, size, prefix):
fs_img = f'{prefix}.{fs_type}.img'
fs_img = os.path.join(config.persistent_data_dir, fs_img)
- if fs_type == 'fat16':
+ if fs_type == 'fat12':
+ mkfs_opt = '-F 12'
+ elif fs_type == 'fat16':
mkfs_opt = '-F 16'
elif fs_type == 'fat32':
mkfs_opt = '-F 32'
@@ -36,7 +39,7 @@ def mk_fs(config, fs_type, size, prefix):
else:
fs_lnxtype = fs_type
- count = (size + 0x100000 - 1) // 0x100000
+ count = (size + size_gran - 1) // size_gran
# Some distributions do not add /sbin to the default PATH, where mkfs lives
if '/sbin' not in os.environ["PATH"].split(os.pathsep):
@@ -44,7 +47,7 @@ def mk_fs(config, fs_type, size, prefix):
try:
check_call(f'rm -f {fs_img}', shell=True)
- check_call(f'dd if=/dev/zero of={fs_img} bs=1M count={count}',
+ check_call(f'dd if=/dev/zero of={fs_img} bs={size_gran} count={count}',
shell=True)
check_call(f'mkfs.{fs_lnxtype} {mkfs_opt} {fs_img}', shell=True)
if fs_type == 'ext4':
diff --git a/test/py/tests/test_bootstage.py b/test/py/tests/test_bootstage.py
new file mode 100644
index 00000000000..a9eb9f0b4a1
--- /dev/null
+++ b/test/py/tests/test_bootstage.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+
+"""
+Test the bootstage command.
+
+It is used for checking the boot progress and timing by printing the bootstage
+report, stashes the data into memory and unstashes the data from memory.
+
+Note: This test relies on boardenv_* containing configuration values to define
+the data size, memory address, and bootstage magic address (defined in
+common/bootstage.c). Without this, bootstage stash and unstash tests will be
+automatically skipped.
+
+For example:
+env__bootstage_cmd_file = {
+ 'addr': 0x200000,
+ 'size': 0x1000,
+ 'bootstage_magic_addr': 0xb00757a3,
+}
+"""
+
+@pytest.mark.buildconfigspec('bootstage')
+@pytest.mark.buildconfigspec('cmd_bootstage')
+def test_bootstage_report(u_boot_console):
+ output = u_boot_console.run_command('bootstage report')
+ assert 'Timer summary in microseconds' in output
+ assert 'Accumulated time:' in output
+ assert 'dm_r' in output
+
+@pytest.mark.buildconfigspec('bootstage')
+@pytest.mark.buildconfigspec('cmd_bootstage')
+@pytest.mark.buildconfigspec('bootstage_stash')
+def test_bootstage_stash(u_boot_console):
+ f = u_boot_console.config.env.get('env__bootstage_cmd_file', None)
+ if not f:
+ pytest.skip('No bootstage environment file is defined')
+
+ addr = f.get('addr')
+ size = f.get('size')
+ bootstage_magic = f.get('bootstage_magic_addr')
+ expected_text = 'dm_r'
+
+ u_boot_console.run_command('bootstage stash %x %x' % (addr, size))
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ output = u_boot_console.run_command('md %x 100' % addr)
+
+ # Check BOOTSTAGE_MAGIC address at 4th byte address
+ assert '0x' + output.split('\n')[0].split()[4] == hex(bootstage_magic)
+
+ # Check expected string in last column of output
+ output_last_col = ''.join([i.split()[-1] for i in output.split('\n')])
+ assert expected_text in output_last_col
+ return addr, size
+
+@pytest.mark.buildconfigspec('bootstage')
+@pytest.mark.buildconfigspec('cmd_bootstage')
+@pytest.mark.buildconfigspec('bootstage_stash')
+def test_bootstage_unstash(u_boot_console):
+ addr, size = test_bootstage_stash(u_boot_console)
+ u_boot_console.run_command('bootstage unstash %x %x' % (addr, size))
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
diff --git a/test/py/tests/test_cleanup_build.py b/test/py/tests/test_cleanup_build.py
index 5206ff73ec7..aca90cb1107 100644
--- a/test/py/tests/test_cleanup_build.py
+++ b/test/py/tests/test_cleanup_build.py
@@ -17,6 +17,11 @@ import pytest
@pytest.fixture
def tmp_copy_of_builddir(u_boot_config, tmp_path):
"""For each test, provide a temporary copy of the initial build directory."""
+ if os.path.realpath(u_boot_config.source_dir) == os.path.realpath(
+ u_boot_config.build_dir
+ ):
+ pytest.skip("Leftover detection requires out of tree build.")
+ return None
shutil.copytree(
u_boot_config.build_dir,
tmp_path,
diff --git a/test/py/tests/test_fit.py b/test/py/tests/test_fit.py
index f45848484eb..8f9c4b26411 100755
--- a/test/py/tests/test_fit.py
+++ b/test/py/tests/test_fit.py
@@ -339,6 +339,14 @@ def test_fit(u_boot_console):
'U-Boot loaded FDT from offset %#x, FDT is actually at %#x' %
(fit_offset, real_fit_offset))
+ # Check if bootargs strings substitution works
+ output = cons.run_command_list([
+ 'env set bootargs \\\"\'my_boot_var=${foo}\'\\\"',
+ 'env set foo bar',
+ 'bootm prep',
+ 'env print bootargs'])
+ assert 'bootargs="my_boot_var=bar"' in output, "Bootargs strings not substituted"
+
# Now a kernel and an FDT
with cons.log.section('Kernel + FDT load'):
params['fdt_load'] = 'load = <%#x>;' % params['fdt_addr']
@@ -390,10 +398,10 @@ def test_fit(u_boot_console):
cons = u_boot_console
+ # We need to use our own device tree file. Remember to restore it
+ # afterwards.
+ old_dtb = cons.config.dtb
try:
- # We need to use our own device tree file. Remember to restore it
- # afterwards.
- old_dtb = cons.config.dtb
mkimage = cons.config.build_dir + '/tools/mkimage'
run_fit_test(mkimage)
finally:
diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py
index 0d87d180c7b..fca54488374 100644
--- a/test/py/tests/test_fs/conftest.py
+++ b/test/py/tests/test_fs/conftest.py
@@ -9,12 +9,14 @@ import re
from subprocess import call, check_call, check_output, CalledProcessError
from fstest_defs import *
import u_boot_utils as util
+# pylint: disable=E0611
from tests import fs_helper
supported_fs_basic = ['fat16', 'fat32', 'ext4']
-supported_fs_ext = ['fat16', 'fat32']
-supported_fs_mkdir = ['fat16', 'fat32']
-supported_fs_unlink = ['fat16', 'fat32']
+supported_fs_ext = ['fat12', 'fat16', 'fat32']
+supported_fs_fat = ['fat12', 'fat16']
+supported_fs_mkdir = ['fat12', 'fat16', 'fat32']
+supported_fs_unlink = ['fat12', 'fat16', 'fat32']
supported_fs_symlink = ['ext4']
#
@@ -49,6 +51,7 @@ def pytest_configure(config):
"""
global supported_fs_basic
global supported_fs_ext
+ global supported_fs_fat
global supported_fs_mkdir
global supported_fs_unlink
global supported_fs_symlink
@@ -61,6 +64,7 @@ def pytest_configure(config):
print('*** FS TYPE modified: %s' % supported_fs)
supported_fs_basic = intersect(supported_fs, supported_fs_basic)
supported_fs_ext = intersect(supported_fs, supported_fs_ext)
+ supported_fs_fat = intersect(supported_fs, supported_fs_fat)
supported_fs_mkdir = intersect(supported_fs, supported_fs_mkdir)
supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
supported_fs_symlink = intersect(supported_fs, supported_fs_symlink)
@@ -83,6 +87,9 @@ def pytest_generate_tests(metafunc):
if 'fs_obj_ext' in metafunc.fixturenames:
metafunc.parametrize('fs_obj_ext', supported_fs_ext,
indirect=True, scope='module')
+ if 'fs_obj_fat' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_fat', supported_fs_fat,
+ indirect=True, scope='module')
if 'fs_obj_mkdir' in metafunc.fixturenames:
metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
indirect=True, scope='module')
@@ -624,3 +631,44 @@ def fs_obj_symlink(request, u_boot_config):
finally:
call('rmdir %s' % mount_dir, shell=True)
call('rm -f %s' % fs_img, shell=True)
+
+#
+# Fixture for fat test
+#
+@pytest.fixture()
+def fs_obj_fat(request, u_boot_config):
+ """Set up a file system to be used in fat test.
+
+ Args:
+ request: Pytest request object.
+ u_boot_config: U-Boot configuration.
+
+ Return:
+ A fixture for fat test, i.e. a duplet of file system type and
+ volume file name.
+ """
+
+ # the maximum size of a FAT12 filesystem resulting in 4084 clusters
+ MAX_FAT12_SIZE = 261695 * 1024
+
+ # the minimum size of a FAT16 filesystem that can be created with
+ # mkfs.vfat resulting in 4087 clusters
+ MIN_FAT16_SIZE = 8208 * 1024
+
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ fs_size = MAX_FAT12_SIZE if fs_type == 'fat12' else MIN_FAT16_SIZE
+
+ try:
+ # the volume size depends on the filesystem
+ fs_img = fs_helper.mk_fs(u_boot_config, fs_type, fs_size, f'{fs_size}', 1024)
+ except:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ return
+ else:
+ yield [fs_ubtype, fs_img]
+ call('rm -f %s' % fs_img, shell=True)
diff --git a/test/py/tests/test_fs/test_fs_fat.py b/test/py/tests/test_fs/test_fs_fat.py
new file mode 100644
index 00000000000..4009d0b63a3
--- /dev/null
+++ b/test/py/tests/test_fs/test_fs_fat.py
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmüller Interface GmbH & Co. KG
+# Author: Christian Taedcke <christian.taedcke@weidmueller.com>
+#
+# U-Boot File System: FAT Test
+
+"""
+This test verifies fat specific file system behaviour.
+"""
+
+import pytest
+import re
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.slow
+class TestFsFat(object):
+ def test_fs_fat1(self, u_boot_console, fs_obj_fat):
+ """Test that `fstypes` prints a result which includes `sandbox`."""
+ fs_type,fs_img = fs_obj_fat
+ with u_boot_console.log.section('Test Case 1 - fatinfo'):
+ # Test Case 1 - ls
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ 'fatinfo host 0:0'])
+ assert(re.search('Filesystem: %s' % fs_type.upper(), ''.join(output)))
diff --git a/test/py/tests/test_gpio.py b/test/py/tests/test_gpio.py
index 0af186f2360..3e16e636574 100644
--- a/test/py/tests/test_gpio.py
+++ b/test/py/tests/test_gpio.py
@@ -85,6 +85,13 @@ env__gpio_dev_config = {
'gpio_ip_pin_clear':'66',
'gpio_clear_value': 'value is 0',
'gpio_set_value': 'value is 1',
+ # GPIO pin list to test gpio functionality for each pins, pin should be
+ # pin names (str)
+ 'gpio_pin_list': ['gpio@1000031', 'gpio@1000032', 'gpio@20000033'],
+ # GPIO input output list for shorted gpio pins to test gpio
+ # functionality for each of pairs, where the first element is
+ # configured as input and second as output
+ 'gpio_ip_op_list': [['gpio0', 'gpio1'], ['gpio2', 'gpio3']],
}
"""
@@ -223,3 +230,86 @@ def test_gpio_input_generic(u_boot_console):
response = u_boot_console.run_command(cmd)
good_response = gpio_set_value
assert good_response in response
+
+@pytest.mark.buildconfigspec('cmd_gpio')
+def test_gpio_pins_generic(u_boot_console):
+ """Test various gpio related functionality, such as the input, set, clear,
+ and toggle for the set of gpio pin list.
+
+ Specific set of gpio pins (by mentioning gpio pin name) configured as
+ input (mentioned as 'gpio_pin_list') to be tested for multiple gpio
+ commands.
+ """
+
+ f = u_boot_console.config.env.get('env__gpio_dev_config', False)
+ if not f:
+ pytest.skip('gpio not configured')
+
+ gpio_pins = f.get('gpio_pin_list', None)
+ if not gpio_pins:
+ pytest.skip('gpio pin list are not configured')
+
+ for gpin in gpio_pins:
+ # gpio input
+ u_boot_console.run_command(f'gpio input {gpin}')
+ expected_response = f'{gpin}: input:'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio set
+ u_boot_console.run_command(f'gpio set {gpin}')
+ expected_response = f'{gpin}: output: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio clear
+ u_boot_console.run_command(f'gpio clear {gpin}')
+ expected_response = f'{gpin}: output: 0'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+ # gpio toggle
+ u_boot_console.run_command(f'gpio toggle {gpin}')
+ expected_response = f'{gpin}: output: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpin}')
+ assert expected_response in response
+
+@pytest.mark.buildconfigspec('cmd_gpio')
+def test_gpio_pins_input_output_generic(u_boot_console):
+ """Test gpio related functionality such as input and output for the list of
+ shorted gpio pins provided as a pair of input and output pins. This test
+ will fail, if the gpio pins are not shorted properly.
+
+ Specific set of shorted gpio pins (by mentioning gpio pin name)
+ configured as input and output (mentioned as 'gpio_ip_op_list') as a
+ pair to be tested for gpio input output case.
+ """
+
+ f = u_boot_console.config.env.get('env__gpio_dev_config', False)
+ if not f:
+ pytest.skip('gpio not configured')
+
+ gpio_pins = f.get('gpio_ip_op_list', None)
+ if not gpio_pins:
+ pytest.skip('gpio pin list for input and output are not configured')
+
+ for gpins in gpio_pins:
+ u_boot_console.run_command(f'gpio input {gpins[0]}')
+ expected_response = f'{gpins[0]}: input:'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio set {gpins[1]}')
+ expected_response = f'{gpins[1]}: output:'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[1]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio clear {gpins[1]}')
+ expected_response = f'{gpins[0]}: input: 0'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
+
+ u_boot_console.run_command(f'gpio set {gpins[1]}')
+ expected_response = f'{gpins[0]}: input: 1'
+ response = u_boot_console.run_command(f'gpio status -a {gpins[0]}')
+ assert expected_response in response
diff --git a/test/py/tests/test_hush_if_test.py b/test/py/tests/test_hush_if_test.py
deleted file mode 100644
index 3b4b6fcaf40..00000000000
--- a/test/py/tests/test_hush_if_test.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Copyright (c) 2015-2016, NVIDIA CORPORATION. All rights reserved.
-
-# Test operation of the "if" shell command.
-
-import os
-import os.path
-import pytest
-
-# TODO: These tests should be converted to a C test.
-# For more information please take a look at the thread
-# https://lists.denx.de/pipermail/u-boot/2019-October/388732.html
-
-pytestmark = pytest.mark.buildconfigspec('hush_parser')
-
-# The list of "if test" conditions to test.
-subtests = (
- # Base if functionality.
-
- ('true', True),
- ('false', False),
-
- # Basic operators.
-
- ('test aaa = aaa', True),
- ('test aaa = bbb', False),
-
- ('test aaa != bbb', True),
- ('test aaa != aaa', False),
-
- ('test aaa < bbb', True),
- ('test bbb < aaa', False),
-
- ('test bbb > aaa', True),
- ('test aaa > bbb', False),
-
- ('test 123 -eq 123', True),
- ('test 123 -eq 456', False),
-
- ('test 123 -ne 456', True),
- ('test 123 -ne 123', False),
-
- ('test 123 -lt 456', True),
- ('test 123 -lt 123', False),
- ('test 456 -lt 123', False),
-
- ('test 123 -le 456', True),
- ('test 123 -le 123', True),
- ('test 456 -le 123', False),
-
- ('test 456 -gt 123', True),
- ('test 123 -gt 123', False),
- ('test 123 -gt 456', False),
-
- ('test 456 -ge 123', True),
- ('test 123 -ge 123', True),
- ('test 123 -ge 456', False),
-
- # Octal tests
-
- ('test 010 -eq 010', True),
- ('test 010 -eq 011', False),
-
- ('test 010 -ne 011', True),
- ('test 010 -ne 010', False),
-
- # Hexadecimal tests
-
- ('test 0x2000000 -gt 0x2000001', False),
- ('test 0x2000000 -gt 0x2000000', False),
- ('test 0x2000000 -gt 0x1ffffff', True),
-
- # Mixed tests
-
- ('test 010 -eq 10', False),
- ('test 010 -ne 10', True),
- ('test 0xa -eq 10', True),
- ('test 0xa -eq 012', True),
-
- ('test 2000000 -gt 0x1ffffff', False),
- ('test 0x2000000 -gt 1ffffff', True),
- ('test 0x2000000 -lt 1ffffff', False),
- ('test 0x2000000 -eq 2000000', False),
- ('test 0x2000000 -ne 2000000', True),
-
- ('test -z ""', True),
- ('test -z "aaa"', False),
-
- ('test -n "aaa"', True),
- ('test -n ""', False),
-
- # Inversion of simple tests.
-
- ('test ! aaa = aaa', False),
- ('test ! aaa = bbb', True),
- ('test ! ! aaa = aaa', True),
- ('test ! ! aaa = bbb', False),
-
- # Binary operators.
-
- ('test aaa != aaa -o bbb != bbb', False),
- ('test aaa != aaa -o bbb = bbb', True),
- ('test aaa = aaa -o bbb != bbb', True),
- ('test aaa = aaa -o bbb = bbb', True),
-
- ('test aaa != aaa -a bbb != bbb', False),
- ('test aaa != aaa -a bbb = bbb', False),
- ('test aaa = aaa -a bbb != bbb', False),
- ('test aaa = aaa -a bbb = bbb', True),
-
- # Inversion within binary operators.
-
- ('test ! aaa != aaa -o ! bbb != bbb', True),
- ('test ! aaa != aaa -o ! bbb = bbb', True),
- ('test ! aaa = aaa -o ! bbb != bbb', True),
- ('test ! aaa = aaa -o ! bbb = bbb', False),
-
- ('test ! ! aaa != aaa -o ! ! bbb != bbb', False),
- ('test ! ! aaa != aaa -o ! ! bbb = bbb', True),
- ('test ! ! aaa = aaa -o ! ! bbb != bbb', True),
- ('test ! ! aaa = aaa -o ! ! bbb = bbb', True),
-)
-
-def exec_hush_if(u_boot_console, expr, result):
- """Execute a shell "if" command, and validate its result."""
-
- config = u_boot_console.config.buildconfig
- maxargs = int(config.get('config_sys_maxargs', '0'))
- args = len(expr.split(' ')) - 1
- if args > maxargs:
- u_boot_console.log.warning('CONFIG_SYS_MAXARGS too low; need ' +
- str(args))
- pytest.skip()
-
- cmd = 'if ' + expr + '; then echo true; else echo false; fi'
- response = u_boot_console.run_command(cmd)
- assert response.strip() == str(result).lower()
-
-@pytest.mark.buildconfigspec('cmd_echo')
-@pytest.mark.parametrize('expr,result', subtests)
-def test_hush_if_test(u_boot_console, expr, result):
- """Test a single "if test" condition."""
-
- exec_hush_if(u_boot_console, expr, result)
-
-def test_hush_z(u_boot_console):
- """Test the -z operator"""
- u_boot_console.run_command('setenv ut_var_nonexistent')
- u_boot_console.run_command('setenv ut_var_exists 1')
- exec_hush_if(u_boot_console, 'test -z "$ut_var_nonexistent"', True)
- exec_hush_if(u_boot_console, 'test -z "$ut_var_exists"', False)
- u_boot_console.run_command('setenv ut_var_exists')
-
-# We might test this on real filesystems via UMS, DFU, 'save', etc.
-# Of those, only UMS currently allows file removal though.
-@pytest.mark.buildconfigspec('cmd_echo')
-@pytest.mark.boardspec('sandbox')
-def test_hush_if_test_host_file_exists(u_boot_console):
- """Test the "if test -e" shell command."""
-
- test_file = u_boot_console.config.result_dir + \
- '/creating_this_file_breaks_u_boot_tests'
-
- try:
- os.unlink(test_file)
- except:
- pass
- assert not os.path.exists(test_file)
-
- expr = 'test -e hostfs - ' + test_file
- exec_hush_if(u_boot_console, expr, False)
-
- try:
- with open(test_file, 'wb'):
- pass
- assert os.path.exists(test_file)
-
- expr = 'test -e hostfs - ' + test_file
- exec_hush_if(u_boot_console, expr, True)
- finally:
- os.unlink(test_file)
-
- expr = 'test -e hostfs - ' + test_file
- exec_hush_if(u_boot_console, expr, False)
-
-def test_hush_var(u_boot_console):
- """Test the set and unset of variables"""
- u_boot_console.run_command('ut_var_nonexistent=')
- u_boot_console.run_command('ut_var_exists=1')
- u_boot_console.run_command('ut_var_unset=1')
- exec_hush_if(u_boot_console, 'test -z "$ut_var_nonexistent"', True)
- exec_hush_if(u_boot_console, 'test -z "$ut_var_exists"', False)
- exec_hush_if(u_boot_console, 'test -z "$ut_var_unset"', False)
- exec_hush_if(u_boot_console, 'ut_var_unset=', True)
- exec_hush_if(u_boot_console, 'test -z "$ut_var_unset"', True)
- u_boot_console.run_command('ut_var_exists=')
- u_boot_console.run_command('ut_var_unset=')
diff --git a/test/py/tests/test_i2c.py b/test/py/tests/test_i2c.py
new file mode 100644
index 00000000000..825d0c2e6eb
--- /dev/null
+++ b/test/py/tests/test_i2c.py
@@ -0,0 +1,116 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import re
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+the i2c device info including the bus list and eeprom address/value. This test
+will be automatically skipped without this.
+
+For example:
+
+# Setup env__i2c_device_test to set the i2c bus list and probe_all boolean
+# parameter. For i2c_probe_all_buses case, if probe_all parameter is set to
+# False then it probes all the buses listed in bus_list instead of probing all
+# the buses available.
+env__i2c_device_test = {
+ 'bus_list': [0, 2, 5, 12, 16, 18],
+ 'probe_all': False,
+}
+
+# Setup env__i2c_eeprom_device_test to set the i2c bus number, eeprom address
+# and configured value for i2c_eeprom test case. Test will be skipped if
+# env__i2c_eeprom_device_test is not set
+env__i2c_eeprom_device_test = {
+ 'bus': 3,
+ 'eeprom_addr': 0x54,
+ 'eeprom_val': '30 31',
+}
+"""
+
+def get_i2c_test_env(u_boot_console):
+ f = u_boot_console.config.env.get("env__i2c_device_test", None)
+ if not f:
+ pytest.skip("No I2C device to test!")
+ else:
+ bus_list = f.get("bus_list", None)
+ if not bus_list:
+ pytest.skip("I2C bus list is not provided!")
+ probe_all = f.get("probe_all", False)
+ return bus_list, probe_all
+
+@pytest.mark.buildconfigspec("cmd_i2c")
+def test_i2c_bus(u_boot_console):
+ bus_list, probe = get_i2c_test_env(u_boot_console)
+ bus = random.choice(bus_list)
+ expected_response = f"Bus {bus}:"
+ response = u_boot_console.run_command("i2c bus")
+ assert expected_response in response
+
+@pytest.mark.buildconfigspec("cmd_i2c")
+def test_i2c_dev(u_boot_console):
+ bus_list, probe = get_i2c_test_env(u_boot_console)
+ expected_response = "Current bus is"
+ response = u_boot_console.run_command("i2c dev")
+ assert expected_response in response
+
+@pytest.mark.buildconfigspec("cmd_i2c")
+def test_i2c_probe(u_boot_console):
+ bus_list, probe = get_i2c_test_env(u_boot_console)
+ bus = random.choice(bus_list)
+ expected_response = f"Setting bus to {bus}"
+ response = u_boot_console.run_command(f"i2c dev {bus}")
+ assert expected_response in response
+ expected_response = "Valid chip addresses:"
+ response = u_boot_console.run_command("i2c probe")
+ assert expected_response in response
+
+@pytest.mark.buildconfigspec("cmd_i2c")
+def test_i2c_eeprom(u_boot_console):
+ f = u_boot_console.config.env.get("env__i2c_eeprom_device_test", None)
+ if not f:
+ pytest.skip("No I2C eeprom to test!")
+
+ bus = f.get("bus", 0)
+ if bus < 0:
+ pytest.fail("No bus specified via env__i2c_eeprom_device_test!")
+
+ addr = f.get("eeprom_addr", -1)
+ if addr < 0:
+ pytest.fail("No eeprom address specified via env__i2c_eeprom_device_test!")
+
+ value = f.get("eeprom_val")
+ if not value:
+ pytest.fail(
+ "No eeprom configured value provided via env__i2c_eeprom_device_test!"
+ )
+
+ # Enable i2c mux bridge
+ u_boot_console.run_command("i2c dev %x" % bus)
+ u_boot_console.run_command("i2c probe")
+ output = u_boot_console.run_command("i2c md %x 0 5" % addr)
+ assert value in output
+
+@pytest.mark.buildconfigspec("cmd_i2c")
+def test_i2c_probe_all_buses(u_boot_console):
+ bus_list, probe = get_i2c_test_env(u_boot_console)
+ bus = random.choice(bus_list)
+ expected_response = f"Bus {bus}:"
+ response = u_boot_console.run_command("i2c bus")
+ assert expected_response in response
+
+ # Get all the bus list
+ if probe:
+ buses = re.findall("Bus (.+?):", response)
+ bus_list = [int(x) for x in buses]
+
+ for dev in bus_list:
+ expected_response = f"Setting bus to {dev}"
+ response = u_boot_console.run_command(f"i2c dev {dev}")
+ assert expected_response in response
+ expected_response = "Valid chip addresses:"
+ response = u_boot_console.run_command("i2c probe")
+ assert expected_response in response
diff --git a/test/py/tests/test_mdio.py b/test/py/tests/test_mdio.py
new file mode 100644
index 00000000000..89711e70b55
--- /dev/null
+++ b/test/py/tests/test_mdio.py
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+the PHY device info including the device name, address, register address/value
+and write data value. This test will be automatically skipped without this.
+
+For example:
+
+# Setup env__mdio_util_test to set the PHY address, device names, register
+# address, register address value, and write data value to test mdio commands.
+# Test will be skipped if env_mdio_util_test is not set
+env__mdio_util_test = {
+ "eth0": {"phy_addr": 0xc, "device_name": "TI DP83867", "reg": 0,
+ "reg_val": 0x1000, "write_val": 0x100},
+ "eth1": {"phy_addr": 0xa0, "device_name": "TI DP83867", "reg": 1,
+ "reg_val": 0x2000, "write_val": 0x100},
+}
+"""
+
+def get_mdio_test_env(u_boot_console):
+ f = u_boot_console.config.env.get("env__mdio_util_test", None)
+ if not f or len(f) == 0:
+ pytest.skip("No PHY device to test!")
+ else:
+ return f
+
+@pytest.mark.buildconfigspec("cmd_mii")
+@pytest.mark.buildconfigspec("phylib")
+def test_mdio_list(u_boot_console):
+ f = get_mdio_test_env(u_boot_console)
+ output = u_boot_console.run_command("mdio list")
+ for dev, val in f.items():
+ phy_addr = val.get("phy_addr")
+ dev_name = val.get("device_name")
+
+ assert f"{phy_addr:x} -" in output
+ assert dev_name in output
+
+@pytest.mark.buildconfigspec("cmd_mii")
+@pytest.mark.buildconfigspec("phylib")
+def test_mdio_read(u_boot_console):
+ f = get_mdio_test_env(u_boot_console)
+ output = u_boot_console.run_command("mdio list")
+ for dev, val in f.items():
+ phy_addr = hex(val.get("phy_addr"))
+ dev_name = val.get("device_name")
+ reg = hex(val.get("reg"))
+ reg_val = hex(val.get("reg_val"))
+
+ output = u_boot_console.run_command(f"mdio read {phy_addr} {reg}")
+ assert f"PHY at address {int(phy_addr, 16):x}:" in output
+ assert f"{int(reg, 16):x} - {reg_val}" in output
+
+@pytest.mark.buildconfigspec("cmd_mii")
+@pytest.mark.buildconfigspec("phylib")
+def test_mdio_write(u_boot_console):
+ f = get_mdio_test_env(u_boot_console)
+ output = u_boot_console.run_command("mdio list")
+ for dev, val in f.items():
+ phy_addr = hex(val.get("phy_addr"))
+ dev_name = val.get("device_name")
+ reg = hex(val.get("reg"))
+ reg_val = hex(val.get("reg_val"))
+ wr_val = hex(val.get("write_val"))
+
+ u_boot_console.run_command(f"mdio write {phy_addr} {reg} {wr_val}")
+ output = u_boot_console.run_command(f"mdio read {phy_addr} {reg}")
+ assert f"PHY at address {int(phy_addr, 16):x}:" in output
+ assert f"{int(reg, 16):x} - {wr_val}" in output
+
+ u_boot_console.run_command(f"mdio write {phy_addr} {reg} {reg_val}")
+ output = u_boot_console.run_command(f"mdio read {phy_addr} {reg}")
+ assert f"PHY at address {int(phy_addr, 16):x}:" in output
+ assert f"{int(reg, 16):x} - {reg_val}" in output
diff --git a/test/py/tests/test_memtest.py b/test/py/tests/test_memtest.py
new file mode 100644
index 00000000000..0618d96f1be
--- /dev/null
+++ b/test/py/tests/test_memtest.py
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+the memory test parameters such as start address, memory size, pattern,
+iterations and timeout. This test will be automatically skipped without this.
+
+For example:
+
+# Setup env__memtest to set the start address of the memory range, size of the
+# memory range to test from starting address, pattern to be written to memory,
+# number of test iterations, and expected time to complete the test of mtest
+# command. start address, size, and pattern parameters value should be in hex
+# and rest of the params value should be integer.
+env__memtest = {
+ 'start_addr': 0x0,
+ 'size': 0x1000,
+ 'pattern': 0x0,
+ 'iteration': 16,
+ 'timeout': 50000,
+}
+"""
+
+def get_memtest_env(u_boot_console):
+ f = u_boot_console.config.env.get("env__memtest", None)
+ if not f:
+ pytest.skip("memtest is not enabled!")
+ else:
+ start = f.get("start_addr", 0x0)
+ size = f.get("size", 0x1000)
+ pattern = f.get("pattern", 0x0)
+ iteration = f.get("iteration", 2)
+ timeout = f.get("timeout", 50000)
+ end = hex(int(start) + int(size))
+ return start, end, pattern, iteration, timeout
+
+@pytest.mark.buildconfigspec("cmd_memtest")
+def test_memtest_negative(u_boot_console):
+ """Negative testcase where end address is smaller than starting address and
+ pattern is invalid."""
+ start, end, pattern, iteration, timeout = get_memtest_env(u_boot_console)
+ expected_response = "Refusing to do empty test"
+ response = u_boot_console.run_command(
+ f"mtest 2000 1000 {pattern} {hex(iteration)}"
+ )
+ assert expected_response in response
+ output = u_boot_console.run_command("echo $?")
+ assert not output.endswith("0")
+ u_boot_console.run_command(f"mtest {start} {end} 'xyz' {hex(iteration)}")
+ output = u_boot_console.run_command("echo $?")
+ assert not output.endswith("0")
+
+@pytest.mark.buildconfigspec("cmd_memtest")
+def test_memtest_ddr(u_boot_console):
+ """Test that md reads memory as expected, and that memory can be modified
+ using the mw command."""
+ start, end, pattern, iteration, timeout = get_memtest_env(u_boot_console)
+ expected_response = f"Tested {str(iteration)} iteration(s) with 0 errors."
+ with u_boot_console.temporary_timeout(timeout):
+ response = u_boot_console.run_command(
+ f"mtest {start} {end} {pattern} {hex(iteration)}"
+ )
+ assert expected_response in response
+ output = u_boot_console.run_command("echo $?")
+ assert output.endswith("0")
diff --git a/test/py/tests/test_mii.py b/test/py/tests/test_mii.py
new file mode 100644
index 00000000000..7b6816d1089
--- /dev/null
+++ b/test/py/tests/test_mii.py
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+
+"""
+Note: This test doesn't rely on boardenv_* configuration value but they can
+change test behavior.
+
+For example:
+
+# Setup env__mii_deive_test_skip to True if tests with ethernet PHY devices
+# should be skipped. For example: Missing PHY device
+env__mii_device_test_skip = True
+
+# Setup env__mii_device_test to set the MII device names. Test will be skipped
+# if env_mii_device_test is not set
+env__mii_device_test = {
+ 'device_list': ['eth0', 'eth1'],
+}
+"""
+
+@pytest.mark.buildconfigspec("cmd_mii")
+def test_mii_info(u_boot_console):
+ if u_boot_console.config.env.get("env__mii_device_test_skip", False):
+ pytest.skip("MII device test is not enabled!")
+ expected_output = "PHY"
+ output = u_boot_console.run_command("mii info")
+ if not re.search(r"PHY (.+?):", output):
+ pytest.skip("PHY device does not exist!")
+ assert expected_output in output
+
+@pytest.mark.buildconfigspec("cmd_mii")
+def test_mii_list(u_boot_console):
+ if u_boot_console.config.env.get("env__mii_device_test_skip", False):
+ pytest.skip("MII device test is not enabled!")
+
+ f = u_boot_console.config.env.get("env__mii_device_test", None)
+ if not f:
+ pytest.skip("No MII device to test!")
+
+ dev_list = f.get("device_list")
+ if not dev_list:
+ pytest.fail("No MII device list provided via env__mii_device_test!")
+
+ expected_output = "Current device"
+ output = u_boot_console.run_command("mii device")
+ mii_devices = (
+ re.search(r"MII devices: '(.+)'", output).groups()[0].replace("'", "").split()
+ )
+
+ assert len([x for x in dev_list if x in mii_devices]) == len(dev_list)
+ assert expected_output in output
+
+@pytest.mark.buildconfigspec("cmd_mii")
+def test_mii_set_device(u_boot_console):
+ test_mii_list(u_boot_console)
+ f = u_boot_console.config.env.get("env__mii_device_test", None)
+ dev_list = f.get("device_list")
+ output = u_boot_console.run_command("mii device")
+ current_dev = re.search(r"Current device: '(.+?)'", output).groups()[0]
+
+ for dev in dev_list:
+ u_boot_console.run_command(f"mii device {dev}")
+ output = u_boot_console.run_command("echo $?")
+ assert output.endswith("0")
+
+ u_boot_console.run_command(f"mii device {current_dev}")
+ output = u_boot_console.run_command("mii device")
+ dev = re.search(r"Current device: '(.+?)'", output).groups()[0]
+ assert current_dev == dev
+
+@pytest.mark.buildconfigspec("cmd_mii")
+def test_mii_read(u_boot_console):
+ test_mii_list(u_boot_console)
+ output = u_boot_console.run_command("mii info")
+ eth_addr = hex(int(re.search(r"PHY (.+?):", output).groups()[0], 16))
+ u_boot_console.run_command(f"mii read {eth_addr} 0")
+ output = u_boot_console.run_command("echo $?")
+ assert output.endswith("0")
+
+@pytest.mark.buildconfigspec("cmd_mii")
+def test_mii_dump(u_boot_console):
+ test_mii_list(u_boot_console)
+ expected_response = "PHY control register"
+ output = u_boot_console.run_command("mii info")
+ eth_addr = hex(int(re.search(r"PHY (.+?):", output).groups()[0], 16))
+ response = u_boot_console.run_command(f"mii dump {eth_addr} 0")
+ assert expected_response in response
+ output = u_boot_console.run_command("echo $?")
+ assert output.endswith("0")
diff --git a/test/py/tests/test_mmc.py b/test/py/tests/test_mmc.py
new file mode 100644
index 00000000000..a96c4e8fd89
--- /dev/null
+++ b/test/py/tests/test_mmc.py
@@ -0,0 +1,671 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import re
+import u_boot_utils
+
+"""
+Note: This test doesn't rely on boardenv_* configuration values but it can
+change the test behavior. To test MMC file system cases (fat32, ext2, ext4),
+MMC device should be formatted and valid partitions should be created for
+different file system, otherwise it may leads to failure. This test will be
+skipped if the MMC device is not detected.
+
+For example:
+
+# Setup env__mmc_device_test_skip to not skipping the test. By default, its
+# value is set to True. Set it to False to run all tests for MMC device.
+env__mmc_device_test_skip = False
+"""
+
+mmc_set_up = False
+controllers = 0
+devices = {}
+
+def setup_mmc(u_boot_console):
+ if u_boot_console.config.env.get('env__mmc_device_test_skip', True):
+ pytest.skip('MMC device test is not enabled')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_list(u_boot_console):
+ setup_mmc(u_boot_console)
+ output = u_boot_console.run_command('mmc list')
+ if 'No MMC device available' in output:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No SD/MMC card present')
+
+ array = output.split()
+ global devices
+ global controllers
+ controllers = int(len(array) / 2)
+ for x in range(0, controllers):
+ y = x * 2
+ devices[x] = {}
+ devices[x]['name'] = array[y]
+
+ global mmc_set_up
+ mmc_set_up = True
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_dev(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ fail = 0
+ for x in range(0, controllers):
+ devices[x]['detected'] = 'yes'
+ output = u_boot_console.run_command('mmc dev %d' % x)
+
+ # Some sort of switch here
+ if 'Card did not respond to voltage select' in output:
+ fail = 1
+ devices[x]['detected'] = 'no'
+
+ if 'no mmc device at slot' in output:
+ devices[x]['detected'] = 'no'
+
+ if 'MMC: no card present' in output:
+ devices[x]['detected'] = 'no'
+
+ if fail:
+ pytest.fail('Card not present')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmcinfo(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmcinfo')
+ if 'busy timeout' in output:
+ pytest.skip('No SD/MMC/eMMC device present')
+
+ obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ try:
+ capacity = float(obj.groups()[0])
+ print(capacity)
+ devices[x]['capacity'] = capacity
+ print('Capacity of dev %d is: %g GiB' % (x, capacity))
+ except ValueError:
+ pytest.fail('MMC capacity not recognized')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_info(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+
+ output = u_boot_console.run_command('mmc info')
+
+ obj = re.search(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ try:
+ capacity = float(obj.groups()[0])
+ print(capacity)
+ if devices[x]['capacity'] != capacity:
+ pytest.fail("MMC capacity doesn't match mmcinfo")
+
+ except ValueError:
+ pytest.fail('MMC capacity not recognized')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_rescan(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmc rescan')
+ if output:
+ pytest.fail('mmc rescan has something to check')
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+def test_mmc_part(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ output = u_boot_console.run_command('mmc part')
+
+ lines = output.split('\n')
+ part_fat = []
+ part_ext = []
+ for line in lines:
+ obj = re.search(
+ r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
+ if obj:
+ part_id = int(obj.groups()[0])
+ part_type = obj.groups()[1]
+ print('part_id:%d, part_type:%s' % (part_id, part_type))
+
+ if part_type in ['0c', '0b', '0e']:
+ print('Fat detected')
+ part_fat.append(part_id)
+ elif part_type == '83':
+ print('ext detected')
+ part_ext.append(part_id)
+ else:
+ pytest.fail('Unsupported Filesystem on device %d' % x)
+ devices[x]['ext4'] = part_ext
+ devices[x]['ext2'] = part_ext
+ devices[x]['fat'] = part_fat
+
+ if not part_ext and not part_fat:
+ pytest.fail('No partition detected on device %d' % x)
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+def test_mmc_fatls_fatinfo(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ output = u_boot_console.run_command(
+ 'fatls mmc %d:%s' % (x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+
+ if not re.search(r'\d file\(s\), \d dir\(s\)', output):
+ pytest.fail('%s read failed on device %d' % (fs.upper, x))
+ output = u_boot_console.run_command(
+ 'fatinfo mmc %d:%s' % (x, part))
+ string = 'Filesystem: %s' % fs.upper
+ if re.search(string, output):
+ pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_fatload_fatwrite(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ devices[x]['addr_%d' % part] = addr
+ size = random.randint(4, 1 * 1024 * 1024)
+ devices[x]['size_%d' % part] = size
+ # count CRC32
+ 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)
+ devices[x]['expected_crc32_%d' % part] = expected_crc32
+ # do write
+ file = '%s_%d' % ('uboot_test', size)
+ devices[x]['file_%d' % part] = file
+ output = u_boot_console.run_command(
+ '%swrite mmc %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 mmc %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
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext4')
+def test_mmc_ext4ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ u_boot_console.run_command('mmc dev %d' % x)
+ for part in partitions:
+ output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_ext4load_ext4write(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ devices[x]['addr_%d' % part] = addr
+ size = random.randint(4, 1 * 1024 * 1024)
+ devices[x]['size_%d' % part] = size
+ # count CRC32
+ 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)
+ devices[x]['expected_crc32_%d' % part] = expected_crc32
+ # do write
+
+ file = '%s_%d' % ('uboot_test', size)
+ devices[x]['file_%d' % part] = file
+ output = u_boot_console.run_command(
+ '%swrite mmc %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 mmc %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
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext2')
+def test_mmc_ext2ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('%sls mmc %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_ext2')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('ext4_write')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_ext2load(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = devices[x]['size_%d' % part]
+ expected_crc32 = devices[x]['expected_crc32_%d' % part]
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ '%sload mmc %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
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_ls(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('ls mmc %d:%s' % (x, part))
+ if re.search(r'No \w+ table on this device', output):
+ pytest.fail(
+ '%s: Partition table not found %d' % (fs.upper(), x)
+ )
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_load(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = devices[x]['size_%d' % part]
+ expected_crc32 = devices[x]['expected_crc32_%d' % part]
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'load mmc %d:%s %x /%s' % (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
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_mmc_save(u_boot_console):
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = devices[x]['addr_%d' % part]
+ size = 0
+ file = devices[x]['file_%d' % part]
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'save mmc %d:%s %x /%s %d'
+ % (x, part, addr + offset, file, size)
+ )
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_mmc')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_mmc_fat_read_write_files(u_boot_console):
+ test_mmc_list(u_boot_console)
+ test_mmc_dev(u_boot_console)
+ test_mmcinfo(u_boot_console)
+ test_mmc_part(u_boot_console)
+ if not mmc_set_up:
+ pytest.skip('No SD/MMC/eMMC controller available')
+
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+
+ # Number of files to be written/read in MMC card
+ num_files = 100
+
+ for x in range(0, controllers):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('mmc dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ count_f = 0
+ addr_l = []
+ size_l = []
+ file_l = []
+ crc32_l = []
+ offset_l = []
+ addr_l.append(addr)
+
+ while count_f < num_files:
+ size_l.append(random.randint(4, 1 * 1024 * 1024))
+
+ # CRC32 count
+ output = u_boot_console.run_command(
+ 'crc32 %x %x' % (addr_l[count_f], size_l[count_f])
+ )
+ m = re.search('==> (.+?)', output)
+ if not m:
+ pytest.fail('CRC32 failed')
+ crc32_l.append(m.group(1))
+
+ # Write operation
+ file_l.append('%s_%d_%d' % ('uboot_test', count_f, size_l[count_f]))
+ output = u_boot_console.run_command(
+ '%swrite mmc %d:%s %x %s %x'
+ % (
+ fs,
+ x,
+ part,
+ addr_l[count_f],
+ file_l[count_f],
+ size_l[count_f],
+ )
+ )
+ assert 'Unable to write' not in output
+ assert 'Error' not in output
+ assert 'overflow' not in output
+ expected_text = '%d bytes written' % size_l[count_f]
+ assert expected_text in output
+
+ addr_l.append(addr_l[count_f] + size_l[count_f] + 1048576)
+ count_f += 1
+
+ count_f = 0
+ while count_f < num_files:
+ alignment = int(
+ u_boot_console.config.buildconfig.get(
+ 'config_sys_cacheline_size', 128
+ )
+ )
+ offset_l.append(random.randrange(alignment, 1024, alignment))
+
+ # Read operation
+ output = u_boot_console.run_command(
+ '%sload mmc %d:%s %x %s'
+ % (
+ fs,
+ x,
+ part,
+ addr_l[count_f] + offset_l[count_f],
+ file_l[count_f],
+ )
+ )
+ 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_l[count_f]
+ assert expected_text in output
+
+ output = u_boot_console.run_command(
+ 'crc32 %x $filesize' % (addr_l[count_f] + offset_l[count_f])
+ )
+ assert crc32_l[count_f] in output
+
+ count_f += 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
diff --git a/test/py/tests/test_net.py b/test/py/tests/test_net.py
index b2241ae6a48..4ff3dafd629 100644
--- a/test/py/tests/test_net.py
+++ b/test/py/tests/test_net.py
@@ -7,6 +7,7 @@
import pytest
import u_boot_utils
import uuid
+import datetime
"""
Note: This test relies on boardenv_* containing configuration values to define
@@ -51,6 +52,8 @@ env__net_tftp_readable_file = {
'addr': 0x10000000,
'size': 5058624,
'crc32': 'c2244b26',
+ 'timeout': 50000,
+ 'fnu': 'ubtest-upload.bin',
}
# Details regarding a file that may be read from a NFS server. This variable
@@ -96,6 +99,8 @@ def test_net_pre_commands(u_boot_console):
if init_pci:
u_boot_console.run_command('pci enum')
+ u_boot_console.run_command('net list')
+
@pytest.mark.buildconfigspec('cmd_dhcp')
def test_net_dhcp(u_boot_console):
"""Test the dhcp command.
@@ -326,3 +331,71 @@ def test_net_pxe_get(u_boot_console):
assert expected_text_default in output
assert "Config file 'default.boot' found" in output
+
+@pytest.mark.buildconfigspec("cmd_crc32")
+@pytest.mark.buildconfigspec("cmd_net")
+@pytest.mark.buildconfigspec("cmd_tftpput")
+def test_net_tftpput(u_boot_console):
+ """Test the tftpput command.
+
+ A file is downloaded from the TFTP server and then uploaded to the TFTP
+ server, its size and its CRC32 are validated.
+
+ The details of the file to download are provided by the boardenv_* file;
+ see the comment at the beginning of this file.
+ """
+
+ if not net_set_up:
+ pytest.skip("Network not initialized")
+
+ f = u_boot_console.config.env.get("env__net_tftp_readable_file", None)
+ if not f:
+ pytest.skip("No TFTP readable file to read")
+
+ addr = f.get("addr", None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ sz = f.get("size", None)
+ timeout = f.get("timeout", u_boot_console.p.timeout)
+ fn = f["fn"]
+ fnu = f.get("fnu", "_".join([datetime.datetime.now().strftime("%y%m%d%H%M%S"), fn]))
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command("tftpboot %x %s" % (addr, fn))
+
+ assert "TIMEOUT" not in output
+ assert expected_text in output
+
+ expected_tftpb_crc = f.get("crc32", None)
+
+ output = u_boot_console.run_command("crc32 $fileaddr $filesize")
+ assert expected_tftpb_crc in output
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command(
+ "tftpput $fileaddr $filesize $serverip:%s" % (fnu)
+ )
+
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+ addr = addr + sz
+ assert "TIMEOUT" not in output
+ assert "Access violation" not in output
+ assert expected_text in output
+
+ with u_boot_console.temporary_timeout(timeout):
+ output = u_boot_console.run_command("tftpboot %x %s" % (addr, fnu))
+
+ expected_text = "Bytes transferred = "
+ if sz:
+ expected_text += "%d" % sz
+ assert "TIMEOUT" not in output
+ assert expected_text in output
+
+ output = u_boot_console.run_command("crc32 $fileaddr $filesize")
+ assert expected_tftpb_crc in output
diff --git a/test/py/tests/test_scsi.py b/test/py/tests/test_scsi.py
new file mode 100644
index 00000000000..be2e283e7d2
--- /dev/null
+++ b/test/py/tests/test_scsi.py
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+the SCSI device number, type and capacity. This test will be automatically
+skipped without this.
+
+For example:
+
+# Setup env__scsi_device_test to set the SCSI device number/slot, the type of
+device, and the device capacity in MB.
+env__scsi_device_test = {
+ 'dev_num': 0,
+ 'device_type': 'Hard Disk',
+ 'device_capacity': '476940.0 MB',
+}
+"""
+
+def scsi_setup(u_boot_console):
+ f = u_boot_console.config.env.get('env__scsi_device_test', None)
+ if not f:
+ pytest.skip('No SCSI device to test')
+
+ dev_num = f.get('dev_num', None)
+ if not isinstance(dev_num, int):
+ pytest.skip('No device number specified in env file to read')
+
+ dev_type = f.get('device_type')
+ if not dev_type:
+ pytest.skip('No device type specified in env file to read')
+
+ dev_size = f.get('device_capacity')
+ if not dev_size:
+ pytest.skip('No device capacity specified in env file to read')
+
+ return dev_num, dev_type, dev_size
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_reset(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi reset')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_info(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi info')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_scan(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi scan')
+ assert f'Device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_dev(u_boot_console):
+ dev_num, dev_type, dev_size = scsi_setup(u_boot_console)
+ output = u_boot_console.run_command('scsi device')
+ assert 'no scsi devices available' not in output
+ assert f'device {dev_num}:' in output
+ assert f'Type: {dev_type}' in output
+ assert f'Capacity: {dev_size}' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('scsi device %d' % dev_num)
+ assert 'is now current device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_scsi')
+def test_scsi_part(u_boot_console):
+ test_scsi_dev(u_boot_console)
+ output = u_boot_console.run_command('scsi part')
+ assert 'Partition Map for SCSI device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
diff --git a/test/py/tests/test_smbios.py b/test/py/tests/test_smbios.py
new file mode 100644
index 00000000000..82b0b689830
--- /dev/null
+++ b/test/py/tests/test_smbios.py
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+"""Test smbios command"""
+
+import pytest
+
+@pytest.mark.buildconfigspec('cmd_smbios')
+@pytest.mark.notbuildconfigspec('qfw_smbios')
+@pytest.mark.notbuildconfigspec('sandbox')
+def test_cmd_smbios(u_boot_console):
+ """Run the smbios command"""
+ output = u_boot_console.run_command('smbios')
+ assert 'DMI type 127,' in output
+
+@pytest.mark.buildconfigspec('cmd_smbios')
+@pytest.mark.buildconfigspec('qfw_smbios')
+@pytest.mark.notbuildconfigspec('sandbox')
+# TODO:
+# QEMU v8.2.0 lacks SMBIOS support for RISC-V
+# Once support is available in our Docker image we can remove the constraint.
+@pytest.mark.notbuildconfigspec('riscv')
+def test_cmd_smbios_qemu(u_boot_console):
+ """Run the smbios command on QEMU"""
+ output = u_boot_console.run_command('smbios')
+ assert 'DMI type 1,' in output
+ assert 'Manufacturer: QEMU' in output
+ assert 'DMI type 127,' in output
+
+@pytest.mark.buildconfigspec('cmd_smbios')
+@pytest.mark.buildconfigspec('sandbox')
+def test_cmd_smbios_sandbox(u_boot_console):
+ """Run the smbios command on the sandbox"""
+ output = u_boot_console.run_command('smbios')
+ assert 'DMI type 0,' in output
+ assert 'String 1: U-Boot' in output
+ assert 'DMI type 1,' in output
+ assert 'Manufacturer: sandbox' in output
+ assert 'DMI type 2,' in output
+ assert 'DMI type 3,' in output
+ assert 'DMI type 4,' in output
+ assert 'DMI type 127,' in output
diff --git a/test/py/tests/test_trace.py b/test/py/tests/test_trace.py
index 28a6e72f525..7c5696ce747 100644
--- a/test/py/tests/test_trace.py
+++ b/test/py/tests/test_trace.py
@@ -12,7 +12,7 @@ import u_boot_utils as util
TMPDIR = '/tmp/test_trace'
# Decode a function-graph line
-RE_LINE = re.compile(r'.*\[000\]\s*([0-9.]*): func.*[|](\s*)(\S.*)?([{};])$')
+RE_LINE = re.compile(r'.*0\.\.\.\.\. \s*([0-9.]*): func.*[|](\s*)(\S.*)?([{};])$')
def collect_trace(cons):
@@ -113,15 +113,15 @@ def check_function(cons, fname, proftool, map_fname, trace_dat):
assert val > 50000 # Should be at least 50KB of symbols
# Check that the trace has something useful
- cmd = f"trace-cmd report {trace_dat} |grep -E '(initf_|initr_)'"
+ cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_|initr_)'"
out = util.run_and_log(cons, ['sh', '-c', cmd])
# Format:
- # unknown option 14
- # u-boot-1 [000] 60.805596: function: initf_malloc
- # u-boot-1 [000] 60.805597: function: initf_malloc
- # u-boot-1 [000] 60.805601: function: initf_bootstage
- # u-boot-1 [000] 60.805607: function: initf_bootstage
+ # u-boot-1 0..... 60.805596: function: initf_malloc
+ # u-boot-1 0..... 60.805597: function: initf_malloc
+ # u-boot-1 0..... 60.805601: function: initf_bootstage
+ # u-boot-1 0..... 60.805607: function: initf_bootstage
+
lines = [line.replace(':', '').split() for line in out.splitlines()]
vals = {items[4]: float(items[2]) for items in lines if len(items) == 5}
base = None
@@ -161,21 +161,21 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat):
'dump-ftrace', '-f', 'funcgraph'])
# Check that the trace has what we expect
- cmd = f'trace-cmd report {trace_dat} |head -n 70'
+ cmd = f'trace-cmd report -l {trace_dat} |head -n 70'
out = util.run_and_log(cons, ['sh', '-c', cmd])
# First look for this:
- # u-boot-1 [000] 282.101360: funcgraph_entry: 0.004 us | initf_malloc();
+ # u-boot-1 0..... 282.101360: funcgraph_entry: 0.004 us | initf_malloc();
# ...
- # u-boot-1 [000] 282.101369: funcgraph_entry: | initf_bootstage() {
- # u-boot-1 [000] 282.101369: funcgraph_entry: | bootstage_init() {
- # u-boot-1 [000] 282.101369: funcgraph_entry: | dlmalloc() {
+ # u-boot-1 0..... 282.101369: funcgraph_entry: | initf_bootstage() {
+ # u-boot-1 0..... 282.101369: funcgraph_entry: | bootstage_init() {
+ # u-boot-1 0..... 282.101369: funcgraph_entry: | dlmalloc() {
# ...
- # u-boot-1 [000] 282.101375: funcgraph_exit: 0.001 us | }
+ # u-boot-1 0..... 282.101375: funcgraph_exit: 0.001 us | }
# Then look for this:
- # u-boot-1 [000] 282.101375: funcgraph_exit: 0.006 us | }
+ # u-boot-1 0..... 282.101375: funcgraph_exit: 0.006 us | }
# Then check for this:
- # u-boot-1 [000] 282.101375: funcgraph_entry: 0.000 us | initcall_is_event();
+ # u-boot-1 0..... 282.101375: funcgraph_entry: 0.000 us | initcall_is_event();
expected_indent = None
found_start = False
@@ -203,7 +203,7 @@ def check_funcgraph(cons, fname, proftool, map_fname, trace_dat):
# Now look for initf_dm() and dm_timer_init() so we can check the bootstage
# time
- cmd = f"trace-cmd report {trace_dat} |grep -E '(initf_dm|dm_timer_init)'"
+ cmd = f"trace-cmd report -l {trace_dat} |grep -E '(initf_dm|dm_timer_init)'"
out = util.run_and_log(cons, ['sh', '-c', cmd])
start_timestamp = None
diff --git a/test/py/tests/test_usb.py b/test/py/tests/test_usb.py
new file mode 100644
index 00000000000..fb3d20f0826
--- /dev/null
+++ b/test/py/tests/test_usb.py
@@ -0,0 +1,626 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import re
+import u_boot_utils
+
+"""
+Note: This test doesn't rely on boardenv_* configuration values but it can
+change the test behavior. To test USB file system cases (fat32, ext2, ext4),
+USB device should be formatted and valid partitions should be created for
+different file system, otherwise it may leads to failure. This test will be
+skipped if the USB device is not detected.
+
+For example:
+
+# Setup env__usb_device_test_skip to not skipping the test. By default, its
+# value is set to True. Set it to False to run all tests for USB device.
+env__usb_device_test_skip = False
+"""
+
+def setup_usb(u_boot_console):
+ if u_boot_console.config.env.get('env__usb_device_test_skip', True):
+ pytest.skip('USB device test is not enabled')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_start(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb start')
+
+ # if output is empty, usb start may already run as part of preboot command
+ # re-start the usb, in that case
+ if not output:
+ u_boot_console.run_command('usb stop')
+ output = u_boot_console.run_command('usb start')
+
+ if 'No USB device found' in output:
+ pytest.skip('No USB controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No USB device present')
+
+ controllers = 0
+ storage_device = 0
+ obj = re.search(r'\d USB Device\(s\) found', output)
+ controllers = int(obj.group()[0])
+
+ if not controllers:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d Storage Device\(s\) found', output)
+ storage_device = int(obj.group()[0])
+
+ if not storage_device:
+ pytest.skip('No USB storage device present')
+
+ assert 'USB init failed' not in output
+ assert 'starting USB...' in output
+
+ if 'Starting the controller' in output:
+ assert 'USB XHCI' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ return controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_stop(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb stop')
+ assert 'stopping USB..' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ output = u_boot_console.run_command('usb dev')
+ assert "USB is stopped. Please issue 'usb start' first." in output
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_reset(u_boot_console):
+ setup_usb(u_boot_console)
+ output = u_boot_console.run_command('usb reset')
+
+ if 'No USB device found' in output:
+ pytest.skip('No USB controller available')
+
+ if 'Card did not respond to voltage select' in output:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d USB Device\(s\) found', output)
+ usb_dev_num = int(obj.group()[0])
+
+ if not usb_dev_num:
+ pytest.skip('No USB device present')
+
+ obj = re.search(r'\d Storage Device\(s\) found', output)
+ usb_stor_num = int(obj.group()[0])
+
+ if not usb_stor_num:
+ pytest.skip('No USB storage device present')
+
+ assert 'BUG' not in output
+ assert 'USB init failed' not in output
+ assert 'resetting USB...' in output
+
+ if 'Starting the controller' in output:
+ assert 'USB XHCI' in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_info(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb info')
+
+ num_controller = len(re.findall(': Hub,', output))
+ num_mass_storage = len(re.findall(': Mass Storage,', output))
+
+ assert num_controller == controllers - 1
+ assert num_mass_storage == storage_device
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ for i in range(0, storage_device + controllers - 1):
+ output = u_boot_console.run_command('usb info %d' % i)
+ num_controller = len(re.findall(': Hub,', output))
+ num_mass_storage = len(re.findall(': Mass Storage,', output))
+ assert num_controller + num_mass_storage == 1
+ assert 'No device available' not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_tree(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb tree')
+
+ num_controller = len(re.findall('Hub', output))
+ num_mass_storage = len(re.findall('Mass Storage', output))
+
+ assert num_controller == controllers - 1
+ assert num_mass_storage == storage_device
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('usb_storage')
+def test_usb_storage(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb storage')
+
+ obj = re.findall(r'Capacity: (\d+|\d+[\.]?\d)', output)
+ devices = {}
+
+ for key in range(int(storage_device)):
+ devices[key] = {}
+
+ for x in range(int(storage_device)):
+ try:
+ capacity = float(obj[x].split()[0])
+ devices[x]['capacity'] = capacity
+ print('USB storage device %d capacity is: %g MB' % (x, capacity))
+ except ValueError:
+ pytest.fail('USB storage device capacity not recognized')
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_dev(u_boot_console):
+ controllers, storage_device = test_usb_start(u_boot_console)
+ output = u_boot_console.run_command('usb dev')
+
+ assert 'no usb devices available' not in output
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ devices = {}
+
+ for key in range(int(storage_device)):
+ devices[key] = {}
+
+ fail = 0
+ for x in range(0, storage_device):
+ devices[x]['detected'] = 'yes'
+ output = u_boot_console.run_command('usb dev %d' % x)
+
+ if 'Card did not respond to voltage select' in output:
+ fail = 1
+ devices[x]['detected'] = 'no'
+
+ if 'No USB device found' in output:
+ devices[x]['detected'] = 'no'
+
+ if 'unknown device' in output:
+ devices[x]['detected'] = 'no'
+
+ assert 'is now current device' in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ if fail:
+ pytest.fail('USB device not present')
+
+ return devices, controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+def test_usb_part(u_boot_console):
+ devices, controllers, storage_device = test_usb_dev(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ u_boot_console.run_command('usb part')
+
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+ for i in range(0, storage_device):
+ if devices[i]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % i)
+ output = u_boot_console.run_command('usb part')
+
+ lines = output.split('\n')
+ part_fat = []
+ part_ext = []
+ for line in lines:
+ obj = re.search(r'(\d)\s+\d+\s+\d+\s+\w+\d+\w+-\d+\s+(\d+\w+)', line)
+ if obj:
+ part_id = int(obj.groups()[0])
+ part_type = obj.groups()[1]
+ print('part_id:%d, part_type:%s' % (part_id, part_type))
+
+ if part_type == '0c' or part_type == '0b' or part_type == '0e':
+ print('Fat detected')
+ part_fat.append(part_id)
+ elif part_type == '83':
+ print('ext detected')
+ part_ext.append(part_id)
+ else:
+ pytest.fail('Unsupported Filesystem on device %d' % i)
+ devices[i]['ext4'] = part_ext
+ devices[i]['ext2'] = part_ext
+ devices[i]['fat'] = part_fat
+
+ if not part_ext and not part_fat:
+ pytest.fail('No partition detected on device %d' % i)
+
+ return devices, controllers, storage_device
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fat')
+def test_usb_fatls_fatinfo(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ output = u_boot_console.run_command('fatls usb %d:%s' % (x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+
+ if not re.search(r'\d file\(s\), \d dir\(s\)', output):
+ pytest.fail('%s read failed on device %d' % (fs.upper, x))
+
+ output = u_boot_console.run_command('fatinfo usb %d:%s' % (x, part))
+ string = 'Filesystem: %s' % fs.upper
+ if re.search(string, output):
+ pytest.fail('%s FS failed on device %d' % (fs.upper(), x))
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+def test_usb_fatload_fatwrite(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'fat'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ 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
+
+ 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):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ u_boot_console.run_command('usb dev %d' % x)
+ for part in partitions:
+ output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('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)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext4'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ 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
+
+ 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):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('%sls usb %d:%s' % (fs, x, part))
+ if 'Unrecognized filesystem type' in output:
+ partitions.remove(part)
+ pytest.fail('Unrecognized filesystem')
+ part_detect = 1
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_ext2')
+@pytest.mark.buildconfigspec('cmd_ext4')
+@pytest.mark.buildconfigspec('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')
+
+ part_detect = 0
+ fs = 'ext2'
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ 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(
+ '%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
+
+ if not part_detect:
+ pytest.skip('No %s partition detected' % fs.upper())
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_ls(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ output = u_boot_console.run_command('ls usb %d:%s' % (x, part))
+ if re.search(r'No \w+ table on this device', output):
+ pytest.fail(
+ '%s: Partition table not found %d' % (fs.upper(), x)
+ )
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_load(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ if fs == 'fat':
+ file, size = test_usb_fatload_fatwrite(u_boot_console)
+ 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)
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'load usb %d:%s %x /%s' % (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
+
+ if not part_detect:
+ pytest.skip('No partition detected')
+
+@pytest.mark.buildconfigspec('cmd_usb')
+@pytest.mark.buildconfigspec('cmd_fs_generic')
+def test_usb_save(u_boot_console):
+ devices, controllers, storage_device = test_usb_part(u_boot_console)
+ if not devices:
+ pytest.skip('No devices detected')
+
+ part_detect = 0
+ for x in range(0, int(storage_device)):
+ if devices[x]['detected'] == 'yes':
+ u_boot_console.run_command('usb dev %d' % x)
+ for fs in ['fat', 'ext4']:
+ try:
+ partitions = devices[x][fs]
+ except:
+ print('No %s table on this device' % fs.upper())
+ continue
+
+ for part in partitions:
+ part_detect = 1
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ size = random.randint(4, 1 * 1024 * 1024)
+ file = '%s_%d' % ('uboot_test', size)
+
+ offset = random.randrange(128, 1024, 128)
+ output = u_boot_console.run_command(
+ 'save usb %d:%s %x /%s %x'
+ % (x, part, addr + offset, file, size)
+ )
+ expected_text = '%d bytes written' % size
+ assert expected_text in output
+
+ if not part_detect:
+ pytest.skip('No partition detected')
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index 1d9149a3f68..c169c835e38 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -9,6 +9,7 @@ import os.path
import pytest
import u_boot_utils
+# pylint: disable=E0611
from tests import fs_helper
def mkdir_cond(dirname):
@@ -499,5 +500,11 @@ def test_ut(u_boot_console, ut_subtest):
execute command 'ut foo bar'
"""
- output = u_boot_console.run_command('ut ' + ut_subtest)
+ if ut_subtest == 'hush hush_test_simple_dollar':
+ # ut hush hush_test_simple_dollar prints "Unknown command" on purpose.
+ with u_boot_console.disable_check('unknown_command'):
+ output = u_boot_console.run_command('ut ' + ut_subtest)
+ assert('Unknown command \'quux\' - try \'help\'' in output)
+ else:
+ output = u_boot_console.run_command('ut ' + ut_subtest)
assert output.endswith('Failures: 0')
diff --git a/test/py/tests/test_vboot.py b/test/py/tests/test_vboot.py
index 04fa59f98b0..7e0e8e44750 100644
--- a/test/py/tests/test_vboot.py
+++ b/test/py/tests/test_vboot.py
@@ -533,10 +533,10 @@ def test_vboot(u_boot_console, name, sha_algo, padding, sign_options, required,
with open(evil_kernel, 'wb') as fd:
fd.write(500 * b'\x01')
+ # We need to use our own device tree file. Remember to restore it
+ # afterwards.
+ old_dtb = cons.config.dtb
try:
- # We need to use our own device tree file. Remember to restore it
- # afterwards.
- old_dtb = cons.config.dtb
cons.config.dtb = dtb
if global_sign:
test_global_sign(sha_algo, padding, sign_options)
diff --git a/test/py/tests/test_zynq_secure.py b/test/py/tests/test_zynq_secure.py
new file mode 100644
index 00000000000..0ee5aebc484
--- /dev/null
+++ b/test/py/tests/test_zynq_secure.py
@@ -0,0 +1,190 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+import u_boot_utils
+import test_net
+
+"""
+This test verifies different type of secure boot images to authentication and
+decryption using AES and RSA features for AMD's Zynq SoC.
+
+Note: This test relies on boardenv_* containing configuration values to define
+the network available and files to be used for testing. Without this, this test
+will be automatically skipped. It also relies on dhcp or setup_static net test
+to support tftp to load files from a TFTP server.
+
+For example:
+
+# Details regarding the files that may be read from a TFTP server and addresses
+# and size for aes and rsa cases respectively. This variable may be omitted or
+# set to None if zynqmp secure testing is not possible or desired.
+env__zynq_aes_readable_file = {
+ 'fn': 'zynq_aes_image.bin',
+ 'fnbit': 'zynq_aes_bit.bin',
+ 'fnpbit': 'zynq_aes_par_bit.bin',
+ 'srcaddr': 0x1000000,
+ 'dstaddr': 0x2000000,
+ 'dstlen': 0x1000000,
+}
+
+env__zynq_rsa_readable_file = {
+ 'fn': 'zynq_rsa_image.bin',
+ 'fninvalid': 'zynq_rsa_image_invalid.bin',
+ 'srcaddr': 0x1000000,
+}
+"""
+
+def zynq_secure_pre_commands(u_boot_console):
+ output = u_boot_console.run_command('print modeboot')
+ if not 'modeboot=' in output:
+ pytest.skip('bootmode cannnot be determined')
+ m = re.search('modeboot=(.+?)boot', output)
+ if not m:
+ pytest.skip('bootmode cannnot be determined')
+ bootmode = m.group(1)
+ if bootmode == 'jtag':
+ pytest.skip('skipping due to jtag bootmode')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_image(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ dstaddr = f.get('dstaddr', None)
+ if not dstaddr:
+ pytest.skip('No dstaddr specified in env file to read')
+
+ dstsize = f.get('dstlen', None)
+ if not dstsize:
+ pytest.skip('No dstlen specified in env file to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command(
+ 'zynq aes %x $filesize %x %x' % (srcaddr, dstaddr, dstsize)
+ )
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_bitstream(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fnbit']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command(
+ 'zynq aes load %x $filesize' % (srcaddr)
+ )
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_aes')
+def test_zynq_aes_partial_bitstream(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_aes_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure aes case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fnpbit']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq aes [operation type] <srcaddr>'
+ output = u_boot_console.run_command('zynq aes loadp %x $filesize' % (srcaddr))
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_rsa')
+def test_zynq_rsa_image(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure rsa case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fn))
+ assert expected_tftp in output
+
+ expected_op = 'zynq rsa <baseaddr>'
+ output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
+ assert expected_op not in output
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+
+@pytest.mark.buildconfigspec('cmd_zynq_rsa')
+def test_zynq_rsa_image_invalid(u_boot_console):
+ f = u_boot_console.config.env.get('env__zynq_rsa_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynq secure rsa case to read')
+
+ zynq_secure_pre_commands(u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ srcaddr = f.get('srcaddr', None)
+ if not srcaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fninvalid = f['fninvalid']
+ output = u_boot_console.run_command('tftpboot %x %s' % (srcaddr, fninvalid))
+ assert expected_tftp in output
+
+ expected_op = 'zynq rsa <baseaddr>'
+ output = u_boot_console.run_command('zynq rsa %x ' % (srcaddr))
+ assert expected_op in output
+ output = u_boot_console.run_command('echo $?')
+ assert not output.endswith('0')
diff --git a/test/py/tests/test_zynqmp_rpu.py b/test/py/tests/test_zynqmp_rpu.py
new file mode 100644
index 00000000000..479a612b4ec
--- /dev/null
+++ b/test/py/tests/test_zynqmp_rpu.py
@@ -0,0 +1,208 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import random
+import string
+import test_net
+
+"""
+Note: This test relies on boardenv_* containing configuration values to define
+RPU applications information for AMD's ZynqMP SoC which contains, application
+names, processors, address where it is built, expected output and the tftp load
+addresses. This test will be automatically skipped without this.
+
+It also relies on dhcp or setup_static net test to support tftp to load
+application on DDR. All the environment parameters are stored sequentially.
+The length of all parameters values should be same. For example, if 2 app_names
+are defined in a list as a value of parameter 'app_name' then the other
+parameters value also should have a list with 2 items.
+It will run RPU cases for all the applications defined in boardenv_*
+configuration file.
+
+Example:
+env__zynqmp_rpu_apps = {
+ 'app_name': ['hello_world_r5_0_ddr.elf', 'hello_world_r5_1_ddr.elf'],
+ 'proc': ['rpu0', 'rpu1'],
+ 'cpu_num': [4, 5],
+ 'addr': [0xA00000, 0xB00000],
+ 'output': ['Successfully ran Hello World application on DDR from RPU0',
+ 'Successfully ran Hello World application on DDR from RPU1'],
+ 'tftp_addr': [0x100000, 0x200000],
+}
+"""
+
+# Get rpu apps params from env
+def get_rpu_apps_env(u_boot_console):
+ rpu_apps = u_boot_console.config.env.get('env__zynqmp_rpu_apps', False)
+ if not rpu_apps:
+ pytest.skip('ZynqMP RPU application info not defined!')
+
+ apps = rpu_apps.get('app_name', None)
+ if not apps:
+ pytest.skip('No RPU application found!')
+
+ procs = rpu_apps.get('proc', None)
+ if not procs:
+ pytest.skip('No RPU application processor provided!')
+
+ cpu_nums = rpu_apps.get('cpu_num', None)
+ if not cpu_nums:
+ pytest.skip('No CPU number for respective processor provided!')
+
+ addrs = rpu_apps.get('addr', None)
+ if not addrs:
+ pytest.skip('No RPU application build address found!')
+
+ outputs = rpu_apps.get('output', None)
+ if not outputs:
+ pytest.skip('Expected output not found!')
+
+ tftp_addrs = rpu_apps.get('tftp_addr', None)
+ if not tftp_addrs:
+ pytest.skip('TFTP address to load application not found!')
+
+ return apps, procs, cpu_nums, addrs, outputs, tftp_addrs
+
+# Check return code
+def ret_code(u_boot_console):
+ return u_boot_console.run_command('echo $?')
+
+# Initialize tcm
+def tcminit(u_boot_console, rpu_mode):
+ output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert 'Initializing TCM overwrites TCM content' in output
+ return ret_code(u_boot_console)
+
+# Load application in DDR
+def load_app_ddr(u_boot_console, tftp_addr, app):
+ output = u_boot_console.run_command('tftpboot %x %s' % (tftp_addr, app))
+ assert 'TIMEOUT' not in output
+ assert 'Bytes transferred = ' in output
+
+ # Load elf
+ u_boot_console.run_command('bootelf -p %x' % tftp_addr)
+ assert ret_code(u_boot_console).endswith('0')
+
+# Disable cpus
+def disable_cpus(u_boot_console, cpu_nums):
+ for num in cpu_nums:
+ u_boot_console.run_command(f'cpu {num} disable')
+
+# Load apps on RPU cores
+def rpu_apps_load(u_boot_console, rpu_mode):
+ apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
+ u_boot_console)
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ try:
+ assert tcminit(u_boot_console, rpu_mode).endswith('0')
+
+ for i in range(len(apps)):
+ if rpu_mode == 'lockstep' and procs[i] != 'rpu0':
+ continue
+
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+ rel_addr = int(addrs[i] + 0x3C)
+
+ # Release cpu at app load address
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ u_boot_console.wait_for(outputs[i])
+ assert ret_code(u_boot_console).endswith('0')
+ finally:
+ disable_cpus(u_boot_console, cpu_nums)
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_split(u_boot_console):
+ rpu_apps_load(u_boot_console, 'split')
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_lockstep(u_boot_console):
+ rpu_apps_load(u_boot_console, 'lockstep')
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_rpu_app_load_negative(u_boot_console):
+ apps, procs, cpu_nums, addrs, outputs, tftp_addrs = get_rpu_apps_env(
+ u_boot_console)
+
+ # Invalid commands
+ u_boot_console.run_command('zynqmp tcminit mode')
+ assert ret_code(u_boot_console).endswith('1')
+
+ rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
+ u_boot_console.run_command('zynqmp tcminit %s' % rand_str)
+ assert ret_code(u_boot_console).endswith('1')
+
+ rand_num = random.randint(2, 100)
+ u_boot_console.run_command('zynqmp tcminit %d' % rand_num)
+ assert ret_code(u_boot_console).endswith('1')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ try:
+ rpu_mode = 'split'
+ assert tcminit(u_boot_console, rpu_mode).endswith('0')
+
+ for i in range(len(apps)):
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+
+ # Run in split mode at different load address
+ rel_addr = int(addrs[i]) + random.randint(200, 1000)
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ assert not outputs[i] in output
+
+ # Invalid rpu mode
+ rand_str = ''.join(random.choices(string.ascii_lowercase, k=4))
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rand_str)
+ output = u_boot_console.run_command(cmd)
+ assert exp_op in output
+ assert f'Unsupported mode' in output
+ assert not ret_code(u_boot_console).endswith('0')
+
+ # Switch to lockstep mode, without disabling CPUs
+ rpu_mode = 'lockstep'
+ u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert not ret_code(u_boot_console).endswith('0')
+
+ # Disable cpus
+ disable_cpus(u_boot_console, cpu_nums)
+
+ # Switch to lockstep mode, after disabling CPUs
+ output = u_boot_console.run_command('zynqmp tcminit %s' % rpu_mode)
+ assert 'Initializing TCM overwrites TCM content' in output
+ assert ret_code(u_boot_console).endswith('0')
+
+ # Run lockstep mode for RPU1
+ for i in range(len(apps)):
+ if procs[i] == 'rpu0':
+ continue
+
+ load_app_ddr(u_boot_console, tftp_addrs[i], apps[i])
+ rel_addr = int(addrs[i] + 0x3C)
+ cpu_num = cpu_nums[i]
+ cmd = 'cpu %d release %x %s' % (cpu_num, rel_addr, rpu_mode)
+ output = u_boot_console.run_command(cmd)
+ exp_op = f'Using TCM jump trampoline for address {hex(rel_addr)}'
+ assert exp_op in output
+ assert f'R5 {rpu_mode} mode' in output
+ assert u_boot_console.p.expect([outputs[i]])
+ finally:
+ disable_cpus(u_boot_console, cpu_nums)
+ # This forces the console object to be shutdown, so any subsequent test
+ # will reset the board back into U-Boot.
+ u_boot_console.drain_console()
+ u_boot_console.cleanup_spawn()
diff --git a/test/py/tests/test_zynqmp_secure.py b/test/py/tests/test_zynqmp_secure.py
new file mode 100644
index 00000000000..570bd2439c1
--- /dev/null
+++ b/test/py/tests/test_zynqmp_secure.py
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2023, Advanced Micro Devices, Inc.
+
+import pytest
+import re
+import u_boot_utils
+import test_net
+
+"""
+This test verifies different type of secure boot images loaded at the DDR for
+AMD's ZynqMP SoC.
+
+Note: This test relies on boardenv_* containing configuration values to define
+the files to be used for testing. Without this, this test will be automatically
+skipped. It also relies on dhcp or setup_static net test to support tftp to
+load files from a TFTP server.
+
+For example:
+
+# Details regarding the files that may be read from a TFTP server. This
+# variable may be omitted or set to None if zynqmp secure testing is not
+# possible or desired.
+env__zynqmp_secure_readable_file = {
+ 'fn': 'auth_bhdr_ppk1.bin',
+ 'enckupfn': 'auth_bhdr_enc_kup_load.bin',
+ 'addr': 0x1000000,
+ 'keyaddr': 0x100000,
+ 'keyfn': 'aes.txt',
+}
+"""
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_secure_boot_image(u_boot_console):
+ """This test verifies secure boot image at the DDR address for
+ authentication only case.
+ """
+
+ f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynqmp secure cases to read')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ addr = f.get('addr', None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+
+ expected_tftp = 'Bytes transferred = '
+ fn = f['fn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
+ assert expected_tftp in output
+
+ output = u_boot_console.run_command('zynqmp secure %x $filesize' % (addr))
+ assert 'Verified image at' in output
+ ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('print zynqmp_verified_img_addr')
+ assert f'zynqmp_verified_img_addr={ver_addr}' in output
+ assert 'Error' not in output
+
+
+@pytest.mark.buildconfigspec('cmd_zynqmp')
+def test_zynqmp_secure_boot_img_kup(u_boot_console):
+ """This test verifies secure boot image at the DDR address for encryption
+ with kup key case.
+ """
+
+ f = u_boot_console.config.env.get('env__zynqmp_secure_readable_file', None)
+ if not f:
+ pytest.skip('No TFTP readable file for zynqmp secure cases to read')
+
+ test_net.test_net_dhcp(u_boot_console)
+ if not test_net.net_set_up:
+ test_net.test_net_setup_static(u_boot_console)
+
+ keyaddr = f.get('keyaddr', None)
+ if not keyaddr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ expected_tftp = 'Bytes transferred = '
+ keyfn = f['keyfn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (keyaddr, keyfn))
+ assert expected_tftp in output
+
+ addr = f.get('addr', None)
+ if not addr:
+ addr = u_boot_utils.find_ram_base(u_boot_console)
+ expected_tftp = 'Bytes transferred = '
+ fn = f['enckupfn']
+ output = u_boot_console.run_command('tftpboot %x %s' % (addr, fn))
+ assert expected_tftp in output
+
+ output = u_boot_console.run_command(
+ 'zynqmp secure %x $filesize %x' % (addr, keyaddr)
+ )
+ assert 'Verified image at' in output
+ ver_addr = re.search(r'Verified image at 0x(.+)', output).group(1)
+ output = u_boot_console.run_command('echo $?')
+ assert output.endswith('0')
+ output = u_boot_console.run_command('print zynqmp_verified_img_addr')
+ assert f'zynqmp_verified_img_addr={ver_addr}' in output
+ assert 'Error' not in output
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
index 1d0d90c2d73..47c3f52774c 100644
--- a/test/unicode_ut.c
+++ b/test/unicode_ut.c
@@ -752,9 +752,10 @@ static int unicode_test_utf8_to_utf32_stream(struct unit_test_state *uts)
const u32 u1[] = {0x55, 0x2D, 0x42, 0x6F, 0x6F, 0x74, 0x0000};
const u32 u2[] = {0x6B, 0x61, 0x66, 0x62, 0xE1, 0x74, 0x75, 0x72, 0x00};
- const u32 u3[] = {0x0392, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74,
- 0x20, 0x42, 0x00};
+ const u32 u3[] = {0x6f5c, 0x6c34, 0x8266};
const u32 u4[] = {0x6A, 0x32, 0x6C, 0x00};
+ const u32 u5[] = {0x0392, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74,
+ 0x20, 0x42, 0x00};
memset(buf, 0, sizeof(buf));
utf8_to_utf32_stream_helper(d1, buf);
@@ -765,10 +766,14 @@ static int unicode_test_utf8_to_utf32_stream(struct unit_test_state *uts)
ut_asserteq_mem(u2, buf, sizeof(u2));
memset(buf, 0, sizeof(buf));
- utf8_to_utf32_stream_helper(d5, buf);
+ utf8_to_utf32_stream_helper(d3, buf);
ut_asserteq_mem(u3, buf, sizeof(u3));
memset(buf, 0, sizeof(buf));
+ utf8_to_utf32_stream_helper(d5, buf);
+ ut_asserteq_mem(u5, buf, sizeof(u5));
+
+ memset(buf, 0, sizeof(buf));
utf8_to_utf32_stream_helper(j2, buf);
ut_asserteq_mem(u4, buf, sizeof(u4));
diff --git a/test/ut.c b/test/ut.c
index 28da417686e..628e9dc9805 100644
--- a/test/ut.c
+++ b/test/ut.c
@@ -121,6 +121,33 @@ int ut_check_skipline(struct unit_test_state *uts)
return 0;
}
+int ut_check_skip_to_linen(struct unit_test_state *uts, const char *fmt, ...)
+{
+ va_list args;
+ int len;
+ int ret;
+
+ va_start(args, fmt);
+ len = vsnprintf(uts->expect_str, sizeof(uts->expect_str), fmt, args);
+ va_end(args);
+ if (len >= sizeof(uts->expect_str)) {
+ ut_fail(uts, __FILE__, __LINE__, __func__,
+ "unit_test_state->expect_str too small");
+ return -EOVERFLOW;
+ }
+ while (1) {
+ if (!console_record_avail())
+ return -ENOENT;
+ ret = readline_check(uts);
+ if (ret < 0)
+ return ret;
+
+ if (!strncmp(uts->expect_str, uts->actual_str,
+ strlen(uts->expect_str)))
+ return 0;
+ }
+}
+
int ut_check_skip_to_line(struct unit_test_state *uts, const char *fmt, ...)
{
va_list args;