[U-Boot] [PATCH 04/15] test: unit tests for Unicode functions

Heinrich Schuchardt xypron.glpk at gmx.de
Sat Aug 11 15:28:09 UTC 2018


Provide unit tests for Unicode functions.

Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
---
 MAINTAINERS           |   1 +
 include/test/suites.h |   3 +-
 test/Kconfig          |   8 +
 test/Makefile         |   1 +
 test/cmd_ut.c         |  14 +-
 test/unicode_ut.c     | 470 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 493 insertions(+), 4 deletions(-)
 create mode 100644 test/unicode_ut.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 51a1472cf8..a324139471 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -374,6 +374,7 @@ F:	include/asm-generic/pe.h
 F:	lib/charset.c
 F:	lib/efi*/
 F:	test/py/tests/test_efi*
+F:	test/unicode_ut.c
 F:	cmd/bootefi.c
 F:	tools/file2include.c
 
diff --git a/include/test/suites.h b/include/test/suites.h
index b5019a7cd2..8e4eac60eb 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -23,10 +23,11 @@ struct unit_test;
 int cmd_ut_category(const char *name, struct unit_test *tests, int n_ents,
 		    int argc, char * const argv[]);
 
+int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
-int do_ut_compression(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __TEST_SUITES_H__ */
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..d6a2593850 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -49,6 +49,10 @@ 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 defined(CONFIG_UT_UNICODE) && \
+	!defined(CONFIG_SPL_BUILD) && !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 +97,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 +112,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 Unicode functions\n"
 #endif
 	;
-#endif
+#endif /* CONFIG_SYS_LONGHELP */
 
 U_BOOT_CMD(
 	ut, CONFIG_SYS_MAXARGS, 1, do_ut,
diff --git a/test/unicode_ut.c b/test/unicode_ut.c
new file mode 100644
index 0000000000..29316606c4
--- /dev/null
+++ b/test/unicode_ut.c
@@ -0,0 +1,470 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Unit tests for Unicode functions
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk at gmx.de>
+ */
+
+#include <common.h>
+#include <charset.h>
+#include <command.h>
+#include <errno.h>
+
+/* 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};
+
+/* 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};
+
+static int ut_utf8_get(void)
+{
+	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 */
+		if (code != c2[i])
+			return -1;
+		if (!code)
+			break;
+	}
+	if (s != d2 + 9)
+		return -1;
+
+	/* 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 */
+		if (code != c3[i])
+			return -1;
+		if (!code)
+			break;
+	}
+	if (s != d3 + 9)
+		return -1;
+
+	/* Check character greater 0xffff */
+	s = d4;
+	code = utf8_get((const char **)&s);
+	if (code != 0x0001048d)
+		return -1;
+	if (s != d4 + 4)
+		return -1;
+
+	return 0;
+}
+
+static int ut_utf8_put(void)
+{
+	char buffer[8] = { 0, };
+	char *pos;
+
+	/* Commercial at, translates to one character */
+	pos = buffer;
+	if (utf8_put('@', &pos))
+		return -1;
+	if (pos - buffer != 1)
+		return -1;
+	if (buffer[0] != '@' || buffer[1])
+		return -1;
+
+	/* Latin letter G with acute, translates to two charactes */
+	pos = buffer;
+	if (utf8_put(0x1f4, &pos))
+		return -1;
+	if (pos - buffer != 2)
+		return -1;
+	if (buffer[0] != (char)0xc7 || buffer[1] != (char)0xb4 || buffer[2])
+		return -1;
+
+	/* Tagalog letter i, translates to three characters */
+	pos = buffer;
+	if (utf8_put(0x1701, &pos))
+		return -1;
+	if (pos - buffer != 3)
+		return -1;
+	if (buffer[0] != (char)0xe1 || buffer[1] != (char)0x9c ||
+	    buffer[2] != (char)0x81 || buffer[3])
+		return -1;
+
+	/* Hamster face, translates to four characters */
+	pos = buffer;
+	if (utf8_put(0x1f439, &pos))
+		return -1;
+	if (pos - buffer != 4)
+		return -1;
+	if (buffer[0] != (char)0xf0 || buffer[1] != (char)0x9f ||
+	    buffer[2] != (char)0x90 || buffer[3] != (char)0xb9 || buffer[4])
+		return -1;
+
+	/* Illegal code */
+	pos = buffer;
+	if (utf8_put(0xd888, &pos) != -1)
+		return -1;
+
+	return 0;
+}
+
+int ut_utf8_utf16_strlen(void)
+{
+	if (utf8_utf16_strlen(d1) != 6)
+		return 1;
+	if (utf8_utf16_strlen(d2) != 8)
+		return 1;
+	if (utf8_utf16_strlen(d3) != 3)
+		return 1;
+	if (utf8_utf16_strlen(d4) != 6)
+		return 1;
+	return 0;
+}
+
+int ut_utf8_utf16_strnlen(void)
+{
+	if (utf8_utf16_strnlen(d1, 3) != 3)
+		return 1;
+	if (utf8_utf16_strnlen(d1, 13) != 6)
+		return 1;
+	if (utf8_utf16_strnlen(d2, 6) != 6)
+		return 1;
+	if (utf8_utf16_strnlen(d3, 2) != 2)
+		return 1;
+	if (utf8_utf16_strnlen(d4, 2) != 4)
+		return 1;
+	if (utf8_utf16_strnlen(d4, 3) != 6)
+		return 1;
+	return 0;
+}
+
+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;
+}
+
+int ut_utf8_utf16_strcpy(void)
+{
+	u16 buf[16];
+	u16 *pos;
+
+	pos = buf;
+	utf8_utf16_strcpy(&pos, d1);
+	if (pos - buf != 6)
+		return 1;
+	if (ut_u16_strcmp(buf, c1, 16))
+		return 1;
+
+	pos = buf;
+	utf8_utf16_strcpy(&pos, d2);
+	if (pos - buf != 8)
+		return 1;
+	if (ut_u16_strcmp(buf, c2, 16))
+		return 1;
+
+	pos = buf;
+	utf8_utf16_strcpy(&pos, d3);
+	if (pos - buf != 3)
+		return 1;
+	if (ut_u16_strcmp(buf, c3, 16))
+		return 1;
+
+	pos = buf;
+	utf8_utf16_strcpy(&pos, d4);
+	if (pos - buf != 6)
+		return 1;
+	if (ut_u16_strcmp(buf, c4, 16))
+		return 1;
+
+	return 0;
+}
+
+int ut_utf8_utf16_strncpy(void)
+{
+	u16 buf[16];
+	u16 *pos;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf8_utf16_strncpy(&pos, d1, 4);
+	if (pos - buf != 4)
+		return 1;
+	if (buf[4])
+		return 1;
+	if (ut_u16_strcmp(buf, c1, 4))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf8_utf16_strncpy(&pos, d2, 10);
+	if (pos - buf != 8)
+		return 1;
+	if (!buf[4])
+		return 1;
+	if (ut_u16_strcmp(buf, c2, SIZE_MAX))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf8_utf16_strncpy(&pos, d3, 2);
+	if (pos - buf != 2)
+		return 1;
+	if (buf[2])
+		return 1;
+	if (ut_u16_strcmp(buf, c3, 2))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf8_utf16_strncpy(&pos, d4, 2);
+	if (pos - buf != 4)
+		return 1;
+	if (buf[4])
+		return 1;
+	if (ut_u16_strcmp(buf, c4, 4))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf8_utf16_strncpy(&pos, d4, 10);
+	if (pos - buf != 6)
+		return 1;
+	if (!buf[5])
+		return 1;
+	if (ut_u16_strcmp(buf, c4, SIZE_MAX))
+		return 1;
+
+	return 0;
+}
+
+static int ut_utf16_get(void)
+{
+	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);
+		if (code != c2[i])
+			return -1;
+		if (!code)
+			break;
+	}
+	if (s != c2 + 8)
+		return -1;
+
+	/* Check character greater 0xffff */
+	s = c4;
+	code = utf16_get((const u16 **)&s);
+	if (code != 0x0001048d)
+		return -1;
+	if (s != c4 + 2)
+		return -1;
+
+	return 0;
+}
+
+static int ut_utf16_put(void)
+{
+	u16 buffer[4] = { 0, };
+	u16 *pos;
+
+	/* Commercial at, translates to one word */
+	pos = buffer;
+	if (utf16_put('@', &pos))
+		return -1;
+	if (pos - buffer != 1)
+		return -1;
+	if (buffer[0] != (u16)'@' || buffer[1])
+		return -1;
+
+	/* Hamster face, translates to two words */
+	pos = buffer;
+	if (utf16_put(0x1f439, &pos))
+		return -1;
+	if (pos - buffer != 2)
+		return -1;
+	if (buffer[0] != (u16)0xd83d || buffer[1] != (u16)0xdc39 || buffer[2])
+		return -1;
+
+	/* Illegal code */
+	pos = buffer;
+	if (utf16_put(0xd888, &pos) != -1)
+		return -1;
+
+	return 0;
+}
+
+int ut_utf16_utf8_strlen(void)
+{
+	if (utf16_utf8_strlen(c1) != 6)
+		return 1;
+	if (utf16_utf8_strlen(c2) != 9)
+		return 1;
+	if (utf16_utf8_strlen(c3) != 9)
+		return 1;
+	if (utf16_utf8_strlen(c4) != 12)
+		return 1;
+	return 0;
+}
+
+int ut_utf16_utf8_strnlen(void)
+{
+	if (utf16_utf8_strnlen(c1, 3) != 3)
+		return 1;
+	if (utf16_utf8_strnlen(c1, 13) != 6)
+		return 1;
+	if (utf16_utf8_strnlen(c2, 6) != 7)
+		return 1;
+	if (utf16_utf8_strnlen(c3, 2) != 6)
+		return 1;
+	if (utf16_utf8_strnlen(c4, 2) != 8)
+		return 1;
+	if (utf16_utf8_strnlen(c4, 3) != 12)
+		return 1;
+	return 0;
+}
+
+int ut_utf16_utf8_strcpy(void)
+{
+	char buf[16];
+	char *pos;
+
+	pos = buf;
+	utf16_utf8_strcpy(&pos, c1);
+	if (pos - buf != 6)
+		return 1;
+	if (strcmp(buf, d1))
+		return 1;
+
+	pos = buf;
+	utf16_utf8_strcpy(&pos, c2);
+	if (pos - buf != 9)
+		return 1;
+	if (strcmp(buf, d2))
+		return 1;
+
+	pos = buf;
+	utf16_utf8_strcpy(&pos, c3);
+	if (pos - buf != 9)
+		return 1;
+	if (strcmp(buf, d3))
+		return 1;
+
+	pos = buf;
+	utf16_utf8_strcpy(&pos, c4);
+	if (pos - buf != 12)
+		return 1;
+	if (strcmp(buf, d4))
+		return 1;
+
+	return 0;
+}
+
+int ut_utf16_utf8_strncpy(void)
+{
+	char buf[16];
+	char *pos;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf16_utf8_strncpy(&pos, c1, 4);
+	if (pos - buf != 4)
+		return 1;
+	if (buf[4])
+		return 1;
+	if (strncmp(buf, d1, 4))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf16_utf8_strncpy(&pos, c2, 10);
+	if (pos - buf != 9)
+		return 1;
+	if (!buf[4])
+		return 1;
+	if (strncmp(buf, d2, SIZE_MAX))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf16_utf8_strncpy(&pos, c3, 2);
+	if (pos - buf != 6)
+		return 1;
+	if (buf[6])
+		return 1;
+	if (strncmp(buf, d3, 6))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf16_utf8_strncpy(&pos, c4, 2);
+	if (pos - buf != 8)
+		return 1;
+	if (buf[8])
+		return 1;
+	if (strncmp(buf, d4, 8))
+		return 1;
+
+	pos = buf;
+	memset(buf, 0, sizeof(buf));
+	utf16_utf8_strncpy(&pos, c4, 10);
+	if (pos - buf != 12)
+		return 1;
+	if (!buf[5])
+		return 1;
+	if (strncmp(buf, d4, SIZE_MAX))
+		return 1;
+
+	return 0;
+}
+
+int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret = 0;
+
+	ret |= ut_utf8_get();
+	ret |= ut_utf8_put();
+	ret |= ut_utf8_utf16_strlen();
+	ret |= ut_utf8_utf16_strnlen();
+	ret |= ut_utf8_utf16_strcpy();
+	ret |= ut_utf8_utf16_strncpy();
+	ret |= ut_utf16_get();
+	ret |= ut_utf16_put();
+	ret |= ut_utf16_utf8_strlen();
+	ret |= ut_utf16_utf8_strnlen();
+	ret |= ut_utf16_utf8_strcpy();
+	ret |= ut_utf16_utf8_strncpy();
+
+	printf("Test %s\n", ret ? "failed" : "passed");
+
+	return ret ? CMD_RET_FAILURE : CMD_RET_SUCCESS;
+}
-- 
2.18.0



More information about the U-Boot mailing list