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