• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramLen);
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