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
22bool 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
52bool 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
99int 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
110bool 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
131bool ppoll_negative_test(void) {
132    struct timespec timeout_ts = {-1, -1};
133    return ppoll_test_handler(&timeout_ts);
134}
135
136bool ppoll_null_test(void) {
137    return ppoll_test_handler(NULL);
138}
139
140bool 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
146bool 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
162bool 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
203bool 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
224bool 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
261BEGIN_TEST_CASE(fdio_handle_fd_test)
262RUN_TEST(close_test);
263RUN_TEST(pipe_test);
264RUN_TEST(ppoll_negative_test);
265RUN_TEST(ppoll_null_test);
266RUN_TEST(ppoll_overflow_test);
267RUN_TEST(ppoll_immediate_timeout_test);
268RUN_TEST(transfer_fd_test);
269RUN_TEST(transfer_device_test);
270RUN_TEST(create_fd_from_connected_socket);
271END_TEST_CASE(fdio_handle_fd_test)
272