1 // Copyright 2016 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <assert.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <threads.h>
14 #include <unistd.h>
15
16 #include <lib/fdio/io.h>
17 #include <lib/fdio/util.h>
18 #include <unittest/unittest.h>
19 #include <zircon/processargs.h>
20 #include <zircon/syscalls.h>
21
close_test(void)22 bool close_test(void) {
23 BEGIN_TEST;
24
25 zx_handle_t h = ZX_HANDLE_INVALID;
26 ASSERT_EQ(ZX_OK, zx_event_create(0u, &h), "zx_event_create() failed");
27 ASSERT_NE(h, ZX_HANDLE_INVALID, "");
28
29 // fdio_handle_fd() with shared_handle = true
30 int fd = fdio_handle_fd(h, ZX_USER_SIGNAL_0, ZX_USER_SIGNAL_1, true);
31 ASSERT_GT(fd, 0, "fdio_handle_fd() failed");
32
33 close(fd);
34
35 // close(fd) has not closed the wrapped handle
36 EXPECT_EQ(ZX_OK, zx_object_signal(h, 0, ZX_USER_SIGNAL_0),
37 "zx_object_signal() should succeed");
38
39 // fdio_handle_fd() with shared_handle = false
40 fd = fdio_handle_fd(h, ZX_USER_SIGNAL_0, ZX_USER_SIGNAL_1, false);
41 ASSERT_GT(fd, 0, "fdio_handle_fd() failed");
42
43 close(fd);
44
45 // close(fd) has closed the wrapped handle
46 EXPECT_EQ(ZX_ERR_BAD_HANDLE, zx_object_signal(h, 0, ZX_USER_SIGNAL_0),
47 "zx_object_signal() should fail");
48
49 END_TEST;
50 }
51
pipe_test(void)52 bool pipe_test(void) {
53 BEGIN_TEST;
54
55 int fds[2];
56 int status = pipe(fds);
57 ASSERT_EQ(status, 0, "pipe() failed");
58
59 struct stat st;
60 ASSERT_EQ(fstat(fds[0], &st), 0, "fstat() on pipe failed");
61 ASSERT_EQ(st.st_mode & S_IFMT, (mode_t) S_IFIFO, "Unexpected mode");
62 ASSERT_EQ(fstat(fds[1], &st), 0, "fstat() on pipe failed");
63 ASSERT_EQ(st.st_mode & S_IFMT, (mode_t) S_IFIFO, "Unexpected mode");
64
65 status = fcntl(fds[0], F_GETFL);
66 ASSERT_EQ(status, 0, "fcntl(F_GETFL) failed");
67
68 status |= O_NONBLOCK;
69 status = fcntl(fds[0], F_SETFL, status);
70 ASSERT_EQ(status, 0, "fcntl(FSETFL, O_NONBLOCK) failed");
71
72 status = fcntl(fds[0], F_GETFL);
73 ASSERT_EQ(status, O_NONBLOCK, "fcntl(F_GETFL) failed");
74
75 int message[2] = {-6, 1};
76 ssize_t written = write(fds[1], message, sizeof(message));
77 ASSERT_GE(written, 0, "write() failed");
78 ASSERT_EQ((uint32_t)written, sizeof(message),
79 "write() should have written the whole message.");
80
81 int available = 0;
82 status = ioctl(fds[0], FIONREAD, &available);
83 ASSERT_GE(status, 0, "ioctl(FIONREAD) failed");
84 EXPECT_EQ((uint32_t)available, sizeof(message),
85 "ioctl(FIONREAD) queried wrong number of bytes");
86
87 int read_message[2];
88 ssize_t bytes_read = read(fds[0], read_message, sizeof(read_message));
89 ASSERT_GE(bytes_read, 0, "read() failed");
90 ASSERT_EQ((uint32_t)bytes_read, sizeof(read_message),
91 "read() read wrong number of bytes");
92
93 EXPECT_EQ(read_message[0], message[0], "read() read wrong value");
94 EXPECT_EQ(read_message[1], message[1], "read() read wrong value");
95
96 END_TEST;
97 }
98
write_thread(void * arg)99 int write_thread(void* arg) {
100 // Sleep to try to ensure the write happens after the poll.
101 zx_nanosleep(ZX_MSEC(5));
102 int message[2] = {-6, 1};
103 ssize_t written = write(*(int*)arg, message, sizeof(message));
104 ASSERT_GE(written, 0, "write() failed");
105 ASSERT_EQ((uint32_t)written, sizeof(message),
106 "write() should have written the whole message.");
107 return 0;
108 }
109
ppoll_test_handler(struct timespec * timeout)110 bool ppoll_test_handler(struct timespec* timeout) {
111 BEGIN_TEST;
112
113 int fds[2];
114 int status = pipe(fds);
115 ASSERT_EQ(status, 0, "pipe() failed");
116
117 thrd_t t;
118 int thrd_create_result = thrd_create(&t, write_thread, &fds[1]);
119 ASSERT_EQ(thrd_create_result, thrd_success, "create blocking send thread");
120
121 struct pollfd poll_fds[1] = {{fds[0], POLLIN, 0}};
122 int ppoll_result = ppoll(poll_fds, 1, timeout, NULL);
123
124 EXPECT_EQ(1, ppoll_result, "didn't read anything");
125
126 ASSERT_EQ(thrd_join(t, NULL), thrd_success, "join blocking send thread");
127
128 END_TEST;
129 }
130
ppoll_negative_test(void)131 bool ppoll_negative_test(void) {
132 struct timespec timeout_ts = {-1, -1};
133 return ppoll_test_handler(&timeout_ts);
134 }
135
ppoll_null_test(void)136 bool ppoll_null_test(void) {
137 return ppoll_test_handler(NULL);
138 }
139
ppoll_overflow_test(void)140 bool ppoll_overflow_test(void) {
141 unsigned int nanoseconds_in_seconds = 1000000000;
142 struct timespec timeout_ts = {UINT64_MAX / nanoseconds_in_seconds, UINT64_MAX % nanoseconds_in_seconds};
143 return ppoll_test_handler(&timeout_ts);
144 }
145
ppoll_immediate_timeout_test(void)146 bool ppoll_immediate_timeout_test(void) {
147 BEGIN_TEST;
148
149 int fds[2];
150 int status = pipe(fds);
151 ASSERT_EQ(status, 0, "pipe() failed");
152
153 struct timespec timeout = {0, 0};
154 struct pollfd poll_fds[1] = {{fds[0], POLLIN, 0}};
155 int ppoll_result = ppoll(poll_fds, 1, &timeout, NULL);
156
157 EXPECT_EQ(0, ppoll_result, "no fds should be readable");
158
159 END_TEST;
160 }
161
transfer_fd_test(void)162 bool transfer_fd_test(void) {
163 BEGIN_TEST;
164
165 int fds[2];
166 int status = pipe(fds);
167 ASSERT_EQ(status, 0, "pipe() failed");
168
169 // Make pipe nonblocking, write message
170 status |= O_NONBLOCK;
171 status = fcntl(fds[0], F_SETFL, status);
172 ASSERT_EQ(status, 0, "fcntl(FSETFL, O_NONBLOCK) failed");
173 int message[2] = {-6, 1};
174 ssize_t written = write(fds[1], message, sizeof(message));
175 ASSERT_GE(written, 0, "write() failed");
176 ASSERT_EQ((uint32_t)written, sizeof(message),
177 "write() should have written the whole message.");
178
179
180 // fd --> handles
181 zx_handle_t handles[FDIO_MAX_HANDLES];
182 uint32_t types[FDIO_MAX_HANDLES];
183 zx_status_t r = fdio_transfer_fd(fds[0], 0, handles, types);
184 ASSERT_GT(r, 0, "failed to transfer fds to handles");
185
186 // handles --> fd
187 ASSERT_EQ(fdio_create_fd(handles, types, r, &fds[0]), ZX_OK,
188 "failed to transfer handles to fds");
189
190 // Read message
191 int read_message[2];
192 ssize_t bytes_read = read(fds[0], read_message, sizeof(read_message));
193 ASSERT_GE(bytes_read, 0, "read() failed");
194 ASSERT_EQ((uint32_t)bytes_read, sizeof(read_message),
195 "read() read wrong number of bytes");
196
197 EXPECT_EQ(read_message[0], message[0], "read() read wrong value");
198 EXPECT_EQ(read_message[1], message[1], "read() read wrong value");
199
200 END_TEST;
201 }
202
transfer_device_test(void)203 bool transfer_device_test(void) {
204 BEGIN_TEST;
205
206 int fd = open("/dev/zero", O_RDONLY);
207 ASSERT_GE(fd, 0, "Failed to open /dev/zero");
208
209 // fd --> handles
210 zx_handle_t handles[FDIO_MAX_HANDLES];
211 uint32_t types[FDIO_MAX_HANDLES];
212 zx_status_t r = fdio_transfer_fd(fd, 0, handles, types);
213 ASSERT_GT(r, 0, "failed to transfer fds to handles");
214
215 // handles --> fd
216 ASSERT_EQ(fdio_create_fd(handles, types, r, &fd), ZX_OK,
217 "failed to transfer handles to fds");
218
219 ASSERT_EQ(close(fd), 0, "Failed to close fd");
220
221 END_TEST;
222 }
223
create_fd_from_connected_socket(void)224 bool create_fd_from_connected_socket(void) {
225 BEGIN_TEST;
226
227 int fd;
228 uint32_t type = PA_FDIO_SOCKET;
229 zx_handle_t h1, h2;
230 ASSERT_EQ(ZX_OK, zx_socket_create(ZX_SOCKET_STREAM, &h1, &h2),
231 "failed to create socket pair");
232 ASSERT_EQ(ZX_OK, fdio_create_fd(&h1, &type, 1, &fd),
233 "failed to create FD for socket handle");
234
235 int message[2] = {0xab, 0x1234};
236 size_t written;
237 ASSERT_EQ(ZX_OK, zx_socket_write(h2, 0, message, sizeof(message), &written),
238 "failed to write to socket handle");
239 ASSERT_EQ(sizeof(message), written,
240 "failed to write full message to socket handle");
241
242 int read_message[2] = {};
243 ssize_t bytes_read = read(fd, read_message, sizeof(read_message));
244 ASSERT_EQ(sizeof(message), (uint32_t)bytes_read,
245 "failed to read from socket fd");
246 ASSERT_EQ(0, memcmp(message, read_message, sizeof(message)),
247 "incorrect bytes read from socket fd");
248
249 // Set O_NONBLOCK
250 int flags = fcntl(fd, F_GETFL);
251 ASSERT_EQ(flags, 0, "fcntl(F_GETFL) failed");
252 flags |= O_NONBLOCK;
253 int ret = fcntl(fd, F_SETFL, flags);
254 ASSERT_EQ(ret, 0, "fcntl(FSETFL, O_NONBLOCK) failed");
255 ASSERT_EQ(-1, read(fd, read_message, sizeof(read_message)),
256 "failed to read from socket with O_NONBLOCK");
257 ASSERT_EQ(EAGAIN, errno, "errno incorrect");
258 END_TEST;
259 }
260
bind_to_fd_invalid_tests(void)261 static bool bind_to_fd_invalid_tests(void) {
262 BEGIN_TEST;
263
264 fdio_t* fdio = fdio_null_create();
265 EXPECT_NONNULL(fdio, "");
266
267 // When binding and not providing a specific |fd|, the
268 // |starting_fd| must be nonnegative.
269 int fd = fdio_bind_to_fd(fdio, -1, -1);
270 int err = errno;
271 EXPECT_LT(fd, 0, "");
272 EXPECT_EQ(err, EINVAL, "");
273
274 // Starting with a huge |starting_fd| will fail since the table
275 // does not hold so many.
276 fd = fdio_bind_to_fd(fdio, -1, INT_MAX);
277 err = errno;
278 EXPECT_LT(fd, 0, "");
279 EXPECT_EQ(err, EMFILE, "");
280
281 END_TEST;
282 }
283
284 BEGIN_TEST_CASE(fdio_handle_fd_test)
285 RUN_TEST(close_test);
286 RUN_TEST(pipe_test);
287 RUN_TEST(ppoll_negative_test);
288 RUN_TEST(ppoll_null_test);
289 RUN_TEST(ppoll_overflow_test);
290 RUN_TEST(ppoll_immediate_timeout_test);
291 RUN_TEST(transfer_fd_test);
292 RUN_TEST(transfer_device_test);
293 RUN_TEST(create_fd_from_connected_socket);
294 RUN_TEST(bind_to_fd_invalid_tests);
295
296 END_TEST_CASE(fdio_handle_fd_test)
297