1 /*
2 * Copyright (c) 2021-2024, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <service/test_runner/provider/test_runner_backend.h>
7 #include <service/test_runner/provider/test_runner_provider.h>
8 #include "simple_c_test_runner.h"
9 #include <string.h>
10
11
12 /* Private defines */
13 #define SIMPLE_C_TEST_GROUP_LIMIT (50)
14
15 /**
16 * The simple_c test runner specialises the base test_runner_backend
17 * to add a regsitry of registered test groups.
18 */
19 static struct simple_c_test_runner
20 {
21 struct test_runner_backend base_backend;
22 size_t num_groups;
23 const struct simple_c_test_group *groups[SIMPLE_C_TEST_GROUP_LIMIT];
24 } the_test_runner;
25
26 /* Concrete test_runner_backed functions */
27 static size_t count_tests(const struct test_spec *spec);
28 static int run_tests(const struct test_spec *spec,
29 struct test_summary *summary, struct test_result *results, size_t result_limit);
30 static void list_tests(const struct test_spec *spec,
31 struct test_summary *summary, struct test_result *results, size_t result_limit);
32
33
simple_c_test_runner_init(struct test_runner_provider * frontend)34 void simple_c_test_runner_init(struct test_runner_provider *frontend)
35 {
36 /* Initialise base test_runner_backend */
37 the_test_runner.base_backend.count_tests = count_tests;
38 the_test_runner.base_backend.run_tests = run_tests;
39 the_test_runner.base_backend.list_tests = list_tests;
40 the_test_runner.base_backend.next = NULL;
41
42 /* Registry initially empty */
43 the_test_runner.num_groups = 0;
44
45 test_runner_provider_register_backend(frontend, &the_test_runner.base_backend);
46 }
47
simple_c_test_runner_register_group(const struct simple_c_test_group * test_group)48 void simple_c_test_runner_register_group(const struct simple_c_test_group *test_group)
49 {
50 if (the_test_runner.num_groups < SIMPLE_C_TEST_GROUP_LIMIT) {
51
52 the_test_runner.groups[the_test_runner.num_groups] = test_group;
53 ++the_test_runner.num_groups;
54 }
55 }
56
does_qualify(const char * spec_string,const char * test_string)57 static bool does_qualify(const char *spec_string, const char *test_string)
58 {
59 return ((strlen(spec_string) == 0) || (strcmp(spec_string, test_string) == 0));
60 }
61
test_iterate(const struct test_spec * spec,bool list_only,struct test_summary * summary,struct test_result * results,size_t result_limit)62 static int test_iterate(const struct test_spec *spec, bool list_only,
63 struct test_summary *summary, struct test_result *results, size_t result_limit)
64 {
65 summary->num_tests = 0;
66 summary->num_results = 0;
67 summary->num_passed = 0;
68 summary->num_failed = 0;
69
70 for (size_t group_index = 0; group_index < the_test_runner.num_groups; ++group_index) {
71
72 const struct simple_c_test_group *test_group = the_test_runner.groups[group_index];
73
74 if (does_qualify(spec->group, test_group->group)) {
75
76 for (size_t test_index = 0; test_index < test_group->num_test_cases; ++test_index) {
77
78 const struct simple_c_test_case *test_case = &test_group->test_cases[test_index];
79
80 if (does_qualify(spec->name, test_case->name)) {
81
82 enum test_run_state run_state = TEST_RUN_STATE_NOT_RUN;
83 struct test_failure failure = {0};
84
85 /* Run the qualifying test case if we're not just listing tests */
86 if (!list_only) {
87
88 if (test_case->test_func(&failure)) {
89
90 run_state = TEST_RUN_STATE_PASSED;
91 ++summary->num_passed;
92 }
93 else {
94
95 run_state = TEST_RUN_STATE_FAILED;
96 ++summary->num_failed;
97 }
98 }
99
100 /* Update result object if capacity - common for listing and running tests */
101 if (summary->num_tests < result_limit) {
102
103 struct test_result *new_result = &results[summary->num_results];
104 size_t len = 0;
105
106 new_result->run_state = run_state;
107 new_result->failure = failure;
108
109 len = strlen(test_group->group) + 1;
110 if (len > sizeof(new_result->group))
111 return -1;
112
113 memcpy(new_result->group, test_group->group, len);
114
115 len = strlen(test_case->name) + 1;
116 if (len > sizeof(new_result->name))
117 return -1;
118
119 memcpy(new_result->name, test_case->name, len);
120
121 ++summary->num_results;
122 }
123
124 ++summary->num_tests;
125 }
126 }
127 }
128 }
129
130 return 0;
131 }
132
count_tests(const struct test_spec * spec)133 static size_t count_tests(const struct test_spec *spec)
134 {
135 size_t count = 0;
136
137 for (size_t group_index = 0; group_index < the_test_runner.num_groups; ++group_index) {
138
139 count += the_test_runner.groups[group_index]->num_test_cases;
140 }
141
142 return count;
143 }
144
run_tests(const struct test_spec * spec,struct test_summary * summary,struct test_result * results,size_t result_limit)145 static int run_tests(const struct test_spec *spec,
146 struct test_summary *summary, struct test_result *results, size_t result_limit)
147 {
148 return test_iterate(spec, false, summary, results, result_limit);
149 }
150
list_tests(const struct test_spec * spec,struct test_summary * summary,struct test_result * results,size_t result_limit)151 static void list_tests(const struct test_spec *spec,
152 struct test_summary *summary, struct test_result *results, size_t result_limit)
153 {
154 test_iterate(spec, true, summary, results, result_limit);
155 }
156