QCBOR: Add library test suite to regression test

QCBOR library has delivered together with a comprehensive
regression test suite. QCBOR library and its test suite has
integrated with TF-M regression test.

Change-Id: Ia2329abcd30132d8d842e78ebc9db7b162121ec3
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 11706de..e19051a 100755
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -160,7 +160,7 @@
 	set(VENEER_NAME ${_MY_PARAMS_VENEER_NAME}${_MY_PARAMS_POSTFIX}.o)
 
 	#Create linker target: add object library to executable
-	add_executable(${EXE_NAME} $<TARGET_OBJECTS:${PROJECT_OBJ_LIB}>)
+	add_executable(${EXE_NAME} $<TARGET_OBJECTS:${PROJECT_OBJ_LIB}> $<TARGET_OBJECTS:tfm_qcbor>)
 
 	#Set common linker flags
 	config_setting_shared_linker_flags(${EXE_NAME})
@@ -273,6 +273,10 @@
 	add_subdirectory(../secure_fw ${CMAKE_CURRENT_BINARY_DIR}/secure_fw)
 endif()
 
+if (NOT TARGET tfm_qcbor)
+	add_subdirectory(${TFM_ROOT_DIR}/lib/ext/qcbor ${CMAKE_CURRENT_BINARY_DIR}/qcbor)
+endif()
+
 if (LINK_TO_BOTH_MEMORY_REGION)
 	#Link to primary memory region
 	set_up_app_build(NS_TARGET     ${PROJECT_NAME}
diff --git a/app/main_ns.c b/app/main_ns.c
index b6f1786..e4bf5d6 100644
--- a/app/main_ns.c
+++ b/app/main_ns.c
@@ -81,9 +81,15 @@
  * \brief List of RTOS thread attributes
  */
 #ifdef TEST_FRAMEWORK_NS
+/* Allocate dedicated stack for test executor thread.
+ * It must be 64 bit aligned.
+ */
+static uint64_t test_app_stack[(3u * 1024u) / (sizeof(uint64_t))]; /* 3KB */
+
 static const osThreadAttr_t tserv_test = {
     .name = "test_app",
-    .stack_size = 1024U
+    .stack_size = sizeof(test_app_stack),
+    .stack_mem = test_app_stack,
 };
 #elif PSA_API_TEST_NS
 static const osThreadAttr_t psa_api_test_attr = {
diff --git a/test/CMakeLists.inc b/test/CMakeLists.inc
index 6c22af7..cb36a19 100644
--- a/test/CMakeLists.inc
+++ b/test/CMakeLists.inc
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+# Copyright (c) 2017-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -33,4 +33,5 @@
 include(${CMAKE_CURRENT_LIST_DIR}/suites/audit/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/suites/crypto/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/suites/attestation/CMakeLists.inc)
+include(${CMAKE_CURRENT_LIST_DIR}/suites/qcbor/CMakeLists.inc)
 include(${CMAKE_CURRENT_LIST_DIR}/test_services/CMakeLists.inc)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index de280ab..9afdc11 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -51,6 +51,7 @@
 set(ENABLE_CRYPTO_SERVICE_TESTS TRUE)
 set(ENABLE_INVERT_SERVICE_TESTS TRUE)
 set(ENABLE_ATTESTATION_SERVICE_TESTS TRUE)
+set(ENABLE_QCBOR_TESTS TRUE)
 include(${CMAKE_CURRENT_LIST_DIR}/CMakeLists.inc)
 
 #Build the secure library
diff --git a/test/framework/non_secure_suites.c b/test/framework/non_secure_suites.c
index 724182b..b458224 100644
--- a/test/framework/non_secure_suites.c
+++ b/test/framework/non_secure_suites.c
@@ -14,6 +14,7 @@
 #include "test/suites/audit/non_secure/audit_ns_tests.h"
 #include "test/suites/crypto/non_secure/crypto_ns_tests.h"
 #include "test/suites/attestation/non_secure/attestation_ns_tests.h"
+#include "test/suites/qcbor/non_secure/qcbor_ns_tests.h"
 #include "test/suites/invert/non_secure/invert_ns_tests.h"
 #include "test/suites/core/non_secure/core_ns_tests.h"
 
@@ -22,6 +23,9 @@
 #ifdef SERVICES_TEST_NS
     /* List test cases which compliant with level 3 isolation */
 
+    /* Non-secure QCBOR library test cases */
+    {&register_testsuite_ns_qcbor, 0, 0, 0},
+
 #ifdef TFM_PARTITION_TEST_CORE
     /* Non-secure invert test cases */
     /* Note: since this is sample code, only run if test services are enabled */
@@ -45,6 +49,9 @@
     /* Non-secure initial attestation service test cases */
     {&register_testsuite_ns_attestation_interface, 0, 0, 0},
 
+    /* Non-secure QCBOR library test cases */
+    {&register_testsuite_ns_qcbor, 0, 0, 0},
+
 #ifdef TFM_PARTITION_TEST_CORE
     /* Non-secure invert test cases */
     /* Note: since this is sample code, only run if test services are enabled */
diff --git a/test/suites/qcbor/CMakeLists.inc b/test/suites/qcbor/CMakeLists.inc
new file mode 100644
index 0000000..8d9cc6a
--- /dev/null
+++ b/test/suites/qcbor/CMakeLists.inc
@@ -0,0 +1,49 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2019, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+#Definitions to compile the QCBOR module.
+#This file assumes it will be included from a project specific cmakefile, and
+#will not create a library or executable.
+#Inputs:
+#	TFM_ROOT_DIR - root directory of the TF-M repo.
+#
+#Outputs:
+#	Will modify include directories to make the source compile.
+#	ALL_SRC_C: C source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	ALL_SRC_CXX: C++ source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	ALL_SRC_ASM: assembly source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command.
+#	Include directories will be modified by using the include_directories() commands as needed.
+
+#Get the current directory where this file is located.
+set(QCBOR_TEST_SUIT_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+#Verify input parameters
+if(NOT DEFINED TFM_ROOT_DIR)
+	message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.")
+endif()
+
+#Get the directory where test cases are stored
+set(QCBOR_TEST_DIR "${TFM_ROOT_DIR}/lib/ext/qcbor/test")
+
+if (NOT DEFINED ENABLE_QCBOR_TESTS)
+	message(FATAL_ERROR "Incomplete build configuration: ENABLE_QCBOR_TESTS is undefined.")
+elseif(ENABLE_QCBOR_TESTS)
+	list(APPEND ALL_SRC_C_NS
+		"${QCBOR_TEST_SUIT_DIR}/non_secure/qcbor_ns_testsuite.c"
+		"${QCBOR_TEST_DIR}/float_tests.c"
+		"${QCBOR_TEST_DIR}/half_to_double_from_rfc7049.c"
+		"${QCBOR_TEST_DIR}/qcbor_decode_tests.c"
+		"${QCBOR_TEST_DIR}/qcbor_encode_tests.c"
+		"${QCBOR_TEST_DIR}/run_tests.c"
+		"${QCBOR_TEST_DIR}/UsefulBuf_Tests.c"
+	)
+
+	#Setting include directories
+	embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE)
+	embedded_include_directories(PATH ${TFM_ROOT_DIR}/lib/ext/qcbor/inc ABSOLUTE)
+	embedded_include_directories(PATH ${QCBOR_TEST_DIR} ABSOLUTE)
+endif()
diff --git a/test/suites/qcbor/non_secure/qcbor_ns_tests.h b/test/suites/qcbor/non_secure/qcbor_ns_tests.h
new file mode 100644
index 0000000..03d2e46
--- /dev/null
+++ b/test/suites/qcbor/non_secure/qcbor_ns_tests.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __QCBOR_NS_TESTS_H__
+#define __QCBOR_NS_TESTS_H__
+
+#include "test/framework/test_framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Register test suite for the QCBOR library
+ *
+ * \param[in] p_test_suite The test suite to be executed.
+ */
+void
+register_testsuite_ns_qcbor(struct test_suite_t *p_test_suite);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __QCBOR_NS_TESTS_H__ */
diff --git a/test/suites/qcbor/non_secure/qcbor_ns_testsuite.c b/test/suites/qcbor/non_secure/qcbor_ns_testsuite.c
new file mode 100644
index 0000000..45181d6
--- /dev/null
+++ b/test/suites/qcbor/non_secure/qcbor_ns_testsuite.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "qcbor_ns_tests.h"
+#include <stdio.h>
+#include "run_tests.h"
+
+/*
+ * The QCBOR test cases are defined in: lib/ext/qcbor/test/run_test.c
+ *
+ * There are two types of configuration to execute test cases:
+ *  - All tests: Just pass an array containing a NULL pointer to RunTest():
+ *               qcbor_test_cases_all[]. This is the default configuration.
+ *
+ *  - Selected tests: qcbor_test_cases[] array contains the name of all tests.
+ *                    To execute only selected test cases, just remove/comment
+ *                    out the unwanted tests from the array and pass it to
+ *                    RunTests(). This configuration disables all tests with a
+ *                    long execution time to speed up development.
+ */
+
+/* Define test suite for QCBOR library */
+static void tfm_qcbor_test_7001(struct test_result_t *ret);
+
+static struct test_t qcbor_regression_test[] = {
+    {&tfm_qcbor_test_7001, "TFM_QCBOR_TEST_7001",
+     "Regression test of QCBOR library", {0} },
+};
+
+/* To execute only selected test cases, then remove unwanted ones from the array
+ * and pass it to RunTests().
+ * Not static to avoid compiler warning due to non-usage
+ */
+const char *qcbor_test_cases[] = {
+    "ParseMapAsArrayTest",
+    "AllocAllStringsTest",
+    "IndefiniteLengthNestTest",
+    "NestedMapTestIndefLen",
+    "ParseSimpleTest",
+    "EncodeRawTest",
+    "RTICResultsTest",
+    "MapEncodeTest",
+    "ArrayNestingTest1",
+    "ArrayNestingTest2",
+    "ArrayNestingTest3",
+    "EncodeDateTest",
+    "SimpleValuesTest1",
+    "IntegerValuesTest1",
+    "AllAddMethodsTest",
+    "ParseTooDeepArrayTest",
+    "ComprehensiveInputTest",
+    "ParseMapTest",
+    "IndefiniteLengthArrayMapTest",
+    "BasicEncodeTest",
+    "NestedMapTest",
+    "BignumParseTest",
+    "OptTagParseTest",
+    "DateParseTest",
+    "ShortBufferParseTest2",
+    "ShortBufferParseTest",
+    "ParseDeepArrayTest",
+    "SimpleArrayTest",
+    "IntegerValuesParseTest",
+    "MemPoolTest",
+    "IndefiniteLengthStringTest", /**/
+    "HalfPrecisionDecodeBasicTests",
+    "DoubleAsSmallestTest",
+    "HalfPrecisionAgainstRFCCodeTest",
+    "BstrWrapTest",
+    "BstrWrapErrorTest",
+    "BstrWrapNestTest", /**/
+    "CoseSign1TBSTest",
+    "StringDecoderModeFailTest",
+    /* "BigComprehensiveInputTest", */ /* Takes too long to execute */
+    "EncodeErrorTests",
+    "UBUTest_CopyUtil",
+    "UOBTest_NonAdversarial",
+    "TestBasicSanity",
+    "UOBTest_BoundaryConditionsTest",
+    "UBMacroConversionsTest",
+    "UBUtilTests",
+    "UIBTest_IntegerFormat",
+};
+
+/* To execute all test cases, then pass this array to RunTests()
+ * Test cases are defined in: lib/ext/qcbor/test/run_tests.c
+ */
+const static char *qcbor_test_cases_all[] = {
+    0, /* Indicates to run all enabled test case */
+};
+
+/**
+ * \brief Print QCBOR test results per test case
+ *
+ * \param[in]  szString  String to print out
+ * \param[in]  ctx       Where to print
+ */
+
+static void fputs_wrapper(const char *string, void *out_ctx, int new_line)
+{
+    /* To get test result per test case then remove comments around the
+     * following lines.
+     */
+/*
+    fputs(string, (FILE *)out_ctx);
+    if(new_line) {
+        fputs("\r\n", out_ctx);
+    }
+*/
+}
+
+static void tfm_qcbor_test_7001(struct test_result_t *ret)
+{
+    int32_t test_failed_cnt = 0;
+
+    test_failed_cnt = RunTests(qcbor_test_cases_all, fputs_wrapper,
+                               stdout, NULL);
+    if (test_failed_cnt != 0) {
+        TEST_FAIL("QCBOR test failed");
+        return;
+    }
+
+    ret->val = TEST_PASSED;
+}
+
+void
+register_testsuite_ns_qcbor(struct test_suite_t *p_test_suite)
+{
+    uint32_t list_size;
+
+    list_size = (sizeof(qcbor_regression_test) /
+                 sizeof(qcbor_regression_test[0]));
+
+    set_testsuite("QCBOR regression test"
+                  "(TFM_QCBOR_TEST_7XXX)",
+                  qcbor_regression_test, list_size, p_test_suite);
+}