• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 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 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19 
20 #include "utils.h"
21 #include <gtest/gtest.h>
22 #include "log.h"
23 
24 // init rand seed at startup
Initialize(void)25 __attribute__((constructor)) static void Initialize(void)
26 {
27     LOGD("srand(time(0)) is called.");
28     srand(time(nullptr));
29 }
30 
CheckValueClose(double target,double actual,double accuracy)31 int CheckValueClose(double target, double actual, double accuracy)
32 {
33     double diff = actual - target;
34     double pct;
35     if (diff < 0) {
36         diff = -diff;
37     }
38     if(actual == 0) {
39         return 0;
40     }else {
41         pct = diff / actual;
42     }
43     LOGD("diff=%f, pct=%f\n", diff, pct);
44     return (pct <= accuracy);
45 }
46 
47 const int SYS_US_PER_MS = 1000;
Msleep(int msec)48 void Msleep(int msec)
49 {
50     usleep(msec * SYS_US_PER_MS);
51 }
52 
KeepRun(int msec)53 int KeepRun(int msec)
54 {
55     struct timespec time1 = { 0, 0 };
56     struct timespec time2 = { 0, 0 };
57     clock_gettime(CLOCK_MONOTONIC, &time1);
58     LOGD("KeepRun start : tv_sec=%ld, tv_nsec=%ld\n", time1.tv_sec, time1.tv_nsec);
59     int loop = 0;
60     int runned = 0;
61     while (runned < msec) {
62         ++loop;
63         clock_gettime(CLOCK_MONOTONIC, &time2);
64         runned = (time2.tv_sec - time1.tv_sec) * 1000 + (time2.tv_nsec - time1.tv_nsec) / 1000000;
65     }
66     LOGD("KeepRun end : tv_sec=%ld, tv_nsec=%ld\n", time2.tv_sec, time2.tv_nsec);
67     return loop;
68 }
69 
70 // check process state use 'waitpid'
CheckProcStatus(pid_t pid,int * code,int flag)71 int CheckProcStatus(pid_t pid, int *code, int flag)
72 {
73     int status;
74     int rt = waitpid(pid, &status, flag);
75     errno = 0;
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 -2;
88     }
89     if (code == nullptr) {
90         return -1;
91     }
92 
93     if (WIFEXITED(status)) {
94         *code = WEXITSTATUS(status);
95         return 1;
96     } else if (WIFSIGNALED(status)) {
97         *code = WTERMSIG(status);
98         return 2;
99     } else if (WIFSTOPPED(status)) {
100         *code = WSTOPSIG(status);
101         return 3;
102     }
103     return 4;
104 }
105 
106 // start a elf, only check if execve success or not
StartElf(const char * fname,char * const argv[],char * const envp[])107 static int StartElf(const char *fname, char * const argv[], char * const envp[])
108 {
109     int pid = fork();
110     if (pid == -1) {
111         LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
112         return -1;
113     } else if (pid == 0) { // child
114         errno = 0;
115         int rt = execve(fname, argv, envp);
116         if (rt == -1) {
117             LOGE("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
118             exit(EXECVE_RETURN_ERROR);
119         }
120         LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
121         exit(EXECVE_RETURN_OK);
122     }
123     return pid;
124 }
125 
RunElf(const char * fname,char * const argv[],char * const envp[],int timeoutSec)126 int RunElf(const char *fname, char * const argv[], char * const envp[], int timeoutSec)
127 {
128     int isTimeout = 0;
129     int exitCode;
130     sigset_t set;
131     sigemptyset(&set);
132     sigaddset(&set, SIGCHLD);
133 
134     int pid = StartElf(fname, argv, envp);
135     if (pid == -1) { // fork error
136         return -1;
137     }
138 
139     if (timeoutSec > 0) {
140         struct timespec time1 = { timeoutSec, 0 };
141         if (sigtimedwait(&set, nullptr, &time1) == -1) {
142             if (errno == EAGAIN) {
143                 isTimeout = 1;
144             } else {
145                 LOGE("ERROR: sigtimedwait FAIL: %s\n", strerror(errno));
146                 return -1;
147             }
148             if (kill(pid, SIGKILL) == -1) {
149                 LOGE("ERROR: kill child FAIL: %s\n", strerror(errno));
150                 return -1;
151             }
152         }
153         // else: sigtimedwait return ok, child has exited already, nothing else to do
154     }
155     int rt = CheckProcStatus(pid, &exitCode, 0);
156     if ((rt <= 0) || (exitCode == EXECVE_RETURN_OK) || (exitCode == EXECVE_RETURN_ERROR)) {
157         return -1;
158     }
159     if (isTimeout) {
160         LOGE("ERROR: child execute timed out!\n");
161         return -2;
162     }
163     return exitCode;
164 }
165 
StartExecveError(const char * fname,char * const argv[],char * const envp[])166 int StartExecveError(const char *fname, char * const argv[], char * const envp[])
167 {
168     pid_t pid = fork();
169     if (pid == -1) {
170         LOGE("ERROR: Fork Error, errno=%d, err=%s\n", errno, strerror(errno));
171         return -1;
172     } else if (pid == 0) { // child
173         int rt = execve(fname, argv, envp);
174         if (rt == -1) {
175             LOG("ERROR: execve return -1, errno=%d, err=%s\n", errno, strerror(errno));
176             exit(errno);
177         }
178         LOGE("ERROR: execve should never return on success. rt=%d, errno=%d, err=%s\n", rt, errno, strerror(errno));
179         exit(EXECVE_RETURN_OK);
180     }
181     // parent
182     Msleep(30);
183     int exitCode;
184     int procStat = CheckProcStatus(pid, &exitCode);
185     LOG("procStat=%d, exitCode=%d\n", procStat, exitCode);
186     if (procStat != 1) {
187         return -3;
188     } else if (exitCode == EXECVE_RETURN_OK) {
189         return -2;
190     } else {
191         return exitCode;
192     }
193 }
194 
195 // Get a pid number that currently not exist
196 // by creat a child process and exit.
GetNonExistPid()197 pid_t GetNonExistPid()
198 {
199     pid_t pid = fork();
200     if (pid < 0) {
201         LOG("fork error, wait 5 seconds than try angain...");
202         sleep(5);
203         pid = fork();
204         if (pid < 0) {
205             LOG("still fork error!");
206             return -1;
207         }
208     }
209     if (pid > 0) { // parent
210         Msleep(20);
211         if (waitpid(pid, nullptr, 0) != pid) {
212             LOG("waitpid failed, errno = %d", errno);
213             return -1;
214         }
215     } else { // child
216         exit(0);
217     }
218     return pid;
219 }
220 
221 // return n: 0 < n <= max
GetRandom(uint32_t max)222 uint32_t GetRandom(uint32_t max)
223 {
224     if (max == 0 || max == 1) {
225         return 1;
226     }
227     return (rand() % max) + 1;
228 }
229 
230 // get cur-time plus ms
GetDelayedTime(struct timespec * ts,unsigned int ms)231 void GetDelayedTime(struct timespec *ts, unsigned int ms)
232 {
233     const unsigned int nsecPerSec = 1000000000;
234     unsigned int setTimeNs = ms * 1000000;
235     struct timespec tsNow = { 0 };
236     clock_gettime(CLOCK_REALTIME, &tsNow);
237     ts->tv_sec = tsNow.tv_sec + (tsNow.tv_nsec + setTimeNs) / nsecPerSec;
238     ts->tv_nsec = (tsNow.tv_nsec + setTimeNs) % nsecPerSec;
239 }
240 
241 // calculate time difference, in ms
GetTimeDiff(struct timespec ts1,struct timespec ts2)242 int GetTimeDiff(struct timespec ts1, struct timespec ts2)
243 {
244     const unsigned int nsecPerSec = 1000000000;
245     int ms = (ts1.tv_sec - ts2.tv_sec) * nsecPerSec + (ts1.tv_nsec - ts2.tv_nsec);
246     ms = ms / 1000000;
247     return ms;
248 }
249 
GetCpuCount(void)250 int GetCpuCount(void)
251 {
252     cpu_set_t cpuset;
253 
254     CPU_ZERO(&cpuset);
255     int temp = sched_getaffinity(getpid(), sizeof(cpu_set_t), &cpuset);
256     if (temp != 0) {
257         printf("%s %d Error : %d\n", __FUNCTION__, __LINE__, temp);
258     }
259 
260     return CPU_COUNT(&cpuset);
261 }
262 
FixCurProcessToOneCpu(int cpuIndex,cpu_set_t * pOldMask)263 int FixCurProcessToOneCpu(int cpuIndex, cpu_set_t *pOldMask)
264 {
265     int ret;
266     cpu_set_t setMask;
267     CPU_ZERO(pOldMask);
268     ret = sched_getaffinity(0, sizeof(cpu_set_t), pOldMask);
269     if (ret != 0) {
270         LOG("sched_getaffinity failed, ret = %d", ret);
271         return -1;
272     }
273     if (CPU_ISSET(0, pOldMask)) {
274         LOG("before affinity cpu is 0");
275     }
276     if (CPU_ISSET(1, pOldMask)) {
277         LOG("before affinity cpu is 1");
278     }
279     CPU_ZERO(&setMask);
280     CPU_SET(cpuIndex, &setMask);
281     LOG("fix cpu to %d", cpuIndex);
282     ret = sched_setaffinity(0, sizeof(setMask), &setMask);
283     if (ret != 0) {
284         LOG("sched_setaffinity failed, ret = %d", ret);
285         return -1;
286     }
287     return 0;
288 }