1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <fwk_module.h>
9 #include <fwk_module_idx.h>
10 #include <fwk_noreturn.h>
11 #include <fwk_status.h>
12 #include <fwk_test.h>
13
14 #include <setjmp.h>
15 #include <stdbool.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 /*
19 * This variable is used by arm architecture to ensure spurious nested calls
20 * won't enable interrupts. This is been accessed from inline function defined
21 * in arch_helpers.h
22 */
23 unsigned int critical_section_nest_level;
24
25 /* Test information provided by the test suite */
26 extern struct fwk_test_suite_desc test_suite;
27
28 static jmp_buf test_buf_context;
29
30 struct fwk_module *module_table[FWK_MODULE_IDX_COUNT];
31 struct fwk_module_config *module_config_table[FWK_MODULE_IDX_COUNT];
32
fake_init(fwk_id_t module_id,unsigned int element_count,const void * data)33 static int fake_init(
34 fwk_id_t module_id,
35 unsigned int element_count,
36 const void *data)
37 {
38 return FWK_SUCCESS;
39 }
40
__assert_fail(const char * assertion,const char * file,unsigned int line,const char * function)41 noreturn void __assert_fail(const char *assertion,
42 const char *file, unsigned int line, const char *function)
43 {
44 printf("Assertion failed: %s\n", assertion);
45 printf(" Function: %s\n", function);
46 printf(" File: %-66s\n", file);
47 printf(" Line: %u\n", line);
48 longjmp(test_buf_context, !FWK_SUCCESS);
49 }
50
print_separator(void)51 static void print_separator(void)
52 {
53 printf("----------------------------------------");
54 printf("----------------------------------------\n");
55 }
print_prologue(void)56 static void print_prologue(void)
57 {
58 printf("\nStarting tests for %s\n", test_suite.name);
59 print_separator();
60 }
61
print_epilogue(unsigned int successful_tests)62 static void print_epilogue(unsigned int successful_tests)
63 {
64 int pass_rate = (successful_tests * 100) / test_suite.test_case_count;
65
66 print_separator();
67 printf("%u / %u passed (%d%% pass rate)\n\n", successful_tests,
68 test_suite.test_case_count, pass_rate);
69 }
70
print_result(const char * name,bool success)71 static void print_result(const char *name, bool success)
72 {
73 /* The name is truncated to 72 characters */
74 printf("%-72s %s\n", name, (success ? "SUCCESS" : "FAILURE"));
75 }
76
run_tests(void)77 static unsigned int run_tests(void)
78 {
79 unsigned int i;
80 bool success;
81 unsigned int successful_tests = 0;
82 const struct fwk_test_case_desc *test_case;
83
84 if (test_suite.test_suite_setup != NULL) {
85 if (test_suite.test_suite_setup() != FWK_SUCCESS)
86 return 0;
87 }
88
89 for (i = 0; i < test_suite.test_case_count; i++) {
90 test_case = &test_suite.test_case_table[i];
91
92 if ((test_case->test_execute == NULL) || (test_case->name == NULL)) {
93 print_result("Test case undefined!", false);
94
95 continue;
96 }
97
98 if (test_suite.test_case_setup != NULL)
99 test_suite.test_case_setup();
100
101 /*
102 * The setjmp function stores the execution context of the processor at
103 * that point in time. When called, 0 is returned by default.
104 * If an assertion fails in the test case following, execution returns
105 * to an undefined point within setjmp() which then returns a non-zero
106 * value. See __assert_fail() for exactly how assertion failure is
107 * handled.
108 */
109 if (setjmp(test_buf_context) == FWK_SUCCESS) {
110 test_case->test_execute();
111
112 success = true;
113 successful_tests++;
114 } else
115 success = false;
116
117 if (test_suite.test_case_teardown != NULL)
118 test_suite.test_case_teardown();
119
120 print_result(test_case->name, success);
121 }
122
123 if (test_suite.test_suite_teardown != NULL)
124 test_suite.test_suite_teardown();
125
126 return successful_tests;
127 }
128
main(void)129 int main(void)
130 {
131 unsigned int successful_tests;
132
133 for (enum fwk_module_idx i = 0; i < FWK_MODULE_IDX_COUNT; i++) {
134
135 struct fwk_module *module = malloc(sizeof(*module));
136 struct fwk_module_config *config = malloc(sizeof(*config));
137
138 *module = (struct fwk_module){
139 .type = FWK_MODULE_TYPE_SERVICE,
140 .init = fake_init,
141 };
142
143 *config = (struct fwk_module_config){ 0 };
144
145 module_table[i] = module;
146 module_config_table[i] = config;
147 }
148
149 fwk_module_init();
150
151 if (test_suite.test_case_count != 0) {
152 print_prologue();
153 successful_tests = run_tests();
154 print_epilogue(successful_tests);
155
156 if (successful_tests != test_suite.test_case_count)
157 return EXIT_FAILURE;
158 }
159
160 return EXIT_SUCCESS;
161 }
162