blob: 4e3ccb123c1106069ed005682d8924f9f1985088 [file] [log] [blame]
Pascal Brandc639ac82015-07-02 08:53:34 +02001/*
2 * Copyright (c) 2014, STMicroelectronics International N.V.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/*************************************************************************
15* 1. Includes
16*************************************************************************/
17#include "adbg_int.h"
18
19/*************************************************************************
20* 2. Definition of external constants and variables
21*************************************************************************/
22
23/*************************************************************************
24* 3. File scope types, constants and variables
25*************************************************************************/
26
27/*************************************************************************
28* 4. Declaration of file local functions
29*************************************************************************/
30
31/*
32 * Deletes a subcase. Don't call this function before the
33 * subcase is removed from list.
34 */
35static void ADBG_SubCase_Delete(ADBG_SubCase_t *SubCase);
36
37static ADBG_SubCase_t *ADBG_Case_CreateSubCase(ADBG_Case_t *Case_p,
38 const char *const Title_p);
39
40static ADBG_SubCase_t *ADBG_Case_GetParentSubCase(ADBG_Case_t *Case_p,
41 ADBG_SubCase_t *SubCase_p);
42
43static const char *ADBG_Case_GetTestID(ADBG_Case_t *Case_p);
44
45/*************************************************************************
46* 5. Definition of external functions
47*************************************************************************/
Jens Wiklander47d9a0b2016-12-26 21:39:09 +010048ADBG_Case_t *ADBG_Case_New(const ADBG_Case_SuiteEntry_t *SuiteEntry_p)
Pascal Brandc639ac82015-07-02 08:53:34 +020049{
50 ADBG_Case_t *Case_p;
51
52 Case_p = HEAP_ALLOC(ADBG_Case_t);
53 if (Case_p == NULL)
54 return NULL;
55
56 memset(Case_p, 0, sizeof(ADBG_Case_t));
57 Case_p->SuiteEntry_p = SuiteEntry_p;
Pascal Brandc639ac82015-07-02 08:53:34 +020058 return Case_p;
59}
60
61void ADBG_Case_Delete(
62 ADBG_Case_t *Case_p
63 )
64{
65 ADBG_SubCase_Delete(Case_p->FirstSubCase_p);
66 HEAP_FREE(&Case_p);
67}
68
69bool ADBG_Case_SubCaseIsMain(
70 const ADBG_Case_t *const Case_p,
71 const ADBG_SubCase_t *const SubCase_p
72 )
73{
74 IDENTIFIER_NOT_USED(Case_p)
75 return SubCase_p->Parent_p == NULL;
76}
77
78
79void ADBG_Case_IterateSubCase(
80 ADBG_Case_t *Case_p,
81 ADBG_SubCase_Iterator_t *Iterator_p
82 )
83{
84 Iterator_p->Case_p = Case_p;
85 Iterator_p->CurrentSubCase_p = NULL;
86}
87
88ADBG_SubCase_t *ADBG_Case_NextSubCase(
89 ADBG_SubCase_Iterator_t *Iterator_p
90 )
91{
92 ADBG_Case_t *Case_p = Iterator_p->Case_p;
93 ADBG_SubCase_t *SubCase_p = Iterator_p->CurrentSubCase_p;
94
95
96 /*
97 * Traverse the subcases depth first, that is:
98 * 1.1.1.1
99 * 1.1.1.2
100 * 1.1.1
101 * 1.1.2.1
102 * 1.1.2
103 * 1.1
104 * 1.2.1
105 * 1.2
106 * 1
107 */
108 if (SubCase_p == NULL) {
109 /* Find the first leaf */
110 SubCase_p = Case_p->FirstSubCase_p;
111 if (SubCase_p == NULL)
112 goto CleanupReturn;
113
114 while (!TAILQ_EMPTY(&SubCase_p->SubCasesList))
115 SubCase_p = TAILQ_FIRST(&SubCase_p->SubCasesList);
116 goto CleanupReturn;
117 }
118
119 /*
120 * Look for the next leaf belonging to the parent
121 */
122
123 if (SubCase_p->Parent_p == NULL) {
124 /* If parent is NULL this is the top
125 subcase and we're done */
126 SubCase_p = NULL;
127 goto CleanupReturn;
128 }
129
130 if (TAILQ_NEXT(SubCase_p, Link) == NULL) {
131 /* If this is the last subcase of the
132 parent move up to parent */
133 SubCase_p = SubCase_p->Parent_p;
134 goto CleanupReturn;
135 }
136
137 /*
138 * Find next leaf
139 */
140 SubCase_p = TAILQ_NEXT(SubCase_p, Link);
141 while (!TAILQ_EMPTY(&SubCase_p->SubCasesList))
142 SubCase_p = TAILQ_FIRST(&SubCase_p->SubCasesList);
143
144CleanupReturn:
145 Iterator_p->CurrentSubCase_p = SubCase_p;
146 return SubCase_p;
147}
148
149void Do_ADBG_BeginSubCase(
150 ADBG_Case_t *const Case_p,
151 const char *const FormatTitle_p, ...
152 )
153{
154 ADBG_SubCase_t *SubCase_p = NULL;
155
156 if (Case_p == NULL) {
157 Do_ADBG_Log("Do_ADBG_BeginSubCase: NULL Case_p!");
158 return;
159 }
160
161 if (FormatTitle_p == NULL) {
162 Do_ADBG_Log("Do_ADBG_BeginSubCase: NULL FormatTitle_p!");
163 return;
164 }
165
166 va_list ArgList;
167 char Title[80];
168
Pascal Brandc639ac82015-07-02 08:53:34 +0200169 va_start(ArgList, FormatTitle_p);
Jens Wiklander7e7c9c52016-12-27 17:57:46 +0100170 vsnprintf(Title, sizeof(Title), FormatTitle_p, ArgList);
Pascal Brandc639ac82015-07-02 08:53:34 +0200171 va_end(ArgList);
172
173 SubCase_p = ADBG_Case_CreateSubCase(Case_p, Title);
174
175 if (SubCase_p == NULL) {
176 Do_ADBG_Log("Do_ADBG_BeginSubCase: HEAP_ALLOC failed");
177 return;
178 }
179
180
181 if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) {
182 /* Main SubCase */
183 Do_ADBG_Log(" ");
184 Do_ADBG_Log("* %s %s", SubCase_p->TestID_p, SubCase_p->Title_p);
185 } else {
186 Do_ADBG_Log("o %s %s", SubCase_p->TestID_p, SubCase_p->Title_p);
187 }
188}
189
190void Do_ADBG_EndSubCase(
191 ADBG_Case_t *const Case_p,
192 const char *const FormatTitle_p, ...
193 )
194{
195 va_list ArgList;
196 char Title[80];
197 ADBG_SubCase_t *SubCase_p = NULL;
198
199 if (Case_p == NULL) {
200 Do_ADBG_Log("Do_ADBG_EndSubCase: NULL Case_p!");
201 return;
202 }
203
204 if (FormatTitle_p == NULL) {
205 strcpy(Title, "NULL");
206 } else {
Pascal Brandc639ac82015-07-02 08:53:34 +0200207 va_start(ArgList, FormatTitle_p);
Jens Wiklander7e7c9c52016-12-27 17:57:46 +0100208 vsnprintf(Title, sizeof(Title), FormatTitle_p, ArgList);
Pascal Brandc639ac82015-07-02 08:53:34 +0200209 va_end(ArgList);
210 }
211
212
213 SubCase_p = Case_p->CurrentSubCase_p;
214
215 if (SubCase_p == NULL) {
216 Do_ADBG_Log("Do_ADBG_EndSubCase: "
217 "Have no active SubCase, bailing out for title \"%s\"",
218 Title);
219 return;
220 }
221
222 if (FormatTitle_p != NULL && strcmp(SubCase_p->Title_p, Title) != 0) {
223 Do_ADBG_Log("Do_ADBG_EndSubCase: "
224 "Active SubCase \"%s\" doesn't match supplied title \"%s\"",
225 SubCase_p->Title_p, Title);
226 return;
227 }
228
229 if (ADBG_Case_SubCaseIsMain(Case_p, SubCase_p)) {
230 if (FormatTitle_p == NULL) {
231 /* To end the main subcase we require
232 a matching title */
233 Do_ADBG_Log("Do_ADBG_EndSubCase: "
234 "The main SubCase \"%s\" doesn't match supplied title \"%s\"",
235 SubCase_p->Title_p, Title);
236 return;
237 }
238 /*
239 * Ending the main subcase
240 * make a complete copy of the aggregated result.
241 */
242 Case_p->Result = SubCase_p->Result;
243 } else {
244 /*
245 * Ending a subcase,
246 * Aggregate results to parent.
247 */
248 ADBG_SubCase_t *Parent_p = SubCase_p->Parent_p;
249
250 Parent_p->Result.NumSubTests += SubCase_p->Result.NumTests +
251 SubCase_p->Result.NumSubTests;
252 Parent_p->Result.NumFailedSubTests +=
253 SubCase_p->Result.NumFailedTests +
254 SubCase_p->Result.
255 NumFailedSubTests;
256 Parent_p->Result.AbortTestSuite =
257 SubCase_p->Result.AbortTestSuite;
258 if (SubCase_p->Result.NumTests > 0 ||
259 SubCase_p->Result.NumSubTests > 0)
260 Parent_p->Result.NumFailedSubCases++;
261 }
262
263 /* Print a summary of the subcase result */
264 if (SubCase_p->Result.NumFailedTests > 0 ||
265 SubCase_p->Result.NumFailedSubTests > 0) {
266 Do_ADBG_Log(" %s FAILED", SubCase_p->TestID_p);
267 } else {
268 Do_ADBG_Log(" %s OK", SubCase_p->TestID_p);
269 }
270
271 /* Update current subcase to be the parent of this subcase */
272 Case_p->CurrentSubCase_p =
273 ADBG_Case_GetParentSubCase(Case_p, SubCase_p);
274}
275
Pascal Brandc639ac82015-07-02 08:53:34 +0200276/*************************************************************************
277* 6. Definition of internal functions
278*************************************************************************/
279static ADBG_SubCase_t *ADBG_Case_CreateSubCase(
280 ADBG_Case_t *Case_p,
281 const char *const Title_p
282 )
283{
284 ADBG_SubCase_t *SubCase_p;
285
286 SubCase_p = HEAP_ALLOC(ADBG_SubCase_t);
287 if (SubCase_p == NULL)
288 goto ErrorReturn;
289
290 memset(SubCase_p, 0, sizeof(ADBG_SubCase_t));
291 TAILQ_INIT(&SubCase_p->SubCasesList);
292
293 SubCase_p->Title_p = SECUTIL_HEAP_STRDUP(Title_p);
294 if (SubCase_p->Title_p == NULL)
295 goto ErrorReturn;
296
297 /* Set parent pointer needed "early" below. */
298 SubCase_p->Parent_p = Case_p->CurrentSubCase_p;
299
300 if (SubCase_p->Parent_p == NULL) {
301 /* Main SubCase */
302 SubCase_p->TestID_p =
303 SECUTIL_HEAP_STRDUP(ADBG_Case_GetTestID(Case_p));
304 if (SubCase_p->TestID_p == NULL)
305 goto ErrorReturn;
306
307 Case_p->FirstSubCase_p = SubCase_p;
308 } else {
309 ADBG_SubCase_t *Parent_p = SubCase_p->Parent_p;
310 char PrefixTitle[80];
311
312 /* Update parent SubCase */
313 Parent_p->Result.NumSubCases++;
Jens Wiklander7e7c9c52016-12-27 17:57:46 +0100314 snprintf(PrefixTitle, sizeof(PrefixTitle), "%s.%d",
315 Parent_p->TestID_p, Parent_p->Result.NumSubCases);
Pascal Brandc639ac82015-07-02 08:53:34 +0200316 SubCase_p->TestID_p = SECUTIL_HEAP_STRDUP(PrefixTitle);
317 if (SubCase_p->TestID_p == NULL)
318 goto ErrorReturn;
319
320 TAILQ_INSERT_TAIL(&Parent_p->SubCasesList, SubCase_p, Link);
321 }
322
323 Case_p->CurrentSubCase_p = SubCase_p;
324 return SubCase_p;
325
326ErrorReturn:
327 ADBG_SubCase_Delete(SubCase_p);
328 return NULL;
329}
330
331static void ADBG_SubCase_Delete(
332 ADBG_SubCase_t *SubCase_p
333 )
334{
335 if (SubCase_p != NULL) {
336 /*
337 * Note that Util_ListDestroy() checks
338 * if SubCase_p->SubCasesList_p
339 * is NULL.
340 */
341 while (true) {
342 ADBG_SubCase_t *s =
343 TAILQ_FIRST(&SubCase_p->SubCasesList);
344
345 if (s == NULL)
346 break;
347
348 TAILQ_REMOVE(&SubCase_p->SubCasesList, s, Link);
349 ADBG_SubCase_Delete(s);
350 }
351 HEAP_FREE(&SubCase_p->TestID_p);
352 HEAP_FREE(&SubCase_p->Title_p);
353 HEAP_FREE(&SubCase_p);
354 }
355}
356
357ADBG_SubCase_t *ADBG_Case_GetParentSubCase(
358 ADBG_Case_t *Case_p,
359 ADBG_SubCase_t *SubCase_p
360 )
361{
362 IDENTIFIER_NOT_USED(Case_p)
363 IDENTIFIER_NOT_USED(SubCase_p)
364 return SubCase_p->Parent_p;
365}
366
367static const char *ADBG_Case_GetTestID(ADBG_Case_t *Case_p)
368{
369 IDENTIFIER_NOT_USED(Case_p)
370
371 return Case_p->SuiteEntry_p->CaseDefinition_p->TestID_p;
372}