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