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