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