]> git.saurik.com Git - apple/xnu.git/blame - tests/poll.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / tests / poll.c
CommitLineData
813fb2f6
A
1#ifdef T_NAMESPACE
2#undef T_NAMESPACE
3#endif
4#include <darwintest.h>
5
6#include <dispatch/dispatch.h>
7#include <fcntl.h>
8#include <mach/mach.h>
9#include <poll.h>
10#include <stdint.h>
11#include <unistd.h>
12
cb323159
A
13T_GLOBAL_META(T_META_NAMESPACE("xnu.poll"),
14 T_META_RUN_CONCURRENTLY(true));
813fb2f6
A
15
16#define SLEEP_TIME_SECS 1
17#define POLL_TIMEOUT_MS 1800
18static_assert(POLL_TIMEOUT_MS > (SLEEP_TIME_SECS * 1000),
0a7de745 19 "poll timeout should be longer than sleep time");
813fb2f6
A
20
21/*
22 * This matches the behavior of other UNIXes, but is under-specified in POSIX.
23 *
24 * See <rdar://problem/28372390>.
25 */
26T_DECL(sleep_with_no_fds,
0a7de745 27 "poll() called with no fds provided should act like sleep")
813fb2f6
A
28{
29 uint64_t begin_time, sleep_time, poll_time;
cb323159 30 struct pollfd pfd = { .fd = 0, .events = 0, .revents = 0 };
813fb2f6
A
31
32 begin_time = mach_absolute_time();
33 sleep(SLEEP_TIME_SECS);
34 sleep_time = mach_absolute_time() - begin_time;
35 T_LOG("sleep(%d) ~= %llu mach absolute time units", SLEEP_TIME_SECS, sleep_time);
36
37 begin_time = mach_absolute_time();
38 T_ASSERT_POSIX_SUCCESS(poll(&pfd, 0, POLL_TIMEOUT_MS),
0a7de745 39 "poll() with 0 events and timeout %d ms", POLL_TIMEOUT_MS);
813fb2f6
A
40 poll_time = mach_absolute_time() - begin_time;
41
42 T_EXPECT_GT(poll_time, sleep_time,
0a7de745 43 "poll(... %d) should wait longer than sleep(1)", POLL_TIMEOUT_MS);
813fb2f6
A
44}
45
46#define LAUNCHD_PATH "/sbin/launchd"
47#define PIPE_DIR_TIMEOUT_SECS 1
48
49/*
50 * See <rdar://problem/28539155>.
51 */
52T_DECL(directories,
0a7de745 53 "poll() with directories should return an error")
813fb2f6
A
54{
55 int file, dir, pipes[2];
56 struct pollfd pfd[] = {
57 { .events = POLLIN },
58 { .events = POLLIN },
59 { .events = POLLIN },
60 };
61
62 file = open(LAUNCHD_PATH, O_RDONLY | O_NONBLOCK);
63 T_QUIET; T_ASSERT_POSIX_SUCCESS(file, "open(%s)", LAUNCHD_PATH);
64 dir = open(".", O_RDONLY | O_NONBLOCK);
65 T_QUIET; T_ASSERT_POSIX_SUCCESS(dir, "open(\".\")");
66 T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(pipes), NULL);
67
68 /* just directory */
69 pfd[0].fd = dir;
70 T_EXPECT_POSIX_SUCCESS(poll(pfd, 1, -1), "poll() with a directory");
71 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
0a7de745 72 "directory should be an invalid event");
813fb2f6
A
73
74 /* file and directory */
75 pfd[0].fd = file; pfd[0].revents = 0;
76 pfd[1].fd = dir; pfd[1].revents = 0;
77 T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
0a7de745 78 "poll() with a file and directory");
813fb2f6
A
79 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
80 T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
0a7de745 81 "directory should be an invalid event");
813fb2f6
A
82
83 /* directory and file */
84 pfd[0].fd = dir; pfd[0].revents = 0;
85 pfd[1].fd = file; pfd[1].revents = 0;
86 T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
0a7de745 87 "poll() with a directory and a file");
813fb2f6 88 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
0a7de745 89 "directory should be an invalid event");
813fb2f6
A
90 T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLIN, "file should be readable");
91
92 /* file and pipe */
93 pfd[0].fd = file; pfd[0].revents = 0;
94 pfd[1].fd = pipes[0]; pfd[0].revents = 0;
95 T_EXPECT_POSIX_SUCCESS(poll(pfd, 2, -1),
0a7de745 96 "poll() with a file and pipe");
813fb2f6
A
97 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
98 T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN,
0a7de745 99 "pipe should not be readable");
813fb2f6
A
100
101 /* file, directory, and pipe */
102 pfd[0].fd = file; pfd[0].revents = 0;
103 pfd[1].fd = dir; pfd[1].revents = 0;
104 pfd[2].fd = pipes[0]; pfd[2].revents = 0;
105 T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
0a7de745 106 "poll() with a file, directory, and pipe");
813fb2f6
A
107 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLIN, "file should be readable");
108 T_QUIET; T_EXPECT_TRUE(pfd[1].revents & POLLNVAL,
0a7de745 109 "directory should be an invalid event");
813fb2f6
A
110 T_QUIET; T_EXPECT_FALSE(pfd[2].revents & POLLIN, "pipe should not be readable");
111
112 /* directory and pipe */
113 __block bool timed_out = true;
114 pfd[0].fd = dir; pfd[0].revents = 0;
115 pfd[1].fd = pipes[0]; pfd[1].revents = 0;
116 dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
0a7de745
A
117 PIPE_DIR_TIMEOUT_SECS * NSEC_PER_SEC),
118 dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
813fb2f6 119 T_ASSERT_FALSE(timed_out, "poll timed out after %d seconds",
0a7de745 120 PIPE_DIR_TIMEOUT_SECS);
813fb2f6
A
121 });
122
123 T_EXPECT_POSIX_SUCCESS(poll(pfd, 3, -1),
0a7de745 124 "poll() with a directory and pipe");
813fb2f6
A
125 timed_out = false;
126
127 T_QUIET; T_EXPECT_TRUE(pfd[0].revents & POLLNVAL,
0a7de745 128 "directory should be an invalid event");
813fb2f6
A
129 T_QUIET; T_EXPECT_FALSE(pfd[1].revents & POLLIN, "pipe should not be readable");
130}