]>
Commit | Line | Data |
---|---|---|
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 |
13 | T_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 | |
18 | static_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 | */ | |
26 | T_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 | */ | |
52 | T_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 | } |