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 22__attribute__((constructor)) static void Initialize(void) 23{ 24 LOGD("srand(time(0)) is called."); 25 srand(time(nullptr)); 26} 27 28int 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 44const int SYS_US_PER_MS = 1000; 45void Msleep(int msec) 46{ 47 usleep(msec * SYS_US_PER_MS); 48} 49 50int 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' 70int 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} 107void 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 114void 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 121void 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 130void 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 139void 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 148void 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 157void 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 166void 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 175static 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 194int 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 240int 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. 274pid_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 301uint32_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 322void 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 333int 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 342int 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 355int 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