summaryrefslogtreecommitdiff
path: root/tests/lib
diff options
context:
space:
mode:
authorJakub Czapiga <jacz@semihalf.com>2021-02-19 10:09:42 +0100
committerPatrick Georgi <pgeorgi@google.com>2021-03-01 08:31:11 +0000
commitf5e636ccdb6b7f9cbbdf185298b9de11b733b5f2 (patch)
tree33ad97023a2c48e9c18bc01e0d54e912ad369454 /tests/lib
parent3f7bb7dc4457f0513fcdbc6e8760d94ea063367a (diff)
tests: Add lib/memmove-test test case
Signed-off-by: Jakub Czapiga <jacz@semihalf.com> Change-Id: Ic9b68eb0fa85bbc3f66d57cdcb329073b26bea57 Reviewed-on: https://review.coreboot.org/c/coreboot/+/50902 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Paul Fagerburg <pfagerburg@chromium.org>
Diffstat (limited to 'tests/lib')
-rw-r--r--tests/lib/Makefile.inc3
-rw-r--r--tests/lib/memmove-test.c250
2 files changed, 253 insertions, 0 deletions
diff --git a/tests/lib/Makefile.inc b/tests/lib/Makefile.inc
index d31608c3d0..0f978e7d1d 100644
--- a/tests/lib/Makefile.inc
+++ b/tests/lib/Makefile.inc
@@ -19,6 +19,7 @@ tests-y += memcmp-test
tests-y += memchr-test
tests-y += memcpy-test
tests-y += malloc-test
+tests-y += memmove-test
string-test-srcs += tests/lib/string-test.c
string-test-srcs += src/lib/string.c
@@ -95,3 +96,5 @@ memcpy-test-srcs += tests/lib/memcpy-test.c
malloc-test-srcs += tests/lib/malloc-test.c
malloc-test-srcs += tests/stubs/console.c
+memmove-test-srcs += tests/lib/memmove-test.c
+
diff --git a/tests/lib/memmove-test.c b/tests/lib/memmove-test.c
new file mode 100644
index 0000000000..a1d33cf445
--- /dev/null
+++ b/tests/lib/memmove-test.c
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define memmove cb_memmove
+#include "../lib/memmove.c"
+#undef memmove
+
+#include <stdlib.h>
+#include <tests/test.h>
+#include <commonlib/helpers.h>
+#include <types.h>
+
+#define MEMMOVE_BUFFER_SZ (4 * KiB)
+
+/* Prototype of memmove() from string.h was changed to cb_memmove().
+ It has to be defined again. */
+void *memmove(void *dst, const void *src, size_t n);
+
+struct test_memmove_data {
+ u8 *buffer_from;
+ u8 *buffer_to;
+ u8 *helper_buffer;
+};
+
+int setup_test(void **state)
+{
+ struct test_memmove_data *s = malloc(sizeof(struct test_memmove_data));
+
+ if (!s)
+ return -1;
+
+ s->buffer_from = malloc(MEMMOVE_BUFFER_SZ);
+ s->buffer_to = malloc(MEMMOVE_BUFFER_SZ);
+ s->helper_buffer = malloc(MEMMOVE_BUFFER_SZ);
+
+ if (!s->buffer_from || !s->buffer_to || !s->helper_buffer) {
+ free(s->buffer_from);
+ free(s->buffer_to);
+ free(s->helper_buffer);
+ free(s);
+ return -1;
+ }
+
+ /* Fill buffers with different values (other than zero) to make them distinguishable.
+ The helper buffer is often used as a backup of destination buffer so it has the
+ same value. */
+ memset(s->buffer_from, 0xAB, MEMMOVE_BUFFER_SZ);
+ memset(s->buffer_to, 0xBC, MEMMOVE_BUFFER_SZ);
+ memset(s->helper_buffer, 0xBC, MEMMOVE_BUFFER_SZ);
+
+ *state = s;
+
+ return 0;
+}
+
+int teardown_test(void **state)
+{
+ struct test_memmove_data *s = *state;
+
+ free(s->buffer_from);
+ free(s->buffer_to);
+ free(s->helper_buffer);
+ free(s);
+
+ return 0;
+}
+
+/* Fill buffer with values from provided range [start; end] in circular way. */
+static void fill_buffer_data_range(u8 *buffer, size_t sz, u8 start_value, u8 end_value)
+{
+ for (size_t i = 0; i < sz; ++i)
+ buffer[i] = (start_value + i) % (end_value - start_value + 1);
+}
+
+static void test_memmove_full_buffer_copy(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+
+ fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0, 255);
+
+ res_cb = cb_memmove(s->buffer_to, s->buffer_from, MEMMOVE_BUFFER_SZ);
+
+ assert_ptr_equal(s->buffer_to, res_cb);
+ assert_memory_equal(s->buffer_from, s->buffer_to, MEMMOVE_BUFFER_SZ);
+}
+
+static void test_memmove_zero_size(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+
+ fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 'A', 'Z');
+
+ /* Expect no change in destination buffer. */
+ res_cb = cb_memmove(s->buffer_to, s->buffer_from, 0);
+ assert_ptr_equal(res_cb, s->buffer_to);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
+}
+
+static void test_memmove_buffer_part(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t offset = MEMMOVE_BUFFER_SZ / 4;
+ const size_t sz = MEMMOVE_BUFFER_SZ / 3;
+
+ /* Self-test for correct data ranges */
+ assert_true(offset + sz <= MEMMOVE_BUFFER_SZ);
+
+ fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, '0', '9');
+
+ /* Expect only *sz* bytes of buffer to be copied. Helper buffer is used as template. */
+ res_cb = cb_memmove(s->buffer_to + offset, s->buffer_from, sz);
+ assert_ptr_equal(s->buffer_to + offset, res_cb);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
+ assert_memory_equal(s->buffer_to + offset, s->buffer_from, sz);
+ assert_memory_equal(s->buffer_to + offset + sz, s->helper_buffer + offset + sz,
+ MEMMOVE_BUFFER_SZ - (offset + sz));
+}
+
+static void test_memmove_buffer_part_unaligned(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t dst_offset = MEMMOVE_BUFFER_SZ / 8 + 3;
+ const size_t src_offset = MEMMOVE_BUFFER_SZ / 4 - 3;
+ const size_t sz = MEMMOVE_BUFFER_SZ / 4 + 7;
+
+ /* Self-test for correct data ranges */
+ assert_true(dst_offset + sz <= MEMMOVE_BUFFER_SZ);
+ assert_true(src_offset + sz <= MEMMOVE_BUFFER_SZ);
+
+ fill_buffer_data_range(s->buffer_from, MEMMOVE_BUFFER_SZ, 0x13, 0xB7);
+
+ res_cb = cb_memmove(s->buffer_to + dst_offset, s->buffer_from + src_offset, sz);
+ assert_ptr_equal(s->buffer_to + dst_offset, res_cb);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, dst_offset);
+ assert_memory_equal(s->buffer_to + dst_offset, s->buffer_from + src_offset, sz);
+ assert_memory_equal(s->buffer_to + dst_offset + sz, s->helper_buffer + dst_offset + sz,
+ MEMMOVE_BUFFER_SZ - (dst_offset + sz));
+}
+
+static void test_memmove_copy_to_itself(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+
+ fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'G', 'X');
+ memmove(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
+
+ /* Expect no change in source/destination buffer. */
+ res_cb = cb_memmove(s->buffer_to, s->buffer_to, MEMMOVE_BUFFER_SZ);
+ assert_ptr_equal(res_cb, s->buffer_to);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, MEMMOVE_BUFFER_SZ);
+}
+
+static void test_memmove_self_higher_to_lower(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t offset = MEMMOVE_BUFFER_SZ / 8;
+ const size_t sz = MEMMOVE_BUFFER_SZ - offset;
+
+ fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
+ memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
+
+ /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
+ res_cb = cb_memmove(s->buffer_to, s->buffer_to + offset, sz);
+ assert_ptr_equal(res_cb, s->buffer_to);
+ assert_memory_equal(s->buffer_to, s->helper_buffer + offset, sz);
+ assert_memory_equal(s->buffer_to + sz, s->helper_buffer + sz, offset);
+}
+
+static void test_memmove_self_higher_to_lower_unaligned(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t offset = MEMMOVE_BUFFER_SZ / 6 + 7;
+ const size_t sz = MEMMOVE_BUFFER_SZ - offset;
+
+ fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
+ memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
+
+ /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
+ res_cb = cb_memmove(s->buffer_to, s->buffer_to + offset, sz);
+ assert_ptr_equal(res_cb, s->buffer_to);
+ assert_memory_equal(s->buffer_to, s->helper_buffer + offset, sz);
+ assert_memory_equal(s->buffer_to + sz, s->helper_buffer + sz, offset);
+}
+
+static void test_memmove_self_lower_to_higher(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t offset = MEMMOVE_BUFFER_SZ / 4;
+ const size_t sz = MEMMOVE_BUFFER_SZ - offset;
+
+ fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
+ memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
+
+ /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
+ res_cb = cb_memmove(s->buffer_to + offset, s->buffer_to, sz);
+ assert_ptr_equal(res_cb, s->buffer_to + offset);
+ assert_memory_equal(s->buffer_to + offset, s->helper_buffer, sz);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
+}
+
+static void test_memmove_self_lower_to_higher_unaligned(void **state)
+{
+ struct test_memmove_data *s = *state;
+ void *res_cb;
+ const size_t offset = MEMMOVE_BUFFER_SZ / 4 - 17;
+ const size_t sz = MEMMOVE_BUFFER_SZ - offset;
+
+ fill_buffer_data_range(s->buffer_to, MEMMOVE_BUFFER_SZ, 'd', 'v');
+ memmove(s->helper_buffer, s->buffer_to, MEMMOVE_BUFFER_SZ);
+
+ /* Expect only *sz* bytes to be overwritten and *offset* bytes to be left at the end. */
+ res_cb = cb_memmove(s->buffer_to + offset, s->buffer_to, sz);
+ assert_ptr_equal(res_cb, s->buffer_to + offset);
+ assert_memory_equal(s->buffer_to + offset, s->helper_buffer, sz);
+ assert_memory_equal(s->buffer_to, s->helper_buffer, offset);
+}
+
+int main(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test_setup_teardown(test_memmove_full_buffer_copy,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_zero_size,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_buffer_part,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_buffer_part_unaligned,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_copy_to_itself,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_self_higher_to_lower_unaligned,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher,
+ setup_test, teardown_test),
+ cmocka_unit_test_setup_teardown(test_memmove_self_lower_to_higher_unaligned,
+ setup_test, teardown_test),
+ };
+
+ return cmocka_run_group_tests(tests, NULL, NULL);
+}
+