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