• 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 <setjmp.h>
17 #include <time.h>
18 #include <sys/time.h>
19 
20 static jmp_buf env;
21 static int isSubProc = 0;
GetJmpAddress(void)22 int *GetJmpAddress(void)
23 {
24     return &isSubProc;
25 }
26 
handleSignal()27 void handleSignal()
28 {
29     siglongjmp(env, 1);
30 }
31 
PrintCaseName(FILE * logFile,bool showDetail,const char * name)32 static void PrintCaseName(FILE *logFile, bool showDetail, const char *name)
33 {
34     // print a minimum of 4 dots
35     int32_t dotCount = (OUTPUT_LINE_LENGTH - (int32_t)strlen(name) >= 4) ?
36         (OUTPUT_LINE_LENGTH - (int32_t)strlen(name)) : 4;
37     if (showDetail) {
38         Print("%s", name);
39         for (int32_t j = 0; j < dotCount; j++) {
40             Print(".");
41         }
42     }
43     (void)fprintf(logFile, "%s", name);
44     for (int32_t j = 0; j < dotCount; j++) {
45         (void)fprintf(logFile, ".");
46     }
47 }
48 
ParseArgs(const TestArgs * arg,TestParam * info)49 static int ParseArgs(const TestArgs *arg, TestParam *info)
50 {
51     info->hexParamCount = 0;
52     info->intParamCount = 0;
53     info->paramCount = 0;
54     for (uint32_t i = 1; i < arg->argLen; i += 2) { // 2
55         if (strcmp(arg->arg[i], "int") == 0) {
56             if (ConvertInt(arg->arg[i + 1], &(info->intParam[info->intParamCount])) == 0) {
57                 info->param[info->paramCount] = &(info->intParam[info->intParamCount]);
58                 info->intParamCount++;
59             } else {
60                 Print("\nERROR: Int param conversion failed for:\n\"%s\"\n", arg->arg[i + 1]);
61                 return 1;
62             }
63         } else if (strcmp(arg->arg[i], "char") == 0) {
64             info->param[info->paramCount] = arg->arg[i+1];
65         } else if (strcmp(arg->arg[i], "Hex") == 0) {
66             if (ConvertHex(arg->arg[i + 1], &(info->hexParam[info->hexParamCount])) != 0) {
67                 Print("\nERROR: Hex param conversion failed for:\n\"%s\"\n", arg->arg[i + 1]);
68                 return 1;
69             }
70             info->param[info->paramCount] = &(info->hexParam[info->hexParamCount]);
71             info->hexParamCount++;
72         } else if (strcmp(arg->arg[i], "exp") == 0) {
73             int expId = 0;
74             if (ConvertInt(arg->arg[i + 1], &expId) != 0 ||
75                 getExpression(expId, &(info->intParam[info->intParamCount])) != 0) {
76                 Print("\nERROR: Macro param conversion failed\n");
77                 return 1;
78             }
79             info->param[info->paramCount] = &(info->intParam[info->intParamCount]);
80             info->intParamCount++;
81         } else {
82             return 1;
83         }
84         info->paramCount++;
85     }
86 
87     return 0;
88 }
89 
PrintCaseNameResult(FILE * logFile,int vectorCount,int skipCount,int passCount,time_t beginTime)90 static int PrintCaseNameResult(FILE *logFile, int vectorCount, int skipCount, int passCount, time_t beginTime)
91 {
92     char suitePrefix[OUTPUT_LINE_LENGTH] = {0};
93     (void)snprintf_truncated_s(suitePrefix, sizeof(suitePrefix), "%s", suiteName);
94     size_t leftSize = sizeof(suitePrefix) - 1 - strlen(suitePrefix);
95     if (leftSize > 0) {
96         (void)memset_s(suitePrefix + strlen(suitePrefix), sizeof(suitePrefix) - strlen(suitePrefix), '.', leftSize);
97     }
98     int failCount = vectorCount - passCount - skipCount;
99     if (failCount == 0) {
100         Print("%sPASS || Run %-6d testcases, passed: %-6d, skipped: %-6d, failed: %-6d useSec:%-5lu\n", suitePrefix,
101             vectorCount, passCount, skipCount, failCount, time(NULL) - beginTime);
102     } else {
103         Print("%sFAIL || Run %-6d testcases, passed: %-6d, skipped: %-6d, failed: %-6d useSec:%-5lu\n", suitePrefix,
104             vectorCount, passCount, skipCount, failCount, time(NULL) - beginTime);
105     }
106 
107     time_t rawtime;
108     struct tm *timeinfo;
109     (void)time(&rawtime);
110     timeinfo = localtime(&rawtime);
111     (void)fprintf(logFile, "End time: %s", asctime(timeinfo));
112     (void)fprintf(logFile, "Result: Run %d tests, Passed: %d, Skipped: %d, Failed: %d\n", vectorCount, passCount,
113         skipCount, failCount);
114     return failCount;
115 }
116 
ProcessCases(FILE * logFile,bool showDetail,int targetFuncId)117 static int ProcessCases(FILE *logFile, bool showDetail, int targetFuncId)
118 {
119     (void)logFile;
120     volatile int vectorCount = 0;
121     volatile int passCount = 0;
122     volatile int skipCount = 0;
123     volatile int tryNum;
124     time_t beginTime = time(NULL);
125     struct timespec start, end;
126 
127     for (volatile int i = 0; i < g_executeCount; i++) {
128         int funcId = strtoul(g_executeCases[i]->arg[0], NULL, 10); // 10
129         if (funcId < 0 || funcId > ((int)(sizeof(test_funcs)/sizeof(TestWrapper)))) {
130             Print("funcId false!\n");
131             return 1;
132         }
133         if ((targetFuncId != -1) && (funcId != targetFuncId)) {
134             continue;
135         }
136         (void)fprintf(logFile, "%s ", funcName[funcId]);
137         PrintCaseName(logFile, showDetail, g_executeCases[i]->testVectorName);
138         TestParam io;
139         if (ParseArgs(g_executeCases[i], &io) != 0) {
140             return -1;
141         }
142         TestWrapper fp = test_funcs[funcId];
143         g_testResult.result = TEST_RESULT_SUCCEED;
144         tryNum = 0;
145         clock_gettime(CLOCK_REALTIME, &start);
146         do {
147             if (tryNum > 0) {
148                 sleep(10);
149                 g_testResult.result = TEST_RESULT_SUCCEED;
150             }
151             tryNum++;
152 #ifdef  ASAN
153             fp(io.param);
154 #else
155         // Executing Function
156         if (signal(SIGSEGV, handleSignal) == SIG_ERR) {
157             return -1;
158         }
159         int r = sigsetjmp(env, 1);
160         if (r == 0) {
161             fp(io.param);
162         } else if (r == 1){
163             g_testResult.result = TEST_RESULT_FAILED;
164         }
165         if (isSubProc != 0) {
166             break;
167         }
168 #endif
169         } while ((g_testResult.result == TEST_RESULT_FAILED) && (tryNum < FAIL_TRY_TIMES));
170         if (g_testResult.result == TEST_RESULT_SUCCEED) {
171             passCount++;
172         } else if (g_testResult.result == TEST_RESULT_SKIPPED) {
173             skipCount++;
174         }
175         vectorCount++;
176         clock_gettime(CLOCK_REALTIME, &end);
177         uint64_t elapsedms = (end.tv_sec - start.tv_sec) * 1000 + (end.tv_nsec - start.tv_nsec) / 1000000;
178         PrintResult(showDetail, g_executeCases[i]->testVectorName, elapsedms);
179         PrintLog(logFile);
180         for (int j = 0; j < io.hexParamCount; j++) {
181             FreeHex(&io.hexParam[j]);
182         }
183         if (isSubProc != 0) {
184             break;
185         }
186     }
187 
188     return PrintCaseNameResult(logFile, vectorCount, skipCount, passCount, beginTime);
189 }
190 
ExecuteTest(const char * fileName,bool showDetail,int targetFuncId)191 static int ExecuteTest(const char *fileName, bool showDetail, int targetFuncId)
192 {
193     if (LoadDataFile(fileName) != 0) {
194         return -1;
195     }
196     FILE *logFile = NULL;
197     char logFileName[MAX_FILE_NAME] = {0};
198     if (targetFuncId == -1) {
199         if (sprintf_s(logFileName, MAX_FILE_NAME, SUITE_LOG_FORMAT, suiteName) <= 0) {
200             Print("An error occurred while creating the log file\n");
201             return (-1);
202         }
203     } else {
204         if (sprintf_s(logFileName, MAX_FILE_NAME, FUNCTION_LOG_FORMAT, suiteName, funcName[targetFuncId]) <= 0) {
205             Print("An error occurred while creating the log file\n");
206             return (-1);
207         }
208     }
209     time_t rawtime = time(NULL);
210     if (rawtime == 0) {
211         return -1;
212     }
213     logFile = fopen(logFileName, "w");
214     if (logFile != NULL) {
215         struct tm *timeinfo;
216         timeinfo = localtime(&rawtime);
217         if (fprintf(logFile, "Begin time: %s", asctime(timeinfo)) <= 0) {
218             fclose(logFile);
219             return -1;
220         }
221     }
222     int rt = ProcessCases(logFile, showDetail, targetFuncId);
223     if (logFile != NULL) {
224         fclose(logFile);
225     }
226     return rt;
227 }
228 
ProcessMutiArgs(int argc,char ** argv,const char * fileName)229 int ProcessMutiArgs(int argc, char **argv, const char *fileName)
230 {
231     int printDetail = 1;
232     int curTestCnt = 0;
233     int ret = -1;
234     int testCnt = sizeof(test_funcs) / sizeof(test_funcs[0]);
235     int *funcIndex = malloc(sizeof(int) * testCnt);
236     int found;
237 
238     if (funcIndex == NULL) {
239         return ret;
240     }
241 
242     for (int i = 1; i < argc; i++) {
243         if (strcmp(argv[i], "NO_DETAIL") == 0) {
244             printDetail = 0;
245             continue;
246         }
247         found = 0;
248         for (int j = 0; j < testCnt; j++) {
249             if (strcmp(argv[i], funcName[j]) == 0) {
250                 funcIndex[curTestCnt++] = j;
251                 found = 1;
252                 break;
253             }
254         }
255         if (found != 1) {
256             Print("test function '%s' do not exist\n", argv[i]);
257             goto EXIT;
258         }
259     }
260 
261     if (curTestCnt == 0) {
262         ret = ExecuteTest(fileName, printDetail, -1);
263         goto EXIT;
264     }
265 
266     for (int i = 0; i < curTestCnt; i++) {
267         if (ExecuteTest(fileName, printDetail, funcIndex[i]) != 0) {
268             goto EXIT;
269         }
270     }
271     ret = 0;
272 
273 EXIT:
274     free(funcIndex);
275     return ret;
276 }
277 
main(int argc,char ** argv)278 int main(int argc, char **argv)
279 {
280     signal(SIGTTOU, SIG_IGN);
281     signal(SIGTTIN, SIG_IGN);
282     int ret = 0;
283 #ifndef PRINT_TO_TERMINAL
284     char testOutputName[MAX_FILE_NAME] = {0};
285     if (sprintf_s(testOutputName, MAX_FILE_NAME, "%s.output", suiteName) <= 0) {
286         return 0;
287     }
288     FILE *fp = fopen(testOutputName, "w");
289     if (fp == NULL) {
290         return 1;
291     }
292     SetOutputFile(fp);
293 #endif
294 
295     char testName[MAX_FILE_PATH_LEN];
296     if (sprintf_s(testName, MAX_FILE_PATH_LEN, "%s.datax", suiteName) <= 0) {
297         goto EXIT;
298     }
299     if (argc == 1) {
300         ret = ExecuteTest(testName, 1, -1);
301     } else {
302         ret = ProcessMutiArgs(argc, argv, testName);
303     }
304     if (ret != 0) {
305         Print("execute test failed\n");
306     }
307     for (int i = 0; i < g_executeCount; i++) {
308         free(g_executeCases[i]);
309     }
310 EXIT:
311 #ifndef PRINT_TO_TERMINAL
312     (void)fclose(fp);
313 #endif
314     return ret;
315 }
316