Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F152827505
D52800.id163123.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D52800.id163123.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,45 @@
#include <string.h>
#include <unistd.h>
-struct shared_info {
- int failed;
- char tag[64];
- char message[0];
-};
-
-static int test = 1;
-
-static void
-ok(const char *descr)
-{
-
- printf("ok %d - %s\n", test, descr);
- test++;
-}
-
-static void
-fail(const char *descr, const char *fmt, ...)
+#include <atf-c.h>
+
+/*
+ * A variant of ATF_REQUIRE that is suitable for use in child
+ * processes. This only works if the parent process is tripped up by
+ * the early exit and fails some requirement itself.
+ */
+#define CHILD_REQUIRE(exp) do { \
+ if (!(exp)) \
+ child_fail_require(__FILE__, __LINE__, \
+ #exp " not met\n"); \
+} while (0)
+
+#define CHILD_REQUIRE_EQ(actual, expected) do { \
+ __typeof__(expected) _e = expected; \
+ __typeof__(actual) _a = actual; \
+ if (_e != _a) \
+ child_fail_require(__FILE__, __LINE__, #actual \
+ " (%jd) == " #expected " (%jd) not met\n", \
+ (intmax_t)_a, (intmax_t)_e); \
+} while (0)
+
+static __dead2 void
+child_fail_require(const char *file, int line, const char *fmt, ...)
{
va_list ap;
+ char buf[1024];
- 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);
-}
-
-#define fail_err(descr) fail((descr), "%s", strerror(errno))
+ /* Use write() not fprintf() to avoid possible duplicate output. */
+ snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
+ write(STDERR_FILENO, buf, strlen(buf));
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ write(STDERR_FILENO, buf, strlen(buf));
+ va_end(ap);
-static void
-cok(struct shared_info *info, const char *descr)
-{
-
- info->failed = 0;
- strlcpy(info->tag, descr, sizeof(info->tag));
- exit(0);
-}
-
-static void
-cfail(struct shared_info *info, const char *descr, const char *fmt, ...)
-{
- 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);
+ _exit(32);
}
-#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 +94,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 +109,268 @@
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");
+ ATF_REQUIRE_INTEQ(fd, 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");
+ /* 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");
+ closefrom(start + 9);
+ ATF_REQUIRE_INTEQ(start + 8, highest_fd());
- /* Explicitly close descriptors 6 and 8 to create holes. */
- if (close(6) < 0 || close(8) < 0)
- fail_err("close2 ");
- ok("close 2");
+ /* 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 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)");
+ /* 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 from 4 on. */
- closefrom(4);
- fd = highest_fd();
- if (fd != 3)
- fail("closefrom", "highest fd %d", fd);
- ok("closefrom");
+ /* Close most remaining descriptors. */
+ closefrom(start + 2);
+ ATF_REQUIRE_INTEQ(start + 1, highest_fd());
+}
- /* 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");
+ATF_TC_WITHOUT_HEAD(closefrom_zero);
+ATF_TC_BODY(closefrom_zero, tc)
+{
+ pid_t fpid, wpid;
+ int fd, status;
- /* Fork a child process to test closefrom(0). */
- pid = fork();
- if (pid < 0)
- fail_err("fork");
- if (pid == 0) {
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ fpid = fork();
+ ATF_REQUIRE_MSG(fpid != -1, "fork(): %s", strerror(errno));
+ if (fpid == 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 < 0);
+ 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");
- if (pid == 0) {
+
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE_MSG(wpid != -1, "waitpid: %s", strerror(errno));
+ ATF_REQUIRE_INTEQ(fpid, wpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_INTEQ(0, WEXITSTATUS(status));
+}
+
+ATF_TC_WITHOUT_HEAD(closefrom_negative_one);
+ATF_TC_BODY(closefrom_negative_one, tc)
+{
+ pid_t fpid, wpid;
+ int fd, status;
+
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ fpid = fork();
+ ATF_REQUIRE_MSG(fpid != -1, "fork(): %s", strerror(errno));
+ if (fpid == 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 < 0);
+ 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");
+
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE_MSG(wpid != -1, "waitpid: %s", strerror(errno));
+ ATF_REQUIRE_INTEQ(fpid, wpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_INTEQ(0, WEXITSTATUS(status));
+}
+
+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());
+}
- /* Chew up another 8 fd */
+ATF_TC_WITHOUT_HEAD(closerange_basic);
+ATF_TC_BODY(closerange_basic, tc)
+{
+ struct stat sb;
+ int i, start;
+
+ 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");
+ ATF_REQUIRE_INTEQ(0, close_range(start + 1, start + 4, 0));
+ ATF_REQUIRE_INTEQ(start, highest_fd());
+}
- /* Fork a child process to test closefrom(0) twice. */
- pid = fork();
- if (pid < 0)
- fail_err("fork");
- if (pid == 0) {
+ATF_TC_WITHOUT_HEAD(closefrom_zero_twice);
+ATF_TC_BODY(closefrom_zero_twice, tc)
+{
+ pid_t fpid, wpid;
+ int fd, status;
+
+ /* Ensure standard descriptors are open. */
+ ATF_REQUIRE(highest_fd() >= 2);
+
+ fpid = fork();
+ ATF_REQUIRE_MSG(fpid != -1, "fork(): %s", strerror(errno));
+ if (fpid == 0) {
/* Child. */
closefrom(0);
+ fd = highest_fd();
+ CHILD_REQUIRE(fd < 0);
closefrom(0);
- cok(info, "closefrom(0)");
+ fd = highest_fd();
+ CHILD_REQUIRE(fd < 0);
+ 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 */
+ wpid = waitpid(fpid, &status, 0);
+ ATF_REQUIRE_MSG(wpid != -1, "waitpid: %s", strerror(errno));
+ ATF_REQUIRE_INTEQ(fpid, wpid);
+ ATF_REQUIRE(WIFEXITED(status));
+ ATF_REQUIRE_INTEQ(0, WEXITSTATUS(status));
+}
+
+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));
+}
+
+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 (0);
+ return (atf_no_error());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 18, 9:18 AM (1 h, 27 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31710470
Default Alt Text
D52800.id163123.diff (15 KB)
Attached To
Mode
D52800: closefrom_test: Convert to atf-c(3)
Attached
Detach File
Event Timeline
Log In to Comment