1/*
2 * Copyright (c) 2024 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 <errno.h>
17#include <signal.h>
18#include <string.h>
19#include <sys/wait.h>
20#include <sys/select.h>
21#include <sigchain.h>
22#include "fortify_test.h"
23#include "functionalext.h"
24#include "test.h"
25
26/**
27 * @tc.name     : fd_set_0010
28 * @tc.desc     : test FD_SET with normal fd
29 * @tc.level    : Level 1
30 */
31static void fd_set_0010(void)
32{
33    fd_set readfds;
34    FD_ZERO(&readfds);
35    int sockfd = 0;
36    FD_SET(sockfd, &readfds);
37    EXPECT_EQ(fd_set_0010, (&readfds)->fds_bits[0], 1);
38
39    return;
40}
41
42/**
43 * @tc.name     : fd_set_0020
44 * @tc.desc     : test FD_SET with fd < 0
45 * @tc.level    : Level 2
46 */
47static void fd_set_0020(void)
48{
49    struct sigaction sigabrt = {
50        .sa_handler = SignalHandler,
51    };
52    sigaction(SIGABRT, &sigabrt, NULL);
53
54    int status;
55    int pid = fork();
56    fd_set readfds;
57    int sockfd = -1;
58    switch (pid) {
59        case -1:
60            t_error("fork failed: %s\n", strerror(errno));
61            break;
62        case 0:
63            FD_ZERO(&readfds);
64            FD_SET(sockfd, &readfds);
65            exit(0);
66        default:
67            waitpid(pid, &status, WUNTRACED);
68            TEST(WIFEXITED(status) == 0);
69            TEST(WIFSTOPPED(status) == 1);
70            TEST(WSTOPSIG(status) == SIGSTOP);
71            kill(pid, SIGCONT);
72            break;
73    }
74
75    return;
76}
77
78/**
79 * @tc.name     : fd_set_0030
80 * @tc.desc     : test FD_SET with fd >= 1024
81 * @tc.level    : Level 2
82 */
83static void fd_set_0030(void)
84{
85    struct sigaction sigabrt = {
86        .sa_handler = SignalHandler,
87    };
88    sigaction(SIGABRT, &sigabrt, NULL);
89
90    int status;
91    int pid = fork();
92    fd_set readfds;
93    int sockfd = 1024;
94    switch (pid) {
95        case -1:
96            t_error("fork failed: %s\n", strerror(errno));
97            break;
98        case 0:
99            FD_ZERO(&readfds);
100            FD_SET(sockfd, &readfds);
101            exit(0);
102        default:
103            waitpid(pid, &status, WUNTRACED);
104            TEST(WIFEXITED(status) == 0);
105            TEST(WIFSTOPPED(status) == 1);
106            TEST(WSTOPSIG(status) == SIGSTOP);
107            kill(pid, SIGCONT);
108            break;
109    }
110
111    return;
112}
113
114/**
115 * @tc.name     : fd_clr_0010
116 * @tc.desc     : test FD_CLR with normal fd
117 * @tc.level    : Level 1
118 */
119static void fd_clr_0010(void)
120{
121    fd_set readfds;
122    FD_ZERO(&readfds);
123    int sockfd = 0;
124    FD_SET(sockfd, &readfds);
125    FD_CLR(sockfd, &readfds);
126    EXPECT_EQ(fd_set_0010, (&readfds)->fds_bits[0], 0);
127
128    return;
129}
130
131/**
132 * @tc.name     : fd_clr_0020
133 * @tc.desc     : test FD_CLR with fd < 0
134 * @tc.level    : Level 2
135 */
136static void fd_clr_0020(void)
137{
138    struct sigaction sigabrt = {
139        .sa_handler = SignalHandler,
140    };
141    sigaction(SIGABRT, &sigabrt, NULL);
142
143    int status;
144    int pid = fork();
145    fd_set readfds;
146    int sockfd = -1;
147    switch (pid) {
148        case -1:
149            t_error("fork failed: %s\n", strerror(errno));
150            break;
151        case 0:
152            FD_ZERO(&readfds);
153            FD_CLR(sockfd, &readfds);
154            exit(0);
155        default:
156            waitpid(pid, &status, WUNTRACED);
157            TEST(WIFEXITED(status) == 0);
158            TEST(WIFSTOPPED(status) == 1);
159            TEST(WSTOPSIG(status) == SIGSTOP);
160            kill(pid, SIGCONT);
161            break;
162    }
163
164    return;
165}
166
167/**
168 * @tc.name     : fd_clr_0030
169 * @tc.desc     : test FD_CLR with fd >= 1024
170 * @tc.level    : Level 2
171 */
172static void fd_clr_0030(void)
173{
174    struct sigaction sigabrt = {
175        .sa_handler = SignalHandler,
176    };
177    sigaction(SIGABRT, &sigabrt, NULL);
178
179    int status;
180    int pid = fork();
181    fd_set readfds;
182    int sockfd = 1024;
183    switch (pid) {
184        case -1:
185            t_error("fork failed: %s\n", strerror(errno));
186            break;
187        case 0:
188            FD_ZERO(&readfds);
189            FD_CLR(sockfd, &readfds);
190            exit(0);
191        default:
192            waitpid(pid, &status, WUNTRACED);
193            TEST(WIFEXITED(status) == 0);
194            TEST(WIFSTOPPED(status) == 1);
195            TEST(WSTOPSIG(status) == SIGSTOP);
196            kill(pid, SIGCONT);
197            break;
198    }
199
200    return;
201}
202
203/**
204 * @tc.name     : fd_isset_0010
205 * @tc.desc     : test FD_ISSET with normal fd
206 * @tc.level    : Level 1
207 */
208static void fd_isset_0010(void)
209{
210    fd_set readfds;
211    FD_ZERO(&readfds);
212    int sockfd = 0;
213    FD_SET(sockfd, &readfds);
214    int res = FD_ISSET(sockfd, &readfds);
215    EXPECT_EQ(fd_set_0010, res, 1);
216
217    return;
218}
219
220/**
221 * @tc.name     : fd_isset_0020
222 * @tc.desc     : test FD_ISSET with fd < 0
223 * @tc.level    : Level 2
224 */
225static void fd_isset_0020(void)
226{
227    fd_set readfds;
228    FD_ZERO(&readfds);
229    int sockfd = -1;
230    int res = FD_ISSET(sockfd, &readfds);
231    EXPECT_EQ(fd_set_0010, res, 0);
232
233    return;
234}
235
236/**
237 * @tc.name     : fd_isset_0030
238 * @tc.desc     : test FD_ISSET with fd >= 1024
239 * @tc.level    : Level 2
240 */
241static void fd_isset_0030(void)
242{
243    fd_set readfds;
244    FD_ZERO(&readfds);
245    int sockfd = 1024;
246    int res = FD_ISSET(sockfd, &readfds);
247    EXPECT_EQ(fd_set_0010, res, 0);
248
249    return;
250}
251
252int main(int argc, char *argv[])
253{
254    remove_all_special_handler(SIGABRT);
255    fd_set_0010();
256    fd_set_0020();
257    fd_set_0030();
258    fd_clr_0010();
259    fd_clr_0020();
260    fd_clr_0030();
261    fd_isset_0010();
262    fd_isset_0020();
263    fd_isset_0030();
264    return t_status;
265}