1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2014, STMicroelectronics International N.V.
4 */
5
6 /*************************************************************************
7 * 1. Includes
8 ************************************************************************/
9 #include "adbg_int.h"
10
11 /*************************************************************************
12 * 2. Definition of external constants and variables
13 ************************************************************************/
14 #ifndef TAILQ_CONCAT
15 #define TAILQ_CONCAT(head1, head2, field) do { \
16 if (!TAILQ_EMPTY(head2)) { \
17 *(head1)->tqh_last = (head2)->tqh_first; \
18 (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
19 (head1)->tqh_last = (head2)->tqh_last; \
20 TAILQ_INIT((head2)); \
21 } \
22 } while (/*CONSTCOND*/0)
23 #endif
24
25 /*************************************************************************
26 * 3. File scope types, constants and variables
27 ************************************************************************/
28
29 TAILQ_HEAD(ADBG_CaseHead, ADBG_Case);
30 typedef struct ADBG_CaseHead ADBG_CaseHead_t;
31
32 typedef struct ADBG_Runner {
33 ADBG_Result_t Result;
34 const ADBG_Suite_Definition_t *Suite_p;
35
36 ADBG_CaseHead_t CasesList;
37 } ADBG_Runner_t;
38
39 /*************************************************************************
40 * 4. Declaration of file local functions
41 ************************************************************************/
42
43 static int ADBG_RunSuite(ADBG_Runner_t *Runner_p, int argc, char *argv[]);
44
45
46 /*************************************************************************
47 * 5. Definition of external functions
48 ************************************************************************/
Do_ADBG_RunSuite(const ADBG_Suite_Definition_t * Suite_p,int argc,char * argv[])49 int Do_ADBG_RunSuite(
50 const ADBG_Suite_Definition_t *Suite_p,
51 int argc,
52 char *argv[]
53 )
54 {
55 ADBG_Runner_t *Runner_p = NULL;
56
57 Runner_p = calloc(1, sizeof(*Runner_p));
58 if (Runner_p == NULL) {
59 Do_ADBG_Log("calloc failed for Suite %s!",
60 Suite_p->SuiteID_p);
61 return -1;
62 }
63 TAILQ_INIT(&Runner_p->CasesList);
64 Runner_p->Suite_p = Suite_p;
65
66 int ret = ADBG_RunSuite(Runner_p, argc, argv);
67 free(Runner_p);
68 return ret;
69 }
70
Do_ADBG_AppendToSuite(ADBG_Suite_Definition_t * Dest_p,ADBG_Suite_Definition_t * Source_p)71 int Do_ADBG_AppendToSuite(
72 ADBG_Suite_Definition_t *Dest_p,
73 ADBG_Suite_Definition_t *Source_p
74 )
75 {
76 char *p = NULL;
77 size_t size = 0;
78
79 /* Append name of 'Source_p' to name of 'Dest_p' */
80 size = strlen(Source_p->SuiteID_p);
81 if (Dest_p->SuiteID_p) {
82 size += strlen(Dest_p->SuiteID_p);
83 size += 1; /* '+' */
84 }
85 size += 1; /* '\0' */
86 p = malloc(size);
87 if (!p) {
88 fprintf(stderr, "malloc failed\n");
89 return -1;
90 }
91 if (Dest_p->SuiteID_p)
92 snprintf(p, size, "%s+%s", Dest_p->SuiteID_p,
93 Source_p->SuiteID_p);
94 else
95 snprintf(p, size, "%s", Source_p->SuiteID_p);
96 free((void *)Dest_p->SuiteID_p);
97 Dest_p->SuiteID_p = p;
98
99 TAILQ_CONCAT(&Dest_p->cases, &Source_p->cases, link);
100 return 0;
101 }
102
103 /*************************************************************************
104 * 6. Definitions of internal functions
105 ************************************************************************/
ADBG_RunSuite(ADBG_Runner_t * Runner_p,int argc,char * argv[])106 static int ADBG_RunSuite(
107 ADBG_Runner_t *Runner_p,
108 int argc,
109 char *argv[]
110 )
111 {
112 ADBG_Case_t *Case_p = NULL;
113 size_t NumSkippedTestCases = 0;
114 int failed_test = 0;
115 struct adbg_case_def *case_def = NULL;
116
117 Do_ADBG_Log("######################################################");
118 Do_ADBG_Log("#");
119 Do_ADBG_Log("# %s", Runner_p->Suite_p->SuiteID_p);
120 Do_ADBG_Log("#");
121 Do_ADBG_Log("######################################################");
122
123 TAILQ_FOREACH(case_def, &Runner_p->Suite_p->cases, link) {
124 /* Default match if by default all tests are to be run */
125 bool HaveMatch = !argc || !strcmp(argv[0], "-x");
126 int i = 0;
127
128 for (i = 0; i < argc; i++) {
129 if (!strcmp(argv[i], "-x")) {
130 i++;
131 if (i >= argc) {
132 Do_ADBG_Log("Error: -x <test-id>");
133 return 1;
134 }
135 if (strstr(case_def->TestID_p, argv[i]))
136 HaveMatch = false;
137 } else {
138 if (strstr(case_def->TestID_p, argv[i]))
139 HaveMatch = true;
140 }
141 }
142 if (!HaveMatch) {
143 NumSkippedTestCases++;
144 continue;
145 }
146
147 Case_p = ADBG_Case_New(case_def);
148 if (Case_p == NULL) {
149 Do_ADBG_Log("HEAP_ALLOC failed for Case %s!",
150 case_def->TestID_p);
151 Runner_p->Result.AbortTestSuite = 1;
152 break;
153 }
154
155 TAILQ_INSERT_TAIL(&Runner_p->CasesList, Case_p, Link);
156
157 /* Start the parent test case */
158 Do_ADBG_BeginSubCase(Case_p, "%s", case_def->Title_p);
159
160 case_def->Run_fp(Case_p);
161
162 /* End abondoned subcases */
163 while (Case_p->CurrentSubCase_p != Case_p->FirstSubCase_p)
164 Do_ADBG_EndSubCase(Case_p, NULL);
165
166 /* End the parent test case */
167 Do_ADBG_EndSubCase(Case_p, "%s", case_def->Title_p);
168
169 /* Sum up the errors */
170 Runner_p->Result.NumTests += Case_p->Result.NumTests +
171 Case_p->Result.NumSubTests;
172 Runner_p->Result.NumFailedTests +=
173 Case_p->Result.NumFailedTests +
174 Case_p->Result.
175 NumFailedSubTests;
176 Runner_p->Result.NumSubCases++;
177 if (Case_p->Result.NumFailedTests +
178 Case_p->Result.NumFailedSubTests > 0)
179 Runner_p->Result.NumFailedSubCases++;
180
181 Runner_p->Result.AbortTestSuite = Case_p->Result.AbortTestSuite;
182
183 if (Runner_p->Result.AbortTestSuite) {
184 Do_ADBG_Log("Test suite aborted by %s!",
185 case_def->TestID_p);
186 break;
187 }
188 }
189
190 Do_ADBG_Log("+-----------------------------------------------------");
191 if (argc > 0) {
192 bool test_exclusion = false;
193 int i = 0;
194
195 for (i = 0; i < argc; i++) {
196 if (!strcmp(argv[i], "-x")) {
197 test_exclusion = true;
198 continue;
199 }
200 Do_ADBG_Log(
201 "Result of testsuite %s filtered by \"%s%s\":",
202 Runner_p->Suite_p->SuiteID_p,
203 test_exclusion ? "-x " : "", argv[i]);
204 test_exclusion = false;
205 }
206 } else {
207 Do_ADBG_Log("Result of testsuite %s:",
208 Runner_p->Suite_p->SuiteID_p);
209 }
210
211 TAILQ_FOREACH(Case_p, &Runner_p->CasesList, Link) {
212 ADBG_SubCase_Iterator_t Iterator;
213 ADBG_SubCase_t *SubCase_p;
214
215 ADBG_Case_IterateSubCase(Case_p, &Iterator);
216 while ((SubCase_p = ADBG_Case_NextSubCase(&Iterator)) != NULL) {
217 if (SubCase_p->Result.NumFailedTests +
218 SubCase_p->Result.NumFailedSubTests > 0) {
219 if (SubCase_p->Result.FirstFailedFile_p !=
220 NULL) {
221 Do_ADBG_Log(
222 "%s FAILED first error at %s:%d",
223 SubCase_p->TestID_p,
224 SubCase_p->
225 Result.FirstFailedFile_p,
226 SubCase_p->
227 Result.FirstFailedRow);
228 } else {
229 Do_ADBG_Log("%s FAILED",
230 SubCase_p->TestID_p);
231 }
232 } else if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) {
233 /* A level one test case is displayed
234 if successfull too */
235 Do_ADBG_Log("%s OK", SubCase_p->TestID_p);
236 }
237 }
238 }
239
240
241 Do_ADBG_Log("+-----------------------------------------------------");
242 if (Runner_p->Result.AbortTestSuite)
243 Do_ADBG_Log("Test suite was ABORTED");
244
245 Do_ADBG_Log("%d subtest%s of which %d failed",
246 Runner_p->Result.NumTests,
247 Runner_p->Result.NumTests != 1 ? "s" : "",
248 Runner_p->Result.NumFailedTests);
249 Do_ADBG_Log("%d test case%s of which %d failed",
250 Runner_p->Result.NumSubCases,
251 Runner_p->Result.NumSubCases != 1 ? "s" : "",
252 Runner_p->Result.NumFailedSubCases);
253 Do_ADBG_Log("%zu test case%s skipped",
254 NumSkippedTestCases,
255 NumSkippedTestCases != 1 ? "s were" : " was");
256
257 failed_test = Runner_p->Result.NumFailedSubCases;
258
259 while (true) {
260 Case_p = TAILQ_FIRST(&Runner_p->CasesList);
261 if (Case_p == NULL)
262 break;
263 TAILQ_REMOVE(&Runner_p->CasesList, Case_p, Link);
264 ADBG_Case_Delete(Case_p);
265 }
266 return failed_test;
267 }
268