fix(ff-a): tests for FFA_FEATURES

There are different expectations to the result to the FFA_FEATURES
call, provided the feature IDs for ME, SRI and NPI interrupt from
tftf or cactus.

This patch refactors the test to keep the common part equal.
For the differences, locally define the expected test target
for the FFA_FEATURES call.

Signed-off-by: J-Alves <joao.alves@arm.com>
Change-Id: I96f18487c80d789cf4e10ceee0591786708bce51
diff --git a/include/runtime_services/spm_common.h b/include/runtime_services/spm_common.h
index fb1f61e..6c01751 100644
--- a/include/runtime_services/spm_common.h
+++ b/include/runtime_services/spm_common.h
@@ -101,7 +101,10 @@
 
 bool check_spmc_execution_level(void);
 
-unsigned int get_ffa_feature_test_target(const struct ffa_features_test **test_target);
+unsigned int get_ffa_feature_test_target(
+		const struct ffa_features_test **test_target);
+bool ffa_features_test_targets(const struct ffa_features_test *targets,
+			       uint32_t test_target_size);
 
 /**
  * Helper to conduct a memory retrieve. This is to be called by the receiver
diff --git a/spm/common/sp_tests/sp_test_ffa.c b/spm/common/sp_tests/sp_test_ffa.c
index 63bf131..9a32891 100644
--- a/spm/common/sp_tests/sp_test_ffa.c
+++ b/spm/common/sp_tests/sp_test_ffa.c
@@ -80,43 +80,25 @@
  */
 static void ffa_features_test(void)
 {
-	struct ffa_value ffa_ret;
-	unsigned int expected_ret;
-	const struct ffa_features_test *ffa_feature_test_target;
-	unsigned int i, test_target_size =
-		get_ffa_feature_test_target(&ffa_feature_test_target);
-	struct ffa_features_test test_target;
+	const struct ffa_features_test *func_id_targets;
+	/* Get common features between tftf and cactus. */
+	unsigned int test_target_size =
+		get_ffa_feature_test_target(&func_id_targets);
+	const struct ffa_features_test feature_id_targets[] = {
+		{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_SUCCESS_SMC32, 0,
+			MAKE_FFA_VERSION(1, 1)},
+		{"FFA_FEATURE_SRI", FFA_FEATURE_SRI, FFA_ERROR, 0,
+			MAKE_FFA_VERSION(1, 1)},
+		{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_SUCCESS_SMC32, 0,
+			MAKE_FFA_VERSION(1, 1)},
+	};
 
 	INFO("Test FFA_FEATURES.\n");
+	ffa_features_test_targets(func_id_targets, test_target_size);
 
-	for (i = 0U; i < test_target_size; i++) {
-		test_target = ffa_feature_test_target[i];
-
-		ffa_ret = ffa_features_with_input_property(test_target.feature,
-							   test_target.param);
-		expected_ret = FFA_VERSION_COMPILED
-				>= test_target.version_added ?
-				test_target.expected_ret : FFA_ERROR;
-
-		if (ffa_func_id(ffa_ret) != expected_ret) {
-			ERROR("Unexpected return: %s (expected %s)."
-			      " FFA_FEATURES test: %s.\n",
-			      ffa_func_name(ffa_func_id(ffa_ret)),
-			      ffa_func_name(expected_ret),
-			      test_target.test_name);
-		}
-
-		if (expected_ret == FFA_ERROR) {
-			if (ffa_error_code(ffa_ret) !=
-			    FFA_ERROR_NOT_SUPPORTED) {
-				ERROR("Unexpected error code: %s (expected %s)."
-				      " FFA_FEATURES test: %s.\n",
-				      ffa_error_name(ffa_error_code(ffa_ret)),
-				      ffa_error_name(expected_ret),
-				      test_target.test_name);
-			}
-		}
-	}
+	/* Features are expected to be different to tftf. */
+	ffa_features_test_targets(feature_id_targets,
+			ARRAY_SIZE(feature_id_targets));
 }
 
 static void ffa_partition_info_wrong_test(void)
diff --git a/tftf/tests/runtime_services/secure_service/spm_common.c b/tftf/tests/runtime_services/secure_service/spm_common.c
index 8fb3a72..2f68914 100644
--- a/tftf/tests/runtime_services/secure_service/spm_common.c
+++ b/tftf/tests/runtime_services/secure_service/spm_common.c
@@ -197,13 +197,7 @@
 		FFA_SUCCESS_SMC32},
 	{"FFA_NOTIFICATION_INFO_GET_64", FFA_NOTIFICATION_INFO_GET_SMC64,
 		FFA_SUCCESS_SMC32},
-	/* Indirect messaging is only supported in Nwd */
 	{"FFA_YIELD_32", FFA_MSG_YIELD, FFA_ERROR},
-	{"FFA_MSG_SEND_32", FFA_MSG_SEND, FFA_ERROR},
-	{"FFA_MSG_POLL_32", FFA_MSG_POLL, FFA_ERROR},
-	{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_ERROR, 0, MAKE_FFA_VERSION(1, 1)},
-	{"FFA_FEATURE_SRI", FFA_FEATURE_SRI, FFA_SUCCESS_SMC32, 0, MAKE_FFA_VERSION(1, 1)},
-	{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_ERROR, 0, MAKE_FFA_VERSION(1, 1)},
 	{"Check non-existent command", 0xFFFF, FFA_ERROR},
 };
 
@@ -223,6 +217,51 @@
 	       sizeof(struct ffa_features_test);
 }
 
+/**
+ * Leverages the struct ffa_feature_test and validates the result of
+ * FFA_FEATURES calls.
+ */
+bool ffa_features_test_targets(const struct ffa_features_test *targets,
+			       uint32_t test_target_size)
+{
+	bool ret = true;
+
+	for (size_t i = 0U; i < test_target_size; i++) {
+		struct ffa_value ffa_ret;
+		uint32_t expected_ret;
+		const struct ffa_features_test *test_target = &targets[i];
+
+		ffa_ret = ffa_features_with_input_property(test_target->feature,
+							   test_target->param);
+		expected_ret = FFA_VERSION_COMPILED
+				>= test_target->version_added ?
+				test_target->expected_ret : FFA_ERROR;
+
+		if (ffa_func_id(ffa_ret) != expected_ret) {
+			ERROR("Unexpected return: %s (expected %s)."
+			      " FFA_FEATURES test: %s.\n",
+			      ffa_func_name(ffa_func_id(ffa_ret)),
+			      ffa_func_name(expected_ret),
+			      test_target->test_name);
+			ret = false;
+		}
+
+		if (expected_ret == FFA_ERROR) {
+			if (ffa_error_code(ffa_ret) !=
+			    FFA_ERROR_NOT_SUPPORTED) {
+				ERROR("Unexpected error code: %s (expected %s)."
+				      " FFA_FEATURES test: %s.\n",
+				      ffa_error_name(ffa_error_code(ffa_ret)),
+				      ffa_error_name(expected_ret),
+				      test_target->test_name);
+				ret = false;
+			}
+		}
+	}
+
+	return ret;
+}
+
 bool memory_retrieve(struct mailbox_buffers *mb,
 		     struct ffa_memory_region **retrieved, uint64_t handle,
 		     ffa_id_t sender, struct ffa_memory_access receivers[],
diff --git a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
index 621fc69..3813503 100644
--- a/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
+++ b/tftf/tests/runtime_services/secure_service/test_ffa_setup_and_discovery.c
@@ -4,6 +4,7 @@
  * SPDX-License-Identifier: BSD-3-Clause
  */
 
+#include "utils_def.h"
 #include <debug.h>
 
 #include <ffa_endpoints.h>
@@ -86,44 +87,33 @@
 
 test_result_t test_ffa_features(void)
 {
+	const struct ffa_features_test *func_ids_target;
+	const struct ffa_features_test feature_ids_target[] = {
+		{"FFA_FEATURE_MEI", FFA_FEATURE_MEI, FFA_ERROR, 0,
+			MAKE_FFA_VERSION(1, 1)},
+		{"FFA_FEATURE_SRI", FFA_FEATURE_SRI, FFA_SUCCESS_SMC32, 0,
+			MAKE_FFA_VERSION(1, 1)},
+		{"FFA_FEATURE_NPI", FFA_FEATURE_NPI, FFA_ERROR, 0,
+			MAKE_FFA_VERSION(1, 1)},
+	};
+	unsigned int test_target_size =
+		get_ffa_feature_test_target(&func_ids_target);
+
 	SKIP_TEST_IF_FFA_VERSION_LESS_THAN(1, 0);
 
 	/* Check if SPMC is OP-TEE at S-EL1 */
 	if (check_spmc_execution_level()) {
 		/* FFA_FEATURES is not yet supported in OP-TEE */
-		return TEST_RESULT_SUCCESS;
+		return TEST_RESULT_SKIPPED;
 	}
 
-	struct ffa_value ffa_ret;
-	unsigned int expected_ret;
-	const struct ffa_features_test *ffa_feature_test_target;
-	unsigned int i, test_target_size =
-		get_ffa_feature_test_target(&ffa_feature_test_target);
-	struct ffa_features_test test_target;
+	if (!ffa_features_test_targets(func_ids_target, test_target_size)) {
+		return TEST_RESULT_FAIL;
+	}
 
-	for (i = 0U; i < test_target_size; i++) {
-		test_target = ffa_feature_test_target[i];
-		ffa_ret = ffa_features_with_input_property(test_target.feature, test_target.param);
-		expected_ret = FFA_VERSION_COMPILED
-			>= test_target.version_added ?
-			test_target.expected_ret : FFA_ERROR;
-		if (ffa_func_id(ffa_ret) != expected_ret) {
-			tftf_testcase_printf(
-				"%s returned %s, expected %s\n",
-				test_target.test_name,
-				ffa_func_name(ffa_func_id(ffa_ret)),
-				ffa_func_name(expected_ret));
-			return TEST_RESULT_FAIL;
-		}
-		if ((expected_ret == FFA_ERROR) &&
-				(ffa_error_code(ffa_ret) != FFA_ERROR_NOT_SUPPORTED)) {
-			tftf_testcase_printf(
-				"%s failed for the wrong reason: returned %s, expected %s\n",
-				test_target.test_name,
-				ffa_error_name(ffa_error_code(ffa_ret)),
-				ffa_error_name(FFA_ERROR_NOT_SUPPORTED));
-			return TEST_RESULT_FAIL;
-		}
+	if (!ffa_features_test_targets(feature_ids_target,
+				ARRAY_SIZE(feature_ids_target))) {
+		return TEST_RESULT_FAIL;
 	}
 
 	return TEST_RESULT_SUCCESS;