Skip to content

Commit 3b629a3

Browse files
Add test for close_range adapted from t_closefrom
1 parent e83c6ca commit 3b629a3

File tree

2 files changed

+237
-0
lines changed

2 files changed

+237
-0
lines changed

tests/lib/libc/sys/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ TESTS_C+= t_chroot
1414
TESTS_C+= t_clock_gettime
1515
TESTS_C+= t_clock_nanosleep
1616
TESTS_C+= t_clone
17+
TESTS_C+= t_close_range
1718
TESTS_C+= t_connect
1819
TESTS_C+= t_dup
1920
TESTS_C+= t_eventfd

tests/lib/libc/sys/t_close_range.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/*-
2+
* Copyright (c) 2011 The NetBSD Foundation, Inc.
3+
* All rights reserved.
4+
*
5+
* This code is derived from software contributed to The NetBSD Foundation
6+
* by Jukka Ruohonen.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions
10+
* are met:
11+
* 1. Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright
14+
* notice, this list of conditions and the following disclaimer in the
15+
* documentation and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18+
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19+
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20+
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21+
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
*/
29+
#include <sys/cdefs.h>
30+
31+
#include <sys/wait.h>
32+
33+
#include <atf-c.h>
34+
#include <errno.h>
35+
#include <fcntl.h>
36+
#include <limits.h>
37+
#include <unistd.h>
38+
39+
static const char path[] = "close_range";
40+
41+
ATF_TC_WITH_CLEANUP(close_range_basic);
42+
ATF_TC_HEAD(close_range_basic, tc)
43+
{
44+
atf_tc_set_md_var(tc, "descr", "A basic test of close_range(2), #1");
45+
}
46+
47+
ATF_TC_BODY(close_range_basic, tc)
48+
{
49+
int fd, cur1, cur2;
50+
51+
(void)close_range(STDERR_FILENO + 1, UINT_MAX, 0);
52+
53+
fd = open(path, O_RDONLY | O_CREAT, 0400);
54+
ATF_REQUIRE(fd >= 0);
55+
56+
cur1 = fcntl(0, F_MAXFD);
57+
58+
ATF_REQUIRE(cur1 == STDERR_FILENO + 1);
59+
ATF_REQUIRE(close_range(cur1, UINT_MAX, 0) == 0);
60+
61+
cur2 = fcntl(0, F_MAXFD);
62+
63+
ATF_REQUIRE(cur1 - 1 == cur2);
64+
ATF_REQUIRE(close(fd) == -1);
65+
ATF_REQUIRE(unlink(path) == 0);
66+
}
67+
68+
ATF_TC_CLEANUP(close_range_basic, tc)
69+
{
70+
(void)unlink(path);
71+
}
72+
73+
ATF_TC_WITH_CLEANUP(close_range_buffer);
74+
ATF_TC_HEAD(close_range_buffer, tc)
75+
{
76+
atf_tc_set_md_var(tc, "descr", "A basic test of close_range(2), #2");
77+
}
78+
79+
ATF_TC_BODY(close_range_buffer, tc)
80+
{
81+
int buf[16], cur, half;
82+
size_t i;
83+
84+
/*
85+
* Open a buffer of descriptors, close the half of
86+
* these and verify that the result is consistent.
87+
*/
88+
ATF_REQUIRE(close_range(STDERR_FILENO + 1, UINT_MAX, 0) == 0);
89+
90+
cur = fcntl(0, F_MAXFD);
91+
ATF_REQUIRE(cur == STDERR_FILENO);
92+
93+
for (i = 0; i < __arraycount(buf); i++) {
94+
buf[i] = open(path, O_RDWR | O_CREAT, 0600);
95+
ATF_REQUIRE(buf[i] >= 0);
96+
}
97+
98+
cur = fcntl(0, F_MAXFD);
99+
ATF_REQUIRE(cur == __arraycount(buf) + STDERR_FILENO);
100+
101+
half = STDERR_FILENO + __arraycount(buf) / 2;
102+
ATF_REQUIRE(close_range(half, UINT_MAX, 0) == 0);
103+
104+
cur = fcntl(0, F_MAXFD);
105+
ATF_REQUIRE(cur == half - 1);
106+
107+
for (i = 0; i < __arraycount(buf); i++)
108+
(void)close(buf[i]);
109+
}
110+
111+
ATF_TC_CLEANUP(close_range_buffer, tc)
112+
{
113+
(void)unlink(path);
114+
}
115+
116+
ATF_TC(close_range_err);
117+
ATF_TC_HEAD(close_range_err, tc)
118+
{
119+
atf_tc_set_md_var(tc, "descr", "Test errors from close_range(2)");
120+
}
121+
122+
ATF_TC_BODY(close_range_err, tc)
123+
{
124+
125+
errno = 0;
126+
ATF_REQUIRE_ERRNO(EINVAL, close_range(UINT_MAX, 0, 0) == -1);
127+
}
128+
129+
ATF_TC(close_range_one);
130+
ATF_TC_HEAD(close_range_one, tc)
131+
{
132+
atf_tc_set_md_var(tc, "descr", "Test close_range(1, UINT_MAX, 0)");
133+
}
134+
135+
ATF_TC_BODY(close_range_one, tc)
136+
{
137+
pid_t pid;
138+
int sta;
139+
140+
pid = fork();
141+
ATF_REQUIRE(pid >= 0);
142+
143+
if (pid == 0) {
144+
145+
if (close_range(1, UINT_MAX, 0) != 0)
146+
_exit(10);
147+
148+
_exit(fcntl(0, F_MAXFD));
149+
}
150+
151+
152+
(void)wait(&sta);
153+
154+
/*
155+
* STDIN_FILENO should still be open; WEXITSTATUS(1) == 0.
156+
*/
157+
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != 0)
158+
atf_tc_fail("not all descriptors were closed");
159+
}
160+
161+
ATF_TC_WITH_CLEANUP(close_range_cloexec);
162+
ATF_TC_HEAD(close_range_cloexec, tc)
163+
{
164+
atf_tc_set_md_var(tc, "descr", "Test close_range(2) with CLOSE_RANGE_CLOEXEC");
165+
}
166+
167+
ATF_TC_BODY(close_range_cloexec, tc)
168+
{
169+
int fd, cur1, cur2;
170+
int flags;
171+
172+
fd = open(path, O_RDONLY | O_CREAT, 0400);
173+
ATF_REQUIRE(fd >= 0);
174+
175+
flags = fcntl(fd, F_GETFD);
176+
ATF_REQUIRE(flags != -1);
177+
ATF_REQUIRE(fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1);
178+
179+
cur1 = fcntl(0, F_MAXFD);
180+
ATF_REQUIRE(cur1 == STDERR_FILENO + 1);
181+
ATF_REQUIRE(close_range(cur1, UINT_MAX, CLOSE_RANGE_CLOEXEC) == 0);
182+
183+
cur2 = fcntl(0, F_MAXFD);
184+
ATF_REQUIRE(cur1 == cur2);
185+
186+
flags = fcntl(fd, F_GETFD);
187+
ATF_REQUIRE(flags != -1);
188+
ATF_CHECK((flags & FD_CLOEXEC) != 0);
189+
190+
ATF_REQUIRE(close(fd) == 0);
191+
ATF_REQUIRE(unlink(path) == 0);
192+
}
193+
194+
ATF_TC_CLEANUP(close_range_cloexec, tc)
195+
{
196+
(void)unlink(path);
197+
}
198+
199+
ATF_TC_WITH_CLEANUP(close_range_invalid_flag);
200+
ATF_TC_HEAD(close_range_invalid_flag, tc)
201+
{
202+
atf_tc_set_md_var(tc, "descr", "Test close_range(2) with an invalid flag");
203+
}
204+
205+
ATF_TC_BODY(close_range_invalid_flag, tc)
206+
{
207+
int cur1, cur2;
208+
int unused_flag = 0x40000000;
209+
210+
cur1 = fcntl(0, F_MAXFD);
211+
ATF_REQUIRE(cur1 == STDERR_FILENO);
212+
213+
errno = 0;
214+
ATF_REQUIRE_ERRNO(EINVAL, close_range(STDERR_FILENO + 1, UINT_MAX, unused_flag) == -1);
215+
216+
cur2 = fcntl(0, F_MAXFD);
217+
ATF_REQUIRE(cur1 == cur2);
218+
}
219+
220+
ATF_TC_CLEANUP(close_range_invalid_flag, tc)
221+
{
222+
(void)unlink(path);
223+
}
224+
225+
ATF_TP_ADD_TCS(tp)
226+
{
227+
228+
ATF_TP_ADD_TC(tp, close_range_basic);
229+
ATF_TP_ADD_TC(tp, close_range_buffer);
230+
ATF_TP_ADD_TC(tp, close_range_err);
231+
ATF_TP_ADD_TC(tp, close_range_one);
232+
ATF_TP_ADD_TC(tp, close_range_cloexec);
233+
ATF_TP_ADD_TC(tp, close_range_invalid_flag);
234+
235+
return atf_no_error();
236+
}

0 commit comments

Comments
 (0)