summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/Kconfig8
-rw-r--r--test/Makefile1
-rw-r--r--test/cmd_ut.c13
-rwxr-xr-xtest/fs/fs-test.sh24
-rw-r--r--test/print_ut.c6
-rw-r--r--test/py/tests/test_efi_selftest.py151
-rw-r--r--test/py/tests/test_fs/conftest.py392
-rw-r--r--test/py/tests/test_fs/fstest_defs.py13
-rw-r--r--test/py/tests/test_fs/test_basic.py287
-rw-r--r--test/py/tests/test_fs/test_ext.py224
-rw-r--r--test/py/tests/test_fs/test_mkdir.py112
-rw-r--r--test/py/tests/test_fs/test_unlink.py109
-rw-r--r--test/unicode_ut.c543
13 files changed, 1864 insertions, 19 deletions
diff --git a/test/Kconfig b/test/Kconfig
index 3643761bc6..de16d179d0 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -15,6 +15,14 @@ config UT_TIME
problems. But if you are having problems with udelay() and the like,
this is a good place to start.
+config UT_UNICODE
+ bool "Unit tests for Unicode functions"
+ depends on UNIT_TEST
+ default y
+ help
+ Enables the 'ut unicode' command which tests that the functions for
+ manipulating Unicode strings work correctly.
+
source "test/dm/Kconfig"
source "test/env/Kconfig"
source "test/overlay/Kconfig"
diff --git a/test/Makefile b/test/Makefile
index 1092011fdb..a5f52fd5ad 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -8,4 +8,5 @@ obj-$(CONFIG_SANDBOX) += command_ut.o
obj-$(CONFIG_SANDBOX) += compression.o
obj-$(CONFIG_SANDBOX) += print_ut.o
obj-$(CONFIG_UT_TIME) += time_ut.o
+obj-$(CONFIG_UT_UNICODE) += unicode_ut.o
obj-$(CONFIG_$(SPL_)LOG) += log/
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 934a5a931b..b7e01a4847 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -49,6 +49,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
#ifdef CONFIG_UT_TIME
U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
#endif
+#if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD)
+ U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""),
+#endif
#ifdef CONFIG_SANDBOX
U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
"", ""),
@@ -93,6 +96,9 @@ static int do_ut(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_SYS_LONGHELP
static char ut_help_text[] =
"all - execute all enabled tests\n"
+#ifdef CONFIG_SANDBOX
+ "ut compression - Test compressors and bootm decompression\n"
+#endif
#ifdef CONFIG_UT_DM
"ut dm [test-name]\n"
#endif
@@ -105,11 +111,12 @@ static char ut_help_text[] =
#ifdef CONFIG_UT_TIME
"ut time - Very basic test of time functions\n"
#endif
-#ifdef CONFIG_SANDBOX
- "ut compression - Test compressors and bootm decompression\n"
+#if defined(CONFIG_UT_UNICODE) && \
+ !defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+ "ut unicode [test-name] - test Unicode functions\n"
#endif
;
-#endif
+#endif /* CONFIG_SYS_LONGHELP */
U_BOOT_CMD(
ut, CONFIG_SYS_MAXARGS, 1, do_ut,
diff --git a/test/fs/fs-test.sh b/test/fs/fs-test.sh
index 9482239562..86308cfe2d 100755
--- a/test/fs/fs-test.sh
+++ b/test/fs/fs-test.sh
@@ -7,18 +7,20 @@
# It currently tests the fs/sb and native commands for ext4 and fat partitions
# Expected results are as follows:
# EXT4 tests:
-# fs-test.sb.ext4.out: Summary: PASS: 24 FAIL: 0
-# fs-test.ext4.out: Summary: PASS: 24 FAIL: 0
-# fs-test.fs.ext4.out: Summary: PASS: 24 FAIL: 0
+# fs-test.sb.ext4 Summary: PASS: 24 FAIL: 0
+# fs-test.nonfs.ext4 Summary: PASS: 24 FAIL: 0
+# fs-test.fs.ext4 Summary: PASS: 24 FAIL: 0
# FAT16 tests:
-# fs-test.sb.fat16.out: Summary: PASS: 24 FAIL: 0
-# fs-test.fat16.out: Summary: PASS: 20 FAIL: 4
-# fs-test.fs.fat16.out: Summary: PASS: 20 FAIL: 4
+# fs-test.sb.fat16 Summary: PASS: 24 FAIL: 0
+# fs-test.nonfs.fat16 Summary: PASS: 24 FAIL: 0
+# fs-test.fs.fat16 Summary: PASS: 24 FAIL: 0
# FAT32 tests:
-# fs-test.sb.fat32.out: Summary: PASS: 24 FAIL: 0
-# fs-test.fat32.out: Summary: PASS: 20 FAIL: 4
-# fs-test.fs.fat32.out: Summary: PASS: 20 FAIL: 4
-# Total Summary: TOTAL PASS: 200 TOTAL FAIL: 16
+# fs-test.sb.fat32 Summary: PASS: 24 FAIL: 0
+# fs-test.nonfs.fat32 Summary: PASS: 24 FAIL: 0
+# fs-test.fs.fat32 Summary: PASS: 24 FAIL: 0
+# --------------------------------------------
+# Total Summary: TOTAL PASS: 216 TOTAL FAIL: 0
+# --------------------------------------------
# pre-requisite binaries list.
PREREQ_BINS="md5sum mkfs mount umount dd fallocate mkdir"
@@ -522,7 +524,7 @@ function check_results() {
"TC11: 1MB write to $3.w - content verified"
# Check lookup of 'dot' directory
- grep -A4 "Test Case 12 " "$1" | grep -q 'Unable to write file'
+ grep -A4 "Test Case 12 " "$1" | grep -q 'Unable to write'
pass_fail "TC12: 1MB write to . - write denied"
# Check directory traversal
diff --git a/test/print_ut.c b/test/print_ut.c
index fb46db832e..f0f1d6010a 100644
--- a/test/print_ut.c
+++ b/test/print_ut.c
@@ -6,8 +6,7 @@
#define DEBUG
#include <common.h>
-#if defined(CONFIG_EFI_LOADER) && \
- !defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
#include <efi_api.h>
#endif
#include <display_options.h>
@@ -19,8 +18,7 @@
/* Test efi_loader specific printing */
static void efi_ut_print(void)
{
-#if defined(CONFIG_EFI_LOADER) && \
- !defined(CONFIG_SPL_BUILD) && !defined(API_BUILD)
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
char str[10];
u8 buf[sizeof(struct efi_device_path_sd_mmc_path) +
sizeof(struct efi_device_path)];
diff --git a/test/py/tests/test_efi_selftest.py b/test/py/tests/test_efi_selftest.py
index 747d52d935..e0833ffe22 100644
--- a/test/py/tests/test_efi_selftest.py
+++ b/test/py/tests/test_efi_selftest.py
@@ -16,7 +16,7 @@ def test_efi_selftest(u_boot_console):
u_boot_console.run_command(cmd='bootefi selftest', wait_for_prompt=False)
m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
if m != 0:
- raise Exception('Failures occured during the EFI selftest')
+ raise Exception('Failures occurred during the EFI selftest')
u_boot_console.run_command(cmd='', wait_for_echo=False, wait_for_prompt=False);
m = u_boot_console.p.expect(['resetting', 'U-Boot'])
if m != 0:
@@ -48,3 +48,152 @@ def test_efi_selftest_watchdog_reboot(u_boot_console):
if m != 0:
raise Exception('Reset failed in \'watchdog reboot\' test')
u_boot_console.restart_uboot();
+
+@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
+def test_efi_selftest_text_input(u_boot_console):
+ """Test the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
+
+ :param u_boot_console: U-Boot console
+
+ This function calls the text input EFI selftest.
+ """
+ u_boot_console.run_command(cmd='setenv efi_selftest text input')
+ output = u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(['To terminate type \'x\''])
+ if m != 0:
+ raise Exception('No prompt for \'text input\' test')
+ u_boot_console.drain_console()
+ u_boot_console.p.timeout = 500
+ # EOT
+ u_boot_console.run_command(cmd=chr(4), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 4 \(unknown\), scan code 0 \(Null\)'])
+ if m != 0:
+ raise Exception('EOT failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # BS
+ u_boot_console.run_command(cmd=chr(8), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 8 \(BS\), scan code 0 \(Null\)'])
+ if m != 0:
+ raise Exception('BS failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # TAB
+ u_boot_console.run_command(cmd=chr(9), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 9 \(TAB\), scan code 0 \(Null\)'])
+ if m != 0:
+ raise Exception('BS failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # a
+ u_boot_console.run_command(cmd='a', wait_for_echo=False, send_nl=False,
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 97 \(\'a\'\), scan code 0 \(Null\)'])
+ if m != 0:
+ raise Exception('\'a\' failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # UP escape sequence
+ u_boot_console.run_command(cmd=chr(27) + '[A', wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 0 \(Null\), scan code 1 \(Up\)'])
+ if m != 0:
+ raise Exception('UP failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # Euro sign
+ u_boot_console.run_command(cmd='\xe2\x82\xac', wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(['Unicode char 8364 \(\''])
+ if m != 0:
+ raise Exception('Euro sign failed in \'text input\' test')
+ u_boot_console.drain_console()
+ u_boot_console.run_command(cmd='x', wait_for_echo=False, send_nl=False,
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
+ if m != 0:
+ raise Exception('Failures occurred during the EFI selftest')
+ u_boot_console.restart_uboot();
+
+@pytest.mark.buildconfigspec('cmd_bootefi_selftest')
+def test_efi_selftest_text_input_ex(u_boot_console):
+ """Test the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
+
+ :param u_boot_console: U-Boot console
+
+ This function calls the extended text input EFI selftest.
+ """
+ u_boot_console.run_command(cmd='setenv efi_selftest extended text input')
+ output = u_boot_console.run_command(cmd='bootefi selftest',
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(['To terminate type \'CTRL\+x\''])
+ if m != 0:
+ raise Exception('No prompt for \'text input\' test')
+ u_boot_console.drain_console()
+ u_boot_console.p.timeout = 500
+ # EOT
+ u_boot_console.run_command(cmd=chr(4), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 4 \(unknown\), scan code 0 \(CTRL\+Null\)'])
+ if m != 0:
+ raise Exception('EOT failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # BS
+ u_boot_console.run_command(cmd=chr(8), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 8 \(BS\), scan code 0 \(\+Null\)'])
+ if m != 0:
+ raise Exception('BS failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # TAB
+ u_boot_console.run_command(cmd=chr(9), wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 9 \(TAB\), scan code 0 \(\+Null\)'])
+ if m != 0:
+ raise Exception('TAB failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # a
+ u_boot_console.run_command(cmd='a', wait_for_echo=False, send_nl=False,
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 97 \(\'a\'\), scan code 0 \(Null\)'])
+ if m != 0:
+ raise Exception('\'a\' failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # UP escape sequence
+ u_boot_console.run_command(cmd=chr(27) + '[A', wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 0 \(Null\), scan code 1 \(\+Up\)'])
+ if m != 0:
+ raise Exception('UP failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # Euro sign
+ u_boot_console.run_command(cmd='\xe2\x82\xac', wait_for_echo=False,
+ send_nl=False, wait_for_prompt=False)
+ m = u_boot_console.p.expect(['Unicode char 8364 \(\''])
+ if m != 0:
+ raise Exception('Euro sign failed in \'text input\' test')
+ u_boot_console.drain_console()
+ # SHIFT+ALT+FN 5
+ u_boot_console.run_command(cmd='\x1b\x5b\x31\x35\x3b\x34\x7e',
+ wait_for_echo=False, send_nl=False,
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(
+ ['Unicode char 0 \(Null\), scan code 15 \(SHIFT\+ALT\+FN 5\)'])
+ if m != 0:
+ raise Exception('SHIFT+ALT+FN 5 failed in \'text input\' test')
+ u_boot_console.drain_console()
+ u_boot_console.run_command(cmd=chr(24), wait_for_echo=False, send_nl=False,
+ wait_for_prompt=False)
+ m = u_boot_console.p.expect(['Summary: 0 failures', 'Press any key'])
+ if m != 0:
+ raise Exception('Failures occurred during the EFI selftest')
+ u_boot_console.restart_uboot();
diff --git a/test/py/tests/test_fs/conftest.py b/test/py/tests/test_fs/conftest.py
new file mode 100644
index 0000000000..6404b311bc
--- /dev/null
+++ b/test/py/tests/test_fs/conftest.py
@@ -0,0 +1,392 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018, Linaro Limited
+# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
+
+import os
+import os.path
+import pytest
+import re
+from subprocess import call, check_call, check_output, CalledProcessError
+from fstest_defs import *
+
+supported_fs_basic = ['fat16', 'fat32', 'ext4']
+supported_fs_ext = ['fat16', 'fat32']
+supported_fs_mkdir = ['fat16', 'fat32']
+supported_fs_unlink = ['fat16', 'fat32']
+
+#
+# Filesystem test specific setup
+#
+def pytest_addoption(parser):
+ parser.addoption('--fs-type', action='append', default=None,
+ help='Targeting Filesystem Types')
+
+def pytest_configure(config):
+ global supported_fs_basic
+ global supported_fs_ext
+ global supported_fs_mkdir
+ global supported_fs_unlink
+
+ def intersect(listA, listB):
+ return [x for x in listA if x in listB]
+
+ supported_fs = config.getoption('fs_type')
+ if supported_fs:
+ 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_mkdir = intersect(supported_fs, supported_fs_mkdir)
+ supported_fs_unlink = intersect(supported_fs, supported_fs_unlink)
+
+def pytest_generate_tests(metafunc):
+ if 'fs_obj_basic' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_basic', supported_fs_basic,
+ indirect=True, scope='module')
+ if 'fs_obj_ext' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_ext', supported_fs_ext,
+ indirect=True, scope='module')
+ if 'fs_obj_mkdir' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_mkdir', supported_fs_mkdir,
+ indirect=True, scope='module')
+ if 'fs_obj_unlink' in metafunc.fixturenames:
+ metafunc.parametrize('fs_obj_unlink', supported_fs_unlink,
+ indirect=True, scope='module')
+
+#
+# Helper functions
+#
+def fstype_to_ubname(fs_type):
+ if re.match('fat', fs_type):
+ return 'fat'
+ else:
+ return fs_type
+
+def check_ubconfig(config, fs_type):
+ if not config.buildconfig.get('config_cmd_%s' % fs_type, None):
+ pytest.skip('.config feature "CMD_%s" not enabled' % fs_type.upper())
+ if not config.buildconfig.get('config_%s_write' % fs_type, None):
+ pytest.skip('.config feature "%s_WRITE" not enabled'
+ % fs_type.upper())
+
+def mk_fs(config, fs_type, size, id):
+ fs_img = '%s.%s.img' % (id, fs_type)
+ fs_img = config.persistent_data_dir + '/' + fs_img
+
+ if fs_type == 'fat16':
+ mkfs_opt = '-F 16'
+ elif fs_type == 'fat32':
+ mkfs_opt = '-F 32'
+ else:
+ mkfs_opt = ''
+
+ if re.match('fat', fs_type):
+ fs_lnxtype = 'vfat'
+ else:
+ fs_lnxtype = fs_type
+
+ count = (size + 1048576 - 1) / 1048576
+
+ try:
+ check_call('rm -f %s' % fs_img, shell=True)
+ check_call('dd if=/dev/zero of=%s bs=1M count=%d'
+ % (fs_img, count), shell=True)
+ check_call('mkfs.%s %s %s'
+ % (fs_lnxtype, mkfs_opt, fs_img), shell=True)
+ return fs_img
+ except CalledProcessError:
+ call('rm -f %s' % fs_img, shell=True)
+ raise
+
+# from test/py/conftest.py
+def tool_is_in_path(tool):
+ for path in os.environ["PATH"].split(os.pathsep):
+ fn = os.path.join(path, tool)
+ if os.path.isfile(fn) and os.access(fn, os.X_OK):
+ return True
+ return False
+
+fuse_mounted = False
+
+def mount_fs(fs_type, device, mount_point):
+ global fuse_mounted
+
+ fuse_mounted = False
+ try:
+ if tool_is_in_path('guestmount'):
+ fuse_mounted = True
+ check_call('guestmount -a %s -m /dev/sda %s'
+ % (device, mount_point), shell=True)
+ else:
+ mount_opt = "loop,rw"
+ if re.match('fat', fs_type):
+ mount_opt += ",umask=0000"
+
+ check_call('sudo mount -o %s %s %s'
+ % (mount_opt, device, mount_point), shell=True)
+
+ # may not be effective for some file systems
+ check_call('sudo chmod a+rw %s' % mount_point, shell=True)
+ except CalledProcessError:
+ raise
+
+def umount_fs(fs_type, mount_point):
+ if fuse_mounted:
+ call('sync')
+ call('guestunmount %s' % mount_point, shell=True)
+ else:
+ call('sudo umount %s' % mount_point, shell=True)
+
+#
+# Fixture for basic fs test
+# derived from test/fs/fs-test.sh
+#
+# NOTE: yield_fixture was deprecated since pytest-3.0
+@pytest.yield_fixture()
+def fs_obj_basic(request, u_boot_config):
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ mount_dir = u_boot_config.persistent_data_dir + '/mnt'
+
+ small_file = mount_dir + '/' + SMALL_FILE
+ big_file = mount_dir + '/' + BIG_FILE
+
+ try:
+
+ # 3GiB volume
+ fs_img = mk_fs(u_boot_config, fs_type, 0xc0000000, '3GB')
+
+ # Mount the image so we can populate it.
+ check_call('mkdir -p %s' % mount_dir, shell=True)
+ mount_fs(fs_type, fs_img, mount_dir)
+
+ # Create a subdirectory.
+ check_call('mkdir %s/SUBDIR' % mount_dir, shell=True)
+
+ # Create big file in this image.
+ # Note that we work only on the start 1MB, couple MBs in the 2GB range
+ # and the last 1 MB of the huge 2.5GB file.
+ # So, just put random values only in those areas.
+ check_call('dd if=/dev/urandom of=%s bs=1M count=1'
+ % big_file, shell=True)
+ check_call('dd if=/dev/urandom of=%s bs=1M count=2 seek=2047'
+ % big_file, shell=True)
+ check_call('dd if=/dev/urandom of=%s bs=1M count=1 seek=2499'
+ % big_file, shell=True)
+
+ # Create a small file in this image.
+ check_call('dd if=/dev/urandom of=%s bs=1M count=1'
+ % small_file, shell=True)
+
+ # Delete the small file copies which possibly are written as part of a
+ # previous test.
+ # check_call('rm -f "%s.w"' % MB1, shell=True)
+ # check_call('rm -f "%s.w2"' % MB1, shell=True)
+
+ # Generate the md5sums of reads that we will test against small file
+ out = check_output(
+ 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
+ % small_file, shell=True)
+ md5val = [ out.split()[0] ]
+
+ # Generate the md5sums of reads that we will test against big file
+ # One from beginning of file.
+ out = check_output(
+ 'dd if=%s bs=1M skip=0 count=1 2> /dev/null | md5sum'
+ % big_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # One from end of file.
+ out = check_output(
+ 'dd if=%s bs=1M skip=2499 count=1 2> /dev/null | md5sum'
+ % big_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # One from the last 1MB chunk of 2GB
+ out = check_output(
+ 'dd if=%s bs=1M skip=2047 count=1 2> /dev/null | md5sum'
+ % big_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # One from the start 1MB chunk from 2GB
+ out = check_output(
+ 'dd if=%s bs=1M skip=2048 count=1 2> /dev/null | md5sum'
+ % big_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # One 1MB chunk crossing the 2GB boundary
+ out = check_output(
+ 'dd if=%s bs=512K skip=4095 count=2 2> /dev/null | md5sum'
+ % big_file, shell=True)
+ md5val.append(out.split()[0])
+
+ umount_fs(fs_type, mount_dir)
+ except CalledProcessError:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ return
+ else:
+ yield [fs_ubtype, fs_img, md5val]
+ finally:
+ umount_fs(fs_type, mount_dir)
+ call('rmdir %s' % mount_dir, shell=True)
+ if fs_img:
+ call('rm -f %s' % fs_img, shell=True)
+
+#
+# Fixture for extended fs test
+#
+# NOTE: yield_fixture was deprecated since pytest-3.0
+@pytest.yield_fixture()
+def fs_obj_ext(request, u_boot_config):
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ mount_dir = u_boot_config.persistent_data_dir + '/mnt'
+
+ min_file = mount_dir + '/' + MIN_FILE
+ tmp_file = mount_dir + '/tmpfile'
+
+ try:
+
+ # 128MiB volume
+ fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
+
+ # Mount the image so we can populate it.
+ check_call('mkdir -p %s' % mount_dir, shell=True)
+ mount_fs(fs_type, fs_img, mount_dir)
+
+ # Create a test directory
+ check_call('mkdir %s/dir1' % mount_dir, shell=True)
+
+ # Create a small file and calculate md5
+ check_call('dd if=/dev/urandom of=%s bs=1K count=20'
+ % min_file, shell=True)
+ out = check_output(
+ 'dd if=%s bs=1K 2> /dev/null | md5sum'
+ % min_file, shell=True)
+ md5val = [ out.split()[0] ]
+
+ # Calculate md5sum of Test Case 4
+ check_call('dd if=%s of=%s bs=1K count=20'
+ % (min_file, tmp_file), shell=True)
+ check_call('dd if=%s of=%s bs=1K seek=5 count=20'
+ % (min_file, tmp_file), shell=True)
+ out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
+ % tmp_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # Calculate md5sum of Test Case 5
+ check_call('dd if=%s of=%s bs=1K count=20'
+ % (min_file, tmp_file), shell=True)
+ check_call('dd if=%s of=%s bs=1K seek=5 count=5'
+ % (min_file, tmp_file), shell=True)
+ out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
+ % tmp_file, shell=True)
+ md5val.append(out.split()[0])
+
+ # Calculate md5sum of Test Case 7
+ check_call('dd if=%s of=%s bs=1K count=20'
+ % (min_file, tmp_file), shell=True)
+ check_call('dd if=%s of=%s bs=1K seek=20 count=20'
+ % (min_file, tmp_file), shell=True)
+ out = check_output('dd if=%s bs=1K 2> /dev/null | md5sum'
+ % tmp_file, shell=True)
+ md5val.append(out.split()[0])
+
+ check_call('rm %s' % tmp_file, shell=True)
+ umount_fs(fs_type, mount_dir)
+ except CalledProcessError:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ return
+ else:
+ yield [fs_ubtype, fs_img, md5val]
+ finally:
+ umount_fs(fs_type, mount_dir)
+ call('rmdir %s' % mount_dir, shell=True)
+ if fs_img:
+ call('rm -f %s' % fs_img, shell=True)
+
+#
+# Fixture for mkdir test
+#
+# NOTE: yield_fixture was deprecated since pytest-3.0
+@pytest.yield_fixture()
+def fs_obj_mkdir(request, u_boot_config):
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ try:
+ # 128MiB volume
+ fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
+ except:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ else:
+ yield [fs_ubtype, fs_img]
+ finally:
+ if fs_img:
+ call('rm -f %s' % fs_img, shell=True)
+
+#
+# Fixture for unlink test
+#
+# NOTE: yield_fixture was deprecated since pytest-3.0
+@pytest.yield_fixture()
+def fs_obj_unlink(request, u_boot_config):
+ fs_type = request.param
+ fs_img = ''
+
+ fs_ubtype = fstype_to_ubname(fs_type)
+ check_ubconfig(u_boot_config, fs_ubtype)
+
+ mount_dir = u_boot_config.persistent_data_dir + '/mnt'
+
+ try:
+
+ # 128MiB volume
+ fs_img = mk_fs(u_boot_config, fs_type, 0x8000000, '128MB')
+
+ # Mount the image so we can populate it.
+ check_call('mkdir -p %s' % mount_dir, shell=True)
+ mount_fs(fs_type, fs_img, mount_dir)
+
+ # Test Case 1 & 3
+ check_call('mkdir %s/dir1' % mount_dir, shell=True)
+ check_call('dd if=/dev/urandom of=%s/dir1/file1 bs=1K count=1'
+ % mount_dir, shell=True)
+ check_call('dd if=/dev/urandom of=%s/dir1/file2 bs=1K count=1'
+ % mount_dir, shell=True)
+
+ # Test Case 2
+ check_call('mkdir %s/dir2' % mount_dir, shell=True)
+ for i in range(0, 20):
+ check_call('mkdir %s/dir2/0123456789abcdef%02x'
+ % (mount_dir, i), shell=True)
+
+ # Test Case 4
+ check_call('mkdir %s/dir4' % mount_dir, shell=True)
+
+ # Test Case 5, 6 & 7
+ check_call('mkdir %s/dir5' % mount_dir, shell=True)
+ check_call('dd if=/dev/urandom of=%s/dir5/file1 bs=1K count=1'
+ % mount_dir, shell=True)
+
+ umount_fs(fs_type, mount_dir)
+ except CalledProcessError:
+ pytest.skip('Setup failed for filesystem: ' + fs_type)
+ return
+ else:
+ yield [fs_ubtype, fs_img]
+ finally:
+ umount_fs(fs_type, mount_dir)
+ call('rmdir %s' % mount_dir, shell=True)
+ if fs_img:
+ call('rm -f %s' % fs_img, shell=True)
diff --git a/test/py/tests/test_fs/fstest_defs.py b/test/py/tests/test_fs/fstest_defs.py
new file mode 100644
index 0000000000..5f107562d9
--- /dev/null
+++ b/test/py/tests/test_fs/fstest_defs.py
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+# $MIN_FILE is the name of the 20KB file in the file system image
+MIN_FILE='testfile'
+
+# $SMALL_FILE is the name of the 1MB file in the file system image
+SMALL_FILE='1MB.file'
+
+# $BIG_FILE is the name of the 2.5GB file in the file system image
+BIG_FILE='2.5GB.file'
+
+ADDR=0x01000008
+LENGTH=0x00100000
diff --git a/test/py/tests/test_fs/test_basic.py b/test/py/tests/test_fs/test_basic.py
new file mode 100644
index 0000000000..c067cc9ba3
--- /dev/null
+++ b/test/py/tests/test_fs/test_basic.py
@@ -0,0 +1,287 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018, Linaro Limited
+# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
+#
+# U-Boot File System:Basic Test
+
+"""
+This test verifies basic read/write operation on file system.
+"""
+
+import pytest
+import re
+from fstest_defs import *
+
+@pytest.mark.boardspec('sandbox')
+class TestFsBasic(object):
+ def test_fs1(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 1 - ls command, listing a root directory and invalid directory
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 1a - ls'):
+ # Test Case 1 - ls
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sls host 0:0' % fs_type])
+ assert(re.search('2621440000 *%s' % BIG_FILE, ''.join(output)))
+ assert(re.search('1048576 *%s' % SMALL_FILE, ''.join(output)))
+
+ with u_boot_console.log.section('Test Case 1b - ls (invalid dir)'):
+ # In addition, test with a nonexistent directory to see if we crash.
+ output = u_boot_console.run_command(
+ '%sls host 0:0 invalid_d' % fs_type)
+ if fs_type == 'ext4':
+ assert('Can not find directory' in output)
+ else:
+ assert('' == output)
+
+ def test_fs2(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 2 - size command for a small file
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 2a - size (small)'):
+ # 1MB is 0x0010 0000
+ # Test Case 2a - size of small file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%ssize host 0:0 /%s' % (fs_type, SMALL_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ with u_boot_console.log.section('Test Case 2b - size (/../<file>)'):
+ # Test Case 2b - size of small file via a path using '..'
+ output = u_boot_console.run_command_list([
+ '%ssize host 0:0 /SUBDIR/../%s' % (fs_type, SMALL_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ def test_fs3(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 3 - size command for a large file
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 3 - size (large)'):
+ # 2.5GB (1024*1024*2500) is 0x9C40 0000
+ # Test Case 3 - size of big file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%ssize host 0:0 /%s' % (fs_type, BIG_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=9c400000' in ''.join(output))
+
+ def test_fs4(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 4 - load a small file, 1MB
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 4 - load (small)'):
+ # Test Case 4a - Read full 1MB of small file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 4b - Read full 1MB of small file
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
+
+ def test_fs5(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 5 - load, reading first 1MB of 3GB file
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 5 - load (first 1MB)'):
+ # Test Case 5a - First 1MB of big file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s %x 0x0' % (fs_type, ADDR, BIG_FILE, LENGTH),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 5b - First 1MB of big file
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[1] in ''.join(output))
+
+ def test_fs6(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 6 - load, reading last 1MB of 3GB file
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 6 - load (last 1MB)'):
+ # fails for ext as no offset support
+ # Test Case 6a - Last 1MB of big file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s %x 0x9c300000'
+ % (fs_type, ADDR, BIG_FILE, LENGTH),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 6b - Last 1MB of big file
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[2] in ''.join(output))
+
+ def test_fs7(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 7 - load, 1MB from the last 1MB in 2GB
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 7 - load (last 1MB in 2GB)'):
+ # fails for ext as no offset support
+ # Test Case 7a - One from the last 1MB chunk of 2GB
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s %x 0x7ff00000'
+ % (fs_type, ADDR, BIG_FILE, LENGTH),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 7b - One from the last 1MB chunk of 2GB
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[3] in ''.join(output))
+
+ def test_fs8(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 8 - load, reading first 1MB in 2GB
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 8 - load (first 1MB in 2GB)'):
+ # fails for ext as no offset support
+ # Test Case 8a - One from the start 1MB chunk from 2GB
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s %x 0x80000000'
+ % (fs_type, ADDR, BIG_FILE, LENGTH),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 8b - One from the start 1MB chunk from 2GB
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[4] in ''.join(output))
+
+ def test_fs9(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 9 - load, 1MB crossing 2GB boundary
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 9 - load (crossing 2GB boundary)'):
+ # fails for ext as no offset support
+ # Test Case 9a - One 1MB chunk crossing the 2GB boundary
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s %x 0x7ff80000'
+ % (fs_type, ADDR, BIG_FILE, LENGTH),
+ 'printenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ # Test Case 9b - One 1MB chunk crossing the 2GB boundary
+ output = u_boot_console.run_command_list([
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[5] in ''.join(output))
+
+ def test_fs10(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 10 - load, reading beyond file end'):
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 10 - load (beyond file end)'):
+ # Generic failure case
+ # Test Case 10 - 2MB chunk from the last 1MB of big file
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s 0x00200000 0x9c300000'
+ % (fs_type, ADDR, BIG_FILE),
+ 'printenv filesize',
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert('filesize=100000' in ''.join(output))
+
+ def test_fs11(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 11 - write'
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 11 - write'):
+ # Read 1MB from small file
+ # Write it back to test the writes
+ # Test Case 11a - Check that the write succeeded
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
+ '%swrite host 0:0 %x /%s.w $filesize'
+ % (fs_type, ADDR, SMALL_FILE)])
+ assert('1048576 bytes written' in ''.join(output))
+
+ # Test Case 11b - Check md5 of written to is same
+ # as the one read from
+ output = u_boot_console.run_command_list([
+ '%sload host 0:0 %x /%s.w' % (fs_type, ADDR, SMALL_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
+
+ def test_fs12(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 12 - write to "." directory
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 12 - write (".")'):
+ # Next test case checks writing a file whose dirent
+ # is the first in the block, which is always true for "."
+ # The write should fail, but the lookup should work
+ # Test Case 12 - Check directory traversal
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%swrite host 0:0 %x /. 0x10' % (fs_type, ADDR)])
+ assert('Unable to write' in ''.join(output))
+
+ def test_fs13(self, u_boot_console, fs_obj_basic):
+ """
+ Test Case 13 - write to a file with "/./<filename>"
+ """
+ fs_type,fs_img,md5val = fs_obj_basic
+ with u_boot_console.log.section('Test Case 13 - write ("./<file>")'):
+ # Read 1MB from small file
+ # Write it via "same directory", i.e. "." dirent
+ # Test Case 13a - Check directory traversal
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, SMALL_FILE),
+ '%swrite host 0:0 %x /./%s2 $filesize'
+ % (fs_type, ADDR, SMALL_FILE)])
+ assert('1048576 bytes written' in ''.join(output))
+
+ # Test Case 13b - Check md5 of written to is same
+ # as the one read from
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /./%s2' % (fs_type, ADDR, SMALL_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
+
+ # Test Case 13c - Check md5 of written to is same
+ # as the one read from
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /%s2' % (fs_type, ADDR, SMALL_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
diff --git a/test/py/tests/test_fs/test_ext.py b/test/py/tests/test_fs/test_ext.py
new file mode 100644
index 0000000000..38217d08bf
--- /dev/null
+++ b/test/py/tests/test_fs/test_ext.py
@@ -0,0 +1,224 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018, Linaro Limited
+# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
+#
+# U-Boot File System:Exntented Test
+
+"""
+This test verifies extended write operation on file system.
+"""
+
+import pytest
+import re
+from fstest_defs import *
+
+@pytest.mark.boardspec('sandbox')
+class TestFsExt(object):
+ def test_fs_ext1(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 1 - write a file with absolute path
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 1 - write with abs path'):
+ # Test Case 1a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w1 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ assert('20480 bytes written' in ''.join(output))
+
+ # Test Case 1b - Check md5 of file content
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /dir1/%s.w1' % (fs_type, ADDR, MIN_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
+
+ def test_fs_ext2(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 2 - write to a file with relative path
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 2 - write with rel path'):
+ # Test Case 2a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x dir1/%s.w2 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ assert('20480 bytes written' in ''.join(output))
+
+ # Test Case 2b - Check md5 of file content
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x dir1/%s.w2' % (fs_type, ADDR, MIN_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[0] in ''.join(output))
+
+ def test_fs_ext3(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 3 - write to a file with invalid path
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 3 - write with invalid path'):
+ # Test Case 3 - Check if command expectedly failed
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/none/%s.w3 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ assert('Unable to write "/dir1/none/' in ''.join(output))
+
+ def test_fs_ext4(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 4 - write at non-zero offset, enlarging file size
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 4 - write at non-zero offset, enlarging file size'):
+ # Test Case 4a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w4 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ output = u_boot_console.run_command(
+ '%swrite host 0:0 %x /dir1/%s.w4 $filesize 0x1400'
+ % (fs_type, ADDR, MIN_FILE))
+ assert('20480 bytes written' in output)
+
+ # Test Case 4b - Check size of written file
+ output = u_boot_console.run_command_list([
+ '%ssize host 0:0 /dir1/%s.w4' % (fs_type, MIN_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=6400' in ''.join(output))
+
+ # Test Case 4c - Check md5 of file content
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /dir1/%s.w4' % (fs_type, ADDR, MIN_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[1] in ''.join(output))
+
+ def test_fs_ext5(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 5 - write at non-zero offset, shrinking file size
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 5 - write at non-zero offset, shrinking file size'):
+ # Test Case 5a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w5 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ output = u_boot_console.run_command(
+ '%swrite host 0:0 %x /dir1/%s.w5 0x1400 0x1400'
+ % (fs_type, ADDR, MIN_FILE))
+ assert('5120 bytes written' in output)
+
+ # Test Case 5b - Check size of written file
+ output = u_boot_console.run_command_list([
+ '%ssize host 0:0 /dir1/%s.w5' % (fs_type, MIN_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=2800' in ''.join(output))
+
+ # Test Case 5c - Check md5 of file content
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /dir1/%s.w5' % (fs_type, ADDR, MIN_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[2] in ''.join(output))
+
+ def test_fs_ext6(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 6 - write nothing at the start, truncating to zero
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 6 - write nothing at the start, truncating to zero'):
+ # Test Case 6a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w6 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ output = u_boot_console.run_command(
+ '%swrite host 0:0 %x /dir1/%s.w6 0 0'
+ % (fs_type, ADDR, MIN_FILE))
+ assert('0 bytes written' in output)
+
+ # Test Case 6b - Check size of written file
+ output = u_boot_console.run_command_list([
+ '%ssize host 0:0 /dir1/%s.w6' % (fs_type, MIN_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=0' in ''.join(output))
+
+ def test_fs_ext7(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 7 - write at the end (append)
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 7 - write at the end (append)'):
+ # Test Case 7a - Check if command successfully returned
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w7 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ output = u_boot_console.run_command(
+ '%swrite host 0:0 %x /dir1/%s.w7 $filesize $filesize'
+ % (fs_type, ADDR, MIN_FILE))
+ assert('20480 bytes written' in output)
+
+ # Test Case 7b - Check size of written file
+ output = u_boot_console.run_command_list([
+ '%ssize host 0:0 /dir1/%s.w7' % (fs_type, MIN_FILE),
+ 'printenv filesize',
+ 'setenv filesize'])
+ assert('filesize=a000' in ''.join(output))
+
+ # Test Case 7c - Check md5 of file content
+ output = u_boot_console.run_command_list([
+ 'mw.b %x 00 100' % ADDR,
+ '%sload host 0:0 %x /dir1/%s.w7' % (fs_type, ADDR, MIN_FILE),
+ 'md5sum %x $filesize' % ADDR,
+ 'setenv filesize'])
+ assert(md5val[3] in ''.join(output))
+
+ def test_fs_ext8(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 8 - write at offset beyond the end of file
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 8 - write beyond the end'):
+ # Test Case 8a - Check if command expectedly failed
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w8 $filesize'
+ % (fs_type, ADDR, MIN_FILE)])
+ output = u_boot_console.run_command(
+ '%swrite host 0:0 %x /dir1/%s.w8 0x1400 %x'
+ % (fs_type, ADDR, MIN_FILE, 0x100000 + 0x1400))
+ assert('Unable to write "/dir1' in output)
+
+ def test_fs_ext9(self, u_boot_console, fs_obj_ext):
+ """
+ Test Case 9 - write to a non-existing file at non-zero offset
+ """
+ fs_type,fs_img,md5val = fs_obj_ext
+ with u_boot_console.log.section('Test Case 9 - write to non-existing file with non-zero offset'):
+ # Test Case 9a - Check if command expectedly failed
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%sload host 0:0 %x /%s' % (fs_type, ADDR, MIN_FILE),
+ '%swrite host 0:0 %x /dir1/%s.w9 0x1400 0x1400'
+ % (fs_type, ADDR, MIN_FILE)])
+ assert('Unable to write "/dir1' in ''.join(output))
diff --git a/test/py/tests/test_fs/test_mkdir.py b/test/py/tests/test_fs/test_mkdir.py
new file mode 100644
index 0000000000..d9da97b56b
--- /dev/null
+++ b/test/py/tests/test_fs/test_mkdir.py
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018, Linaro Limited
+# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
+#
+# U-Boot File System:mkdir Test
+
+"""
+This test verifies mkdir operation on file system.
+"""
+
+import pytest
+
+@pytest.mark.boardspec('sandbox')
+class TestMkdir(object):
+ def test_mkdir1(self, u_boot_console, fs_obj_mkdir):
+ """
+ Test Case 1 - create a directory under a root
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 1 - mkdir'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 dir1' % fs_type,
+ '%sls host 0:0 /' % fs_type])
+ assert('dir1/' in ''.join(output))
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir1' % fs_type)
+ assert('./' in output)
+ assert('../' in output)
+
+ def test_mkdir2(self, u_boot_console, fs_obj_mkdir):
+ """
+ Test Case 2 - create a directory under a sub-directory
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 2 - mkdir (sub-sub directory)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 dir1/dir2' % fs_type,
+ '%sls host 0:0 dir1' % fs_type])
+ assert('dir2/' in ''.join(output))
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir1/dir2' % fs_type)
+ assert('./' in output)
+ assert('../' in output)
+
+ def test_mkdir3(self, u_boot_console, fs_obj_mkdir):
+ """
+ Test Case 3 - trying to create a directory with a non-existing
+ path should fail
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 3 - mkdir (non-existing path)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 none/dir3' % fs_type])
+ assert('Unable to create a directory' in ''.join(output))
+
+ def test_mkdir4(self, u_boot_console, fs_obj_mkdir):
+ """
+ Test Case 4 - trying to create "." should fail
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 4 - mkdir (".")'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 .' % fs_type])
+ assert('Unable to create a directory' in ''.join(output))
+
+ def test_mkdir5(self, u_boot_console, fs_obj_mkdir):
+ """
+ Test Case 5 - trying to create ".." should fail
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 5 - mkdir ("..")'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 ..' % fs_type])
+ assert('Unable to create a directory' in ''.join(output))
+
+ def test_mkdir6(self, u_boot_console, fs_obj_mkdir):
+ """
+ 'Test Case 6 - create as many directories as amount of directory
+ entries goes beyond a cluster size)'
+ """
+ fs_type,fs_img = fs_obj_mkdir
+ with u_boot_console.log.section('Test Case 6 - mkdir (create many)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%smkdir host 0:0 dir6' % fs_type,
+ '%sls host 0:0 /' % fs_type])
+ assert('dir6/' in ''.join(output))
+
+ for i in range(0, 20):
+ output = u_boot_console.run_command(
+ '%smkdir host 0:0 dir6/0123456789abcdef%02x'
+ % (fs_type, i))
+ output = u_boot_console.run_command('%sls host 0:0 dir6' % fs_type)
+ assert('0123456789abcdef00/' in output)
+ assert('0123456789abcdef13/' in output)
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir6/0123456789abcdef13/.' % fs_type)
+ assert('./' in output)
+ assert('../' in output)
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir6/0123456789abcdef13/..' % fs_type)
+ assert('0123456789abcdef00/' in output)
+ assert('0123456789abcdef13/' in output)
diff --git a/test/py/tests/test_fs/test_unlink.py b/test/py/tests/test_fs/test_unlink.py
new file mode 100644
index 0000000000..69c1a6e078
--- /dev/null
+++ b/test/py/tests/test_fs/test_unlink.py
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2018, Linaro Limited
+# Author: Takahiro Akashi <takahiro.akashi@linaro.org>
+#
+# U-Boot File System:unlink Test
+
+"""
+This test verifies unlink operation (deleting a file or a directory)
+on file system.
+"""
+
+import pytest
+
+@pytest.mark.boardspec('sandbox')
+class TestUnlink(object):
+ def test_unlink1(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 1 - delete a file
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 1 - unlink (file)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir1/file1' % fs_type,
+ '%sls host 0:0 dir1/file1' % fs_type])
+ assert('' == ''.join(output))
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir1/' % fs_type)
+ assert(not 'file1' in output)
+ assert('file2' in output)
+
+ def test_unlink2(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 2 - delete many files
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 2 - unlink (many)'):
+ output = u_boot_console.run_command('host bind 0 %s' % fs_img)
+
+ for i in range(0, 20):
+ output = u_boot_console.run_command_list([
+ '%srm host 0:0 dir2/0123456789abcdef%02x' % (fs_type, i),
+ '%sls host 0:0 dir2/0123456789abcdef%02x' % (fs_type, i)])
+ assert('' == ''.join(output))
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 dir2' % fs_type)
+ assert('0 file(s), 2 dir(s)' in output)
+
+ def test_unlink3(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 3 - trying to delete a non-existing file should fail
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 3 - unlink (non-existing)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir1/nofile' % fs_type])
+ assert('nofile: doesn\'t exist' in ''.join(output))
+
+ def test_unlink4(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 4 - delete an empty directory
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 4 - unlink (directory)'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir4' % fs_type])
+ assert('' == ''.join(output))
+
+ output = u_boot_console.run_command(
+ '%sls host 0:0 /' % fs_type)
+ assert(not 'dir4' in output)
+
+ def test_unlink5(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 5 - trying to deleting a non-empty directory ".."
+ should fail
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 5 - unlink ("non-empty directory")'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir5' % fs_type])
+ assert('directory is not empty' in ''.join(output))
+
+ def test_unlink6(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 6 - trying to deleting a "." should fail
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 6 - unlink (".")'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir5/.' % fs_type])
+ assert('directory is not empty' in ''.join(output))
+
+ def test_unlink7(self, u_boot_console, fs_obj_unlink):
+ """
+ Test Case 7 - trying to deleting a ".." should fail
+ """
+ fs_type,fs_img = fs_obj_unlink
+ with u_boot_console.log.section('Test Case 7 - unlink ("..")'):
+ output = u_boot_console.run_command_list([
+ 'host bind 0 %s' % fs_img,
+ '%srm host 0:0 dir5/..' % fs_type])
+ assert('directory is not empty' in ''.join(output))
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
new file mode 100644
index 0000000000..b115d18afd
--- /dev/null
+++ b/test/unicode_ut.c
@@ -0,0 +1,543 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Unit tests for Unicode functions
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <command.h>
+#include <errno.h>
+#include <test/test.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+/* Linker list entry for a Unicode test */
+#define UNICODE_TEST(_name) UNIT_TEST(_name, 0, unicode_test)
+
+/* Constants c1-c4 and d1-d4 encode the same letters */
+
+/* Six characters translating to one utf-8 byte each. */
+static const u16 c1[] = {0x55, 0x2d, 0x42, 0x6f, 0x6f, 0x74, 0x00};
+/* One character translating to two utf-8 bytes */
+static const u16 c2[] = {0x6b, 0x61, 0x66, 0x62, 0xe1, 0x74, 0x75, 0x72, 0x00};
+/* Three characters translating to three utf-8 bytes each */
+static const u16 c3[] = {0x6f5c, 0x6c34, 0x8266, 0x00};
+/* Three letters translating to four utf-8 bytes each */
+static const u16 c4[] = {0xd801, 0xdc8d, 0xd801, 0xdc96, 0xd801, 0xdc87,
+ 0x0000};
+
+/* Illegal utf-16 strings */
+static const u16 i1[] = {0x69, 0x31, 0xdc87, 0x6c, 0x00};
+static const u16 i2[] = {0x69, 0x32, 0xd801, 0xd801, 0x6c, 0x00};
+static const u16 i3[] = {0x69, 0x33, 0xd801, 0x00};
+
+/* Six characters translating to one utf-16 word each. */
+static const char d1[] = {0x55, 0x2d, 0x42, 0x6f, 0x6f, 0x74, 0x00};
+/* Eight characters translating to one utf-16 word each */
+static const char d2[] = {0x6b, 0x61, 0x66, 0x62, 0xc3, 0xa1, 0x74, 0x75,
+ 0x72, 0x00};
+/* Three characters translating to one utf-16 word each */
+static const char d3[] = {0xe6, 0xbd, 0x9c, 0xe6, 0xb0, 0xb4, 0xe8, 0x89,
+ 0xa6, 0x00};
+/* Three letters translating to two utf-16 word each */
+static const char d4[] = {0xf0, 0x90, 0x92, 0x8d, 0xf0, 0x90, 0x92, 0x96,
+ 0xf0, 0x90, 0x92, 0x87, 0x00};
+
+/* Illegal utf-8 strings */
+static const char j1[] = {0x6a, 0x31, 0xa1, 0x6c, 0x00};
+static const char j2[] = {0x6a, 0x32, 0xc3, 0xc3, 0x6c, 0x00};
+static const char j3[] = {0x6a, 0x33, 0xf0, 0x90, 0xf0, 0x00};
+
+/* U-Boot uses UTF-16 strings in the EFI context only. */
+#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD)
+static int ut_string16(struct unit_test_state *uts)
+{
+ char buf[20];
+
+ /* Test length and precision */
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%8.6ls", c2);
+ ut_asserteq(' ', buf[1]);
+ ut_assert(!strncmp(&buf[2], d2, 7));
+ ut_assert(!buf[9]);
+
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%8.6ls", c4);
+ ut_asserteq(' ', buf[4]);
+ ut_assert(!strncmp(&buf[5], d4, 12));
+ ut_assert(!buf[17]);
+
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%-8.2ls", c4);
+ ut_asserteq(' ', buf[8]);
+ ut_assert(!strncmp(buf, d4, 8));
+ ut_assert(!buf[14]);
+
+ /* Test handling of illegal utf-16 sequences */
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%ls", i1);
+ ut_asserteq_str("i1?l", buf);
+
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%ls", i2);
+ ut_asserteq_str("i2?l", buf);
+
+ memset(buf, 0xff, sizeof(buf));
+ sprintf(buf, "%ls", i3);
+ ut_asserteq_str("i3?", buf);
+
+ return 0;
+}
+UNICODE_TEST(ut_string16);
+#endif
+
+static int ut_utf8_get(struct unit_test_state *uts)
+{
+ const char *s;
+ s32 code;
+ int i;
+
+ /* Check characters less than 0x800 */
+ s = d2;
+ for (i = 0; i < 8; ++i) {
+ code = utf8_get((const char **)&s);
+ /* c2 is the utf-8 encoding of d2 */
+ ut_asserteq(c2[i], code);
+ if (!code)
+ break;
+ }
+ ut_asserteq_ptr(s, d2 + 9)
+
+ /* Check characters less than 0x10000 */
+ s = d3;
+ for (i = 0; i < 4; ++i) {
+ code = utf8_get((const char **)&s);
+ /* c3 is the utf-8 encoding of d3 */
+ ut_asserteq(c3[i], code);
+ if (!code)
+ break;
+ }
+ ut_asserteq_ptr(s, d3 + 9)
+
+ /* Check character greater 0xffff */
+ s = d4;
+ code = utf8_get((const char **)&s);
+ ut_asserteq(0x0001048d, code);
+ ut_asserteq_ptr(s, d4 + 4);
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_get);
+
+static int ut_utf8_put(struct unit_test_state *uts)
+{
+ char buffer[8] = { 0, };
+ char *pos;
+
+ /* Commercial at, translates to one character */
+ pos = buffer;
+ ut_assert(!utf8_put('@', &pos))
+ ut_asserteq(1, pos - buffer);
+ ut_asserteq('@', buffer[0]);
+ ut_assert(!buffer[1]);
+
+ /* Latin letter G with acute, translates to two charactes */
+ pos = buffer;
+ ut_assert(!utf8_put(0x1f4, &pos));
+ ut_asserteq(2, pos - buffer);
+ ut_asserteq_str("\xc7\xb4", buffer);
+
+ /* Tagalog letter i, translates to three characters */
+ pos = buffer;
+ ut_assert(!utf8_put(0x1701, &pos));
+ ut_asserteq(3, pos - buffer);
+ ut_asserteq_str("\xe1\x9c\x81", buffer);
+
+ /* Hamster face, translates to four characters */
+ pos = buffer;
+ ut_assert(!utf8_put(0x1f439, &pos));
+ ut_asserteq(4, pos - buffer);
+ ut_asserteq_str("\xf0\x9f\x90\xb9", buffer);
+
+ /* Illegal code */
+ pos = buffer;
+ ut_asserteq(-1, utf8_put(0xd888, &pos));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_put);
+
+static int ut_utf8_utf16_strlen(struct unit_test_state *uts)
+{
+ ut_asserteq(6, utf8_utf16_strlen(d1));
+ ut_asserteq(8, utf8_utf16_strlen(d2));
+ ut_asserteq(3, utf8_utf16_strlen(d3));
+ ut_asserteq(6, utf8_utf16_strlen(d4));
+
+ /* illegal utf-8 sequences */
+ ut_asserteq(4, utf8_utf16_strlen(j1));
+ ut_asserteq(4, utf8_utf16_strlen(j2));
+ ut_asserteq(3, utf8_utf16_strlen(j3));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_utf16_strlen);
+
+static int ut_utf8_utf16_strnlen(struct unit_test_state *uts)
+{
+ ut_asserteq(3, utf8_utf16_strnlen(d1, 3));
+ ut_asserteq(6, utf8_utf16_strnlen(d1, 13));
+ ut_asserteq(6, utf8_utf16_strnlen(d2, 6));
+ ut_asserteq(2, utf8_utf16_strnlen(d3, 2));
+ ut_asserteq(4, utf8_utf16_strnlen(d4, 2));
+ ut_asserteq(6, utf8_utf16_strnlen(d4, 3));
+
+ /* illegal utf-8 sequences */
+ ut_asserteq(4, utf8_utf16_strnlen(j1, 16));
+ ut_asserteq(4, utf8_utf16_strnlen(j2, 16));
+ ut_asserteq(3, utf8_utf16_strnlen(j3, 16));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_utf16_strnlen);
+
+/**
+ * ut_u16_strcmp() - Compare to u16 strings.
+ *
+ * @a1: first string
+ * @a2: second string
+ * @count: number of u16 to compare
+ * Return: -1 if a1 < a2, 0 if a1 == a2, 1 if a1 > a2
+ */
+static int ut_u16_strcmp(const u16 *a1, const u16 *a2, size_t count)
+{
+ for (; (*a1 || *a2) && count; ++a1, ++a2, --count) {
+ if (*a1 < *a2)
+ return -1;
+ if (*a1 > *a2)
+ return 1;
+ }
+ return 0;
+}
+
+static int ut_utf8_utf16_strcpy(struct unit_test_state *uts)
+{
+ u16 buf[16];
+ u16 *pos;
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, d1);
+ ut_asserteq(6, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, c1, SIZE_MAX));
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, d2);
+ ut_asserteq(8, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, d3);
+ ut_asserteq(3, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, c3, SIZE_MAX));
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, d4);
+ ut_asserteq(6, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
+
+ /* Illegal utf-8 strings */
+ pos = buf;
+ utf8_utf16_strcpy(&pos, j1);
+ ut_asserteq(4, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, L"j1?l", SIZE_MAX));
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, j2);
+ ut_asserteq(4, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, L"j2?l", SIZE_MAX));
+
+ pos = buf;
+ utf8_utf16_strcpy(&pos, j3);
+ ut_asserteq(3, pos - buf);
+ ut_assert(!ut_u16_strcmp(buf, L"j3?", SIZE_MAX));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_utf16_strcpy);
+
+int ut_utf8_utf16_strncpy(struct unit_test_state *uts)
+{
+ u16 buf[16];
+ u16 *pos;
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf8_utf16_strncpy(&pos, d1, 4);
+ ut_asserteq(4, pos - buf);
+ ut_assert(!buf[4]);
+ ut_assert(!ut_u16_strcmp(buf, c1, 4));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf8_utf16_strncpy(&pos, d2, 10);
+ ut_asserteq(8, pos - buf);
+ ut_assert(buf[4]);
+ ut_assert(!ut_u16_strcmp(buf, c2, SIZE_MAX));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf8_utf16_strncpy(&pos, d3, 2);
+ ut_asserteq(2, pos - buf);
+ ut_assert(!buf[2]);
+ ut_assert(!ut_u16_strcmp(buf, c3, 2));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf8_utf16_strncpy(&pos, d4, 2);
+ ut_asserteq(4, pos - buf);
+ ut_assert(!buf[4]);
+ ut_assert(!ut_u16_strcmp(buf, c4, 4));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf8_utf16_strncpy(&pos, d4, 10);
+ ut_asserteq(6, pos - buf);
+ ut_assert(buf[5]);
+ ut_assert(!ut_u16_strcmp(buf, c4, SIZE_MAX));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf8_utf16_strncpy);
+
+static int ut_utf16_get(struct unit_test_state *uts)
+{
+ const u16 *s;
+ s32 code;
+ int i;
+
+ /* Check characters less than 0x10000 */
+ s = c2;
+ for (i = 0; i < 9; ++i) {
+ code = utf16_get((const u16 **)&s);
+ ut_asserteq(c2[i], code);
+ if (!code)
+ break;
+ }
+ ut_asserteq_ptr(c2 + 8, s);
+
+ /* Check character greater 0xffff */
+ s = c4;
+ code = utf16_get((const u16 **)&s);
+ ut_asserteq(0x0001048d, code);
+ ut_asserteq_ptr(c4 + 2, s);
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_get);
+
+static int ut_utf16_put(struct unit_test_state *uts)
+{
+ u16 buffer[4] = { 0, };
+ u16 *pos;
+
+ /* Commercial at, translates to one word */
+ pos = buffer;
+ ut_assert(!utf16_put('@', &pos));
+ ut_asserteq(1, pos - buffer);
+ ut_asserteq((u16)'@', buffer[0]);
+ ut_assert(!buffer[1]);
+
+ /* Hamster face, translates to two words */
+ pos = buffer;
+ ut_assert(!utf16_put(0x1f439, &pos));
+ ut_asserteq(2, pos - buffer);
+ ut_asserteq((u16)0xd83d, buffer[0]);
+ ut_asserteq((u16)0xdc39, buffer[1]);
+ ut_assert(!buffer[2]);
+
+ /* Illegal code */
+ pos = buffer;
+ ut_asserteq(-1, utf16_put(0xd888, &pos));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_put);
+
+int ut_utf16_strnlen(struct unit_test_state *uts)
+{
+ ut_asserteq(3, utf16_strnlen(c1, 3));
+ ut_asserteq(6, utf16_strnlen(c1, 13));
+ ut_asserteq(6, utf16_strnlen(c2, 6));
+ ut_asserteq(2, utf16_strnlen(c3, 2));
+ ut_asserteq(2, utf16_strnlen(c4, 2));
+ ut_asserteq(3, utf16_strnlen(c4, 3));
+
+ /* illegal utf-16 word sequences */
+ ut_asserteq(4, utf16_strnlen(i1, 16));
+ ut_asserteq(4, utf16_strnlen(i2, 16));
+ ut_asserteq(3, utf16_strnlen(i3, 16));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_strnlen);
+
+int ut_utf16_utf8_strlen(struct unit_test_state *uts)
+{
+ ut_asserteq(6, utf16_utf8_strlen(c1));
+ ut_asserteq(9, utf16_utf8_strlen(c2));
+ ut_asserteq(9, utf16_utf8_strlen(c3));
+ ut_asserteq(12, utf16_utf8_strlen(c4));
+
+ /* illegal utf-16 word sequences */
+ ut_asserteq(4, utf16_utf8_strlen(i1));
+ ut_asserteq(4, utf16_utf8_strlen(i2));
+ ut_asserteq(3, utf16_utf8_strlen(i3));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_utf8_strlen);
+
+int ut_utf16_utf8_strnlen(struct unit_test_state *uts)
+{
+ ut_asserteq(3, utf16_utf8_strnlen(c1, 3));
+ ut_asserteq(6, utf16_utf8_strnlen(c1, 13));
+ ut_asserteq(7, utf16_utf8_strnlen(c2, 6));
+ ut_asserteq(6, utf16_utf8_strnlen(c3, 2));
+ ut_asserteq(8, utf16_utf8_strnlen(c4, 2));
+ ut_asserteq(12, utf16_utf8_strnlen(c4, 3));
+ return 0;
+}
+UNICODE_TEST(ut_utf16_utf8_strnlen);
+
+int ut_utf16_utf8_strcpy(struct unit_test_state *uts)
+{
+ char buf[16];
+ char *pos;
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, c1);
+ ut_asserteq(6, pos - buf);
+ ut_asserteq_str(d1, buf);
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, c2);
+ ut_asserteq(9, pos - buf);
+ ut_asserteq_str(d2, buf);
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, c3);
+ ut_asserteq(9, pos - buf);
+ ut_asserteq_str(d3, buf);
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, c4);
+ ut_asserteq(12, pos - buf);
+ ut_asserteq_str(d4, buf);
+
+ /* Illegal utf-16 strings */
+ pos = buf;
+ utf16_utf8_strcpy(&pos, i1);
+ ut_asserteq(4, pos - buf);
+ ut_asserteq_str("i1?l", buf);
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, i2);
+ ut_asserteq(4, pos - buf);
+ ut_asserteq_str("i2?l", buf);
+
+ pos = buf;
+ utf16_utf8_strcpy(&pos, i3);
+ ut_asserteq(3, pos - buf);
+ ut_asserteq_str("i3?", buf);
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_utf8_strcpy);
+
+int ut_utf16_utf8_strncpy(struct unit_test_state *uts)
+{
+ char buf[16];
+ char *pos;
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf16_utf8_strncpy(&pos, c1, 4);
+ ut_asserteq(4, pos - buf);
+ ut_assert(!buf[4]);
+ ut_assert(!strncmp(buf, d1, 4));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf16_utf8_strncpy(&pos, c2, 10);
+ ut_asserteq(9, pos - buf);
+ ut_assert(buf[4]);
+ ut_assert(!strncmp(buf, d2, SIZE_MAX));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf16_utf8_strncpy(&pos, c3, 2);
+ ut_asserteq(6, pos - buf);
+ ut_assert(!buf[6]);
+ ut_assert(!strncmp(buf, d3, 6));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf16_utf8_strncpy(&pos, c4, 2);
+ ut_asserteq(8, pos - buf);
+ ut_assert(!buf[8]);
+ ut_assert(!strncmp(buf, d4, 8));
+
+ pos = buf;
+ memset(buf, 0, sizeof(buf));
+ utf16_utf8_strncpy(&pos, c4, 10);
+ ut_asserteq(12, pos - buf);
+ ut_assert(buf[5]);
+ ut_assert(!strncmp(buf, d4, SIZE_MAX));
+
+ return 0;
+}
+UNICODE_TEST(ut_utf16_utf8_strncpy);
+
+int ut_utf_to_lower(struct unit_test_state *uts)
+{
+ ut_asserteq('@', utf_to_lower('@'));
+ ut_asserteq('a', utf_to_lower('A'));
+ ut_asserteq('z', utf_to_lower('Z'));
+ ut_asserteq('[', utf_to_lower('['));
+ ut_asserteq('m', utf_to_lower('m'));
+ /* Latin letter O with diaresis (umlaut) */
+ ut_asserteq(0x00f6, utf_to_lower(0x00d6));
+#ifdef CONFIG_EFI_UNICODE_CAPITALIZATION
+ /* Cyrillic letter I*/
+ ut_asserteq(0x0438, utf_to_lower(0x0418));
+#endif
+ return 0;
+}
+UNICODE_TEST(ut_utf_to_lower);
+
+int ut_utf_to_upper(struct unit_test_state *uts)
+{
+ ut_asserteq('`', utf_to_upper('`'));
+ ut_asserteq('A', utf_to_upper('a'));
+ ut_asserteq('Z', utf_to_upper('z'));
+ ut_asserteq('{', utf_to_upper('{'));
+ ut_asserteq('M', utf_to_upper('M'));
+ /* Latin letter O with diaresis (umlaut) */
+ ut_asserteq(0x00d6, utf_to_upper(0x00f6));
+#ifdef CONFIG_EFI_UNICODE_CAPITALIZATION
+ /* Cyrillic letter I */
+ ut_asserteq(0x0418, utf_to_upper(0x0438));
+#endif
+ return 0;
+}
+UNICODE_TEST(ut_utf_to_upper);
+
+int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);
+ const int n_ents = ll_entry_count(struct unit_test, unicode_test);
+
+ return cmd_ut_category("Unicode", tests, n_ents, argc, argv);
+}