diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/Kconfig | 2 | ||||
| -rw-r--r-- | test/Makefile | 2 | ||||
| -rw-r--r-- | test/boot/bootflow.c | 2 | ||||
| -rw-r--r-- | test/cmd/Makefile | 1 | ||||
| -rw-r--r-- | test/cmd/mem_copy.c | 168 | ||||
| -rw-r--r-- | test/dm/spmi.c | 4 | ||||
| -rwxr-xr-x | test/fs/fs-test.sh | 118 | ||||
| -rw-r--r-- | test/py/requirements.txt | 4 | ||||
| -rw-r--r-- | test/py/tests/test_bootstage.py | 67 | ||||
| -rw-r--r-- | test/py/tests/test_cleanup_build.py | 5 | ||||
| -rw-r--r-- | test/py/tests/test_i2c.py | 116 | ||||
| -rw-r--r-- | test/py/tests/test_mdio.py | 79 | ||||
| -rw-r--r-- | test/py/tests/test_memtest.py | 68 | ||||
| -rw-r--r-- | test/py/tests/test_mii.py | 92 | ||||
| -rw-r--r-- | test/py/tests/test_net.py | 2 | ||||
| -rw-r--r-- | test/py/tests/test_trace.py | 32 |
16 files changed, 680 insertions, 82 deletions
diff --git a/test/Kconfig b/test/Kconfig index e842c01308f..e2ec0994a2e 100644 --- a/test/Kconfig +++ b/test/Kconfig @@ -67,7 +67,7 @@ endif config UT_BOOTSTD bool "Unit tests for standard boot" - depends on UNIT_TEST && SANDBOX + depends on UNIT_TEST && BOOTSTD && SANDBOX default y config UT_COMPRESSION diff --git a/test/Makefile b/test/Makefile index 9aeef02f9ee..ed312cd0a48 100644 --- a/test/Makefile +++ b/test/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_UT_TIME) += time_ut.o obj-y += ut.o ifeq ($(CONFIG_SPL_BUILD),) -obj-$(CONFIG_$(SPL_)UT_BOOTSTD) += boot/ +obj-y += boot/ obj-$(CONFIG_UNIT_TEST) += common/ obj-y += log/ obj-$(CONFIG_$(SPL_)UT_UNICODE) += unicode_ut.o diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 104f49deef2..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_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), diff --git a/test/cmd/Makefile b/test/cmd/Makefile index 7e40e25b9e8..478ef4c6f05 100644 --- a/test/cmd/Makefile +++ b/test/cmd/Makefile @@ -19,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/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/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/py/requirements.txt b/test/py/requirements.txt index f7e76bdb918..c3cc9163fb8 100644 --- a/test/py/requirements.txt +++ b/test/py/requirements.txt @@ -8,11 +8,11 @@ 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 +pycryptodomex==3.19.1 pyelftools==0.27 pygit2==1.9.2 pyparsing==3.0.7 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_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_net.py b/test/py/tests/test_net.py index 2495608786d..4ff3dafd629 100644 --- a/test/py/tests/test_net.py +++ b/test/py/tests/test_net.py @@ -99,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. 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 |
