Testing object_pool

Add unit tests for object_pool functions. It need a C wrapper because
the macros for creating pool do not work when compiling in C++. The
declaration and initialization order of structure members must be the
same in C++ while this is not a requirement in C.

Change-Id: Id06bcd39cabfcbb57584c8ef7f8a118e3226c3c2
Signed-off-by: Imre Kis <imre.kis@arm.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bcfb234..3ad62d2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2019, Arm Limited. All rights reserved.
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -112,3 +112,4 @@
 include_directories(${CMAKE_CURRENT_LIST_DIR}/include)
 
 include(tests/lib/libc/test_libc.cmake)
+include(tests/lib/object_pool/test_object_pool.cmake)
diff --git a/tests/lib/object_pool/object_pool_allocator_wrapper.c b/tests/lib/object_pool/object_pool_allocator_wrapper.c
new file mode 100644
index 0000000..1a7fc6d
--- /dev/null
+++ b/tests/lib/object_pool/object_pool_allocator_wrapper.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "object_pool_allocator_wrapper.h"
+#include "lib/object_pool.h"
+#include <string.h>
+
+uint32_t array[POOL_SIZE];
+
+void object_pool_allocate(struct object_pool *pool) {
+	OBJECT_POOL_ARRAY(local_pool, array);
+	memcpy(pool, &local_pool, sizeof(*pool));
+}
diff --git a/tests/lib/object_pool/object_pool_allocator_wrapper.h b/tests/lib/object_pool/object_pool_allocator_wrapper.h
new file mode 100644
index 0000000..e6953e7
--- /dev/null
+++ b/tests/lib/object_pool/object_pool_allocator_wrapper.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "lib/object_pool.h"
+
+#define POOL_SIZE (16)
+extern uint32_t array[POOL_SIZE];
+void object_pool_allocate(struct object_pool *pool);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/tests/lib/object_pool/test_object_pool.cmake b/tests/lib/object_pool/test_object_pool.cmake
new file mode 100644
index 0000000..d3ef9a5
--- /dev/null
+++ b/tests/lib/object_pool/test_object_pool.cmake
@@ -0,0 +1,21 @@
+#
+# Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include(UnitTest)
+
+unit_test_add_suite(
+	NAME object_pool
+	SOURCES
+		${CMAKE_CURRENT_LIST_DIR}/test_object_pool.cpp
+		${CMAKE_CURRENT_LIST_DIR}/object_pool_allocator_wrapper.c
+		${TF_A_UNIT_TESTS_PATH}/mocks/common/debug.cpp
+	INCLUDE_DIRECTORIES
+		${TF_A_UNIT_TESTS_PATH}/mocks/include/
+		${TF_A_UNIT_TESTS_PATH}/mocks/include/lib/libc/
+		${TF_A_PATH}/include
+	COMPILE_DEFINITIONS
+		LOG_LEVEL=50
+)
diff --git a/tests/lib/object_pool/test_object_pool.cpp b/tests/lib/object_pool/test_object_pool.cpp
new file mode 100644
index 0000000..603fc94
--- /dev/null
+++ b/tests/lib/object_pool/test_object_pool.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+extern "C" {
+#include "lib/object_pool.h"
+}
+#include "object_pool_allocator_wrapper.h"
+#include "common/mock_debug.h"
+#include "CppUTest/TestHarness.h"
+#include "CppUTestExt/MockSupport.h"
+#include <string.h>
+
+#define POOL_TEST_VALUE0	(0x01234567)
+#define POOL_TEST_VALUE1	(0xf0123456)
+
+TEST_GROUP(object_pool) {
+	TEST_SETUP() {
+		memset(array, 0x00, sizeof(array));
+		object_pool_allocate(&pool); // Invoking C wrapper
+	}
+
+	TEST_TEARDOWN() {
+		mock().checkExpectations();
+		mock().clear();
+	}
+
+	void check_remaining_fields(size_t start) {
+		for (size_t i = start; i < POOL_SIZE; i++) {
+			UNSIGNED_LONGS_EQUAL(0, array[i]);
+		}
+	}
+
+	struct object_pool pool = {0};
+};
+
+TEST(object_pool, allocate_one) {
+	uint32_t *first = (uint32_t *)pool_alloc(&pool);
+	*first = POOL_TEST_VALUE0;
+
+	UNSIGNED_LONGS_EQUAL(POOL_TEST_VALUE0, array[0]);
+	check_remaining_fields(1);
+}
+
+TEST(object_pool, allocate_two) {
+	uint32_t *first = (uint32_t *)pool_alloc(&pool);
+	*first = POOL_TEST_VALUE0;
+
+	uint32_t *second = (uint32_t *)pool_alloc(&pool);
+	*second = POOL_TEST_VALUE1;
+
+	UNSIGNED_LONGS_EQUAL(POOL_TEST_VALUE0, array[0]);
+	UNSIGNED_LONGS_EQUAL(POOL_TEST_VALUE1, array[1]);
+	check_remaining_fields(2);
+}
+
+TEST(object_pool, allocate_two_at_once) {
+	uint32_t *items = (uint32_t *)pool_alloc_n(&pool, 2);
+	items[0] = POOL_TEST_VALUE0;
+	items[1] = POOL_TEST_VALUE1;
+
+	UNSIGNED_LONGS_EQUAL(POOL_TEST_VALUE0, array[0]);
+	UNSIGNED_LONGS_EQUAL(POOL_TEST_VALUE1, array[1]);
+	check_remaining_fields(2);
+}
+
+TEST(object_pool, allocate_one_then_overflow) {
+	panic_environment_t env;
+
+	uint32_t *first = (uint32_t*) pool_alloc(&pool);
+	*first = POOL_TEST_VALUE0;
+
+	if (SETUP_PANIC_ENVIRONMENT(env)) {
+		expect_tf_log(
+				"Cannot allocate 16 objects out of pool (15 objects left).\n");
+		pool_alloc_n(&pool, POOL_SIZE);
+	}
+}
+
+TEST(object_pool, overflow) {
+	panic_environment_t env;
+
+	if (SETUP_PANIC_ENVIRONMENT(env)) {
+		expect_tf_log("Cannot allocate 17 objects out of pool (16 objects left).\n");
+		pool_alloc_n(&pool, POOL_SIZE + 1);
+	}
+}