Implement mock RPMB backend
The backend uses CppUMock for enabling the testing of upper RPMB layers.
Signed-off-by: Imre Kis <imre.kis@arm.com>
Change-Id: I1289ffa335610a6558a6d133351b47005cb39b7d
diff --git a/components/service/rpmb/backend/mock/component.cmake b/components/service/rpmb/backend/mock/component.cmake
new file mode 100644
index 0000000..b75d6e3
--- /dev/null
+++ b/components/service/rpmb/backend/mock/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/rpmb_backend_mock.cpp"
+ )
diff --git a/components/service/rpmb/backend/mock/rpmb_backend_mock.cpp b/components/service/rpmb/backend/mock/rpmb_backend_mock.cpp
new file mode 100644
index 0000000..83bde95
--- /dev/null
+++ b/components/service/rpmb/backend/mock/rpmb_backend_mock.cpp
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTestExt/MockSupport.h>
+#include "rpmb_backend_mock.h"
+
+void rpmb_backend_mock_expect_get_dev_info(void *context, uint32_t dev_id,
+ const struct rpmb_dev_info *dev_info,
+ psa_status_t result)
+{
+ mock().expectOneCall("get_dev_info").
+ onObject(context).
+ withUnsignedIntParameter("dev_id", dev_id).
+ withOutputParameterReturning("dev_info", dev_info, sizeof(*dev_info)).
+ andReturnValue(result);
+}
+
+static psa_status_t rpmb_backend_mock_get_dev_info(void *context, uint32_t dev_id,
+ struct rpmb_dev_info *dev_info)
+{
+ return mock().actualCall("get_dev_info").
+ onObject(context).
+ withUnsignedIntParameter("dev_id", dev_id).
+ withOutputParameter("dev_info", dev_info).
+ returnIntValue();
+}
+
+void rpmb_backend_mock_expect_data_request(
+ void *context, uint32_t dev_id, const struct rpmb_data_frame *request_frames,
+ size_t request_frame_count, const struct rpmb_data_frame *response_frames,
+ size_t response_frame_count_in, size_t *response_frame_count_out, psa_status_t result)
+{
+ size_t request_size = sizeof(*request_frames) * request_frame_count;
+ size_t response_size = sizeof(*response_frames) * (*response_frame_count_out);
+
+ mock().expectOneCall("data_request").
+ onObject(context).
+ withUnsignedIntParameter("dev_id", dev_id).
+ withMemoryBufferParameter("request_frames", (const unsigned char *)request_frames,
+ request_size).
+ withUnsignedIntParameter("request_frame_count", request_frame_count).
+ withOutputParameterReturning("response_frames", response_frames, response_size).
+ withUnsignedIntParameter("response_frame_count_in", response_frame_count_in).
+ withOutputParameterReturning("response_frame_count_out", response_frame_count_out,
+ sizeof(*response_frame_count_out)).
+ andReturnValue(result);
+}
+
+static psa_status_t rpmb_backend_mock_data_request(
+ void *context, uint32_t dev_id, const struct rpmb_data_frame *request_frames,
+ size_t request_frame_count, struct rpmb_data_frame *response_frames,
+ size_t *response_frame_count)
+{
+ size_t request_size = sizeof(*request_frames) * request_frame_count;
+
+ return mock().actualCall("data_request").
+ onObject(context).
+ withUnsignedIntParameter("dev_id", dev_id).
+ withMemoryBufferParameter("request_frames", (const unsigned char *)request_frames,
+ request_size).
+ withUnsignedIntParameter("request_frame_count", request_frame_count).
+ withOutputParameter("response_frames", response_frames).
+ withUnsignedIntParameter("response_frame_count_in", *response_frame_count).
+ withOutputParameter("response_frame_count_out", response_frame_count).
+ returnIntValue();
+}
+
+struct rpmb_backend *rpmb_backend_mock_init(struct rpmb_backend_mock *context)
+{
+ static const struct rpmb_backend_interface interface = {
+ rpmb_backend_mock_get_dev_info,
+ rpmb_backend_mock_data_request,
+ };
+
+ if (!context)
+ return NULL;
+
+ context->backend.context = context;
+ context->backend.interface = &interface;
+
+ return &context->backend;
+}
+
+void rpmb_backend_mock_deinit(struct rpmb_backend_mock *context)
+{
+ *context = (struct rpmb_backend_mock){ 0 };
+}
diff --git a/components/service/rpmb/backend/mock/rpmb_backend_mock.h b/components/service/rpmb/backend/mock/rpmb_backend_mock.h
new file mode 100644
index 0000000..1268d42
--- /dev/null
+++ b/components/service/rpmb/backend/mock/rpmb_backend_mock.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPMB_BACKEND_MOCK_H_
+#define RPMB_BACKEND_MOCK_H_
+
+#include "../rpmb_backend.h"
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Mock RPMB backend
+ *
+ * Backend for testing purposes
+ */
+struct rpmb_backend_mock {
+ struct rpmb_backend backend;
+};
+
+struct rpmb_backend *rpmb_backend_mock_init(struct rpmb_backend_mock *context);
+void rpmb_backend_mock_deinit(struct rpmb_backend_mock *context);
+
+void rpmb_backend_mock_expect_get_dev_info(void *context, uint32_t dev_id,
+ const struct rpmb_dev_info *dev_info,
+ psa_status_t result);
+
+void rpmb_backend_mock_expect_data_request(
+ void *context, uint32_t dev_id, const struct rpmb_data_frame *request_frames,
+ size_t request_frame_count, const struct rpmb_data_frame *response_frames,
+ size_t response_frame_count_in, size_t *response_frame_count_out, psa_status_t result);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* RPMB_BACKEND_MOCK_H_ */
diff --git a/components/service/rpmb/backend/mock/test/component.cmake b/components/service/rpmb/backend/mock/test/component.cmake
new file mode 100644
index 0000000..86506bf
--- /dev/null
+++ b/components/service/rpmb/backend/mock/test/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/test_rpmb_backend_mock.cpp"
+ )
diff --git a/components/service/rpmb/backend/mock/test/test_rpmb_backend_mock.cpp b/components/service/rpmb/backend/mock/test/test_rpmb_backend_mock.cpp
new file mode 100644
index 0000000..594ba3c
--- /dev/null
+++ b/components/service/rpmb/backend/mock/test/test_rpmb_backend_mock.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <CppUTest/TestHarness.h>
+#include "../rpmb_backend_mock.h"
+#include <string.h>
+
+TEST_GROUP(rpmb_backend_mock) {
+ TEST_SETUP()
+ {
+ backend = rpmb_backend_mock_init(&mock_backend);
+ }
+
+ TEST_TEARDOWN()
+ {
+ rpmb_backend_mock_deinit(&mock_backend);
+ }
+
+ struct rpmb_backend *backend;
+ struct rpmb_backend_mock mock_backend;
+ const uint32_t dev_id = 1;
+};
+
+TEST(rpmb_backend_mock, get_dev_info)
+{
+ const struct rpmb_dev_info expected_dev_info = {
+ .cid = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f},
+ .rpmb_size_mult = 100
+ };
+ struct rpmb_dev_info dev_info = { 0 };
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+
+ rpmb_backend_mock_expect_get_dev_info(backend, dev_id, &expected_dev_info, PSA_SUCCESS);
+
+ status = rpmb_backend_get_dev_info(backend, dev_id, &dev_info);
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ MEMCMP_EQUAL(&expected_dev_info, &dev_info, sizeof(expected_dev_info));
+}
+
+TEST(rpmb_backend_mock, data_request)
+{
+ struct rpmb_data_frame request_frames[2];
+ struct rpmb_data_frame expected_response_frames[3];
+ struct rpmb_data_frame response_frames[3] = { 0 };
+ size_t expected_response_frame_count = 3;
+ size_t response_frame_count = 4;
+ psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+
+ memset(request_frames, 0x11, sizeof(request_frames));
+ memset(expected_response_frames, 0x22, sizeof(response_frames));
+
+ rpmb_backend_mock_expect_data_request(backend, dev_id,
+ request_frames, 2,
+ expected_response_frames, 4, &expected_response_frame_count,
+ PSA_SUCCESS);
+
+ status = rpmb_backend_data_request(backend, dev_id, request_frames, 2,
+ response_frames, &response_frame_count);
+ LONGS_EQUAL(PSA_SUCCESS, status);
+ UNSIGNED_LONGS_EQUAL(expected_response_frame_count, response_frame_count);
+ MEMCMP_EQUAL(&expected_response_frames, &response_frames, sizeof(expected_response_frames));
+}
\ No newline at end of file