• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "utils.h"
17 #include <gtest/gtest.h>
18 #include "log.h"
19 
20 
21 // init rand seed at startup
Initialize(void)22 __attribute__((constructor)) static void Initialize(void)
23 {
24     LOGD("srand(time(0)) is called.");
25     srand(time(nullptr));
26 }
27 
CheckValueClose(double target,double actual,double accuracy)28 int CheckValueClose(double target, double actual, double accuracy)
29 {
30     double diff = actual - target;
31     double pct;
32     if (diff < 0) {
33         diff = -diff;
34     }
35     if (actual == 0) {
36         return 0;
37     } else {
38         pct = diff / actual;
39     }
40     LOGD("diff=%f, pct=%f\n", diff, pct);
41     return (pct <= accuracy);
42 }
43 
44 const int SYS_US_PER_MS = 1000;
Msleep(int msec)45 void Msleep(int msec)
46 {
47     usleep(msec * SYS_US_PER_MS);
48 }
49 
KeepRun(int msec)50 int KeepRun(int msec)
51 {
52     struct timespec time1 = { 0, 0 };
53     struct timespec time2 = { 0, 0 };
54     clock_gettime(CLOCK_MONOTONIC, &time1);
55     LOGD("KeepRun start : tv_sec=%ld, tv_nsec=%ld\n", time1.tv_sec, time1.tv_nsec);
56     int loop = 0;
57     int runned = 0;
58     int sectomsec = 1000;
59     int nsectomsec = 1000000;
60     while (runned < msec) {
61         ++loop;
62         clock_gettime(CLOCK_MONOTONIC, &time2);
63         runned = (time2.tv_sec - time1.tv_sec) * sectomsec + (time2.tv_nsec - time1.tv_nsec) / nsectomsec;
64     }
65     LOGD("KeepRun end : tv_sec=%ld, tv_nsec=%ld\n", time2.tv_sec, time2.tv_nsec);
66     return loop;
67 }
68 
69 // check process state use 'waitpid'
CheckProcStatus(pid_t pid,int * code,int flag)70 int CheckProcStatus(pid_t pid, int *code, int flag)
71 {
72     int status;
73     int rt = waitpid(pid, &status, flag);
74     errno = 0;
75     int errorcode = -2;
76     if (rt == -1) {
77         LOGE("waitpid return -1, errno=%d:%s\n", errno, strerror(errno));
78         return -1;
79     } else if (rt == 0) {
80         return 0;
81     } else if (rt != pid) { // waitpid return error
82         if (errno) {
83             LOGE("waitpid return error, rt=%d, errno=%d:%s\n", rt, errno, strerror(errno));
84         } else {
85             LOGE("waitpid return error, errno is not set(no more info)\n");
86         }
87         return errorcode;
88     }
89     if (code == nullptr) {
90         return -1;
91     }
92     int num2 = 2;
93     int num3 = 3;
94     int num4 = 4;
95     if (WIFEXITED(status)) {
96         *code = WEXITSTATUS(status);
97         return 1;
98     } else if (WIFSIGNALED(status)) {
99         *code = WTERMSIG(status);
100         return num2;
101     } else if (WIFSTOPPED(status)) {
102         *code = WSTOPSIG(status);
103         return num3;
104     }
105     return num4;
106 }
AssertProcAlive(pid_t pid)107 void AssertProcAlive(pid_t pid)
108 {
109     int exitCode;
110     int procStat = CheckProcStatus(pid, &exitCode);
111     ASSERT_EQ(procStat, 0) << "target process should still alive.\n";
112 }
113 
ExpectProcAlive(pid_t pid)114 void ExpectProcAlive(pid_t pid)
115 {
116     int exitCode;
117     int procStat = CheckProcStatus(pid, &exitCode);
118     EXPECT_EQ(procStat, 0) << "target process should still alive.\n";
119 }
120 
AssertProcExitedOK(pid_t pid)121 void AssertProcExitedOK(pid_t pid)
122 {
123     int exitCode;
124     int processExistd = 1;
125     int procStat = CheckProcStatus(pid, &exitCode);
126     EXPECT_EQ(procStat, processExistd);
127     ASSERT_EQ(exitCode, 0) << "target process should exited 0.\n";
128 }
129 
ExpectProcExitedOK(pid_t pid)130 void ExpectProcExitedOK(pid_t pid)
131 {
132     int exitCode;
133     int processExistd = 1;
134     int procStat = CheckProcStatus(pid, &exitCode);
135     EXPECT_EQ(procStat, processExistd);
136     EXPECT_EQ(exitCode, 0) << "target process should exited 0.\n";
137 }
138 
WaitProcExitedOK(pid_t pid)139 void WaitProcExitedOK(pid_t pid)
140 {
141     int exitCode;
142     int processExistd = 1;
143     int procStat = CheckProcStatus(pid, &exitCode, 0);
144     EXPECT_EQ(procStat, processExistd);
145     EXPECT_EQ(exitCode, 0) << "target process should exited 0.\n";
146 }
147 
ExpectProcKilled(pid_t pid,int signum)148 void ExpectProcKilled(pid_t pid, int signum)
149 {
150     int exitCode;
151     int killedBySignal = 2;
152     int procStat = CheckProcStatus(pid, &exitCode);
153     EXPECT_EQ(procStat, killedBySignal);
154     EXPECT_EQ(exitCode, signum) << "target process should killed by " << signum;
155 }
156 
AssertProcKilled(pid_t pid,int signum)157 void AssertProcKilled(pid_t pid, int signum)
158 {
159     int exitCode;
160     int killedBySignal = 2;
161     int procStat = CheckProcStatus(pid, &exitCode);
162     EXPECT_EQ(procStat, killedBySignal);
163     EXPECT_EQ(exitCode, signum) << "target process should killed by " << signum;
164 }
165 
WaitProcKilled(pid_t pid,int signum)166 void WaitProcKilled(pid_t pid, int signum)
167 {
168     int exitCode;
169     int killedBySignal = 2;
170     int procStat = CheckProcStatus(pid, &exitCode, 0);
171     ASSERT_EQ(procStat, killedBySignal) << "target process should killed by " << signum;
172     ASSERT_EQ(exitCode, signum) << "target process should killed by " << signum;
173 }
174 // start an elf, only check if execve success or not
StartElf(const char * fname,char * const argv[],char * const envp[])175 static int StartElf(const char *fname, char * const argv[], char * const envp[])
176 {
177     int pid = fork();
178     if (pid == -1) {
179         LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
180         return -1;
181     } else if (pid == 0) { // child
182         errno = 0;
183         int rt = execve(fname, argv, envp);
184         if (rt == -1) {
185             LOGE("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
186             _Exit(EXECVE_RETURN_ERROR);
187         }
188         LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
189         _Exit(EXECVE_RETURN_OK);
190     }
191     return pid;
192 }
193 
RunElf(const char * fname,char * const argv[],char * const envp[],int timeoutSec)194 int RunElf(const char *fname, char * const argv[], char * const envp[], int timeoutSec)
195 {
196     int isTimeout = 0;
197     int exitCode;
198     sigset_t set;
199     sigset_t origMask;
200     sigemptyset(&set);
201     sigaddset(&set, SIGCHLD);
202 
203     if (sigprocmask(SIG_BLOCK, &set, &origMask) < 0) {
204         LOG("sigprocmask");
205     }
206     int pid = StartElf(fname, argv, envp);
207     if (pid == -1) { // fork error
208         return -1;
209     }
210 
211     if (timeoutSec > 0) {
212         struct timespec time1 = { timeoutSec, 0 };
213         if (sigtimedwait(&set, nullptr, &time1) == -1) {
214             if (errno == EAGAIN) {
215                 isTimeout = 1;
216             } else {
217                 LOGE("ERROR: sigtimedwait FAIL: %s\n", strerror(errno));
218                 return -1;
219             }
220             if (kill(pid, SIGTERM) == -1) {
221                 LOGE("ERROR: kill child FAIL: %s\n", strerror(errno));
222                 return -1;
223             }
224         }
225         // else: sigtimedwait return ok, child has exited already, nothing else to do
226     }
227     int errorcode1 = -1;
228     int errorcode2 = -2;
229     int rt = CheckProcStatus(pid, &exitCode, 0);
230     if ((rt <= 0) || (exitCode == EXECVE_RETURN_OK) || (exitCode == EXECVE_RETURN_ERROR)) {
231         return errorcode1;
232     }
233     if (isTimeout) {
234         LOGE("ERROR: child execute timed out!\n");
235         return errorcode2;
236     }
237     return exitCode;
238 }
239 
StartExecveError(const char * fname,char * const argv[],char * const envp[])240 int StartExecveError(const char *fname, char * const argv[], char * const envp[])
241 {
242     int sleeptime = 30;
243     pid_t pid = fork();
244     if (pid == -1) {
245         LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
246         return -1;
247     } else if (pid == 0) { // child
248         int rt = execve(fname, argv, envp);
249         if (rt == -1) {
250             LOG("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
251             _Exit(errno);
252         }
253         LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
254         _Exit(EXECVE_RETURN_OK);
255     }
256     // parent
257     Msleep(sleeptime);
258     int exitCode;
259     int errorcode1 = -2;
260     int errorcode2 = -3;
261     int procStat = CheckProcStatus(pid, &exitCode);
262     LOG("procStat=%d, exitCode=%d\n", procStat, exitCode);
263     if (procStat != 1) {
264         return errorcode2;
265     } else if (exitCode == EXECVE_RETURN_OK) {
266         return errorcode1;
267     } else {
268         return exitCode;
269     }
270 }
271 
272 // Get a pid number that currently not exist
273 // by creat a child process and exit.
GetNonExistPid()274 pid_t GetNonExistPid()
275 {
276     int sleeptime5 = 5;
277     int sleeptime20 = 20;
278     pid_t pid = fork();
279     if (pid < 0) {
280         LOG("fork error, wait 5 seconds than try angain...");
281         sleep(sleeptime5);
282         pid = fork();
283         if (pid < 0) {
284             LOG("still fork error!");
285             return -1;
286         }
287     }
288     if (pid > 0) { // parent
289         Msleep(sleeptime20);
290         if (waitpid(pid, nullptr, 0) != pid) {
291             LOG("waitpid failed, errno = %d", errno);
292             return -1;
293         }
294     } else { // child
295         _Exit(0);
296     }
297     return pid;
298 }
299 
300 // return n: 0 < n <= max
GetRandom(uint32_t max)301 uint32_t GetRandom(uint32_t max)
302 {
303     int fd;
304     int r = 0;
305     if (max == 0 || max == 1) {
306         return 1;
307     }
308     fd = open("/dev/random", O_RDONLY);
309     if (fd == -1) {
310         LOG("open /dev/random failed, errno = %d", errno);
311     }
312     if (read(fd, &r, sizeof(int)) == -1) {
313         LOG("read failed, errno = %d", errno);
314     }
315     if (close(fd) == -1) {
316         LOG("close failed, errno = %d", errno);
317     }
318     return (r % max) + 1;
319 }
320 
321 // get cur-time plus ms
GetDelayedTime(struct timespec * ts,unsigned int ms)322 void GetDelayedTime(struct timespec *ts, unsigned int ms)
323 {
324     const unsigned int nsecPerSec = 1000000000;
325     unsigned int setTimeNs = ms * 1000000;
326     struct timespec tsNow = { 0 };
327     clock_gettime(CLOCK_REALTIME, &tsNow);
328     ts->tv_sec = tsNow.tv_sec + (tsNow.tv_nsec + setTimeNs) / nsecPerSec;
329     ts->tv_nsec = (tsNow.tv_nsec + setTimeNs) % nsecPerSec;
330 }
331 
332 // calculate time difference, in ms
GetTimeDiff(struct timespec ts1,struct timespec ts2)333 int GetTimeDiff(struct timespec ts1, struct timespec ts2)
334 {
335     const unsigned int nsecPerSec = 1000000000;
336     const unsigned int nsectomsec = 1000000;
337     int ms = (ts1.tv_sec - ts2.tv_sec) * nsecPerSec + (ts1.tv_nsec - ts2.tv_nsec);
338     ms = ms / nsectomsec;
339     return ms;
340 }
341 
GetCpuCount(void)342 int GetCpuCount(void)
343 {
344     cpu_set_t cpuset;
345 
346     CPU_ZERO(&cpuset);
347     int temp = sched_getaffinity(getpid(), sizeof(cpu_set_t), &cpuset);
348     if (temp != 0) {
349         printf("%s %d Error : %d\n", __FUNCTION__, __LINE__, temp);
350     }
351 
352     return CPU_COUNT(&cpuset);
353 }
354 
FixCurProcessToOneCpu(int cpuIndex,cpu_set_t * pOldMask)355 int FixCurProcessToOneCpu(int cpuIndex, cpu_set_t *pOldMask)
356 {
357     int ret;
358     cpu_set_t setMask;
359     CPU_ZERO(pOldMask);
360     ret = sched_getaffinity(0, sizeof(cpu_set_t), pOldMask);
361     if (ret != 0) {
362         LOG("sched_getaffinity failed, ret = %d", ret);
363         return -1;
364     }
365     if (CPU_ISSET(0, pOldMask)) {
366         LOG("before affinity cpu is 0");
367     }
368     if (CPU_ISSET(1, pOldMask)) {
369         LOG("before affinity cpu is 1");
370     }
371     CPU_ZERO(&setMask);
372     CPU_SET(cpuIndex, &setMask);
373     LOG("fix cpu to %d", cpuIndex);
374     ret = sched_setaffinity(0, sizeof(setMask), &setMask);
375     if (ret != 0) {
376         LOG("sched_setaffinity failed, ret = %d", ret);
377         return -1;
378     }
379     return 0;
380 }
381