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