1
0
mirror of https://xff.cz/git/u-boot/ synced 2025-09-30 06:51:28 +02:00

test: provide unit test for memory functions

Memory functions may have architecture specific implementations. These
should be tested.

Provide unit tests for memset(), memcpy(), memmove().

Provide a 'ut lib' sub-command to execute the tests.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Heinrich Schuchardt
2019-01-30 07:53:31 +01:00
committed by Tom Rini
parent eca61ae70c
commit 2dd0111adc
7 changed files with 245 additions and 0 deletions

14
include/test/lib.h Normal file
View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
*/
#ifndef __TEST_LIB_H__
#define __TEST_LIB_H__
#include <test/test.h>
/* Declare a new library function test */
#define LIB_TEST(_name, _flags) UNIT_TEST(_name, _flags, lib_test)
#endif /* __TEST_LIB_H__ */

View File

@@ -27,6 +27,7 @@ int do_ut_bloblist(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_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_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_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
int do_ut_lib(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_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_time(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[]); int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);

View File

@@ -6,6 +6,14 @@ menuconfig UNIT_TEST
This does not require sandbox to be included, but it is most This does not require sandbox to be included, but it is most
often used there. often used there.
config UT_LIB
bool "Unit tests for library functions"
depends on UNIT_TEST
default y
help
Enables the 'ut lib' command which tests library functions like
memcat(), memcyp(), memmove().
config UT_TIME config UT_TIME
bool "Unit tests for time functions" bool "Unit tests for time functions"
depends on UNIT_TEST depends on UNIT_TEST

View File

@@ -46,6 +46,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
#ifdef CONFIG_UT_OVERLAY #ifdef CONFIG_UT_OVERLAY
U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""), U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
#endif #endif
#ifdef CONFIG_UT_LIB
U_BOOT_CMD_MKENT(lib, CONFIG_SYS_MAXARGS, 1, do_ut_lib, "", ""),
#endif
#ifdef CONFIG_UT_TIME #ifdef CONFIG_UT_TIME
U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""), U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
#endif #endif
@@ -108,6 +111,9 @@ static char ut_help_text[] =
#ifdef CONFIG_UT_ENV #ifdef CONFIG_UT_ENV
"ut env [test-name]\n" "ut env [test-name]\n"
#endif #endif
#ifdef CONFIG_UT_LIB
"ut lib [test-name] - test library functions\n"
#endif
#ifdef CONFIG_UT_OVERLAY #ifdef CONFIG_UT_OVERLAY
"ut overlay [test-name]\n" "ut overlay [test-name]\n"
#endif #endif

View File

@@ -2,5 +2,7 @@
# #
# (C) Copyright 2018 # (C) Copyright 2018
# Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
obj-y += cmd_ut_lib.o
obj-y += hexdump.o obj-y += hexdump.o
obj-y += lmb.o obj-y += lmb.o
obj-y += string.o

20
test/lib/cmd_ut_lib.c Normal file
View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* Unit tests for library functions
*/
#include <common.h>
#include <command.h>
#include <test/lib.h>
#include <test/suites.h>
#include <test/ut.h>
int do_ut_lib(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct unit_test *tests = ll_entry_start(struct unit_test, lib_test);
const int n_ents = ll_entry_count(struct unit_test, lib_test);
return cmd_ut_category("lib", tests, n_ents, argc, argv);
}

194
test/lib/string.c Normal file
View File

@@ -0,0 +1,194 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
*
* Unit tests for memory functions
*
* The architecture dependent implementations run through different lines of
* code depending on the alignment and length of memory regions copied or set.
* This has to be considered in testing.
*/
#include <common.h>
#include <command.h>
#include <test/lib.h>
#include <test/test.h>
#include <test/ut.h>
/* Xor mask used for marking memory regions */
#define MASK 0xA5
/* Number of different alignment values */
#define SWEEP 16
/* Allow for copying up to 32 bytes */
#define BUFLEN (SWEEP + 33)
/**
* init_buffer() - initialize buffer
*
* The buffer is filled with incrementing values xor'ed with the mask.
*
* @buf: buffer
* @mask: xor mask
*/
static void init_buffer(u8 buf[], u8 mask)
{
int i;
for (i = 0; i < BUFLEN; ++i)
buf[i] = i ^ mask;
}
/**
* test_memset() - test result of memset()
*
* @uts: unit test state
* @buf: buffer
* @mask: value set by memset()
* @offset: relative start of region changed by memset() in buffer
* @len: length of region changed by memset()
* Return: 0 = success, 1 = failure
*/
static int test_memset(struct unit_test_state *uts, u8 buf[], u8 mask,
int offset, int len)
{
int i;
for (i = 0; i < BUFLEN; ++i) {
if (i < offset || i >= offset + len) {
ut_asserteq(i, buf[i]);
} else {
ut_asserteq(mask, buf[i]);
}
}
return 0;
}
/**
* lib_memset() - unit test for memset()
*
* Test memset() with varied alignment and length of the changed buffer.
*
* @uts: unit test state
* Return: 0 = success, 1 = failure
*/
static int lib_memset(struct unit_test_state *uts)
{
u8 buf[BUFLEN];
int offset, len;
void *ptr;
for (offset = 0; offset <= SWEEP; ++offset) {
for (len = 1; len < BUFLEN - SWEEP; ++len) {
init_buffer(buf, 0);
ptr = memset(buf + offset, MASK, len);
ut_asserteq_ptr(buf + offset, (u8 *)ptr);
if (test_memset(uts, buf, MASK, offset, len)) {
debug("%s: failure %d, %d\n",
__func__, offset, len);
return CMD_RET_FAILURE;
}
}
}
return 0;
}
LIB_TEST(lib_memset, 0);
/**
* test_memmove() - test result of memcpy() or memmove()
*
* @uts: unit test state
* @buf: buffer
* @mask: xor mask used to initialize source buffer
* @offset1: relative start of copied region in source buffer
* @offset2: relative start of copied region in destination buffer
* @len: length of region changed by memset()
* Return: 0 = success, 1 = failure
*/
static int test_memmove(struct unit_test_state *uts, u8 buf[], u8 mask,
int offset1, int offset2, int len)
{
int i;
for (i = 0; i < BUFLEN; ++i) {
if (i < offset2 || i >= offset2 + len) {
ut_asserteq(i, buf[i]);
} else {
ut_asserteq((i + offset1 - offset2) ^ mask, buf[i]);
}
}
return 0;
}
/**
* lib_memcpy() - unit test for memcpy()
*
* Test memcpy() with varied alignment and length of the copied buffer.
*
* @uts: unit test state
* Return: 0 = success, 1 = failure
*/
static int lib_memcpy(struct unit_test_state *uts)
{
u8 buf1[BUFLEN];
u8 buf2[BUFLEN];
int offset1, offset2, len;
void *ptr;
init_buffer(buf1, MASK);
for (offset1 = 0; offset1 <= SWEEP; ++offset1) {
for (offset2 = 0; offset2 <= SWEEP; ++offset2) {
for (len = 1; len < BUFLEN - SWEEP; ++len) {
init_buffer(buf2, 0);
ptr = memcpy(buf2 + offset2, buf1 + offset1,
len);
ut_asserteq_ptr(buf2 + offset2, (u8 *)ptr);
if (test_memmove(uts, buf2, MASK, offset1,
offset2, len)) {
debug("%s: failure %d, %d, %d\n",
__func__, offset1, offset2, len);
return CMD_RET_FAILURE;
}
}
}
}
return 0;
}
LIB_TEST(lib_memcpy, 0);
/**
* lib_memmove() - unit test for memmove()
*
* Test memmove() with varied alignment and length of the copied buffer.
*
* @uts: unit test state
* Return: 0 = success, 1 = failure
*/
static int lib_memmove(struct unit_test_state *uts)
{
u8 buf[BUFLEN];
int offset1, offset2, len;
void *ptr;
for (offset1 = 0; offset1 <= SWEEP; ++offset1) {
for (offset2 = 0; offset2 <= SWEEP; ++offset2) {
for (len = 1; len < BUFLEN - SWEEP; ++len) {
init_buffer(buf, 0);
ptr = memmove(buf + offset2, buf + offset1,
len);
ut_asserteq_ptr(buf + offset2, (u8 *)ptr);
if (test_memmove(uts, buf, 0, offset1, offset2,
len)) {
debug("%s: failure %d, %d, %d\n",
__func__, offset1, offset2, len);
return CMD_RET_FAILURE;
}
}
}
}
return 0;
}
LIB_TEST(lib_memmove, 0);