Initial commit
Change-Id: I26f6fdfd4962e2c724bf6b68893156f11d37d4b1
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
new file mode 100644
index 0000000..fb07b9c
--- /dev/null
+++ b/test/CMakeLists.txt
@@ -0,0 +1,18 @@
+#
+# Copyright (c) 2024, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+file(GLOB TEST_SOURCES "*.c")
+
+foreach(src IN ITEMS ${TEST_SOURCES})
+ get_filename_component(suite_name ${src} NAME_WE)
+ add_executable(${suite_name} ${src})
+
+ target_link_libraries(${suite_name} unity tl)
+ add_test(${suite_name} ${suite_name})
+endforeach()
+
+enable_testing()
diff --git a/test/entry_manipulation.c b/test/entry_manipulation.c
new file mode 100644
index 0000000..72088bb
--- /dev/null
+++ b/test/entry_manipulation.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright The Transfer List Library Contributors
+ *
+ * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+#include "transfer_list.h"
+#include "unity.h"
+
+void *buffer = NULL;
+
+uint8_t byte_sum(const char *ptr, size_t len)
+{
+ uint8_t sum;
+
+ for (size_t i = 0; i < len; i++) {
+ sum += ptr[i];
+ }
+
+ return sum;
+}
+
+void test_add()
+{
+ struct transfer_list_header *tl;
+ struct transfer_list_entry *te;
+
+ TEST_ASSERT(tl = transfer_list_init((void *)buffer, TL_SIZE));
+
+ TEST_ASSERT(te = transfer_list_add(tl, test_tag, sizeof(test_data),
+ &test_data));
+ TEST_ASSERT_EQUAL(0, byte_sum((char *)tl, tl->max_size));
+ TEST_ASSERT(*(int *)transfer_list_entry_data(te) == test_data);
+
+ /* Try to add a TE larger greater than allocated TL space */
+ TEST_ASSERT_NULL(te = transfer_list_add(tl, 2, TL_SIZE, &test_data));
+ TEST_ASSERT_EQUAL(0, byte_sum((char *)tl, tl->max_size));
+ TEST_ASSERT_NULL(transfer_list_find(tl, 0x2));
+
+ unsigned int tags[4] = { TAG_GENERIC_START, TAG_GENERIC_END,
+ TAG_NON_STANDARD_START, TAG_NON_STANDARD_END };
+
+ for (size_t i = 0; i < 4; i++) {
+ TEST_ASSERT(te = transfer_list_add(tl, tags[i],
+ sizeof(test_data),
+ &test_data));
+ TEST_ASSERT_EQUAL(0, byte_sum((char *)tl, tl->max_size));
+ TEST_ASSERT(te = transfer_list_find(tl, tags[i]));
+ TEST_ASSERT(*(int *)transfer_list_entry_data(te) == test_data);
+ }
+
+ transfer_list_dump(tl);
+ /* Add some out of bound tags. */
+ TEST_ASSERT_NULL(
+ transfer_list_add(tl, 1 << 24, sizeof(test_data), &test_data));
+
+ TEST_ASSERT_NULL(
+ transfer_list_add(tl, -1, sizeof(test_data), &test_data));
+}
+
+void test_add_with_align()
+{
+ struct transfer_list_header *tl =
+ transfer_list_init(buffer, TL_MAX_SIZE);
+ struct transfer_list_entry *te;
+
+ unsigned int test_id = 1;
+ const unsigned int entry_size = 0xff;
+ int *data;
+
+ TEST_ASSERT(tl->size == tl->hdr_size);
+
+ /*
+ * When a new TE with a larger alignment requirement than already exists
+ * appears, the TE should be added and TL alignement updated.
+ */
+ for (char align = 0; align < (1 << 4); align++, test_id++) {
+ TEST_ASSERT(
+ te = transfer_list_add_with_align(
+ tl, test_id, entry_size, &test_data, align));
+ TEST_ASSERT(tl->alignment >= align);
+ TEST_ASSERT(te = transfer_list_find(tl, test_id));
+ TEST_ASSERT(data = transfer_list_entry_data(te));
+ TEST_ASSERT_FALSE((uintptr_t)data % (1 << align));
+ TEST_ASSERT_EQUAL(*(int *)data, test_data);
+ }
+}
+
+void test_rem()
+{
+ struct transfer_list_header *tl = transfer_list_init(buffer, TL_SIZE);
+ struct transfer_list_entry *te;
+
+ TEST_ASSERT_EQUAL(tl->size, tl->hdr_size);
+
+ /* Add a test TE, check the TL has been updated with its contents. */
+ TEST_ASSERT(
+ transfer_list_add(tl, test_tag, tl->max_size / 8, &test_data));
+ TEST_ASSERT(te = transfer_list_find(tl, test_tag));
+ TEST_ASSERT(byte_sum((void *)tl, tl->size) == 0);
+
+ /* Remove the TE and make sure it isn't present in the TL. */
+ TEST_ASSERT_TRUE(transfer_list_rem(tl, te));
+ TEST_ASSERT(byte_sum((void *)tl, tl->size) == 0);
+ TEST_ASSERT_NULL(transfer_list_find(tl, test_tag));
+}
+
+void setUp(void)
+{
+ buffer = malloc(TL_MAX_SIZE);
+}
+
+void tearDown(void)
+{
+ free(buffer);
+ buffer = NULL;
+}
+
+int main(void)
+{
+ UNITY_BEGIN();
+ RUN_TEST(test_add);
+ RUN_TEST(test_add_with_align);
+ return UNITY_END();
+}
diff --git a/test/test.h b/test/test.h
new file mode 100644
index 0000000..8ae4d3f
--- /dev/null
+++ b/test/test.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright The Transfer List Library Contributors
+ *
+ * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
+ */
+
+#if !defined(TEST_H)
+#define TEST_H
+
+#define TL_MAX_SIZE 0x10000
+#define TL_SIZE 0x1000
+
+enum {
+ TAG_GENERIC_START = 0,
+ TAG_GENERIC_END = 0x7fffff,
+ TAG_NON_STANDARD_START = 0xfff000,
+ TAG_NON_STANDARD_END = 0xffffff,
+ TAG_OUT_OF_BOUND = (1 << 24),
+};
+
+const unsigned int test_tag = 1;
+int test_data = 0xdeadbeef;
+
+#endif /* TEST_H */
diff --git a/test/transfer_list_setup.c b/test/transfer_list_setup.c
new file mode 100644
index 0000000..d2c6aec
--- /dev/null
+++ b/test/transfer_list_setup.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright The Transfer List Library Contributors
+ *
+ * SPDX-License-Identifier: MIT OR GPL-2.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "test.h"
+#include "transfer_list.h"
+#include "unity.h"
+
+void *buffer = NULL;
+
+void test_init()
+{
+ struct transfer_list_header *tl = buffer;
+
+ /* Attempt to init TL with 0 size */
+ TEST_ASSERT_NULL(transfer_list_init(tl, 0));
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_NON);
+
+ /* Init TL with an invalid memory address */
+ TEST_ASSERT_NULL(transfer_list_init((void *)1, TL_SIZE));
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_NON);
+
+ /* Valid memory address and large enough TL */
+ TEST_ASSERT(transfer_list_init(tl, TL_SIZE));
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_ALL);
+ TEST_ASSERT_NULL(transfer_list_next(tl, NULL));
+}
+
+void test_init_alignment()
+{
+ struct transfer_list_header *tl = buffer;
+ memset(tl, 0, TL_SIZE);
+
+ TEST_ASSERT_NULL(transfer_list_init((void *)tl + 0xff, TL_SIZE));
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_NON);
+}
+
+void test_relocate()
+{
+ struct transfer_list_header *tl, *new_tl;
+ struct transfer_list_entry *te;
+
+ void *new_buf = malloc(TL_SIZE * 2);
+ unsigned int test_tag = 0x1;
+ int test_payload = 0xdeadbeef;
+
+ tl = buffer;
+ memset(tl, 0, TL_SIZE);
+
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_NON);
+
+ tl = transfer_list_init(tl, TL_SIZE / 2);
+
+ // Add TE's until we run out of space
+ while ((te = transfer_list_add(tl, test_tag, tl->max_size / 8,
+ &test_payload))) {
+ TEST_ASSERT(te = transfer_list_find(tl, test_tag++));
+ TEST_ASSERT(*(int *)transfer_list_entry_data(te) ==
+ test_payload++);
+ }
+
+ // Relocate the TL and make sure all the information we put in is still there.
+ TEST_ASSERT(
+ new_tl = transfer_list_relocate(tl, new_buf, tl->max_size * 2));
+ TEST_ASSERT(transfer_list_check_header(new_tl) == TL_OPS_ALL);
+
+ unsigned int i = test_tag;
+ while ((te = transfer_list_find(tl, --i))) {
+ int *data = transfer_list_entry_data(te);
+ TEST_ASSERT_NOT_NULL(data);
+ TEST_ASSERT(*data == --test_payload);
+ }
+
+ // Add the last TE we failed to add into the relocated TL.
+ TEST_ASSERT(te = transfer_list_add(new_tl, test_tag, TL_SIZE / 8,
+ &test_payload));
+ TEST_ASSERT(*(int *)transfer_list_find(new_tl, test_tag) =
+ ++test_payload);
+}
+
+void test_bad_reloc()
+{
+ struct transfer_list_header *tl = transfer_list_init(buffer, TL_SIZE);
+ void *new_buf = malloc(TL_SIZE);
+
+ /* Relocate to invalid memory address. */
+ TEST_ASSERT_NULL(transfer_list_relocate(tl, 0, tl->max_size));
+
+ /*
+ * Try relocate to area with insufficent memory, check at the end that we
+ * still have a valid TL in the original location.
+ */
+ TEST_ASSERT_NULL(transfer_list_relocate(tl, new_buf, 0));
+ TEST_ASSERT(transfer_list_check_header(tl) == TL_OPS_ALL);
+}
+
+void setUp(void)
+{
+ buffer = malloc(TL_MAX_SIZE);
+}
+
+void tearDown(void)
+{
+ free(buffer);
+ buffer = NULL;
+}
+
+int main(void)
+{
+ UNITY_BEGIN();
+ RUN_TEST(test_bad_reloc);
+ RUN_TEST(test_init_alignment);
+ RUN_TEST(test_init);
+ RUN_TEST(test_relocate);
+ return UNITY_END();
+}