1f6603c60Sopenharmony_ci/* Copyright (C) 2022 Huawei Device Co., Ltd.
2f6603c60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
3f6603c60Sopenharmony_ci * you may not use this file except in compliance with the License.
4f6603c60Sopenharmony_ci * You may obtain a copy of the License at
5f6603c60Sopenharmony_ci *
6f6603c60Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
7f6603c60Sopenharmony_ci *
8f6603c60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
9f6603c60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
10f6603c60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11f6603c60Sopenharmony_ci * See the License for the specific language governing permissions and
12f6603c60Sopenharmony_ci * limitations under the License.
13f6603c60Sopenharmony_ci */
14f6603c60Sopenharmony_ci#include <iostream>
15f6603c60Sopenharmony_ci#include <cstdlib>
16f6603c60Sopenharmony_ci#include <cstring>
17f6603c60Sopenharmony_ci#include <cerrno>
18f6603c60Sopenharmony_ci#include <ctime>
19f6603c60Sopenharmony_ci#include <cstdio>
20f6603c60Sopenharmony_ci#include <vector>
21f6603c60Sopenharmony_ci#include <csignal>
22f6603c60Sopenharmony_ci#include <unistd.h>
23f6603c60Sopenharmony_ci#include <dirent.h>
24f6603c60Sopenharmony_ci#include <sys/types.h>
25f6603c60Sopenharmony_ci#include <sys/wait.h>
26f6603c60Sopenharmony_ci#include <sys/time.h>
27f6603c60Sopenharmony_ci#include <sys/resource.h>
28f6603c60Sopenharmony_ci
29f6603c60Sopenharmony_ci#include "gtest/gtest.h"
30f6603c60Sopenharmony_ci#include "runtest.h"
31f6603c60Sopenharmony_ci
32f6603c60Sopenharmony_ciusing namespace std;
33f6603c60Sopenharmony_ciusing namespace testing::ext;
34f6603c60Sopenharmony_ciusing namespace testing;
35f6603c60Sopenharmony_cinamespace OHOS {
36f6603c60Sopenharmony_ciclass Toolchaintest : public ::testing::TestWithParam<string> {};
37f6603c60Sopenharmony_ci
38f6603c60Sopenharmony_cistatic string g_filepath = "/data/local/tmp/libc-test";
39f6603c60Sopenharmony_cistatic vector<std::string> temp = Runtest::GetFileNames(g_filepath);
40f6603c60Sopenharmony_ci
41f6603c60Sopenharmony_civolatile int g_tStatus = 0;
42f6603c60Sopenharmony_ci
43f6603c60Sopenharmony_cistatic void Handler(int sig)
44f6603c60Sopenharmony_ci{
45f6603c60Sopenharmony_ci}
46f6603c60Sopenharmony_ci
47f6603c60Sopenharmony_cistatic int Start(const char *argvs)
48f6603c60Sopenharmony_ci{
49f6603c60Sopenharmony_ci    int pid, spaceSize = 100 * 1024;
50f6603c60Sopenharmony_ci    // Create a child process
51f6603c60Sopenharmony_ci    // Set the process stack space
52f6603c60Sopenharmony_ci    pid = fork();
53f6603c60Sopenharmony_ci    if (pid == 0) {
54f6603c60Sopenharmony_ci        Runtest::TSetrlim(RLIMIT_STACK, spaceSize);
55f6603c60Sopenharmony_ci        // Overloading the subprocess space
56f6603c60Sopenharmony_ci        int exe = execl(argvs, "strptime", nullptr);
57f6603c60Sopenharmony_ci        printf("exe:%d %s exec failed: %s\n", exe, argvs, strerror(errno));
58f6603c60Sopenharmony_ci        exit(1);
59f6603c60Sopenharmony_ci    }
60f6603c60Sopenharmony_ci    return pid;
61f6603c60Sopenharmony_ci}
62f6603c60Sopenharmony_ci
63f6603c60Sopenharmony_cistatic int RunTests(const char *argvs)
64f6603c60Sopenharmony_ci{
65f6603c60Sopenharmony_ci    int timeoutsec = 10, timeout = 0;
66f6603c60Sopenharmony_ci    int status, pid;
67f6603c60Sopenharmony_ci    sigset_t set;
68f6603c60Sopenharmony_ci    void (*retfunc)(int);
69f6603c60Sopenharmony_ci    // signal set
70f6603c60Sopenharmony_ci    sigemptyset(&set);
71f6603c60Sopenharmony_ci    sigaddset(&set, SIGCHLD);
72f6603c60Sopenharmony_ci    sigprocmask(SIG_BLOCK, &set, nullptr);
73f6603c60Sopenharmony_ci    retfunc = signal(SIGCHLD, Handler);
74f6603c60Sopenharmony_ci    if (retfunc == SIG_ERR) {
75f6603c60Sopenharmony_ci        printf("signal triggering failed:%s\n", strerror(errno));
76f6603c60Sopenharmony_ci    }
77f6603c60Sopenharmony_ci    pid = Start(argvs);
78f6603c60Sopenharmony_ci    // The function system call failed
79f6603c60Sopenharmony_ci    if (pid == -1) {
80f6603c60Sopenharmony_ci        printf("%s fork failed: %s\n", argvs, strerror(errno));
81f6603c60Sopenharmony_ci        printf("FAIL %s [internal]\n", argvs);
82f6603c60Sopenharmony_ci        return -1;
83f6603c60Sopenharmony_ci    }
84f6603c60Sopenharmony_ci    struct timespec tp;
85f6603c60Sopenharmony_ci    // Maximum blocking time
86f6603c60Sopenharmony_ci    tp.tv_sec = timeoutsec;
87f6603c60Sopenharmony_ci    tp.tv_nsec = 0;
88f6603c60Sopenharmony_ci    if (sigtimedwait(&set, nullptr, &tp) == -1) {
89f6603c60Sopenharmony_ci        // Call it again
90f6603c60Sopenharmony_ci        if (errno == EAGAIN) {
91f6603c60Sopenharmony_ci            timeout = 1;
92f6603c60Sopenharmony_ci        } else {
93f6603c60Sopenharmony_ci            printf("%s sigtimedwait failed: %s\n", argvs, strerror(errno));
94f6603c60Sopenharmony_ci        }
95f6603c60Sopenharmony_ci        if (kill(pid, SIGKILL) == -1) {
96f6603c60Sopenharmony_ci            printf("%s kill failed: %s\n", argvs, strerror(errno));
97f6603c60Sopenharmony_ci        }
98f6603c60Sopenharmony_ci    }
99f6603c60Sopenharmony_ci    // Waiting for the process to stop
100f6603c60Sopenharmony_ci    if (waitpid(pid, &status, 0) != pid) {
101f6603c60Sopenharmony_ci        printf("%s waitpid failed: %s\n", argvs, strerror(errno));
102f6603c60Sopenharmony_ci        printf("FAIL %s [internal]\n", argvs);
103f6603c60Sopenharmony_ci        return -1;
104f6603c60Sopenharmony_ci    }
105f6603c60Sopenharmony_ci    // Process state
106f6603c60Sopenharmony_ci    if (WIFEXITED(status)) { // The right exit
107f6603c60Sopenharmony_ci        if (WEXITSTATUS(status) == 0) { // operate successfully
108f6603c60Sopenharmony_ci            return g_tStatus;
109f6603c60Sopenharmony_ci        }
110f6603c60Sopenharmony_ci        printf("FAIL %s [status %d]\n", argvs, WEXITSTATUS(status));
111f6603c60Sopenharmony_ci    } else if (timeout) {
112f6603c60Sopenharmony_ci        printf("FAIL %s [timed out]\n", argvs);
113f6603c60Sopenharmony_ci    } else if (WIFSIGNALED(status)) {
114f6603c60Sopenharmony_ci        printf("FAIL %s [signal %s]\n", argvs, strsignal(WTERMSIG(status)));
115f6603c60Sopenharmony_ci    } else {
116f6603c60Sopenharmony_ci        printf("FAIL %s [unknown]\n", argvs);
117f6603c60Sopenharmony_ci    }
118f6603c60Sopenharmony_ci    return 1;
119f6603c60Sopenharmony_ci}
120f6603c60Sopenharmony_ci
121f6603c60Sopenharmony_ci
122f6603c60Sopenharmony_ci/**
123f6603c60Sopenharmony_ci * @tc.name      : Toolchaintest.LibcTest
124f6603c60Sopenharmony_ci * @tc.desc      : start test
125f6603c60Sopenharmony_ci * @tc.level     : Level 3
126f6603c60Sopenharmony_ci */
127f6603c60Sopenharmony_ciHWTEST_P(Toolchaintest, LibcTest, Function | MediumTest | Level3)
128f6603c60Sopenharmony_ci{
129f6603c60Sopenharmony_ci    int ret;
130f6603c60Sopenharmony_ci    string testName = GetParam();
131f6603c60Sopenharmony_ci    ret = RunTests(testName.c_str());
132f6603c60Sopenharmony_ci    if (ret == 0) {
133f6603c60Sopenharmony_ci        EXPECT_EQ(0, ret) << "test  " << testName  << "  succeed" << endl;
134f6603c60Sopenharmony_ci    } else {
135f6603c60Sopenharmony_ci        EXPECT_EQ(1, ret) << "test  " << testName  << "  failed" << endl;
136f6603c60Sopenharmony_ci        EXPECT_EQ(-1, ret) << "test  " << testName  << "  failed" << endl;
137f6603c60Sopenharmony_ci    }
138f6603c60Sopenharmony_ci}
139f6603c60Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(libcTest, Toolchaintest, testing::ValuesIn(temp.begin(), temp.end()));
140f6603c60Sopenharmony_ci} // namespace OHOS
141