1 // Copyright 2017 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 <poll.h>
9 #include <sys/ioctl.h>
10 #include <sys/socket.h>
11 #include <sys/types.h>
12 #include <threads.h>
13 #include <unistd.h>
14 
15 #include <lib/fdio/limits.h>
16 #include <lib/fdio/unsafe.h>
17 #include <lib/fdio/util.h>
18 #include <zircon/processargs.h>
19 #include <zircon/syscalls.h>
20 
21 #include <unittest/unittest.h>
22 
socketpair_test(void)23 bool socketpair_test(void) {
24     BEGIN_TEST;
25 
26     int fds[2];
27     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
28     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
29 
30     // write() and read() should work.
31     char buf[4] = "abc\0";
32     status = write(fds[0], buf, 4);
33     if (status < 0)
34         printf("write failed %s\n", strerror(errno));
35     EXPECT_EQ(status, 4, "write failed");
36 
37     char recvbuf[4];
38     status = read(fds[1], recvbuf, 4);
39     if (status < 0)
40         printf("read failed %s\n", strerror(errno));
41     EXPECT_EQ(status, 4, "read failed");
42 
43     EXPECT_EQ(memcmp(buf, recvbuf, 4), 0, "data did not make it after write+read");
44 
45     // send() and recv() should also work.
46     memcpy(buf, "def", 4);
47     status = send(fds[1], buf, 4, 0);
48     if (status < 0)
49         printf("send failed %s\n", strerror(errno));
50     EXPECT_EQ(status, 4, "send failed");
51 
52     status = recv(fds[0], recvbuf, 4, 0);
53     if (status < 0)
54         printf("recv failed %s\n", strerror(errno));
55 
56     EXPECT_EQ(memcmp(buf, recvbuf, 4), 0, "data did not make it after send+recv");
57 
58     EXPECT_EQ(close(fds[0]), 0, "close(fds[0]) failed");
59     EXPECT_EQ(close(fds[1]), 0, "close(fds[1]) failed");
60 
61     END_TEST;
62 }
63 
64 static_assert(EAGAIN == EWOULDBLOCK, "Assuming EAGAIN and EWOULDBLOCK have same value");
65 
socketpair_shutdown_setup(int fds[2])66 bool socketpair_shutdown_setup(int fds[2]) {
67     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
68     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
69 
70     // Set both ends to non-blocking to make testing for readability/writability easier.
71     ASSERT_EQ(fcntl(fds[0], F_SETFL, O_NONBLOCK), 0, "");
72     ASSERT_EQ(fcntl(fds[1], F_SETFL, O_NONBLOCK), 0, "");
73 
74     char buf[1] = {};
75     // Both sides should be readable.
76     errno = 0;
77     status = read(fds[0], buf, sizeof(buf));
78     EXPECT_EQ(status, -1, "fds[0] should initially be readable");
79     EXPECT_EQ(errno, EAGAIN, "");
80     errno = 0;
81     status = read(fds[1], buf, sizeof(buf));
82     EXPECT_EQ(status, -1, "fds[1] should initially be readable");
83     EXPECT_EQ(errno, EAGAIN, "");
84 
85     // Both sides should be writable.
86     EXPECT_EQ(write(fds[0], buf, sizeof(buf)), 1, "fds[0] should be initially writable");
87     EXPECT_EQ(write(fds[1], buf, sizeof(buf)), 1, "fds[1] should be initially writable");
88 
89     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), 1, "");
90     EXPECT_EQ(read(fds[1], buf, sizeof(buf)), 1, "");
91 
92     return true;
93 }
94 
95 #if defined(__Fuchsia__)
96 #define SEND_FLAGS 0
97 #else
98 #define SEND_FLAGS MSG_NOSIGNAL
99 #endif
100 
socketpair_shutdown_rd_test(void)101 bool socketpair_shutdown_rd_test(void) {
102     BEGIN_TEST;
103 
104     int fds[2];
105     socketpair_shutdown_setup(fds);
106 
107     // Write a byte into fds[1] to test for readability later.
108     char buf[1] = {};
109     EXPECT_EQ(write(fds[1], buf, sizeof(buf)), 1, "");
110 
111     // Close one side down for reading.
112     int status = shutdown(fds[0], SHUT_RD);
113     EXPECT_EQ(status, 0, "shutdown(fds[0], SHUT_RD)");
114     if (status != 0)
115         printf("\nerrno %d\n", errno);
116 
117     // Can read the byte already written into the pipe.
118     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), 1, "fds[0] should not be readable after SHUT_RD");
119 
120     // But not send any further bytes
121     EXPECT_EQ(send(fds[1], buf, sizeof(buf), SEND_FLAGS), -1, "");
122     EXPECT_EQ(errno, EPIPE, "send should return EPIPE after shutdown(SHUT_RD) on other side");
123 
124     // Or read any more
125     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), 0, "");
126 
127     EXPECT_EQ(close(fds[0]), 0, "");
128     EXPECT_EQ(close(fds[1]), 0, "");
129 
130     END_TEST;
131 }
132 
socketpair_shutdown_wr_test(void)133 bool socketpair_shutdown_wr_test(void) {
134     BEGIN_TEST;
135 
136     int fds[2];
137     socketpair_shutdown_setup(fds);
138 
139     // Close one side down for writing.
140     int status = shutdown(fds[0], SHUT_WR);
141     EXPECT_EQ(status, 0, "shutdown(fds[0], SHUT_WR)");
142     if (status != 0)
143         printf("\nerrno %d\n", errno);
144 
145     char buf[1] = {};
146 
147     // Should still be readable.
148     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), -1, "");
149     EXPECT_EQ(errno, EAGAIN, "errno after read after SHUT_WR");
150 
151     // But not writable
152     EXPECT_EQ(send(fds[0], buf, sizeof(buf), SEND_FLAGS), -1, "write after SHUT_WR");
153     EXPECT_EQ(errno, EPIPE, "errno after write after SHUT_WR");
154 
155     // Should still be able to write + read a message in the other direction.
156     EXPECT_EQ(write(fds[1], buf, sizeof(buf)), 1, "");
157     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), 1, "");
158 
159     EXPECT_EQ(close(fds[0]), 0, "");
160     EXPECT_EQ(close(fds[1]), 0, "");
161 
162     END_TEST;
163 }
164 
socketpair_shutdown_rdwr_test(void)165 bool socketpair_shutdown_rdwr_test(void) {
166     BEGIN_TEST;
167 
168     int fds[2];
169     socketpair_shutdown_setup(fds);
170 
171     // Close one side for reading and writing.
172     int status = shutdown(fds[0], SHUT_RDWR);
173     EXPECT_EQ(status, 0, "shutdown(fds[0], SHUT_RDWR");
174     if (status != 0)
175         printf("\nerrno %d\n", errno);
176 
177     char buf[1] = {};
178 
179     // Writing should fail.
180     EXPECT_EQ(send(fds[0], buf, sizeof(buf), SEND_FLAGS), -1, "");
181     EXPECT_EQ(errno, EPIPE, "errno after write after SHUT_RDWR");
182 
183     // Reading should return no data.
184     EXPECT_EQ(read(fds[0], buf, sizeof(buf)), 0, "");
185 
186     END_TEST;
187 }
188 
189 typedef struct poll_for_read_args {
190     int fd;
191     int poll_result;
192     zx_time_t poll_time;
193 } poll_for_read_args_t;
194 
poll_for_read_with_timeout(void * arg)195 int poll_for_read_with_timeout(void* arg) {
196     poll_for_read_args_t* poll_args = (poll_for_read_args_t*)arg;
197     struct pollfd pollfd;
198     pollfd.fd = poll_args->fd;
199     pollfd.events = POLLIN;
200     pollfd.revents = 0;
201 
202     int timeout_ms = 100;
203     zx_time_t time_before = zx_clock_get(CLOCK_MONOTONIC);
204     poll_args->poll_result = poll(&pollfd, 1, timeout_ms);
205     zx_time_t time_after = zx_clock_get(CLOCK_MONOTONIC);
206     poll_args->poll_time = time_after - time_before;
207 
208     int num_readable = 0;
209     EXPECT_EQ(ioctl(poll_args->fd, FIONREAD, &num_readable), 0, "ioctl(FIONREAD)");
210     EXPECT_EQ(num_readable, 0, "");
211 
212     return 0;
213 }
214 
socketpair_shutdown_self_wr_poll_test(void)215 bool socketpair_shutdown_self_wr_poll_test(void) {
216     BEGIN_TEST;
217 
218     int fds[2];
219     socketpair_shutdown_setup(fds);
220 
221     poll_for_read_args_t poll_args = {};
222     poll_args.fd = fds[0];
223     thrd_t poll_thread;
224     int thrd_create_result = thrd_create(&poll_thread, poll_for_read_with_timeout, &poll_args);
225     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking read thread");
226 
227     shutdown(fds[0], SHUT_RDWR);
228 
229     ASSERT_EQ(thrd_join(poll_thread, NULL), thrd_success, "join blocking read thread");
230 
231     EXPECT_EQ(poll_args.poll_result, 1, "poll should have one entry");
232     EXPECT_LT(poll_args.poll_time, 100u * 1000 * 1000, "poll should not have timed out");
233 
234     END_TEST;
235 }
236 
socketpair_shutdown_peer_wr_poll_test(void)237 bool socketpair_shutdown_peer_wr_poll_test(void) {
238     BEGIN_TEST;
239 
240     int fds[2];
241     socketpair_shutdown_setup(fds);
242 
243     poll_for_read_args_t poll_args = {};
244     poll_args.fd = fds[0];
245     thrd_t poll_thread;
246     int thrd_create_result = thrd_create(&poll_thread, poll_for_read_with_timeout, &poll_args);
247     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking read thread");
248 
249     shutdown(fds[1], SHUT_RDWR);
250 
251     ASSERT_EQ(thrd_join(poll_thread, NULL), thrd_success, "join blocking read thread");
252 
253     EXPECT_EQ(poll_args.poll_result, 1, "poll should have one entry");
254     EXPECT_LT(poll_args.poll_time, 100u * 1000 * 1000, "poll should not have timed out");
255 
256     END_TEST;
257 }
258 
259 #define BUF_SIZE 256
260 
261 typedef struct recv_args {
262     int fd;
263     int recv_result;
264     int recv_errno;
265     char buf[BUF_SIZE];
266 } recv_args_t;
267 
recv_thread(void * arg)268 int recv_thread(void* arg) {
269     recv_args_t* recv_args = (recv_args_t*)arg;
270 
271     recv_args->recv_result = recv(recv_args->fd, recv_args->buf, BUF_SIZE, 0u);
272     if (recv_args->recv_result < 0)
273         recv_args->recv_errno = errno;
274 
275     return 0;
276 }
277 
socketpair_shutdown_self_rd_during_recv_test(void)278 bool socketpair_shutdown_self_rd_during_recv_test(void) {
279     BEGIN_TEST;
280 
281     int fds[2];
282     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
283     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
284 
285     recv_args_t recv_args = {};
286     recv_args.fd = fds[0];
287     thrd_t t;
288     int thrd_create_result = thrd_create(&t, recv_thread, &recv_args);
289     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking read thread");
290 
291     shutdown(fds[0], SHUT_RD);
292 
293     ASSERT_EQ(thrd_join(t, NULL), thrd_success, "join blocking read thread");
294 
295     EXPECT_EQ(recv_args.recv_result, 0, "recv should have returned 0");
296     EXPECT_EQ(recv_args.recv_errno, 0, "recv should have left errno alone");
297 
298     END_TEST;
299 }
300 
socketpair_shutdown_peer_wr_during_recv_test(void)301 bool socketpair_shutdown_peer_wr_during_recv_test(void) {
302     BEGIN_TEST;
303 
304     int fds[2];
305     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
306     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
307 
308     recv_args_t recv_args = {};
309     recv_args.fd = fds[0];
310     thrd_t t;
311     int thrd_create_result = thrd_create(&t, recv_thread, &recv_args);
312     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking read thread");
313 
314     shutdown(fds[1], SHUT_WR);
315 
316     ASSERT_EQ(thrd_join(t, NULL), thrd_success, "join blocking read thread");
317 
318     EXPECT_EQ(recv_args.recv_result, 0, "recv should have returned 0");
319     EXPECT_EQ(recv_args.recv_errno, 0, "recv should have left errno alone");
320     END_TEST;
321 }
322 
323 typedef struct send_args {
324     int fd;
325     int send_result;
326     int send_errno;
327     char buf[BUF_SIZE];
328 } send_args_t;
329 
send_thread(void * arg)330 int send_thread(void* arg) {
331     send_args_t* send_args = (send_args_t*)arg;
332 
333     send_args->send_result = send(send_args->fd, send_args->buf, BUF_SIZE, 0u);
334     if (send_args->send_result < 0)
335         send_args->send_errno = errno;
336 
337     return 0;
338 }
339 
socketpair_shutdown_self_wr_during_send_test(void)340 bool socketpair_shutdown_self_wr_during_send_test(void) {
341     BEGIN_TEST;
342 
343     int fds[2];
344     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
345     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
346 
347     // First, fill up the socket so the next send() will block.
348     char buf[BUF_SIZE] = {};
349     while (true) {
350         status = send(fds[0], buf, sizeof(buf), MSG_DONTWAIT);
351         if (status < 0) {
352             ASSERT_EQ(errno, EAGAIN, "send should eventually return EAGAIN when full");
353             break;
354         }
355     }
356     send_args_t send_args = {};
357     send_args.fd = fds[0];
358     thrd_t t;
359     // Then start a thread blocking on a send().
360     int thrd_create_result = thrd_create(&t, send_thread, &send_args);
361     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking send thread");
362 
363     shutdown(fds[0], SHUT_WR);
364 
365     ASSERT_EQ(thrd_join(t, NULL), thrd_success, "join blocking send thread");
366 
367     EXPECT_EQ(send_args.send_result, -1, "send should have returned -1");
368     EXPECT_EQ(send_args.send_errno, EPIPE, "send should have set errno to EPIPE");
369 
370     END_TEST;
371 }
372 
socketpair_shutdown_peer_rd_during_send_test(void)373 bool socketpair_shutdown_peer_rd_during_send_test(void) {
374     BEGIN_TEST;
375 
376     int fds[2];
377     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
378     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
379 
380     // First, fill up the socket so the next send() will block.
381     char buf[BUF_SIZE] = {};
382     while (true) {
383         status = send(fds[0], buf, sizeof(buf), MSG_DONTWAIT);
384         if (status < 0) {
385             ASSERT_EQ(errno, EAGAIN, "send should eventually return EAGAIN when full");
386             break;
387         }
388     }
389     send_args_t send_args = {};
390     send_args.fd = fds[0];
391     thrd_t t;
392     int thrd_create_result = thrd_create(&t, send_thread, &send_args);
393     ASSERT_EQ(thrd_create_result, thrd_success, "create blocking send thread");
394 
395     shutdown(fds[1], SHUT_RD);
396 
397     ASSERT_EQ(thrd_join(t, NULL), thrd_success, "join blocking send thread");
398 
399     EXPECT_EQ(send_args.send_result, -1, "send should have returned -1");
400     EXPECT_EQ(send_args.send_errno, EPIPE, "send should have set errno to EPIPE");
401 
402     END_TEST;
403 }
404 
socketpair_clone_or_unwrap_and_wrap_test(void)405 bool socketpair_clone_or_unwrap_and_wrap_test(void) {
406     BEGIN_TEST;
407 
408     int fds[2];
409     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
410     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
411 
412     zx_handle_t handles[FDIO_MAX_HANDLES];
413     uint32_t types[FDIO_MAX_HANDLES];
414     zx_status_t handle_count = fdio_clone_fd(fds[0], fds[0], handles, types);
415     ASSERT_GT(handle_count, 0, "fdio_clone_fd() failed");
416     EXPECT_EQ(PA_HND_TYPE(types[0]), PA_FDIO_SOCKET, "Wrong cloned fd type");
417 
418     int cloned_fd = -1;
419     status = fdio_create_fd(handles, types, handle_count, &cloned_fd);
420     EXPECT_EQ(status, 0, "fdio_create_fd(..., &cloned_fd) failed");
421 
422     handle_count = fdio_transfer_fd(fds[0], fds[0], handles, types);
423     ASSERT_GT(handle_count, 0, "fdio_transfer_fd() failed");
424     EXPECT_EQ(PA_HND_TYPE(types[0]), PA_FDIO_SOCKET, "Wrong transferred fd type");
425 
426     int transferred_fd = -1;
427     status = fdio_create_fd(handles, types, handle_count, &transferred_fd);
428     EXPECT_EQ(status, 0, "fdio_create_fd(..., &transferred_fd) failed");
429 
430     // Verify that an operation specific to socketpairs works on these fds.
431     ASSERT_EQ(shutdown(cloned_fd, SHUT_RD), 0, "shutdown(cloned_fd, SHUT_RD) failed");
432     ASSERT_EQ(shutdown(transferred_fd, SHUT_WR), 0, "shutdown(transferred_fd, SHUT_WR) failed");
433 
434     if (cloned_fd != -1)
435         ASSERT_EQ(close(cloned_fd), 0, "Failed to close cloned_fd");
436     if (transferred_fd != -1)
437         ASSERT_EQ(close(transferred_fd), 0, "Failed to close transferred_fd");
438 
439     END_TEST;
440 }
441 
442 // Verify scenario, where multi-segment recvmsg is requested, but the socket has
443 // just enough data to *completely* fill one segment.
444 // In this scenario, an attempt to read data for the next segment immediately
445 // fails with ZX_ERR_SHOULD_WAIT; at this point recvmsg should report total
446 // number of bytes read, instead of failing with EAGAIN.
socketpair_recvmsg_nonblock_boundary_test(void)447 bool socketpair_recvmsg_nonblock_boundary_test(void) {
448     BEGIN_TEST;
449 
450     int fds[2];
451     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
452     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
453 
454     ASSERT_EQ(fcntl(fds[0], F_SETFL, O_NONBLOCK), 0, "");
455     ASSERT_EQ(fcntl(fds[1], F_SETFL, O_NONBLOCK), 0, "");
456 
457     // Write 4 bytes of data to socket.
458     size_t actual;
459     const uint32_t data_out = 0x12345678;
460     EXPECT_EQ((ssize_t)sizeof(data_out), write(fds[0], &data_out, sizeof(data_out)), "Socket write failed");
461 
462     uint32_t data_in1, data_in2;
463     // Fail at compilation stage if anyone changes types.
464     // This is mandatory here: we need the first chunk to be exactly the same
465     // length as total size of data we just wrote.
466     assert(sizeof(data_in1) == sizeof(data_out));
467 
468     struct iovec iov[2];
469     iov[0].iov_base = &data_in1;
470     iov[0].iov_len = sizeof(data_in1);
471     iov[1].iov_base = &data_in2;
472     iov[1].iov_len = sizeof(data_in2);
473 
474     struct msghdr msg;
475     msg.msg_name = NULL;
476     msg.msg_namelen = 0;
477     msg.msg_iov = iov;
478     msg.msg_iovlen = sizeof(iov) / sizeof(*iov);
479     msg.msg_control = NULL;
480     msg.msg_controllen = 0;
481     msg.msg_flags = 0;
482 
483     actual = recvmsg(fds[1], &msg, 0);
484     EXPECT_EQ(sizeof(data_in1), actual, "Socket read failed");
485 
486     close(fds[0]);
487     close(fds[1]);
488 
489     END_TEST;
490 }
491 
492 // Verify scenario, where multi-segment sendmsg is requested, but the socket has
493 // just enough spare buffer to *completely* read one segment.
494 // In this scenario, an attempt to send second segment should immediately fail
495 // with ZX_ERR_SHOULD_WAIT, but the sendmsg should report first segment length
496 // rather than failing with EAGAIN.
socketpair_sendmsg_nonblock_boundary_test(void)497 bool socketpair_sendmsg_nonblock_boundary_test(void) {
498     BEGIN_TEST;
499 
500     const ssize_t memlength = 65536;
501     void* memchunk = malloc(memlength);
502 
503     struct iovec iov[2];
504     iov[0].iov_base = memchunk;
505     iov[0].iov_len = memlength;
506     iov[1].iov_base = memchunk;
507     iov[1].iov_len = memlength;
508 
509     int fds[2];
510     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
511     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
512 
513     ASSERT_EQ(fcntl(fds[0], F_SETFL, O_NONBLOCK), 0, "");
514     ASSERT_EQ(fcntl(fds[1], F_SETFL, O_NONBLOCK), 0, "");
515 
516     struct msghdr msg;
517     msg.msg_name = NULL;
518     msg.msg_namelen = 0;
519     msg.msg_iov = iov;
520     msg.msg_iovlen = sizeof(iov) / sizeof(*iov);
521     msg.msg_control = NULL;
522     msg.msg_controllen = 0;
523     msg.msg_flags = 0;
524 
525     // 1. Keep sending data until socket is saturated.
526     while (sendmsg(fds[0], &msg, 0) > 0)
527         ;
528 
529     // 2. Consume one segment of the data.
530     EXPECT_EQ(memlength, read(fds[1], memchunk, memlength), "Socket read failed.");
531 
532     // 3. Push again 2 packets of <memlength> bytes, observe only one sent.
533     EXPECT_EQ(memlength, sendmsg(fds[0], &msg, 0),
534               "Partial sendmsg failed; is the socket buffer varying?");
535 
536     close(fds[0]);
537     close(fds[1]);
538 
539     free(memchunk);
540     END_TEST;
541 }
542 
socketpair_wait_begin_end(void)543 bool socketpair_wait_begin_end(void) {
544     BEGIN_TEST;
545 
546     int fds[2];
547     int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
548     ASSERT_EQ(status, 0, "socketpair(AF_UNIX, SOCK_STREAM, 0, fds) failed");
549 
550     fdio_t* io = fdio_unsafe_fd_to_io(fds[0]);
551 
552     // fdio_unsafe_wait_begin
553 
554     zx_handle_t handle = ZX_HANDLE_INVALID;
555     zx_signals_t signals = ZX_SIGNAL_NONE;
556     fdio_unsafe_wait_begin(io, POLLIN, &handle, &signals);
557     EXPECT_NE(handle, ZX_HANDLE_INVALID, "");
558     EXPECT_EQ(signals, ZX_SOCKET_READABLE | ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_PEER_WRITE_DISABLED, "");
559 
560     handle = ZX_HANDLE_INVALID;
561     signals = ZX_SIGNAL_NONE;
562     fdio_unsafe_wait_begin(io, POLLOUT, &handle, &signals);
563     EXPECT_NE(handle, ZX_HANDLE_INVALID, "");
564     EXPECT_EQ(signals, ZX_SOCKET_WRITABLE | ZX_SOCKET_WRITE_DISABLED, "");
565 
566     handle = ZX_HANDLE_INVALID;
567     signals = ZX_SIGNAL_NONE;
568     fdio_unsafe_wait_begin(io, POLLRDHUP, &handle, &signals);
569     EXPECT_NE(handle, ZX_HANDLE_INVALID, "");
570     EXPECT_EQ(signals, ZX_SOCKET_PEER_CLOSED | ZX_SOCKET_PEER_WRITE_DISABLED, "");
571 
572     // fdio_unsafe_wait_end
573 
574     uint32_t events = 0u;
575     fdio_unsafe_wait_end(io, ZX_SOCKET_READABLE, &events);
576     EXPECT_EQ(events, (uint32_t)POLLIN, "");
577 
578     events = 0u;
579     fdio_unsafe_wait_end(io, ZX_SOCKET_PEER_CLOSED, &events);
580     EXPECT_EQ(events, (uint32_t)(POLLIN | POLLRDHUP), "");
581 
582     events = 0u;
583     fdio_unsafe_wait_end(io, ZX_SOCKET_PEER_WRITE_DISABLED, &events);
584     EXPECT_EQ(events, (uint32_t)(POLLIN | POLLRDHUP), "");
585 
586     events = 0u;
587     fdio_unsafe_wait_end(io, ZX_SOCKET_WRITABLE, &events);
588     EXPECT_EQ(events, (uint32_t)POLLOUT, "");
589 
590     events = 0u;
591     fdio_unsafe_wait_end(io, ZX_SOCKET_WRITE_DISABLED, &events);
592     EXPECT_EQ(events, (uint32_t)POLLOUT, "");
593 
594     fdio_unsafe_release(io);
595     close(fds[0]);
596     close(fds[1]);
597 
598     END_TEST;
599 }
600 
601 BEGIN_TEST_CASE(fdio_socketpair_test)
602 RUN_TEST(socketpair_test);
603 RUN_TEST(socketpair_shutdown_rd_test);
604 RUN_TEST(socketpair_shutdown_wr_test);
605 RUN_TEST(socketpair_shutdown_rdwr_test);
606 RUN_TEST(socketpair_shutdown_self_wr_poll_test);
607 RUN_TEST(socketpair_shutdown_peer_wr_poll_test);
608 RUN_TEST(socketpair_shutdown_self_rd_during_recv_test);
609 RUN_TEST(socketpair_shutdown_peer_wr_during_recv_test);
610 RUN_TEST(socketpair_shutdown_self_wr_during_send_test);
611 RUN_TEST(socketpair_shutdown_peer_rd_during_send_test);
612 RUN_TEST(socketpair_clone_or_unwrap_and_wrap_test);
613 RUN_TEST(socketpair_recvmsg_nonblock_boundary_test);
614 RUN_TEST(socketpair_sendmsg_nonblock_boundary_test);
615 RUN_TEST(socketpair_wait_begin_end);
616 END_TEST_CASE(fdio_socketpair_test)
617