1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "helper.h"
17 #include <dirent.h>
18 #include "securec.h"
19 #include "crypt_utils.h"
20
21 #define INCLUDE_BASE "/* INCLUDE_BASE"
22 #define BEGIN_HEADER "/* BEGIN_HEADER */"
23 #define END_HEADER "/* END_HEADER */"
24 #define BEGIN_CASE "/* BEGIN_CASE */"
25 #define END_CASE "/* END_CASE */"
26
27 #define PRINT_TESTSUITES_TAG "</testsuites>\n"
28 #define PRINT_TESTSUITE_TAG " </testsuite>\n"
29 #define PRINT_TESTCASE_TAG " </testcase>\n"
30 #define PRINT_TESTCASE_LIST_TAG " <testcase name=\"%s\" status=\"run\" time=\"0\" classname=\"%s\" />\n"
31 #define PRINT_FAILURE_TAG " <failure message=\"failed\" type=\"\" />\n"
32
33 #define LINE_BREAK_SYMBOL '\n'
34 #define LINE_HEAD_SYMBOL '\r'
35
36 FunctionTable g_testFunc[MAX_TEST_FUCNTION_COUNT];
37 int g_testFuncCount = 0;
38 char g_expTable[MAX_EXPRESSION_COUNT][MAX_EXPRESSION_LEN];
39 int g_expCount = 0;
40 FILE *g_fpOutput = NULL;
41 int g_lineCount = 0;
42 char g_suiteFileName[MAX_FILE_PATH_LEN];
43
SetOutputFile(FILE * fp)44 void SetOutputFile(FILE *fp)
45 {
46 g_fpOutput = fp;
47 }
48
GetOutputFile(void)49 FILE *GetOutputFile(void)
50 {
51 return g_fpOutput;
52 }
53
FreeHex(Hex * data)54 void FreeHex(Hex *data)
55 {
56 if (data == NULL) {
57 return;
58 }
59 data->len = 0;
60 if (data->x != NULL) {
61 free(data->x);
62 data->x = NULL;
63 }
64 }
65
NewHex(void)66 Hex *NewHex(void)
67 {
68 Hex *data = (Hex *)malloc(sizeof(Hex));
69 if (data == NULL) {
70 return NULL;
71 }
72 data->len = 0;
73 data->x = NULL;
74 return data;
75 }
76
IsInt(const char * str)77 int IsInt(const char *str)
78 {
79 uint32_t i = 0;
80 if (str[0] == '-') {
81 i = 1;
82 }
83 for (; i < strlen(str); i++) {
84 if (str[i] > '9' || str[i] < '0') {
85 return 0;
86 }
87 }
88 return 1;
89 }
90
Print(const char * fmt,...)91 void Print(const char *fmt, ...)
92 {
93 #ifdef PRINT_TO_TERMINAL
94 va_list args;
95 va_start(args, fmt);
96 vprintf(fmt, args);
97 va_end(args);
98 #else
99 va_list args;
100 va_start(args, fmt);
101 (void)vfprintf(g_fpOutput, fmt, args);
102 va_end(args);
103 #endif
104 }
105
ReadLine(FILE * file,char * buf,uint32_t bufLen,bool skipHash,bool skipEmptyLine)106 int ReadLine(FILE *file, char *buf, uint32_t bufLen, bool skipHash, bool skipEmptyLine)
107 {
108 int foundLine = 0;
109 int i;
110 char *ret = NULL;
111 while (!foundLine) {
112 ret = fgets(buf, bufLen, file);
113 if (ret == NULL) {
114 return -1;
115 }
116 g_lineCount++;
117
118 int len = strlen(buf);
119 if ((buf[0] == '#') && skipHash) {
120 continue;
121 }
122 if (!skipEmptyLine) {
123 foundLine = 1;
124 }
125 for (i = 0; i < len; i++) {
126 char cur = buf[i];
127 if (cur != ' ' && cur != LINE_BREAK_SYMBOL && cur != LINE_HEAD_SYMBOL) {
128 foundLine = 1;
129 }
130 if (cur == LINE_BREAK_SYMBOL || cur == LINE_HEAD_SYMBOL) {
131 buf[i] = '\0';
132 break;
133 }
134 }
135 }
136 return 0;
137 }
138
SplitArguments(char * inStr,uint32_t inLen,char ** outParam,uint32_t * paramLen)139 int SplitArguments(char *inStr, uint32_t inLen, char **outParam, uint32_t *paramLen)
140 {
141 uint32_t cur = 0;
142 uint32_t count = 0;
143 bool inString = false;
144 char *in = inStr;
145 char **param = outParam;
146
147 param[count] = &in[cur];
148 count++;
149 cur++;
150 if (count > *paramLen) {
151 return 1;
152 }
153 while (cur < inLen && in[cur] != '\0') {
154 if (in[cur] == '\"') {
155 inString = !inString;
156 }
157 if (in[cur] == ':' && !inString) {
158 if (cur == inLen - 1) {
159 param[count] = &in[cur];
160 } else {
161 param[count] = &in[cur + 1];
162 count++;
163 }
164 if (count > *paramLen) {
165 printf("Exceed maximum param limit, expect num %u, actual num %u\n",
166 *paramLen, count);
167 return 1;
168 }
169 in[cur] = '\0';
170 }
171 cur++;
172 }
173 if (in[cur - 1] == '\n') {
174 in[cur - 1] = '\0';
175 }
176
177 *paramLen = count;
178 if (inString) {
179 return 1;
180 }
181 return 0;
182 }
183 static int g_fuzzEnd = 0;
CheckTag(char * in,uint32_t len)184 int CheckTag(char *in, uint32_t len)
185 {
186 char *cur = in;
187 while (*cur == ' ') {
188 cur++;
189 }
190
191 uint32_t beginHeaderLen = strlen(BEGIN_HEADER);
192 uint32_t endHeaderLen = strlen(END_HEADER);
193 uint32_t beginCaseLen = strlen(BEGIN_CASE);
194 uint32_t endCaseLen = strlen(END_CASE);
195 uint32_t includeBaseLen = strlen(INCLUDE_BASE);
196
197 if ((len >= beginHeaderLen) && (strlen(cur) >= beginHeaderLen) &&
198 (strncmp(cur, BEGIN_HEADER, beginHeaderLen) == 0)) {
199 return TAG_BEGIN_HEADER;
200 } else if ((len >= endHeaderLen) && (strlen(cur) >= endHeaderLen) &&
201 (strncmp(cur, END_HEADER, endHeaderLen) == 0)) {
202 return TAG_END_HEADER;
203 } else if ((len >= beginCaseLen) && (strlen(cur) >= beginCaseLen) &&
204 (strncmp(cur, BEGIN_CASE, beginCaseLen) == 0)) {
205 return TAG_BEGIN_CASE;
206 } else if ((len >= endCaseLen) && (strlen(cur) >= endCaseLen) &&
207 (strncmp(cur, END_CASE, endCaseLen) == 0)) {
208 return TAG_END_CASE;
209 } else if ((len >= includeBaseLen) && (strlen(cur) >= includeBaseLen) &&
210 (strncmp(cur, INCLUDE_BASE, includeBaseLen) == 0)) {
211 return TAG_INCLUDE_BASE;
212 }
213 return TAG_NOT_TAG;
214 }
215
ClearVoid(const char * in,const uint32_t inLen,uint32_t * cur,uint32_t * prev)216 static int ClearVoid(const char *in, const uint32_t inLen, uint32_t *cur, uint32_t *prev)
217 {
218 uint32_t localCur = *cur;
219 uint32_t localPrev;
220 while (localCur < inLen && in[localCur] == ' ') {
221 localCur++;
222 }
223 localPrev = localCur;
224
225 if (strncmp(&in[localCur], "void", strlen("void")) != 0) {
226 return 1;
227 }
228
229 localCur += strlen("void");
230 while (localCur < inLen && in[localCur] == ' ') {
231 localCur++;
232 }
233 localPrev = localCur;
234
235 *cur = localCur;
236 *prev = localPrev;
237 return 0;
238 }
239
NextArgument(const char * in,const uint32_t inLen,uint32_t * cur)240 static int NextArgument(const char *in, const uint32_t inLen, uint32_t *cur)
241 {
242 uint32_t localCur = *cur;
243
244 while (localCur < inLen && in[localCur] != ',' && in[localCur] != ')') {
245 localCur++;
246 }
247
248 if (localCur >= inLen) {
249 return 1;
250 }
251
252 *cur = localCur;
253 return 0;
254 }
255
CheckType(const char * in,const uint32_t cur,const uint32_t prev,int * outType)256 static int CheckType(const char *in, const uint32_t cur, const uint32_t prev, int *outType)
257 {
258 int *type = outType;
259 if ((cur - prev == strlen("int")) && (strncmp(&in[prev], "int", strlen("int")) == 0)) {
260 *type = ARG_TYPE_INT;
261 } else if ((cur - prev == strlen("Hex")) && (strncmp(&in[prev], "Hex", strlen("Hex")) == 0)) {
262 *type = ARG_TYPE_HEX;
263 } else if ((cur - prev == strlen("char")) && (strncmp(&in[prev], "char", strlen("char")) == 0)) {
264 *type = ARG_TYPE_STR;
265 } else {
266 return 1;
267 }
268
269 return 0;
270 }
271
ReadFunction(const char * in,const uint32_t inLen,char * outFuncName,uint32_t outLen,int argv[MAX_ARGUMENT_COUNT],uint32_t * argCount)272 int ReadFunction(const char *in, const uint32_t inLen, char *outFuncName, uint32_t outLen, int argv[MAX_ARGUMENT_COUNT],
273 uint32_t *argCount)
274 {
275 uint32_t cur = 0;
276 uint32_t prev = 0;
277 char *funcName = outFuncName;
278
279 if (ClearVoid(in, inLen, &cur, &prev) != 0) {
280 return 1;
281 }
282
283 // get function name
284 while (cur < inLen && in[cur] != '(') {
285 cur++;
286 }
287 if (cur >= inLen) {
288 return 1;
289 }
290 if (strncpy_s(funcName, outLen, &in[prev], cur - prev) != 0) {
291 return 1;
292 }
293 funcName[cur - prev] = '\0';
294 cur++;
295
296 // get argument types
297 uint32_t count = 0;
298 while (cur < inLen) {
299 while (cur < inLen && in[cur] == ' ') {
300 cur++;
301 }
302 prev = cur;
303
304 while (cur < inLen && in[cur] != ' ' && in[cur] != ',' && in[cur] != '*' && in[cur] != ')') {
305 cur++;
306 }
307
308 if (in[cur] == ')') {
309 break;
310 }
311
312 if (cur == inLen || in[cur] == ',') {
313 return 1;
314 }
315
316 int type = -1;
317 if (CheckType(in, cur, prev, &type) != 0) {
318 Print("******\nERROR: check type failed at: \n");
319 return 1;
320 }
321 argv[count] = type;
322
323 count++;
324 if (NextArgument(in, inLen, &cur) != 0) {
325 return 1;
326 }
327 if (in[cur] == ')') {
328 break;
329 }
330 cur++;
331 }
332
333 *argCount = count;
334
335 return 0;
336 }
337
AddFunction(const char * funcName,int argv[MAX_ARGUMENT_COUNT],const uint32_t argCount)338 int AddFunction(const char *funcName, int argv[MAX_ARGUMENT_COUNT], const uint32_t argCount)
339 {
340 if (g_testFuncCount >= MAX_TEST_FUCNTION_COUNT || argCount > MAX_ARGUMENT_COUNT) {
341 return 1;
342 }
343
344 if (strcpy_s(g_testFunc[g_testFuncCount].name, MAX_TEST_FUNCTION_NAME, funcName) != 0) {
345 return 1;
346 }
347 g_testFunc[g_testFuncCount].argCount = argCount;
348 for (uint32_t i = 0; i < argCount; i++) {
349 g_testFunc[g_testFuncCount].argType[i] = argv[i];
350 }
351
352 g_testFunc[g_testFuncCount].id = g_testFuncCount;
353 g_testFuncCount++;
354
355 return 0;
356 }
357
GenFunctionWrapper(FILE * file,FunctionTable * function)358 int GenFunctionWrapper(FILE *file, FunctionTable *function)
359 {
360 int ret;
361 ret = fprintf(file, "void %s_wrapper(void **param)\n", function->name);
362 if (ret < 0) {
363 return 1;
364 }
365 ret = fprintf(file, "{\n");
366 if (ret < 0) {
367 return 1;
368 }
369 if (function->argCount == 0) {
370 ret = fprintf(file, " (void) param;\n");
371 if (ret < 0) {
372 return 1;
373 }
374 }
375 ret = fprintf(file, " %s(", function->name);
376 if (ret < 0) {
377 return 1;
378 }
379 for (uint32_t i = 0; i < function->argCount; i++) {
380 if (function->argType[i] == ARG_TYPE_INT) {
381 ret = fprintf(file, "*((int*)param[%d])", (int)i);
382 if (ret < 0) {
383 return 1;
384 }
385 } else if (function->argType[i] == ARG_TYPE_STR) {
386 ret = fprintf(file, "(char*)param[%d]", (int)i);
387 if (ret < 0) {
388 return 1;
389 }
390 } else if (function->argType[i] == ARG_TYPE_HEX) {
391 ret = fprintf(file, "(Hex*)param[%d]", (int)i);
392 if (ret < 0) {
393 return 1;
394 }
395 }
396 if (i != function->argCount - 1) {
397 ret = fprintf(file, ", ");
398 if (ret < 0) {
399 return 1;
400 }
401 }
402 }
403 ret = fprintf(file, ");\n}\n\n");
404 if (ret < 0) {
405 return 1;
406 }
407 return 0;
408 }
409
GenFunctionPointer(FILE * file)410 int GenFunctionPointer(FILE *file)
411 {
412 if (file == NULL) {
413 return 1;
414 }
415 int ret;
416 ret = fprintf(file, "%s\n\n", "typedef void (*TestWrapper)(void **param);");
417 if (ret < 0) {
418 return 1;
419 }
420 ret = fprintf(file, "%s\n%s\n", "TestWrapper test_funcs[] = ", "{");
421 if (ret < 0) {
422 return 1;
423 }
424 for (int i = 0; i < g_testFuncCount; i++) {
425 ret = fprintf(file, " %s_wrapper, \n", g_testFunc[i].name);
426 if (ret < 0) {
427 return 1;
428 }
429 }
430 ret = fprintf(file, "%s\n", "};");
431 if (ret < 0) {
432 return 1;
433 }
434 return 0;
435 }
436
ConnectFunction(char * lineBuf,uint32_t bufLen,FILE * fp)437 static int ConnectFunction(char *lineBuf, uint32_t bufLen, FILE *fp)
438 {
439 char buf[MAX_FUNCTION_LINE_LEN];
440 bool reachEnd = false;
441 int ret = 0;
442 while (!reachEnd) {
443 for (int i = 0; lineBuf[i] != '\0'; i++) {
444 if (lineBuf[i] == ')') {
445 ret = 0;
446 reachEnd = true;
447 }
448 if (lineBuf[i] == '{') {
449 ret = 1;
450 reachEnd = true;
451 }
452 }
453 if (reachEnd) {
454 break;
455 }
456 if (ReadLine(fp, buf, MAX_FUNCTION_LINE_LEN, 0, 0) == 0) {
457 if (strcat_s(lineBuf, bufLen, buf) != 0) {
458 return 1;
459 }
460 } else {
461 return 1;
462 }
463 }
464 return ret;
465 }
466
ScanAllFunction(FILE * inFile,FILE * outFile)467 int ScanAllFunction(FILE *inFile, FILE *outFile)
468 {
469 char buf[MAX_FUNCTION_LINE_LEN];
470 int ret = 0;
471 uint32_t len = MAX_ARGUMENT_COUNT;
472 bool inFunction = false;
473 bool isDeclaration = true;
474 int arguments[MAX_ARGUMENT_COUNT];
475 char funcName[MAX_TEST_FUNCTION_NAME];
476 while (ReadLine(inFile, buf, MAX_FUNCTION_LINE_LEN, 0, 0) == 0) {
477 int curTag = CheckTag(buf, strlen(buf));
478 if (curTag == TAG_NOT_TAG) {
479 if (!inFunction) {
480 fprintf(outFile, "%s\n", buf);
481 continue;
482 }
483 } else if (curTag == TAG_BEGIN_CASE) {
484 if (!inFunction) {
485 inFunction = true;
486 isDeclaration = true;
487 continue;
488 }
489 Print("ERROR: missing end case tag\n");
490 return 1;
491 } else if (curTag == TAG_END_CASE) {
492 if (inFunction) {
493 inFunction = false;
494 fprintf(outFile, "\n");
495 continue;
496 }
497 return 1;
498 } else {
499 return 1;
500 }
501
502 if (isDeclaration) {
503 if (ConnectFunction(buf, sizeof(buf), inFile) != 0) {
504 Print("******\nERROR: connect function failed at: \n");
505 Print("%s\n", buf);
506 return 1;
507 }
508 ret = ReadFunction(buf, strlen(buf), funcName, sizeof(funcName), arguments, &len);
509 if (ret != 0) {
510 Print("*******\nERROR: Read function failed at: \n");
511 Print("%s\n", buf);
512 return ret;
513 }
514 ret = AddFunction(funcName, arguments, len);
515 if (ret != 0) {
516 return ret;
517 }
518 isDeclaration = false;
519 len = MAX_ARGUMENT_COUNT;
520 }
521
522 (void)fprintf(outFile, "%s\n", buf);
523 }
524
525 return 0;
526 }
527
IncludeBase(char * line,uint32_t len,FILE * outFile,const char * dir)528 static int IncludeBase(char *line, uint32_t len, FILE *outFile, const char *dir)
529 {
530 if (len < strlen(INCLUDE_BASE)) {
531 return 1;
532 }
533
534 char *name = &line[strlen(INCLUDE_BASE)];
535 while (*name == ' ') {
536 name++;
537 }
538
539 if (*name == '\0') {
540 return 1;
541 }
542
543 char *end = name;
544
545 while (*end != ' ') {
546 end++;
547 }
548 *end = '\0';
549
550 char fileBuf[MAX_FILE_PATH_LEN];
551 if (snprintf_s(fileBuf, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN, BASE_FILE_FORMAT, dir, name) == -1) {
552 return 1;
553 }
554 g_lineCount = 0;
555 FILE *fpBase = fopen(fileBuf, "r");
556 if (fpBase == NULL) {
557 Print("ERROR:Open the base file. %s An error occurred when\n", fileBuf);
558 return 1;
559 }
560
561 int ret;
562 char buf[MAX_FUNCTION_LINE_LEN];
563 while (ReadLine(fpBase, buf, MAX_FUNCTION_LINE_LEN, 0, 0) == 0) {
564 ret = fprintf(outFile, "%s\n", buf);
565 if (ret < 0) {
566 goto EXIT;
567 }
568 }
569
570 EXIT:
571 if (fclose(fpBase) != 0) {
572 Print("base file close failed\n");
573 }
574 return 0;
575 }
576
WriteHeader(FILE * outFile)577 int WriteHeader(FILE *outFile)
578 {
579 if (fprintf(outFile, "#include \"helper.h\"\n#include \"test.h\"\n#include <time.h>\n") < 0) {
580 return 1;
581 }
582 return 0;
583 }
584
ScanHeader(FILE * inFile,FILE * outFile,const char * dir)585 int ScanHeader(FILE *inFile, FILE *outFile, const char *dir)
586 {
587 char buf[MAX_FUNCTION_LINE_LEN];
588 bool inHeader = false;
589
590 while (ReadLine(inFile, buf, MAX_FUNCTION_LINE_LEN, 0, !inHeader) == 0) {
591 int curTag = CheckTag(buf, strlen(buf));
592 if (curTag == TAG_BEGIN_HEADER) {
593 if (!inHeader) {
594 inHeader = true;
595 } else {
596 Print("******\nERROR: duplicate begin header tag\n");
597 return 1;
598 }
599 } else if (curTag == TAG_END_HEADER) {
600 if (inHeader) {
601 (void)fprintf(outFile, "%s\n", buf);
602 return 0;
603 } else {
604 Print("******\nERROR: found end header without begin\n");
605 return 1;
606 }
607 } else if (curTag == TAG_INCLUDE_BASE) {
608 int tmpLineCount = g_lineCount;
609 if (IncludeBase(buf, strlen(buf), outFile, dir) != 0) {
610 Print("******\nERROR: include base file failed\n");
611 return 1;
612 }
613 g_lineCount = tmpLineCount;
614 continue;
615 } else if (curTag != TAG_NOT_TAG) {
616 Print("******\nERROR: missing end header tag\n");
617 return 1;
618 }
619 (void)fprintf(outFile, "%s\n", buf);
620 }
621 return 0;
622 }
623
AddExp(const char * exp)624 static int AddExp(const char *exp)
625 {
626 if (g_expCount >= MAX_EXPRESSION_COUNT) {
627 Print("Too much macros. Max macro count is %d\n", MAX_EXPRESSION_COUNT);
628 return -1;
629 }
630 for (int i = 0; i < g_expCount; i++) {
631 if (strcmp(exp, g_expTable[i]) == 0) {
632 return i;
633 }
634 }
635 if (strcpy_s(g_expTable[g_expCount], MAX_EXPRESSION_LEN, exp) != 0) {
636 Print("Macro too long, max length is %d\n", MAX_EXPRESSION_LEN);
637 return -1;
638 }
639 g_expCount++;
640 return g_expCount - 1;
641 }
642
GetFuncIdByName(const char * name,uint32_t len)643 static int GetFuncIdByName(const char *name, uint32_t len)
644 {
645 int funcId = -1;
646 for (int i = 0; i < g_testFuncCount; i++) {
647 if ((len < MAX_TEST_FUNCTION_NAME) && (strcmp(name, g_testFunc[i].name) == 0)) {
648 funcId = i;
649 break;
650 }
651 }
652
653 return funcId;
654 }
655
GenDatax(FILE * inFile,FILE * outFile)656 int GenDatax(FILE *inFile, FILE *outFile)
657 {
658 char buf[MAX_DATA_LINE_LEN];
659 char title[MAX_DATA_LINE_LEN];
660 int ret;
661 int funcId = -1;
662 char *param[MAX_ARGUMENT_COUNT];
663 uint32_t paramLen = MAX_ARGUMENT_COUNT;
664 while (ReadLine(inFile, title, MAX_DATA_LINE_LEN, 1, 1) == 0) {
665 ret = fprintf(outFile, "%s\n", title);
666 if (ret < 0) {
667 return 1;
668 }
669
670 if ((ReadLine(inFile, buf, MAX_DATA_LINE_LEN, 1, 1) != 0)) {
671 return 1;
672 }
673 paramLen = MAX_ARGUMENT_COUNT;
674 ret = SplitArguments(buf, strlen(buf), param, ¶mLen);
675 if (ret != 0) {
676 Print("******\nERROR: Generate datax failed: split argument failed at testcase:\n");
677 Print("%s\n", title);
678 return ret;
679 }
680
681 funcId = GetFuncIdByName(param[0], strlen(param[0]));
682 if (funcId == -1) {
683 Print("******\nERROR: Generate datax failed: no function id for %s at testcase:\n", param[0]);
684 Print("%s\n", title);
685 return 1;
686 }
687
688 if (paramLen != g_testFunc[funcId].argCount + 1) {
689 Print("******\nERROR: Generate datax failed: invalid argument count for function %s at testcase:\n",
690 param[0]);
691 Print("%s\n", title);
692 return 1;
693 }
694
695 ret = fprintf(outFile, "%d:", funcId);
696 if (ret < 0) {
697 return 1;
698 }
699 int expId = 0;
700 for (uint32_t i = 0; i < g_testFunc[funcId].argCount; i++) {
701 if (g_testFunc[funcId].argType[i] == ARG_TYPE_INT && (IsInt(param[i + 1]) == 1)) {
702 ret = fprintf(outFile, "int:%s", param[i + 1]);
703 } else if (g_testFunc[funcId].argType[i] == ARG_TYPE_INT && (!IsInt(param[i + 1]))) {
704 expId = AddExp(param[i + 1]);
705 ret = fprintf(outFile, "exp:%d", expId);
706 } else if (g_testFunc[funcId].argType[i] == ARG_TYPE_STR) {
707 ret = fprintf(outFile, "char:%s", param[i + 1]);
708 } else if (g_testFunc[funcId].argType[i] == ARG_TYPE_HEX) {
709 ret = fprintf(outFile, "Hex:%s", param[i + 1]);
710 } else {
711 Print("invalid argument type\n");
712 return 1;
713 }
714 if (ret < 0) {
715 return 1;
716 }
717 if (i != g_testFunc[funcId].argCount - 1) {
718 ret = fprintf(outFile, ":");
719 }
720 if (expId == -1) {
721 return 1;
722 }
723 expId = 0;
724 }
725 ret = fprintf(outFile, "\n\n");
726 if (ret < 0) {
727 return 1;
728 }
729 }
730
731 return 0;
732 }
733
GenExpTable(FILE * outFile)734 int GenExpTable(FILE *outFile)
735 {
736 int ret;
737 ret = fprintf(outFile, "int getExpression(int expId, int *out)\n{\n");
738 if (ret < 0) {
739 return 1;
740 }
741 if (g_expCount == 0) {
742 ret = fprintf(outFile, " (void) out;\n (void) expId;\n");
743 if (ret < 0) {
744 return 1;
745 }
746 }
747 ret = fprintf(outFile, " int ret = 0;\n");
748 if (ret < 0) {
749 return 1;
750 }
751 ret = fprintf(outFile, " switch (expId)\n {\n");
752 if (ret < 0) {
753 return 1;
754 }
755
756 for (int i = 0; i < g_expCount; i++) {
757 ret = fprintf(outFile, " case %d:\n", i);
758 if (ret < 0) {
759 return 1;
760 }
761 ret = fprintf(outFile, " *out = %s;\n", g_expTable[i]);
762 if (ret < 0) {
763 return 1;
764 }
765 ret = fprintf(outFile, " break;\n");
766 if (ret < 0) {
767 return 1;
768 }
769 }
770
771 ret = fprintf(outFile, " default:\n");
772 if (ret < 0) {
773 return 1;
774 }
775 ret = fprintf(outFile, " ret = 1;\n");
776 if (ret < 0) {
777 return 1;
778 }
779 ret = fprintf(outFile, " break;\n");
780 if (ret < 0) {
781 return 1;
782 }
783 ret = fprintf(outFile, " }\n return ret;\n}\n");
784 if (ret < 0) {
785 return 1;
786 }
787
788 return 0;
789 }
790
LoadFunctionName(FILE * outFile)791 int LoadFunctionName(FILE *outFile)
792 {
793 int ret;
794 ret = fprintf(outFile, "const char * funcName[] = {\n");
795 if (ret < 0) {
796 return 1;
797 }
798 for (int i = 0; i < g_testFuncCount; i++) {
799 ret = fprintf(outFile, " \"%s\",\n", g_testFunc[i].name);
800 if (ret < 0) {
801 return 1;
802 }
803 }
804 ret = fprintf(outFile, "};\n\n");
805 if (ret < 0) {
806 return 1;
807 }
808 return 0;
809 }
810
LoadHelper(FILE * inFile,FILE * outFile)811 int LoadHelper(FILE *inFile, FILE *outFile)
812 {
813 int ret;
814 char buf[MAX_FUNCTION_LINE_LEN];
815 if (inFile == NULL || outFile == NULL) {
816 return 1;
817 }
818 while (fgets(buf, MAX_FUNCTION_LINE_LEN, inFile) != NULL) {
819 ret = fprintf(outFile, "%s", buf);
820 if (ret < 0) {
821 return 1;
822 }
823 }
824 (void)fprintf(outFile, "\n\n");
825 return 0;
826 }
827
SplitHex(Hex * src,Hex * dest,int max)828 int SplitHex(Hex *src, Hex *dest, int max)
829 {
830 uint32_t blocks = src->len / SPILT_HEX_BLOCK_SIZE;
831 uint32_t remain = src->len % SPILT_HEX_BLOCK_SIZE;
832 uint32_t i;
833 if (blocks + 1 > (uint32_t)max) {
834 return 0;
835 }
836 for (i = 0; i < blocks; i++) {
837 dest[i].x = src->x + i * SPILT_HEX_BLOCK_SIZE;
838 dest[i].len = SPILT_HEX_BLOCK_SIZE;
839 }
840
841 if (remain == 0) {
842 return blocks;
843 } else {
844 dest[i].x = src->x + i * SPILT_HEX_BLOCK_SIZE;
845 dest[i].len = remain;
846 return blocks + 1;
847 }
848 }
849
850
SplitHexRand(Hex * src,Hex * dest,int max)851 int SplitHexRand(Hex *src, Hex *dest, int max)
852 {
853 uint32_t left = src->len;
854 int id = 0;
855
856 if (left <= 3) {
857 dest[id].x = src->x;
858 dest[id].len = left;
859 id++;
860 return id;
861 }
862
863 while (left > 3) {
864 dest[id].x = src->x + (src->len - left);
865 uint16_t clen = GET_UINT16_LE(dest[id].x, 0);
866 dest[id].len = clen > left ? left : clen;
867 left -= dest[id].len;
868 id++;
869 if (id > max - 1) {
870 break;
871 }
872 }
873
874 if (left > 0) {
875 dest[id - 1].len += left;
876 }
877
878 return id;
879 }
880
OpenFile(const char * name,const char * option,const char * format)881 FILE *OpenFile(const char *name, const char *option, const char *format)
882 {
883 FILE *fp = NULL;
884 char fileBuf[MAX_FILE_PATH_LEN];
885 if (snprintf_s(fileBuf, MAX_FILE_PATH_LEN, MAX_FILE_PATH_LEN, format, name) == -1) {
886 Print("argument too long\n");
887 return NULL;
888 }
889 fp = fopen(fileBuf, option);
890 return fp;
891 }
892
StripDir(const char * in,char * suiteName,const uint32_t suiteNameLen,char * dir,const uint32_t dirNameLen)893 int StripDir(const char *in, char *suiteName, const uint32_t suiteNameLen, char *dir, const uint32_t dirNameLen)
894 {
895 int len = strlen(in);
896 int begin = len - 1;
897
898 char *localDir = dir;
899 char *localSuiteName = suiteName;
900 while (begin >= 0 && in[begin] != '/') {
901 begin--;
902 }
903
904 if (begin < 0) {
905 return 1;
906 }
907
908 if (strncpy_s(localDir, dirNameLen, in, begin) != 0) {
909 return 1;
910 }
911
912 if (strcpy_s(localSuiteName, suiteNameLen, &in[begin + 1]) != 0) {
913 return 1;
914 }
915
916 if (strcpy_s(g_suiteFileName, MAX_FILE_PATH_LEN, &in[begin + 1]) != 0) {
917 return 1;
918 }
919
920 return 0;
921 }
922
ScanFunctionFile(FILE * fpIn,FILE * fpOut,const char * dir)923 int ScanFunctionFile(FILE *fpIn, FILE *fpOut, const char *dir)
924 {
925 int ret;
926 ret = ScanHeader(fpIn, fpOut, dir);
927 if (ret != 0) {
928 Print("scan header failed\n");
929 return 1;
930 }
931
932 ret = ScanAllFunction(fpIn, fpOut);
933 if (ret != 0) {
934 Print("scan function failed\n");
935 return 1;
936 }
937
938 for (int i = 0; i < g_testFuncCount; i++) {
939 ret = GenFunctionWrapper(fpOut, &g_testFunc[i]);
940 if (ret < 0) {
941 Print("generate function wrapper failed\n");
942 return 1;
943 }
944 }
945 if (g_fuzzEnd == 1) {
946 ret = fprintf(fpOut, "#define FREE_FUZZ_TC 1\n\n");
947 } else {
948 ret = fprintf(fpOut, "#define FREE_FUZZ_TC 0\n\n");
949 }
950 if (ret < 0) {
951 return 1;
952 }
953 return 0;
954 }
955
IsSuite(char * buf,uint32_t bufLen)956 static bool IsSuite(char *buf, uint32_t bufLen)
957 {
958 uint32_t beginTagLen = strlen("Begin time:");
959 uint32_t endTagLen = strlen("End time:");
960 uint32_t resultTagLen = strlen("Result:");
961 uint32_t atTagLen = strlen("at:");
962
963 if (bufLen >= beginTagLen && strncmp(buf, "Begin time:", beginTagLen) == 0) {
964 return false;
965 } else if (bufLen >= endTagLen && strncmp(buf, "End time:", endTagLen) == 0) {
966 return false;
967 } else if (bufLen >= resultTagLen && strncmp(buf, "Result:", resultTagLen) == 0) {
968 return false;
969 } else if (bufLen >= atTagLen && strncmp(buf, "at:", atTagLen) == 0) {
970 return false;
971 }
972
973 return true;
974 }
975
ReadAllLogFile(DIR * logDir,int * totalSuiteCount,FILE * outFile,TestSuiteResult * result,int resultLen)976 static int ReadAllLogFile(DIR *logDir, int *totalSuiteCount, FILE *outFile, TestSuiteResult *result, int resultLen)
977 {
978 struct dirent *dir = NULL;
979 int suiteCount = 0;
980 int cur;
981 DIR *localLogDir = logDir;
982
983 // Stores the execution results of all test cases.
984 FILE *fpAllLog = OpenFile("result.log", "w+", "%s");
985 if (fpAllLog == NULL) {
986 return 1;
987 }
988 FILE *fpLog = NULL;
989
990 while ((dir = readdir(localLogDir)) != NULL) {
991 char buf[MAX_LOG_LEN];
992 uint32_t bufLen = sizeof(buf);
993 if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) {
994 continue;
995 }
996 // len of ".log" is 4
997 if (strlen(dir->d_name) <= 4 || strlen(dir->d_name) > MAX_FILE_PATH_LEN - 1) {
998 (void)fclose(fpAllLog);
999 return 1;
1000 }
1001 fpLog = OpenFile(dir->d_name, "r", LOG_FILE_FORMAT);
1002 if (fpLog == NULL) {
1003 (void)fclose(fpAllLog);
1004 return 1;
1005 }
1006 if (suiteCount >= resultLen) {
1007 Print("Reached maximum suite count\n");
1008 (void)fclose(fpLog);
1009 (void)fclose(fpAllLog);
1010 return 1;
1011 }
1012
1013 if (strcpy_s(result[suiteCount].name, MAX_TEST_FUNCTION_NAME - 1, dir->d_name) != EOK) {
1014 Print("Dir's Name is too long\n");
1015 (void)fclose(fpLog);
1016 (void)fclose(fpAllLog);
1017 return 1;
1018 }
1019 // len of ".log" is 4
1020 result[suiteCount].name[strlen(dir->d_name) - 4] = '\0';
1021 result[suiteCount].total = 0;
1022 result[suiteCount].pass = 0;
1023 result[suiteCount].skip = 0;
1024 result[suiteCount].line = 0;
1025
1026 while (ReadLine(fpLog, buf, bufLen, 0, 0) == 0) {
1027 char testCaseName[MAX_TEST_FUNCTION_NAME];
1028 memset_s(testCaseName, MAX_TEST_FUNCTION_NAME, 0, MAX_TEST_FUNCTION_NAME);
1029 if (!IsSuite(buf, strlen(buf))) {
1030 continue;
1031 }
1032 result[suiteCount].total++;
1033 cur = 0;
1034 while (buf[cur] != '\0' && !(buf[cur] == '.' && buf[cur + 1] == '.')) {
1035 cur++;
1036 }
1037 if (buf[cur] == '\0') {
1038 Print("Read log file %s failed\n", dir->d_name);
1039 (void)fclose(fpLog);
1040 (void)fclose(fpAllLog);
1041 return 1;
1042 }
1043 if (strncpy_s(testCaseName, sizeof(testCaseName) - 1, buf, cur) != EOK) {
1044 Print("TestCaseName is too long\n");
1045 (void)fclose(fpLog);
1046 (void)fclose(fpAllLog);
1047 return 1;
1048 }
1049 testCaseName[cur] = '\0';
1050 while (buf[cur] == '.') {
1051 cur++;
1052 }
1053
1054 if (strncmp(&buf[cur], "pass", strlen("pass")) == 0) {
1055 result[suiteCount].pass++;
1056 result[suiteCount].line++;
1057 (void)fprintf(outFile, PRINT_TESTCASE_LIST_TAG, testCaseName, result[suiteCount].name);
1058 (void)fprintf(fpAllLog, "%s %s\n", testCaseName, "PASS");
1059 } else if (strncmp(&buf[cur], "skip", strlen("skip")) == 0) {
1060 result[suiteCount].skip++;
1061 result[suiteCount].line++;
1062 (void)fprintf(outFile, PRINT_TESTCASE_LIST_TAG, testCaseName, result[suiteCount].name);
1063 (void)fprintf(fpAllLog, "%s %s\n", testCaseName, "SKIP");
1064 } else {
1065 result[suiteCount].line += 3; // Incorrect test case requires 3 lines
1066 (void)fprintf(outFile, PRINT_TESTCASE_LIST_TAG, testCaseName, result[suiteCount].name);
1067 (void)fprintf(fpAllLog, "%s %s\n", testCaseName, "FAIL");
1068 (void)fprintf(outFile, PRINT_FAILURE_TAG);
1069 (void)fprintf(outFile, PRINT_TESTCASE_TAG);
1070 }
1071 }
1072 suiteCount++;
1073 cur = 0;
1074 (void)fclose(fpLog);
1075 }
1076 *totalSuiteCount = suiteCount;
1077 (void)fclose(fpAllLog);
1078 return 0;
1079 }
1080
GenResultFile(FILE * in,FILE * out,TestSuiteResult result[MAX_SUITE_COUNT],int testSuiteCount)1081 static int GenResultFile(FILE *in, FILE *out, TestSuiteResult result[MAX_SUITE_COUNT], int testSuiteCount)
1082 {
1083 int totalTests = 0;
1084 int totalPass = 0;
1085 int totalSkip = 0;
1086
1087 if (testSuiteCount >= MAX_SUITE_COUNT) {
1088 Print("suites count too great\n");
1089 return 1;
1090 }
1091
1092 for (int i = 0; i < testSuiteCount; i++) {
1093 totalTests += result[i].total;
1094 totalPass += result[i].pass;
1095 totalSkip += result[i].skip;
1096 }
1097 (void)fprintf(out, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1098 (void)fprintf(out, "<testsuites tests=\"%d\" failures=\"%d\" disabled=\"%d\" errors=\"0\" ", totalTests,
1099 totalTests - totalPass - totalSkip, totalSkip);
1100 (void)fprintf(out, "timestamp=\"0000-00-00T00:00:00\" time=\"0\" name=\"AllTests\">\n");
1101
1102 for (int i = 0; i < testSuiteCount; i++) {
1103 (void)fprintf(out,
1104 " <testsuite name=\"%s\" tests=\"%d\" skips = \"%d\" failures=\"%d\" ",
1105 result[i].name, result[i].total, result[i].skip,
1106 result[i].total - result[i].pass - result[i].skip);
1107 (void)fprintf(out, "disabled=\"0\" errors=\"0\" time=\"0\">\n");
1108
1109 for (int j = 0; j < result[i].line; j++) {
1110 char buf[MAX_LOG_LEN];
1111 if (fgets(buf, sizeof(buf), in) != NULL) {
1112 (void)fputs(buf, out);
1113 } else {
1114 return 1;
1115 }
1116 }
1117 (void)fprintf(out, PRINT_TESTSUITE_TAG);
1118 }
1119 (void)fprintf(out, PRINT_TESTSUITES_TAG);
1120 return 0;
1121 }
1122
GenResult(void)1123 int GenResult(void)
1124 {
1125 int ret;
1126 TestSuiteResult result[MAX_SUITE_COUNT];
1127 int testSuiteCount = 0;
1128 DIR *logDir = NULL;
1129 logDir = opendir(LOG_FILE_DIR);
1130 if (logDir == NULL) {
1131 Print("fail to open log directory\n");
1132 return 1;
1133 }
1134
1135 FILE *fpTmp = NULL;
1136 fpTmp = fopen("tmp.txt", "w+");
1137 if (fpTmp == NULL) {
1138 Print("open tmp.txt failed\n");
1139 (void)closedir(logDir);
1140 return 1;
1141 }
1142
1143 FILE *fpResult = NULL;
1144 fpResult = fopen("result.xml", "w");
1145 if (fpResult == NULL) {
1146 Print("open result.xml failed\n");
1147 (void)closedir(logDir);
1148 (void)fclose(fpTmp);
1149 (void)remove("tmp.txt");
1150 return 1;
1151 }
1152
1153 ret = ReadAllLogFile(logDir, &testSuiteCount, fpTmp, result, sizeof(result));
1154 if (ret != 0) {
1155 Print("read log failed\n");
1156 goto EXIT;
1157 }
1158
1159 rewind(fpTmp);
1160 ret = GenResultFile(fpTmp, fpResult, result, testSuiteCount);
1161 if (ret != 0) {
1162 Print("gen result failed\n");
1163 goto EXIT;
1164 }
1165
1166 EXIT:
1167 (void)closedir(logDir);
1168 (void)fclose(fpTmp);
1169 (void)fclose(fpResult);
1170 (void)remove("tmp.txt");
1171 return ret;
1172 }
1173