diff options
Diffstat (limited to 'test/lib')
-rw-r--r-- | test/lib/Makefile | 8 | ||||
-rw-r--r-- | test/lib/compression.c | 608 | ||||
-rw-r--r-- | test/lib/str.c | 369 | ||||
-rw-r--r-- | test/lib/time.c | 123 | ||||
-rw-r--r-- | test/lib/unicode.c | 846 |
5 files changed, 1953 insertions, 1 deletions
diff --git a/test/lib/Makefile b/test/lib/Makefile index a54387a058e..f516d001747 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -2,6 +2,9 @@ # # (C) Copyright 2018 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc + +obj-$(CONFIG_$(XPL_)UT_COMPRESSION) += compression.o + ifeq ($(CONFIG_XPL_BUILD),) obj-y += cmd_ut_lib.o obj-y += abuf.o @@ -11,9 +14,10 @@ obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o obj-y += hexdump.o obj-$(CONFIG_SANDBOX) += kconfig.o obj-y += lmb.o -obj-y += longjmp.o +obj-$(CONFIG_HAVE_SETJMP) += longjmp.o obj-$(CONFIG_CONSOLE_RECORD) += test_print.o obj-$(CONFIG_SSCANF) += sscanf.o +obj-$(CONFIG_$(XPL_)CMDLINE) += str.o obj-y += string.o obj-y += strlcat.o obj-$(CONFIG_ERRNO_STR) += test_errno_str.o @@ -23,6 +27,8 @@ obj-$(CONFIG_AES) += test_aes.o obj-$(CONFIG_GETOPT) += getopt.o obj-$(CONFIG_CRC8) += test_crc8.o obj-$(CONFIG_UT_LIB_CRYPT) += test_crypt.o +obj-$(CONFIG_UT_TIME) += time.o +obj-$(CONFIG_$(XPL_)UT_UNICODE) += unicode.o obj-$(CONFIG_LIB_UUID) += uuid.o else obj-$(CONFIG_SANDBOX) += kconfig_spl.o diff --git a/test/lib/compression.c b/test/lib/compression.c new file mode 100644 index 00000000000..31b6e5b1eb4 --- /dev/null +++ b/test/lib/compression.c @@ -0,0 +1,608 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013, The Chromium Authors + */ + +#include <abuf.h> +#include <bootm.h> +#include <command.h> +#include <gzip.h> +#include <image.h> +#include <log.h> +#include <malloc.h> +#include <mapmem.h> +#include <asm/io.h> + +#include <u-boot/lz4.h> +#include <u-boot/zlib.h> +#include <bzlib.h> + +#include <lzma/LzmaTypes.h> +#include <lzma/LzmaDec.h> +#include <lzma/LzmaTools.h> + +#include <linux/lzo.h> +#include <linux/zstd.h> +#include <test/lib.h> +#include <test/ut.h> + +static const char plain[] = + "I am a highly compressable bit of text.\n" + "I am a highly compressable bit of text.\n" + "I am a highly compressable bit of text.\n" + "There are many like me, but this one is mine.\n" + "If I were any shorter, there wouldn't be much sense in\n" + "compressing me in the first place. At least with lzo, anyway,\n" + "which appears to behave poorly in the face of short text\n" + "messages.\n"; + +/* bzip2 -c /tmp/plain.txt > /tmp/plain.bz2 */ +static const char bzip2_compressed[] = + "\x42\x5a\x68\x39\x31\x41\x59\x26\x53\x59\xe5\x63\xdd\x09\x00\x00" + "\x28\x57\x80\x00\x10\x40\x85\x20\x20\x04\x00\x3f\xef\xdf\xf0\x30" + "\x00\xd6\xd0\x34\x91\x89\xa6\xf5\x4d\x19\x1a\x19\x0d\x02\x34\xd4" + "\xc9\x00\x34\x34\x00\x02\x48\x41\x35\x4f\xd4\xc6\x88\xd3\x50\x3d" + "\x4f\x51\x82\x4f\x88\xc3\x0d\x05\x62\x4f\x91\xa3\x52\x1b\xd0\x52" + "\x41\x4a\xa3\x98\xc2\x6b\xca\xa3\x82\xa5\xac\x8b\x15\x99\x68\xad" + "\xdf\x29\xd6\xf1\xf7\x5a\x10\xcd\x8c\x26\x61\x94\x95\xfe\x9e\x16" + "\x18\x28\x69\xd4\x23\x64\xcc\x2b\xe5\xe8\x5f\x00\xa4\x70\x26\x2c" + "\xee\xbd\x59\x6d\x6a\xec\xfc\x31\xda\x59\x0a\x14\x2a\x60\x1c\xf0" + "\x04\x86\x73\x9a\xc5\x5b\x87\x3f\x5b\x4c\x93\xe6\xb5\x35\x0d\xa6" + "\xb1\x2e\x62\x7b\xab\x67\xe7\x99\x2a\x14\x5e\x9f\x64\xcb\x96\xf4" + "\x0d\x65\xd4\x39\xe6\x8b\x7e\xea\x1c\x03\x69\x97\x83\x58\x91\x96" + "\xe1\xf0\x9d\xa4\x15\x8b\xb8\xc6\x93\xdc\x3d\xd9\x3c\x22\x55\xef" + "\xfb\xbb\x2a\xd3\x87\xa2\x8b\x04\xd9\x19\xf8\xe2\xfd\x4f\xdb\x1a" + "\x07\xc8\x60\xa3\x3f\xf8\xbb\x92\x29\xc2\x84\x87\x2b\x1e\xe8\x48"; +static const unsigned long bzip2_compressed_size = sizeof(bzip2_compressed) - 1; + +/* lzma -z -c /tmp/plain.txt > /tmp/plain.lzma */ +static const char lzma_compressed[] = + "\x5d\x00\x00\x80\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x24\x88" + "\x08\x26\xd8\x41\xff\x99\xc8\xcf\x66\x3d\x80\xac\xba\x17\xf1\xc8" + "\xb9\xdf\x49\x37\xb1\x68\xa0\x2a\xdd\x63\xd1\xa7\xa3\x66\xf8\x15" + "\xef\xa6\x67\x8a\x14\x18\x80\xcb\xc7\xb1\xcb\x84\x6a\xb2\x51\x16" + "\xa1\x45\xa0\xd6\x3e\x55\x44\x8a\x5c\xa0\x7c\xe5\xa8\xbd\x04\x57" + "\x8f\x24\xfd\xb9\x34\x50\x83\x2f\xf3\x46\x3e\xb9\xb0\x00\x1a\xf5" + "\xd3\x86\x7e\x8f\x77\xd1\x5d\x0e\x7c\xe1\xac\xde\xf8\x65\x1f\x4d" + "\xce\x7f\xa7\x3d\xaa\xcf\x26\xa7\x58\x69\x1e\x4c\xea\x68\x8a\xe5" + "\x89\xd1\xdc\x4d\xc7\xe0\x07\x42\xbf\x0c\x9d\x06\xd7\x51\xa2\x0b" + "\x7c\x83\x35\xe1\x85\xdf\xee\xfb\xa3\xee\x2f\x47\x5f\x8b\x70\x2b" + "\xe1\x37\xf3\x16\xf6\x27\x54\x8a\x33\x72\x49\xea\x53\x7d\x60\x0b" + "\x21\x90\x66\xe7\x9e\x56\x61\x5d\xd8\xdc\x59\xf0\xac\x2f\xd6\x49" + "\x6b\x85\x40\x08\x1f\xdf\x26\x25\x3b\x72\x44\xb0\xb8\x21\x2f\xb3" + "\xd7\x9b\x24\x30\x78\x26\x44\x07\xc3\x33\xd1\x4d\x03\x1b\xe1\xff" + "\xfd\xf5\x50\x8d\xca"; +static const unsigned long lzma_compressed_size = sizeof(lzma_compressed) - 1; + +/* lzop -c /tmp/plain.txt > /tmp/plain.lzo */ +static const char lzo_compressed[] = + "\x89\x4c\x5a\x4f\x00\x0d\x0a\x1a\x0a\x10\x30\x20\x60\x09\x40\x01" + "\x05\x03\x00\x00\x09\x00\x00\x81\xb4\x52\x09\x54\xf1\x00\x00\x00" + "\x00\x09\x70\x6c\x61\x69\x6e\x2e\x74\x78\x74\x65\xb1\x07\x9c\x00" + "\x00\x01\x5e\x00\x00\x01\x0f\xc3\xc7\x7a\xe0\x00\x16\x49\x20\x61" + "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72" + "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74" + "\x65\x78\x74\x2e\x0a\x20\x2f\x9c\x00\x00\x22\x54\x68\x65\x72\x65" + "\x20\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d" + "\x65\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20" + "\x69\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x84" + "\x06\x0a\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x90" + "\x08\x00\x08\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d" + "\x75\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xf8\x19\x02" + "\x69\x6e\x67\x20\x6d\x64\x02\x64\x06\x00\x5a\x20\x66\x69\x72\x73" + "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73" + "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x20\x61\x6e\x79\x77" + "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72" + "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72" + "\x6c\x79\x20\x69\x6e\x20\x74\x68\x65\x20\x66\x61\x63\x65\x20\x6f" + "\x66\x20\x73\x68\x6f\x72\x74\x20\x74\x65\x78\x74\x0a\x6d\x65\x73" + "\x73\x61\x67\x65\x73\x2e\x0a\x11\x00\x00\x00\x00\x00\x00"; +static const unsigned long lzo_compressed_size = sizeof(lzo_compressed) - 1; + +/* lz4 -z /tmp/plain.txt > /tmp/plain.lz4 */ +static const char lz4_compressed[] = + "\x04\x22\x4d\x18\x64\x70\xb9\x01\x01\x00\x00\xff\x19\x49\x20\x61" + "\x6d\x20\x61\x20\x68\x69\x67\x68\x6c\x79\x20\x63\x6f\x6d\x70\x72" + "\x65\x73\x73\x61\x62\x6c\x65\x20\x62\x69\x74\x20\x6f\x66\x20\x74" + "\x65\x78\x74\x2e\x0a\x28\x00\x3d\xf1\x25\x54\x68\x65\x72\x65\x20" + "\x61\x72\x65\x20\x6d\x61\x6e\x79\x20\x6c\x69\x6b\x65\x20\x6d\x65" + "\x2c\x20\x62\x75\x74\x20\x74\x68\x69\x73\x20\x6f\x6e\x65\x20\x69" + "\x73\x20\x6d\x69\x6e\x65\x2e\x0a\x49\x66\x20\x49\x20\x77\x32\x00" + "\xd1\x6e\x79\x20\x73\x68\x6f\x72\x74\x65\x72\x2c\x20\x74\x45\x00" + "\xf4\x0b\x77\x6f\x75\x6c\x64\x6e\x27\x74\x20\x62\x65\x20\x6d\x75" + "\x63\x68\x20\x73\x65\x6e\x73\x65\x20\x69\x6e\x0a\xcf\x00\x50\x69" + "\x6e\x67\x20\x6d\x12\x00\x00\x32\x00\xf0\x11\x20\x66\x69\x72\x73" + "\x74\x20\x70\x6c\x61\x63\x65\x2e\x20\x41\x74\x20\x6c\x65\x61\x73" + "\x74\x20\x77\x69\x74\x68\x20\x6c\x7a\x6f\x2c\x63\x00\xf5\x14\x77" + "\x61\x79\x2c\x0a\x77\x68\x69\x63\x68\x20\x61\x70\x70\x65\x61\x72" + "\x73\x20\x74\x6f\x20\x62\x65\x68\x61\x76\x65\x20\x70\x6f\x6f\x72" + "\x6c\x79\x4e\x00\x30\x61\x63\x65\x27\x01\x01\x95\x00\x01\x2d\x01" + "\xb0\x0a\x6d\x65\x73\x73\x61\x67\x65\x73\x2e\x0a\x00\x00\x00\x00" + "\x9d\x12\x8c\x9d"; +static const unsigned long lz4_compressed_size = sizeof(lz4_compressed) - 1; + +/* zstd -19 -c /tmp/plain.txt > /tmp/plain.zst */ +static const char zstd_compressed[] = + "\x28\xb5\x2f\xfd\x64\x5e\x00\xbd\x05\x00\x02\x0e\x26\x1a\x70\x17" + "\xb8\x0d\x0c\x53\x5c\x9d\x97\xee\xa0\x5d\x84\x89\x3f\x5c\x7a\x78" + "\x00\x80\x80\x0f\xe8\xdf\xaf\x06\x66\xd0\x23\xa6\x7a\x64\x8e\xf4" + "\x0d\x5b\x47\x65\x26\x7e\x81\xdd\x0b\xe7\x5a\x95\x3d\x49\xcc\x67" + "\xe0\x2d\x46\x58\xb6\xac\x64\x16\xf2\xe0\xf8\x16\x17\xaf\xda\x8f" + "\x37\xc0\xc3\x0d\x3b\x89\x57\x15\x1e\x46\x46\x12\x9a\x84\xbe\xa6" + "\xab\xcf\x50\x90\x5f\x78\x01\xd2\xc0\x51\x72\x59\x0b\xea\xab\xf2" + "\xd4\x2b\x2d\x26\x7c\x10\x66\x78\x42\x64\x45\x3f\xa5\x15\x6f\xbd" + "\x4a\x61\xe1\xc8\x27\xc0\xe3\x95\x0c\xf9\xca\x7c\xf5\x13\x30\xc3" + "\x1a\x7c\x7d\xa4\x17\x0b\xff\x14\xa6\x7a\x95\xa0\x34\xbc\xce\x21" + "\x78\x36\x23\x33\x11\x09\x00\x60\x13\x00\x63\xa3\x8e\x28\x94\x55" + "\x15\xb6\x26\x68\x05\x4f\x23\x12\xee\x53\x55\x2d\x44\x2f\x54\x95" + "\x01\xe4\xf4\x6e\xfa"; +static const unsigned long zstd_compressed_size = sizeof(zstd_compressed) - 1; + +#define TEST_BUFFER_SIZE 512 + +typedef int (*mutate_func)(struct unit_test_state *uts, void *, unsigned long, + void *, unsigned long, unsigned long *); + +static int compress_using_gzip(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + unsigned long inout_size = out_max; + + ret = gzip(out, &inout_size, in, in_size); + if (out_size) + *out_size = inout_size; + + return ret; +} + +static int uncompress_using_gzip(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + unsigned long inout_size = in_size; + + ret = gunzip(out, out_max, in, &inout_size); + if (out_size) + *out_size = inout_size; + + return ret; +} + +static int compress_using_bzip2(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* There is no bzip2 compression in u-boot, so fake it. */ + ut_asserteq(in_size, strlen(plain)); + ut_asserteq_mem(plain, in, in_size); + + if (bzip2_compressed_size > out_max) + return -1; + + memcpy(out, bzip2_compressed, bzip2_compressed_size); + if (out_size) + *out_size = bzip2_compressed_size; + + return 0; +} + +static int uncompress_using_bzip2(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + unsigned int inout_size = out_max; + + ret = BZ2_bzBuffToBuffDecompress(out, &inout_size, in, in_size, + CONFIG_SYS_MALLOC_LEN < (4096 * 1024), 0); + if (out_size) + *out_size = inout_size; + + return (ret != BZ_OK); +} + +static int compress_using_lzma(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* There is no lzma compression in u-boot, so fake it. */ + ut_asserteq(in_size, strlen(plain)); + ut_asserteq_mem(plain, in, in_size); + + if (lzma_compressed_size > out_max) + return -1; + + memcpy(out, lzma_compressed, lzma_compressed_size); + if (out_size) + *out_size = lzma_compressed_size; + + return 0; +} + +static int uncompress_using_lzma(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + SizeT inout_size = out_max; + + ret = lzmaBuffToBuffDecompress(out, &inout_size, in, in_size); + if (out_size) + *out_size = inout_size; + + return (ret != SZ_OK); +} + +static int compress_using_lzo(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* There is no lzo compression in u-boot, so fake it. */ + ut_asserteq(in_size, strlen(plain)); + ut_asserteq_mem(plain, in, in_size); + + if (lzo_compressed_size > out_max) + return -1; + + memcpy(out, lzo_compressed, lzo_compressed_size); + if (out_size) + *out_size = lzo_compressed_size; + + return 0; +} + +static int uncompress_using_lzo(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + size_t input_size = in_size; + size_t output_size = out_max; + + ret = lzop_decompress(in, input_size, out, &output_size); + if (out_size) + *out_size = output_size; + + return (ret != LZO_E_OK); +} + +static int compress_using_lz4(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* There is no lz4 compression in u-boot, so fake it. */ + ut_asserteq(in_size, strlen(plain)); + ut_asserteq_mem(plain, in, in_size); + + if (lz4_compressed_size > out_max) + return -1; + + memcpy(out, lz4_compressed, lz4_compressed_size); + if (out_size) + *out_size = lz4_compressed_size; + + return 0; +} + +static int uncompress_using_lz4(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + int ret; + size_t input_size = in_size; + size_t output_size = out_max; + + ret = ulz4fn(in, input_size, out, &output_size); + if (out_size) + *out_size = output_size; + + return (ret != 0); +} + +static int compress_using_zstd(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* There is no zstd compression in u-boot, so fake it. */ + ut_asserteq(in_size, strlen(plain)); + ut_asserteq_mem(plain, in, in_size); + + if (zstd_compressed_size > out_max) + return -1; + + memcpy(out, zstd_compressed, zstd_compressed_size); + if (out_size) + *out_size = zstd_compressed_size; + + return 0; +} + +static int uncompress_using_zstd(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + struct abuf in_buf, out_buf; + int ret; + + abuf_init_set(&in_buf, in, in_size); + abuf_init_set(&out_buf, out, out_max); + + ret = zstd_decompress(&in_buf, &out_buf); + if (ret >= 0) { + *out_size = ret; + ret = 0; + } + + return ret; +} + +#define errcheck(statement) if (!(statement)) { \ + fprintf(stderr, "\tFailed: %s\n", #statement); \ + ret = 1; \ + goto out; \ +} + +struct buf_state { + ulong orig_size; + ulong compressed_size; + ulong uncompressed_size; + void *orig_buf; + void *compressed_buf; + void *uncompressed_buf; + void *compare_buf; +}; + +static int run_test_internal(struct unit_test_state *uts, char *name, + mutate_func compress, mutate_func uncompress, + struct buf_state *buf) +{ + int ret; + + /* Compress works as expected. */ + printf("\torig_size:%lu\n", buf->orig_size); + memset(buf->compressed_buf, 'A', TEST_BUFFER_SIZE); + ut_assertok(compress(uts, buf->orig_buf, buf->orig_size, + buf->compressed_buf, buf->compressed_size, + &buf->compressed_size)); + printf("\tcompressed_size:%lu\n", buf->compressed_size); + ut_assert(buf->compressed_size > 0); + ut_assert(buf->compressed_size < buf->orig_size); + ut_assert(((char *)buf->compressed_buf)[buf->compressed_size - 1] + != 'A'); + ut_asserteq(((char *)buf->compressed_buf)[buf->compressed_size], 'A'); + + /* Uncompresses with space remaining. */ + ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size, + buf->uncompressed_buf, buf->uncompressed_size, + &buf->uncompressed_size)); + printf("\tuncompressed_size:%lu\n", buf->uncompressed_size); + ut_asserteq(buf->uncompressed_size, buf->orig_size); + ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size); + + /* Uncompresses with exactly the right size output buffer. */ + memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE); + ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size, + buf->uncompressed_buf, buf->orig_size, + &buf->uncompressed_size)); + ut_asserteq(buf->uncompressed_size, buf->orig_size); + ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size); + ut_asserteq(((char *)buf->uncompressed_buf)[buf->orig_size], 'A'); + + /* Uncompresses with trailing garbage in input buffer. */ + memset(buf->uncompressed_buf, 'A', TEST_BUFFER_SIZE); + ut_assertok(uncompress(uts, buf->compressed_buf, buf->compressed_size + 4, + buf->uncompressed_buf, buf->uncompressed_size, + &buf->uncompressed_size)); + ut_asserteq(buf->uncompressed_size, buf->orig_size); + ut_asserteq_mem(buf->orig_buf, buf->uncompressed_buf, buf->orig_size); + + /* Make sure compression does not over-run. */ + memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE); + ret = compress(uts, buf->orig_buf, buf->orig_size, + buf->compare_buf, buf->compressed_size - 1, + NULL); + ut_asserteq(((char *)buf->compare_buf)[buf->compressed_size], 'A'); + ut_assert(ret != 0); + printf("\tcompress does not overrun\n"); + + /* Make sure decompression does not over-run. */ + memset(buf->compare_buf, 'A', TEST_BUFFER_SIZE); + ret = uncompress(uts, buf->compressed_buf, buf->compressed_size, + buf->compare_buf, buf->uncompressed_size - 1, + NULL); + ut_asserteq(((char *)buf->compare_buf)[buf->uncompressed_size - 1], 'A'); + ut_assert(ret != 0); + printf("\tuncompress does not overrun\n"); + + /* Got here, everything is fine. */ + return 0; +} + +static int run_test(struct unit_test_state *uts, char *name, + mutate_func compress, mutate_func uncompress) +{ + struct buf_state sbuf, *buf = &sbuf; + int ret; + + printf(" testing %s ...\n", name); + + buf->orig_buf = (void *)plain; + buf->orig_size = strlen(buf->orig_buf); /* Trailing NUL not included */ + errcheck(buf->orig_size > 0); + + buf->compressed_size = TEST_BUFFER_SIZE; + buf->uncompressed_size = TEST_BUFFER_SIZE; + buf->compressed_buf = malloc(buf->compressed_size); + errcheck(buf->compressed_buf); + buf->uncompressed_buf = malloc(buf->uncompressed_size); + errcheck(buf->uncompressed_buf); + buf->compare_buf = malloc(buf->uncompressed_size); + errcheck(buf->compare_buf); + + ret = run_test_internal(uts, name, compress, uncompress, buf); +out: + printf(" %s: %s\n", name, ret == 0 ? "ok" : "FAILED"); + + free(buf->compare_buf); + free(buf->uncompressed_buf); + free(buf->compressed_buf); + + return ret; +} + +static int compression_test_gzip(struct unit_test_state *uts) +{ + return run_test(uts, "gzip", compress_using_gzip, + uncompress_using_gzip); +} +LIB_TEST(compression_test_gzip, 0); + +static int compression_test_bzip2(struct unit_test_state *uts) +{ + return run_test(uts, "bzip2", compress_using_bzip2, + uncompress_using_bzip2); +} +LIB_TEST(compression_test_bzip2, 0); + +static int compression_test_lzma(struct unit_test_state *uts) +{ + return run_test(uts, "lzma", compress_using_lzma, + uncompress_using_lzma); +} +LIB_TEST(compression_test_lzma, 0); + +static int compression_test_lzo(struct unit_test_state *uts) +{ + return run_test(uts, "lzo", compress_using_lzo, uncompress_using_lzo); +} +LIB_TEST(compression_test_lzo, 0); + +static int compression_test_lz4(struct unit_test_state *uts) +{ + return run_test(uts, "lz4", compress_using_lz4, uncompress_using_lz4); +} +LIB_TEST(compression_test_lz4, 0); + +static int compression_test_zstd(struct unit_test_state *uts) +{ + return run_test(uts, "zstd", compress_using_zstd, + uncompress_using_zstd); +} +LIB_TEST(compression_test_zstd, 0); + +static int compress_using_none(struct unit_test_state *uts, + void *in, unsigned long in_size, + void *out, unsigned long out_max, + unsigned long *out_size) +{ + /* Here we just copy */ + memcpy(out, in, in_size); + *out_size = in_size; + + return 0; +} + +/** + * run_bootm_test() - Run tests on the bootm decompression function + * + * @comp_type: Compression type to test + * @compress: Our function to compress data + * Return: 0 if OK, non-zero on failure + */ +static int run_bootm_test(struct unit_test_state *uts, int comp_type, + mutate_func compress) +{ + ulong compress_size = 1024; + void *compress_buff; + int unc_len; + int err = 0; + const ulong image_start = 0; + const ulong load_addr = 0x1000; + ulong load_end; + + printf("Testing: %s\n", genimg_get_comp_name(comp_type)); + compress_buff = map_sysmem(image_start, 0); + unc_len = strlen(plain); + compress(uts, (void *)plain, unc_len, compress_buff, compress_size, + &compress_size); + err = image_decomp(comp_type, load_addr, image_start, + IH_TYPE_KERNEL, map_sysmem(load_addr, 0), + compress_buff, compress_size, unc_len, + &load_end); + ut_assertok(err); + err = image_decomp(comp_type, load_addr, image_start, + IH_TYPE_KERNEL, map_sysmem(load_addr, 0), + compress_buff, compress_size, unc_len - 1, + &load_end); + ut_assert(err); + + /* We can't detect corruption when not decompressing */ + if (comp_type == IH_COMP_NONE) + return 0; + memset(compress_buff + compress_size / 2, '\x49', + compress_size / 2); + err = image_decomp(comp_type, load_addr, image_start, + IH_TYPE_KERNEL, map_sysmem(load_addr, 0), + compress_buff, compress_size, 0x10000, + &load_end); + ut_assert(err); + + return 0; +} + +static int compression_test_bootm_gzip(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_GZIP, compress_using_gzip); +} +LIB_TEST(compression_test_bootm_gzip, 0); + +static int compression_test_bootm_bzip2(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_BZIP2, compress_using_bzip2); +} +LIB_TEST(compression_test_bootm_bzip2, 0); + +static int compression_test_bootm_lzma(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_LZMA, compress_using_lzma); +} +LIB_TEST(compression_test_bootm_lzma, 0); + +static int compression_test_bootm_lzo(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_LZO, compress_using_lzo); +} +LIB_TEST(compression_test_bootm_lzo, 0); + +static int compression_test_bootm_lz4(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_LZ4, compress_using_lz4); +} +LIB_TEST(compression_test_bootm_lz4, 0); + +static int compression_test_bootm_zstd(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_ZSTD, compress_using_zstd); +} +LIB_TEST(compression_test_bootm_zstd, 0); + +static int compression_test_bootm_none(struct unit_test_state *uts) +{ + return run_bootm_test(uts, IH_COMP_NONE, compress_using_none); +} +LIB_TEST(compression_test_bootm_none, 0); diff --git a/test/lib/str.c b/test/lib/str.c new file mode 100644 index 00000000000..e62045318c0 --- /dev/null +++ b/test/lib/str.c @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 Google LLC + */ + +#include <vsprintf.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.h> + +/* This is large enough for any of the test strings */ +#define TEST_STR_SIZE 200 + +static const char str1[] = "I'm sorry I'm late."; +static const char str2[] = "1099abNo, don't bother apologising."; +static const char str3[] = "0xbI'm sorry you're alive."; +static const char str4[] = "1234567890123 I lost closer friends"; +static const char str5[] = "0x9876543210the last time I was deloused"; +static const char str6[] = "0778octal is seldom used"; +static const char str7[] = "707it is a piece of computing history"; +static const char str8[] = "0x887e2561352d80fa"; +static const char str9[] = "614FF7EAA63009DA"; + +static int str_upper(struct unit_test_state *uts) +{ + char out[TEST_STR_SIZE]; + + /* Make sure it adds a terminator */ + out[strlen(str1)] = 'a'; + str_to_upper(str1, out, SIZE_MAX); + ut_asserteq_str("I'M SORRY I'M LATE.", out); + + /* In-place operation */ + strcpy(out, str2); + str_to_upper(out, out, SIZE_MAX); + ut_asserteq_str("1099ABNO, DON'T BOTHER APOLOGISING.", out); + + /* Limited length */ + str_to_upper(str1, out, 7); + ut_asserteq_str("I'M SORO, DON'T BOTHER APOLOGISING.", out); + + /* In-place with limited length */ + strcpy(out, str2); + str_to_upper(out, out, 7); + ut_asserteq_str("1099ABNo, don't bother apologising.", out); + + /* Copy an empty string to a buffer with space*/ + out[1] = 0x7f; + str_to_upper("", out, SIZE_MAX); + ut_asserteq('\0', *out); + ut_asserteq(0x7f, out[1]); + + /* Copy an empty string to a buffer with no space*/ + out[0] = 0x7f; + str_to_upper("", out, 0); + ut_asserteq(0x7f, out[0]); + + return 0; +} +LIB_TEST(str_upper, 0); + +static int run_strtoul(struct unit_test_state *uts, const char *str, int base, + ulong expect_val, int expect_endp_offset, bool upper) +{ + char out[TEST_STR_SIZE]; + char *endp; + ulong val; + + strcpy(out, str); + if (upper) + str_to_upper(out, out, -1); + + val = simple_strtoul(out, &endp, base); + ut_asserteq(expect_val, val); + ut_asserteq(expect_endp_offset, endp - out); + + return 0; +} + +static int str_simple_strtoul(struct unit_test_state *uts) +{ + int upper; + + /* Check that it is case-insentive */ + for (upper = 0; upper < 2; upper++) { + /* Base 10 and base 16 */ + ut_assertok(run_strtoul(uts, str2, 10, 1099, 4, upper)); + ut_assertok(run_strtoul(uts, str2, 16, 0x1099ab, 6, upper)); + ut_assertok(run_strtoul(uts, str3, 16, 0xb, 3, upper)); + ut_assertok(run_strtoul(uts, str3, 10, 0xb, 3, upper)); + + /* Octal */ + ut_assertok(run_strtoul(uts, str6, 0, 63, 3, upper)); + ut_assertok(run_strtoul(uts, str7, 8, 0x1c7, 3, upper)); + + /* Invalid string */ + ut_assertok(run_strtoul(uts, str1, 10, 0, 0, upper)); + + /* Base 0 */ + ut_assertok(run_strtoul(uts, str1, 0, 0, 0, upper)); + ut_assertok(run_strtoul(uts, str2, 0, 1099, 4, upper)); + ut_assertok(run_strtoul(uts, str3, 0, 0xb, 3, upper)); + + /* Base 2 */ + ut_assertok(run_strtoul(uts, str1, 2, 0, 0, upper)); + ut_assertok(run_strtoul(uts, str2, 2, 2, 2, upper)); + } + + /* Check endp being NULL */ + ut_asserteq(1099, simple_strtoul(str2, NULL, 0)); + + return 0; +} +LIB_TEST(str_simple_strtoul, 0); + +static int run_strtoull(struct unit_test_state *uts, const char *str, int base, + unsigned long long expect_val, int expect_endp_offset, + bool upper) +{ + char out[TEST_STR_SIZE]; + char *endp; + unsigned long long val; + + strcpy(out, str); + if (upper) + str_to_upper(out, out, -1); + + val = simple_strtoull(out, &endp, base); + ut_asserteq(expect_val, val); + ut_asserteq(expect_endp_offset, endp - out); + + return 0; +} + +static int str_simple_strtoull(struct unit_test_state *uts) +{ + int upper; + + /* Check that it is case-insentive */ + for (upper = 0; upper < 2; upper++) { + /* Base 10 and base 16 */ + ut_assertok(run_strtoull(uts, str2, 10, 1099, 4, upper)); + ut_assertok(run_strtoull(uts, str2, 16, 0x1099ab, 6, upper)); + ut_assertok(run_strtoull(uts, str3, 16, 0xb, 3, upper)); + ut_assertok(run_strtoull(uts, str3, 10, 0xb, 3, upper)); + + /* Octal */ + ut_assertok(run_strtoull(uts, str6, 0, 63, 3, upper)); + ut_assertok(run_strtoull(uts, str7, 8, 0x1c7, 3, upper)); + + /* Large values */ + ut_assertok(run_strtoull(uts, str4, 10, 1234567890123, 13, + upper)); + ut_assertok(run_strtoull(uts, str4, 16, 0x1234567890123, 13, + upper)); + ut_assertok(run_strtoull(uts, str5, 0, 0x9876543210, 12, + upper)); + + /* Invalid string */ + ut_assertok(run_strtoull(uts, str1, 10, 0, 0, upper)); + + /* Base 0 */ + ut_assertok(run_strtoull(uts, str1, 0, 0, 0, upper)); + ut_assertok(run_strtoull(uts, str2, 0, 1099, 4, upper)); + ut_assertok(run_strtoull(uts, str3, 0, 0xb, 3, upper)); + + /* Base 2 */ + ut_assertok(run_strtoull(uts, str1, 2, 0, 0, upper)); + ut_assertok(run_strtoull(uts, str2, 2, 2, 2, upper)); + } + + /* Check endp being NULL */ + ut_asserteq(1099, simple_strtoull(str2, NULL, 0)); + + return 0; +} +LIB_TEST(str_simple_strtoull, 0); + +static int str_hextoul(struct unit_test_state *uts) +{ + char *endp; + + /* Just a simple test, since we know this uses simple_strtoul() */ + ut_asserteq(0x1099ab, hextoul(str2, &endp)); + ut_asserteq(6, endp - str2); + + return 0; +} +LIB_TEST(str_hextoul, 0); + +static int str_hextoull(struct unit_test_state *uts) +{ + char *endp; + + /* Just a simple test, since we know this uses simple_strtoull() */ + ut_asserteq_64(0x887e2561352d80faULL, hextoull(str8, &endp)); + ut_asserteq_64(0x12, endp - str8); + ut_asserteq_64(0x614ff7eaa63009daULL, hextoull(str9, &endp)); + ut_asserteq_64(0x10, endp - str9); + ut_asserteq_64(0x887e2561352d80faULL, hextoull(str8, NULL)); + ut_asserteq_64(0x614ff7eaa63009daULL, hextoull(str9, NULL)); + + return 0; +} +LIB_TEST(str_hextoull, 0); + +static int str_dectoul(struct unit_test_state *uts) +{ + char *endp; + + /* Just a simple test, since we know this uses simple_strtoul() */ + ut_asserteq(1099, dectoul(str2, &endp)); + ut_asserteq(4, endp - str2); + + return 0; +} +LIB_TEST(str_dectoul, 0); + +static int str_itoa(struct unit_test_state *uts) +{ + ut_asserteq_str("123", simple_itoa(123)); + ut_asserteq_str("0", simple_itoa(0)); + ut_asserteq_str("2147483647", simple_itoa(0x7fffffff)); + ut_asserteq_str("4294967295", simple_itoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("9223372036854775807", + simple_itoa((1UL << 63) - 1)); + ut_asserteq_str("18446744073709551615", simple_itoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +LIB_TEST(str_itoa, 0); + +static int str_xtoa(struct unit_test_state *uts) +{ + ut_asserteq_str("7f", simple_xtoa(127)); + ut_asserteq_str("00", simple_xtoa(0)); + ut_asserteq_str("7fffffff", simple_xtoa(0x7fffffff)); + ut_asserteq_str("ffffffff", simple_xtoa(0xffffffff)); + + /* Use #ifdef here to avoid a compiler warning on 32-bit machines */ +#ifdef CONFIG_PHYS_64BIT + if (sizeof(ulong) == 8) { + ut_asserteq_str("7fffffffffffffff", + simple_xtoa((1UL << 63) - 1)); + ut_asserteq_str("ffffffffffffffff", simple_xtoa(-1)); + } +#endif /* CONFIG_PHYS_64BIT */ + + return 0; +} +LIB_TEST(str_xtoa, 0); + +static int str_trailing(struct unit_test_state *uts) +{ + const char str1[] = "abc123def"; + const char str2[] = "abc123def456"; + const char *end; + + ut_asserteq(-1, trailing_strtol("")); + ut_asserteq(-1, trailing_strtol("123")); + ut_asserteq(123, trailing_strtol("abc123")); + ut_asserteq(4, trailing_strtol("12c4")); + ut_asserteq(-1, trailing_strtol("abd")); + ut_asserteq(-1, trailing_strtol("abc123def")); + + ut_asserteq(-1, trailing_strtoln(str1, NULL)); + ut_asserteq(123, trailing_strtoln(str1, str1 + 6)); + ut_asserteq(-1, trailing_strtoln(str1, str1 + 9)); + + ut_asserteq(3, trailing_strtol("a3")); + + ut_asserteq(123, trailing_strtoln_end(str1, str1 + 6, &end)); + ut_asserteq(3, end - str1); + + ut_asserteq(-1, trailing_strtoln_end(str1, str1 + 7, &end)); + ut_asserteq(7, end - str1); + + ut_asserteq(456, trailing_strtoln_end(str2, NULL, &end)); + ut_asserteq(9, end - str2); + + return 0; +} +LIB_TEST(str_trailing, 0); + +static int test_str_to_list(struct unit_test_state *uts) +{ + const char **ptr; + ulong start; + + /* check out of memory */ + start = ut_check_delta(0); + malloc_enable_testing(0); + ut_assertnull(str_to_list("")); + ut_assertok(ut_check_delta(start)); + + ut_assertnull(str_to_list("this is a test")); + ut_assertok(ut_check_delta(start)); + + malloc_enable_testing(1); + ut_assertnull(str_to_list("this is a test")); + ut_assertok(ut_check_delta(start)); + + /* for an empty string, only one nalloc is needed */ + malloc_enable_testing(1); + ptr = str_to_list(""); + ut_assertnonnull(ptr); + ut_assertnull(ptr[0]); + str_free_list(ptr); + ut_assertok(ut_check_delta(start)); + + malloc_disable_testing(); + + /* test the same again, without any nalloc restrictions */ + ptr = str_to_list(""); + ut_assertnonnull(ptr); + ut_assertnull(ptr[0]); + str_free_list(ptr); + ut_assertok(ut_check_delta(start)); + + /* test a single string */ + start = ut_check_delta(0); + ptr = str_to_list("hi"); + ut_assertnonnull(ptr); + ut_assertnonnull(ptr[0]); + ut_asserteq_str("hi", ptr[0]); + ut_assertnull(ptr[1]); + str_free_list(ptr); + ut_assertok(ut_check_delta(start)); + + /* test two strings */ + ptr = str_to_list("hi there"); + ut_assertnonnull(ptr); + ut_assertnonnull(ptr[0]); + ut_asserteq_str("hi", ptr[0]); + ut_assertnonnull(ptr[1]); + ut_asserteq_str("there", ptr[1]); + ut_assertnull(ptr[2]); + str_free_list(ptr); + ut_assertok(ut_check_delta(start)); + + /* test leading, trailing and multiple spaces */ + ptr = str_to_list(" more space "); + ut_assertnonnull(ptr); + ut_assertnonnull(ptr[0]); + ut_asserteq_str("", ptr[0]); + ut_assertnonnull(ptr[1]); + ut_asserteq_str("more", ptr[1]); + ut_assertnonnull(ptr[2]); + ut_asserteq_str("", ptr[2]); + ut_assertnonnull(ptr[3]); + ut_asserteq_str("space", ptr[3]); + ut_assertnonnull(ptr[4]); + ut_asserteq_str("", ptr[4]); + ut_assertnull(ptr[5]); + str_free_list(ptr); + ut_assertok(ut_check_delta(start)); + + /* test freeing a NULL pointer */ + str_free_list(NULL); + + return 0; +} +LIB_TEST(test_str_to_list, 0); diff --git a/test/lib/time.c b/test/lib/time.c new file mode 100644 index 00000000000..2095bef7589 --- /dev/null +++ b/test/lib/time.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2015 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <errno.h> +#include <time.h> +#include <linux/delay.h> +#include <test/lib.h> +#include <test/ut.h> + +static int test_get_timer(struct unit_test_state *uts) +{ + ulong base, start, next, diff; + int iter; + + base = get_timer(0); + start = get_timer(0); + for (iter = 0; iter < 10; iter++) { + do { + next = get_timer(0); + } while (start == next); + + if (start + 1 != next) { + printf("%s: iter=%d, start=%lu, next=%lu, expected a difference of 1\n", + __func__, iter, start, next); + return -EINVAL; + } + start++; + } + + /* + * Check that get_timer(base) matches our elapsed time, allowing that + * an extra millisecond may have passed. + */ + diff = get_timer(base); + if (diff != iter && diff != iter + 1) { + printf("%s: expected get_timer(base) to match elapsed time: diff=%lu, expected=%d\n", + __func__, diff, iter); + return -EINVAL; + } + + return 0; +} +LIB_TEST(test_get_timer, 0); + +static int test_timer_get_us(struct unit_test_state *uts) +{ + ulong prev, next, min = 1000000; + long delta; + int iter; + + /* Find the minimum delta we can measure, in microseconds */ + prev = timer_get_us(); + for (iter = 0; iter < 100; ) { + next = timer_get_us(); + if (next != prev) { + delta = next - prev; + if (delta < 0) { + printf("%s: timer_get_us() went backwards from %lu to %lu\n", + __func__, prev, next); + return -EINVAL; + } else if (delta != 0) { + if (delta < min) + min = delta; + prev = next; + iter++; + } + } + } + + if (min != 1) { + printf("%s: Minimum microsecond delta should be 1 but is %lu\n", + __func__, min); + return -EINVAL; + } + + return 0; +} +LIB_TEST(test_timer_get_us, 0); + +static int test_time_comparison(struct unit_test_state *uts) +{ + ulong start_us, end_us, delta_us; + long error; + ulong start; + + start = get_timer(0); + start_us = timer_get_us(); + while (get_timer(start) < 1000) + ; + end_us = timer_get_us(); + delta_us = end_us - start_us; + error = delta_us - 1000000; + printf("%s: Microsecond time for 1 second: %lu, error = %ld\n", + __func__, delta_us, error); + if (abs(error) > 1000) + return -EINVAL; + + return 0; +} +LIB_TEST(test_time_comparison, 0); + +static int test_udelay(struct unit_test_state *uts) +{ + long error; + ulong start, delta; + int iter; + + start = get_timer(0); + for (iter = 0; iter < 1000; iter++) + udelay(1000); + delta = get_timer(start); + error = delta - 1000; + printf("%s: Delay time for 1000 udelay(1000): %lu ms, error = %ld\n", + __func__, delta, error); + if (abs(error) > 100) + return -EINVAL; + + return 0; +} +LIB_TEST(test_udelay, 0); diff --git a/test/lib/unicode.c b/test/lib/unicode.c new file mode 100644 index 00000000000..673470c8d2c --- /dev/null +++ b/test/lib/unicode.c @@ -0,0 +1,846 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Unit tests for Unicode functions + * + * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> + */ + +#include <charset.h> +#include <command.h> +#include <efi_loader.h> +#include <errno.h> +#include <log.h> +#include <malloc.h> +#include <test/lib.h> +#include <test/test.h> +#include <test/ut.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}; + +/* 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}; +/* Letter not in code page 437 */ +static const char d5[] = {0xCE, 0x92, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, + 0x74, 0x20, 0x42, 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}; +static const char j4[] = {0xa1, 0x00}; + +static int unicode_test_u16_strlen(struct unit_test_state *uts) +{ + ut_asserteq(6, u16_strlen(c1)); + ut_asserteq(8, u16_strlen(c2)); + ut_asserteq(3, u16_strlen(c3)); + ut_asserteq(6, u16_strlen(c4)); + return 0; +} +LIB_TEST(unicode_test_u16_strlen, 0); + +static int unicode_test_u16_strnlen(struct unit_test_state *uts) +{ + ut_asserteq(0, u16_strnlen(c1, 0)); + ut_asserteq(4, u16_strnlen(c1, 4)); + ut_asserteq(6, u16_strnlen(c1, 6)); + ut_asserteq(6, u16_strnlen(c1, 7)); + + return 0; +} +LIB_TEST(unicode_test_u16_strnlen, 0); + +static int unicode_test_u16_strdup(struct unit_test_state *uts) +{ + u16 *copy = u16_strdup(c4); + + ut_assert(copy != c4); + ut_asserteq_mem(copy, c4, sizeof(c4)); + free(copy); + + return 0; +} +LIB_TEST(unicode_test_u16_strdup, 0); + +static int unicode_test_u16_strcpy(struct unit_test_state *uts) +{ + u16 *r; + u16 copy[10]; + + r = u16_strcpy(copy, c1); + ut_assert(r == copy); + ut_asserteq_mem(copy, c1, sizeof(c1)); + + return 0; +} +LIB_TEST(unicode_test_u16_strcpy, 0); + +/* U-Boot uses UTF-16 strings in the EFI context only. */ +#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) +static int unicode_test_string16(struct unit_test_state *uts) +{ + char buf[20]; + int ret; + + /* 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); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 4, "%ls", c1); + ut_asserteq(6, ret); + ut_asserteq_str("U-B", buf); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 6, "%ls", c2); + ut_asserteq_str("kafb", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 7, "%ls", c2); + ut_asserteq_str("kafb\xC3\xA1", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 8, "%ls", c3); + ut_asserteq_str("\xE6\xBD\x9C\xE6\xB0\xB4", buf); + ut_asserteq(9, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 11, "%ls", c4); + ut_asserteq_str("\xF0\x90\x92\x8D\xF0\x90\x92\x96", buf); + ut_asserteq(12, ret); + + memset(buf, 0xff, sizeof(buf)); + ret = snprintf(buf, 4, "%ls", c4); + ut_asserteq_str("", buf); + ut_asserteq(12, ret); + + return 0; +} +LIB_TEST(unicode_test_string16, 0); +#endif + +static int unicode_test_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); + + /* Check illegal character */ + s = j4; + code = utf8_get((const char **)&s); + ut_asserteq(-1, code); + ut_asserteq_ptr(j4 + 1, s); + + return 0; +} +LIB_TEST(unicode_test_utf8_get, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf8_put, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf8_utf16_strlen, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf8_utf16_strnlen, 0); + +/** + * 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 unicode_test_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 unicode_test_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(!unicode_test_u16_strcmp(buf, c1, SIZE_MAX)); + + pos = buf; + utf8_utf16_strcpy(&pos, d2); + ut_asserteq(8, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, c2, SIZE_MAX)); + + pos = buf; + utf8_utf16_strcpy(&pos, d3); + ut_asserteq(3, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, c3, SIZE_MAX)); + + pos = buf; + utf8_utf16_strcpy(&pos, d4); + ut_asserteq(6, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX)); + + /* Illegal utf-8 strings */ + pos = buf; + utf8_utf16_strcpy(&pos, j1); + ut_asserteq(4, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, u"j1?l", SIZE_MAX)); + + pos = buf; + utf8_utf16_strcpy(&pos, j2); + ut_asserteq(4, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, u"j2?l", SIZE_MAX)); + + pos = buf; + utf8_utf16_strcpy(&pos, j3); + ut_asserteq(3, pos - buf); + ut_assert(!unicode_test_u16_strcmp(buf, u"j3?", SIZE_MAX)); + + return 0; +} +LIB_TEST(unicode_test_utf8_utf16_strcpy, 0); + +static int unicode_test_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(!unicode_test_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(!unicode_test_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(!unicode_test_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(!unicode_test_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(!unicode_test_u16_strcmp(buf, c4, SIZE_MAX)); + + return 0; +} +LIB_TEST(unicode_test_utf8_utf16_strncpy, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_get, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_put, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_strnlen, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_utf8_strlen, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_utf8_strnlen, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_utf8_strcpy, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf16_utf8_strncpy, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf_to_lower, 0); + +static int unicode_test_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; +} +LIB_TEST(unicode_test_utf_to_upper, 0); + +static int unicode_test_u16_strcasecmp(struct unit_test_state *uts) +{ + ut_assert(u16_strcasecmp(u"abcd", u"abcd") == 0); + ut_assert(u16_strcasecmp(u"aBcd", u"abcd") == 0); + ut_assert(u16_strcasecmp(u"abcd", u"abCd") == 0); + ut_assert(u16_strcasecmp(u"abcdE", u"abcd") > 0); + ut_assert(u16_strcasecmp(u"abcd", u"abcdE") < 0); + ut_assert(u16_strcasecmp(u"abcE", u"abcd") > 0); + ut_assert(u16_strcasecmp(u"abcd", u"abcE") < 0); + ut_assert(u16_strcasecmp(u"abcd", u"abcd") == 0); + ut_assert(u16_strcasecmp(u"abcd", u"abcd") == 0); + if (CONFIG_IS_ENABLED(EFI_UNICODE_CAPITALIZATION)) { + /* Cyrillic letters */ + ut_assert(u16_strcasecmp(u"\x043a\x043d\x0438\x0433\x0430", + u"\x041a\x041d\x0418\x0413\x0410") == 0); + ut_assert(u16_strcasecmp(u"\x043a\x043d\x0438\x0433\x0430", + u"\x041a\x041d\x0418\x0413\x0411") < 0); + ut_assert(u16_strcasecmp(u"\x043a\x043d\x0438\x0433\x0431", + u"\x041a\x041d\x0418\x0413\x0410") > 0); + } + + return 0; +} +LIB_TEST(unicode_test_u16_strcasecmp, 0); + +static int unicode_test_u16_strncmp(struct unit_test_state *uts) +{ + ut_assert(u16_strncmp(u"abc", u"abc", 3) == 0); + ut_assert(u16_strncmp(u"abcdef", u"abcghi", 3) == 0); + ut_assert(u16_strncmp(u"abcdef", u"abcghi", 6) < 0); + ut_assert(u16_strncmp(u"abcghi", u"abcdef", 6) > 0); + ut_assert(u16_strcmp(u"abc", u"abc") == 0); + ut_assert(u16_strcmp(u"abcdef", u"deghi") < 0); + ut_assert(u16_strcmp(u"deghi", u"abcdef") > 0); + return 0; +} +LIB_TEST(unicode_test_u16_strncmp, 0); + +static int unicode_test_u16_strsize(struct unit_test_state *uts) +{ + ut_asserteq_64(u16_strsize(c1), 14); + ut_asserteq_64(u16_strsize(c2), 18); + ut_asserteq_64(u16_strsize(c3), 8); + ut_asserteq_64(u16_strsize(c4), 14); + return 0; +} +LIB_TEST(unicode_test_u16_strsize, 0); + +static int unicode_test_utf_to_cp(struct unit_test_state *uts) +{ + int ret; + s32 c; + + c = '\n'; + ret = utf_to_cp(&c, codepage_437); + ut_asserteq(0, ret); + ut_asserteq('\n', c); + + c = 'a'; + ret = utf_to_cp(&c, codepage_437); + ut_asserteq(0, ret); + ut_asserteq('a', c); + + c = 0x03c4; /* Greek small letter tau */ + ret = utf_to_cp(&c, codepage_437); + ut_asserteq(0, ret); + ut_asserteq(0xe7, c); + + c = 0x03a4; /* Greek capital letter tau */ + ret = utf_to_cp(&c, codepage_437); + ut_asserteq(-ENOENT, ret); + ut_asserteq('?', c); + + return 0; +} +LIB_TEST(unicode_test_utf_to_cp, 0); + +static void utf8_to_cp437_stream_helper(const char *in, char *out) +{ + char buffer[5]; + int ret; + + *buffer = 0; + for (; *in; ++in) { + ret = utf8_to_cp437_stream(*in, buffer); + if (ret) + *out++ = ret; + } + *out = 0; +} + +static int unicode_test_utf8_to_cp437_stream(struct unit_test_state *uts) +{ + char buf[16]; + + utf8_to_cp437_stream_helper(d1, buf); + ut_asserteq_str("U-Boot", buf); + utf8_to_cp437_stream_helper(d2, buf); + ut_asserteq_str("kafb\xa0tur", buf); + utf8_to_cp437_stream_helper(d5, buf); + ut_asserteq_str("? is not B", buf); + utf8_to_cp437_stream_helper(j2, buf); + ut_asserteq_str("j2l", buf); + + return 0; +} +LIB_TEST(unicode_test_utf8_to_cp437_stream, 0); + +static void utf8_to_utf32_stream_helper(const char *in, s32 *out) +{ + char buffer[5]; + int ret; + + *buffer = 0; + for (; *in; ++in) { + ret = utf8_to_utf32_stream(*in, buffer); + if (ret) + *out++ = ret; + } + *out = 0; +} + +static int unicode_test_utf8_to_utf32_stream(struct unit_test_state *uts) +{ + s32 buf[16]; + + const u32 u1[] = {0x55, 0x2D, 0x42, 0x6F, 0x6F, 0x74, 0x0000}; + const u32 u2[] = {0x6B, 0x61, 0x66, 0x62, 0xE1, 0x74, 0x75, 0x72, 0x00}; + const u32 u3[] = {0x6f5c, 0x6c34, 0x8266}; + const u32 u4[] = {0x6A, 0x32, 0x6C, 0x00}; + const u32 u5[] = {0x0392, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, + 0x20, 0x42, 0x00}; + + memset(buf, 0, sizeof(buf)); + utf8_to_utf32_stream_helper(d1, buf); + ut_asserteq_mem(u1, buf, sizeof(u1)); + + memset(buf, 0, sizeof(buf)); + utf8_to_utf32_stream_helper(d2, buf); + ut_asserteq_mem(u2, buf, sizeof(u2)); + + memset(buf, 0, sizeof(buf)); + utf8_to_utf32_stream_helper(d3, buf); + ut_asserteq_mem(u3, buf, sizeof(u3)); + + memset(buf, 0, sizeof(buf)); + utf8_to_utf32_stream_helper(d5, buf); + ut_asserteq_mem(u5, buf, sizeof(u5)); + + memset(buf, 0, sizeof(buf)); + utf8_to_utf32_stream_helper(j2, buf); + ut_asserteq_mem(u4, buf, sizeof(u4)); + + return 0; +} +LIB_TEST(unicode_test_utf8_to_utf32_stream, 0); + +#ifdef CONFIG_EFI_LOADER +static int unicode_test_efi_create_indexed_name(struct unit_test_state *uts) +{ + u16 buf[16]; + u16 const expected[] = u"Capsule0AF9"; + u16 *pos; + + memset(buf, 0xeb, sizeof(buf)); + pos = efi_create_indexed_name(buf, sizeof(buf), "Capsule", 0x0af9); + + ut_asserteq_mem(expected, buf, sizeof(expected)); + ut_asserteq(pos - buf, u16_strnlen(buf, SIZE_MAX)); + + return 0; +} +LIB_TEST(unicode_test_efi_create_indexed_name, 0); +#endif + +static int unicode_test_u16_strlcat(struct unit_test_state *uts) +{ + u16 buf[40]; + u16 dest[] = {0x3053, 0x3093, 0x306b, 0x3061, 0x306f, 0}; + u16 src[] = {0x03B1, 0x2172, 0x6F5C, 0x8247, 0}; + u16 concat_str[] = {0x3053, 0x3093, 0x306b, 0x3061, 0x306f, + 0x03B1, 0x2172, 0x6F5C, 0x8247, 0}; + u16 null_src = u'\0'; + size_t ret, expected; + int i; + + /* dest and src are empty string */ + memset(buf, 0, sizeof(buf)); + ret = u16_strlcat(buf, &null_src, ARRAY_SIZE(buf)); + ut_asserteq(0, ret); + + /* dest is empty string */ + memset(buf, 0, sizeof(buf)); + ret = u16_strlcat(buf, src, ARRAY_SIZE(buf)); + ut_asserteq(4, ret); + ut_assert(!unicode_test_u16_strcmp(buf, src, 40)); + + /* src is empty string */ + memset(buf, 0xCD, (sizeof(buf) - sizeof(u16))); + buf[39] = 0; + memcpy(buf, dest, sizeof(dest)); + ret = u16_strlcat(buf, &null_src, ARRAY_SIZE(buf)); + ut_asserteq(5, ret); + ut_assert(!unicode_test_u16_strcmp(buf, dest, 40)); + + for (i = 0; i <= 40; i++) { + memset(buf, 0xCD, (sizeof(buf) - sizeof(u16))); + buf[39] = 0; + memcpy(buf, dest, sizeof(dest)); + expected = min(5, i) + 4; + ret = u16_strlcat(buf, src, i); + ut_asserteq(expected, ret); + if (i <= 6) { + ut_assert(!unicode_test_u16_strcmp(buf, dest, 40)); + } else if (i < 10) { + ut_assert(!unicode_test_u16_strcmp(buf, concat_str, i - 1)); + } else { + ut_assert(!unicode_test_u16_strcmp(buf, concat_str, 40)); + } + } + + return 0; +} +LIB_TEST(unicode_test_u16_strlcat, 0); |