Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F141939337
D52800.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
14 KB
Referenced Files
None
Subscribers
None
D52800.diff
View Options
diff --git a/tests/sys/file/Makefile b/tests/sys/file/Makefile
--- a/tests/sys/file/Makefile
+++ b/tests/sys/file/Makefile
@@ -3,7 +3,7 @@
BINDIR= ${TESTSDIR}
ATF_TESTS_C+= path_test
-TAP_TESTS_C+= closefrom_test
+ATF_TESTS_C+= closefrom_test
TAP_TESTS_C+= dup_test
ATF_TESTS_C+= fcntlflags_test
TAP_TESTS_SH+= flock_test
diff --git a/tests/sys/file/closefrom_test.c b/tests/sys/file/closefrom_test.c
--- a/tests/sys/file/closefrom_test.c
+++ b/tests/sys/file/closefrom_test.c
@@ -25,13 +25,13 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
* Regression tests for the closefrom(2) system call.
*/
#include <sys/param.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <errno.h>
@@ -44,67 +44,57 @@
#include <string.h>
#include <unistd.h>
-struct shared_info {
- int failed;
- char tag[64];
- char message[0];
-};
+#include <atf-c.h>
-static int test = 1;
+static char *shared_page;
-static void
-ok(const char *descr)
+/*
+ * A variant of ATF_REQUIRE that is suitable for use in child
+ * processes. Since these tests close stderr, errors are reported to
+ * a shared page of memory checked by the parent process.
+ */
+#define CHILD_REQUIRE(exp) do { \
+ if (!(exp)) \
+ child_fail_require(__FILE__, __LINE__, \
+ #exp " not met"); \
+} while (0)
+
+static __dead2 __printflike(3, 4) void
+child_fail_require(const char *file, int line, const char *fmt, ...)
{
+ FILE *fp;
+ va_list ap;
- printf("ok %d - %s\n", test, descr);
- test++;
-}
+ fp = fmemopen(shared_page, PAGE_SIZE - 1, "w");
+ if (fp == NULL)
+ exit(1);
-static void
-fail(const char *descr, const char *fmt, ...)
-{
- va_list ap;
+ fprintf(fp, "%s:%d: ", file, line);
+ va_start(ap, fmt);
+ vfprintf(fp, fmt, ap);
+ va_end(ap);
+ fclose(fp);
- printf("not ok %d - %s", test, descr);
- test++;
- if (fmt) {
- va_start(ap, fmt);
- printf(" # ");
- vprintf(fmt, ap);
- va_end(ap);
- }
- printf("\n");
- exit(1);
+ exit(0);
}
-#define fail_err(descr) fail((descr), "%s", strerror(errno))
-
-static void
-cok(struct shared_info *info, const char *descr)
+static pid_t
+child_fork(void)
{
-
- info->failed = 0;
- strlcpy(info->tag, descr, sizeof(info->tag));
- exit(0);
+ shared_page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANON |
+ MAP_SHARED, -1, 0);
+ ATF_REQUIRE_MSG(shared_page != MAP_FAILED, "mmap: %s", strerror(errno));
+ return (atf_utils_fork());
}
static void
-cfail(struct shared_info *info, const char *descr, const char *fmt, ...)
+child_wait(pid_t pid)
{
- va_list ap;
-
- info->failed = 1;
- strlcpy(info->tag, descr, sizeof(info->tag));
- if (fmt) {
- va_start(ap, fmt);
- vsprintf(info->message, fmt, ap);
- va_end(ap);
- }
- exit(0);
+ atf_utils_wait(pid, 0, "", "");
+ if (shared_page[0] != '\0')
+ atf_tc_fail("%s", shared_page);
}
-#define cfail_err(info, descr) cfail((info), (descr), "%s", strerror(errno))
-
/*
* Use kinfo_getfile() to fetch the list of file descriptors and figure out
* the highest open file descriptor.
@@ -116,9 +106,8 @@
int cnt, i, highest;
kif = kinfo_getfile(getpid(), &cnt);
- if (kif == NULL)
- fail_err("kinfo_getfile");
- highest = INT_MIN;
+ ATF_REQUIRE_MSG(kif != NULL, "kinfo_getfile: %s", strerror(errno));
+ highest = -1;
for (i = 0; i < cnt; i++)
if (kif[i].kf_fd > highest)
highest = kif[i].kf_fd;
@@ -132,262 +121,253 @@
int fd;
fd = open(_PATH_DEVNULL, O_RDONLY);
- if (fd < 0)
- fail_err("open(\" "_PATH_DEVNULL" \")");
+ ATF_REQUIRE_MSG(fd != -1, "open(\" "_PATH_DEVNULL" \"): %s",
+ strerror(errno));
return (fd);
}
-int
-main(void)
+ATF_TC_WITHOUT_HEAD(closefrom_simple);
+ATF_TC_BODY(closefrom_simple, tc)
{
- struct shared_info *info;
- pid_t pid;
- int fd, flags, i, start;
-
- printf("1..22\n");
+ int fd, start;
/* We'd better start up with fd's 0, 1, and 2 open. */
- start = devnull();
- if (start < 3)
- fail("open", "bad descriptor %d", start);
- ok("open");
+ start = highest_fd();
+ ATF_REQUIRE(start >= 2);
+
+ fd = devnull();
+ ATF_REQUIRE(fd > start);
/* Make sure highest_fd() works. */
- fd = highest_fd();
- if (start != fd)
- fail("highest_fd", "bad descriptor %d != %d", start, fd);
- ok("highest_fd");
-
- /* Try to use closefrom() for just closing fd 3. */
- closefrom(start);
- fd = highest_fd();
- if (fd != start - 1)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
+ ATF_REQUIRE_INTEQ(fd, highest_fd());
+
+ /* Try to use closefrom() to close just the new fd. */
+ closefrom(fd);
+ ATF_REQUIRE_INTEQ(start, highest_fd());
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_with_holes);
+ATF_TC_BODY(closefrom_with_holes, tc)
+{
+ int i, start;
+
+ start = highest_fd();
/* Eat up 16 descriptors. */
for (i = 0; i < 16; i++)
(void)devnull();
- fd = highest_fd();
- if (fd != start + 15)
- fail("open 16", "highest fd %d", fd);
- ok("open 16");
+
+ ATF_REQUIRE_INTEQ(start + 16, highest_fd());
/* Close half of them. */
- closefrom(11);
- fd = highest_fd();
- if (fd != 10)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
-
- /* Explicitly close descriptors 6 and 8 to create holes. */
- if (close(6) < 0 || close(8) < 0)
- fail_err("close2 ");
- ok("close 2");
-
- /* Verify that close on 6 and 8 fails with EBADF. */
- if (close(6) == 0)
- fail("close(6)", "did not fail");
- if (errno != EBADF)
- fail_err("close(6)");
- ok("close(6)");
- if (close(8) == 0)
- fail("close(8)", "did not fail");
- if (errno != EBADF)
- fail_err("close(8)");
- ok("close(8)");
-
- /* Close from 4 on. */
- closefrom(4);
- fd = highest_fd();
- if (fd != 3)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
-
- /* Allocate a small SHM region for IPC with our child. */
- info = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANON |
- MAP_SHARED, -1, 0);
- if (info == MAP_FAILED)
- fail_err("mmap");
- ok("mmap");
-
- /* Fork a child process to test closefrom(0). */
- pid = fork();
- if (pid < 0)
- fail_err("fork");
+ closefrom(start + 9);
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
+
+ /* Explicitly close two descriptors to create holes. */
+ ATF_REQUIRE_MSG(close(start + 3) == 0, "close(start + 3): %s",
+ strerror(errno));
+ ATF_REQUIRE_MSG(close(start + 5) == 0, "close(start + 5): %s",
+ strerror(errno));
+
+ /* Verify that close on the closed descriptors fails with EBADF. */
+ ATF_REQUIRE_ERRNO(EBADF, close(start + 3) == -1);
+ ATF_REQUIRE_ERRNO(EBADF, close(start + 5) == -1);
+
+ /* Close most remaining descriptors. */
+ closefrom(start + 2);
+ ATF_REQUIRE_INTEQ(start + 1, highest_fd());
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_zero);
+ATF_TC_BODY(closefrom_zero, tc)
+{
+ pid_t pid;
+ int fd;
+
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ pid = child_fork();
if (pid == 0) {
/* Child. */
closefrom(0);
fd = highest_fd();
- if (fd >= 0)
- cfail(info, "closefrom(0)", "highest fd %d", fd);
- cok(info, "closefrom(0)");
+ CHILD_REQUIRE(fd == -1);
+ exit(0);
}
- if (wait(NULL) < 0)
- fail_err("wait");
- if (info->failed)
- fail(info->tag, "%s", info->message);
- ok(info->tag);
-
- /* Fork a child process to test closefrom(-1). */
- pid = fork();
- if (pid < 0)
- fail_err("fork");
+
+ child_wait(pid);
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_negative_one);
+ATF_TC_BODY(closefrom_negative_one, tc)
+{
+ pid_t pid;
+ int fd;
+
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ pid = child_fork();
if (pid == 0) {
/* Child. */
closefrom(-1);
fd = highest_fd();
- if (fd >= 0)
- cfail(info, "closefrom(-1)", "highest fd %d", fd);
- cok(info, "closefrom(-1)");
+ CHILD_REQUIRE(fd == -1);
+ exit(0);
}
- if (wait(NULL) < 0)
- fail_err("wait");
- if (info->failed)
- fail(info->tag, "%s", info->message);
- ok(info->tag);
-
- /* Dup stdout to 6. */
- if (dup2(1, 6) < 0)
- fail_err("dup2");
- fd = highest_fd();
- if (fd != 6)
- fail("dup2", "highest fd %d", fd);
- ok("dup2");
+
+ child_wait(pid);
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_in_holes);
+ATF_TC_BODY(closefrom_in_holes, tc)
+{
+ int start;
+
+ start = highest_fd();
+ ATF_REQUIRE(start >= 2);
+
+ /* Dup stdout to a higher fd. */
+ ATF_REQUIRE_INTEQ(start + 4, dup2(1, start + 4));
+ ATF_REQUIRE_INTEQ(start + 4, highest_fd());
/* Do a closefrom() starting in a hole. */
- closefrom(4);
- fd = highest_fd();
- if (fd != 3)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
+ closefrom(start + 2);
+ ATF_REQUIRE_INTEQ(start, highest_fd());
/* Do a closefrom() beyond our highest open fd. */
- closefrom(32);
- fd = highest_fd();
- if (fd != 3)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
+ closefrom(start + 32);
+ ATF_REQUIRE_INTEQ(start, highest_fd());
+}
+
+ATF_TC_WITHOUT_HEAD(closerange_basic);
+ATF_TC_BODY(closerange_basic, tc)
+{
+ struct stat sb;
+ int i, start;
- /* Chew up another 8 fd */
+ start = highest_fd();
+
+ /* Open 8 file descriptors */
for (i = 0; i < 8; i++)
(void)devnull();
- fd = highest_fd();
- start = fd - 7;
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
/* close_range() a hole in the middle */
- close_range(start + 3, start + 5, 0);
- for (i = start + 3; i < start + 6; ++i) {
- if (close(i) == 0 || errno != EBADF) {
- --i;
- break;
- }
- }
- if (i != start + 6)
- fail("close_range", "failed to close at %d in %d - %d", i + 1,
- start + 3, start + 6);
- ok("close_range");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 3, start + 5, 0));
+ for (i = start + 3; i < start + 6; ++i)
+ ATF_REQUIRE_ERRNO(EBADF, fstat(i, &sb) == -1);
/* close_range from the middle of the hole */
- close_range(start + 4, start + 6, 0);
- if ((i = highest_fd()) != fd)
- fail("close_range", "highest fd %d", i);
- ok("close_range");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 4, start + 6, 0));
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
/* close_range to the end; effectively closefrom(2) */
- close_range(start + 3, ~0L, 0);
- if ((i = highest_fd()) != start + 2)
- fail("close_range", "highest fd %d", i);
- ok("close_range");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 3, ~0L, 0));
+ ATF_REQUIRE_INTEQ(start + 2, highest_fd());
/* Now close the rest */
- close_range(start, start + 4, 0);
- fd = highest_fd();
- if (fd != 3)
- fail("close_range", "highest fd %d", fd);
- ok("close_range");
-
- /* Fork a child process to test closefrom(0) twice. */
- pid = fork();
- if (pid < 0)
- fail_err("fork");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 1, start + 4, 0));
+ ATF_REQUIRE_INTEQ(start, highest_fd());
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_zero_twice);
+ATF_TC_BODY(closefrom_zero_twice, tc)
+{
+ pid_t pid;
+ int fd;
+
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ pid = child_fork();
if (pid == 0) {
/* Child. */
closefrom(0);
+ fd = highest_fd();
+ CHILD_REQUIRE(fd == -1);
closefrom(0);
- cok(info, "closefrom(0)");
+ fd = highest_fd();
+ CHILD_REQUIRE(fd == -1);
+ exit(0);
}
- if (wait(NULL) < 0)
- fail_err("wait");
- if (info->failed)
- fail(info->tag, "%s", info->message);
- ok(info->tag);
- /* test CLOSE_RANGE_CLOEXEC */
+ child_wait(pid);
+}
+
+static void
+require_fd_flag(int fd, const char *descr, const char *descr2, int flag,
+ bool set)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFD);
+ ATF_REQUIRE_MSG(flags >= 0, "fcntl(.., F_GETFD): %s", strerror(errno));
+
+ if (set) {
+ ATF_REQUIRE_MSG((flags & flag) == flag,
+ "%s did not set %s on fd %d", descr, descr2, fd);
+ } else {
+ ATF_REQUIRE_MSG((flags & flag) == 0,
+ "%s set %s when it should not have on fd %d", descr, descr2,
+ fd);
+ }
+}
+
+ATF_TC_WITHOUT_HEAD(closerange_CLOEXEC);
+ATF_TC_BODY(closerange_CLOEXEC, tc)
+{
+ int i, start;
+
+ start = highest_fd();
+ ATF_REQUIRE(start >= 2);
+
for (i = 0; i < 8; i++)
(void)devnull();
- fd = highest_fd();
- start = fd - 8;
- if (close_range(start + 1, start + 4, CLOSE_RANGE_CLOEXEC) < 0)
- fail_err("close_range(..., CLOSE_RANGE_CLOEXEC)");
- flags = fcntl(start, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOEXEC) != 0)
- fail("close_range", "CLOSE_RANGE_CLOEXEC set close-on-exec "
- "when it should not have on fd %d", start);
- for (i = start + 1; i <= start + 4; i++) {
- flags = fcntl(i, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOEXEC) == 0)
- fail("close_range", "CLOSE_RANGE_CLOEXEC did not set "
- "close-on-exec on fd %d", i);
- }
- for (; i < start + 8; i++) {
- flags = fcntl(i, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOEXEC) != 0)
- fail("close_range", "CLOSE_RANGE_CLOEXEC set close-on-exec "
- "when it should not have on fd %d", i);
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
+
+ ATF_REQUIRE_INTEQ(0, close_range(start + 2, start + 5,
+ CLOSE_RANGE_CLOEXEC));
+ for (i = 1; i < 9; i++) {
+ require_fd_flag(start + i, "CLOSE_RANGE_CLOEXEC",
+ "close-on-exec", FD_CLOEXEC, i >= 2 && i <= 5);
}
- if (close_range(start, start + 8, 0) < 0)
- fail_err("close_range");
- ok("close_range(..., CLOSE_RANGE_CLOEXEC)");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 1, start + 8, 0));
+}
+
+ATF_TC_WITHOUT_HEAD(closerange_CLOFORK);
+ATF_TC_BODY(closerange_CLOFORK, tc)
+{
+ int i, start;
+
+ start = highest_fd();
+ ATF_REQUIRE(start >= 2);
- /* test CLOSE_RANGE_CLOFORK */
for (i = 0; i < 8; i++)
(void)devnull();
- fd = highest_fd();
- start = fd - 8;
- if (close_range(start + 1, start + 4, CLOSE_RANGE_CLOFORK) < 0)
- fail_err("close_range(..., CLOSE_RANGE_CLOFORK)");
- flags = fcntl(start, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOFORK) != 0)
- fail("close_range", "CLOSE_RANGE_CLOFORK set close-on-exec "
- "when it should not have on fd %d", start);
- for (i = start + 1; i <= start + 4; i++) {
- flags = fcntl(i, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOFORK) == 0)
- fail("close_range", "CLOSE_RANGE_CLOFORK did not set "
- "close-on-exec on fd %d", i);
- }
- for (; i < start + 8; i++) {
- flags = fcntl(i, F_GETFD);
- if (flags < 0)
- fail_err("fcntl(.., F_GETFD)");
- if ((flags & FD_CLOFORK) != 0)
- fail("close_range", "CLOSE_RANGE_CLOFORK set close-on-exec "
- "when it should not have on fd %d", i);
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
+
+ ATF_REQUIRE_INTEQ(0, close_range(start + 2, start + 5,
+ CLOSE_RANGE_CLOFORK));
+ for (i = 1; i < 9; i++) {
+ require_fd_flag(start + i, "CLOSE_RANGE_CLOFORK",
+ "close-on-fork", FD_CLOFORK, i >= 2 && i <= 5);
}
- if (close_range(start, start + 8, 0) < 0)
- fail_err("close_range");
- ok("close_range(..., CLOSE_RANGE_CLOFORK)");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 1, start + 8, 0));
+}
- return (0);
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, closefrom_simple);
+ ATF_TP_ADD_TC(tp, closefrom_with_holes);
+ ATF_TP_ADD_TC(tp, closefrom_zero);
+ ATF_TP_ADD_TC(tp, closefrom_negative_one);
+ ATF_TP_ADD_TC(tp, closefrom_in_holes);
+ ATF_TP_ADD_TC(tp, closerange_basic);
+ ATF_TP_ADD_TC(tp, closefrom_zero_twice);
+ ATF_TP_ADD_TC(tp, closerange_CLOEXEC);
+ ATF_TP_ADD_TC(tp, closerange_CLOFORK);
+
+ return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 14, 2:00 PM (6 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27637245
Default Alt Text
D52800.diff (14 KB)
Attached To
Mode
D52800: closefrom_test: Convert to atf-c(3)
Attached
Detach File
Event Timeline
Log In to Comment