1 /*
2 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "_main.h"
8
9 struct ctx {
10 bool should_write;
11 int *fd;
12 k_timeout_t delay;
13 };
14 static ZTEST_BMEM struct ctx ctx;
15 static ZTEST_BMEM struct k_work work;
16
17 /*
18 * Timeout should work the same for blocking & non-blocking threads
19 *
20 * - no bytes available to read after timeout, r: 0 (timeout)
21 * - no bytes available to write after timeout, r: 0 (timeout)
22 */
23
test_socketpair_poll_timeout_common(struct net_socketpair_fixture * fixture)24 static void test_socketpair_poll_timeout_common(struct net_socketpair_fixture *fixture)
25 {
26 int res;
27 struct zsock_pollfd fds[1];
28
29 memset(fds, 0, sizeof(fds));
30 fds[0].fd = fixture->sv[0];
31 fds[0].events |= ZSOCK_POLLIN;
32 res = zsock_poll(fds, 1, 1);
33 zassert_equal(res, 0, "poll: expected: 0 actual: %d", res);
34
35 for (size_t i = 0; i < CONFIG_NET_SOCKETPAIR_BUFFER_SIZE; ++i) {
36 res = zsock_send(fixture->sv[0], "x", 1, 0);
37 zassert_equal(res, 1, "send() failed: %d", res);
38 }
39
40 memset(fds, 0, sizeof(fds));
41 fds[0].fd = fixture->sv[0];
42 fds[0].events |= ZSOCK_POLLOUT;
43 res = zsock_poll(fds, 1, 1);
44 zassert_equal(res, 0, "poll: expected: 0 actual: %d", res);
45 }
46
ZTEST_USER_F(net_socketpair,test_poll_timeout)47 ZTEST_USER_F(net_socketpair, test_poll_timeout)
48 {
49 test_socketpair_poll_timeout_common(fixture);
50 }
51
52 /* O_NONBLOCK should have no affect on poll(2) */
ZTEST_USER_F(net_socketpair,test_poll_timeout_nonblocking)53 ZTEST_USER_F(net_socketpair, test_poll_timeout_nonblocking)
54 {
55 int res;
56
57 res = zsock_fcntl(fixture->sv[0], F_GETFL, 0);
58 zassert_not_equal(res, -1, "fcntl failed: %d", errno);
59
60 int flags = res;
61
62 res = zsock_fcntl(fixture->sv[0], F_SETFL, O_NONBLOCK | flags);
63 zassert_not_equal(res, -1, "fcntl failed: %d", errno);
64
65 res = zsock_fcntl(fixture->sv[1], F_SETFL, O_NONBLOCK | flags);
66 zassert_not_equal(res, -1, "fcntl failed: %d", errno);
67
68 test_socketpair_poll_timeout_common(fixture);
69 }
70
close_fun(struct k_work * w)71 static void close_fun(struct k_work *w)
72 {
73 (void)w;
74
75 if (!(K_TIMEOUT_EQ(ctx.delay, K_NO_WAIT)
76 || K_TIMEOUT_EQ(ctx.delay, K_FOREVER))) {
77 k_sleep(ctx.delay);
78 }
79
80 LOG_DBG("about to close fd %d", *ctx.fd);
81 zsock_close(*ctx.fd);
82 *ctx.fd = -1;
83 }
84
85 /*
86 * Hangup should cause the following behaviour
87 * - close remote fd while the local fd is blocking in poll. r: 1,
88 * POLLIN, read -> r: 0, errno: 0 -> EOF
89 * - close remote fd while the local fd is blocking in poll. r: 1,
90 * POLLOUT, write -> r: -1, errno: EPIPE.
91 */
ZTEST_F(net_socketpair,test_poll_close_remote_end_POLLIN)92 ZTEST_F(net_socketpair, test_poll_close_remote_end_POLLIN)
93 {
94 int res;
95 char c;
96 struct zsock_pollfd fds[1];
97
98 /*
99 * poll until there are bytes to read.
100 * But rather than writing, close the other end of the channel
101 */
102
103 memset(fds, 0, sizeof(fds));
104 fds[0].fd = fixture->sv[0];
105 fds[0].events |= ZSOCK_POLLIN;
106
107 memset(&ctx, 0, sizeof(ctx));
108 ctx.fd = &fixture->sv[1];
109 ctx.delay = K_MSEC(1000);
110
111 LOG_DBG("scheduling work");
112 k_work_init(&work, close_fun);
113 k_work_submit(&work);
114
115 res = zsock_poll(fds, 1, -1);
116 zassert_equal(res, 1, "poll() failed: %d", res);
117 zassert_equal(fds[0].revents & ZSOCK_POLLIN, ZSOCK_POLLIN, "POLLIN not set");
118
119 res = zsock_recv(fixture->sv[0], &c, 1, 0);
120 zassert_equal(res, 0, "read did not return EOF");
121 }
122
ZTEST_F(net_socketpair,test_poll_close_remote_end_POLLOUT)123 ZTEST_F(net_socketpair, test_poll_close_remote_end_POLLOUT)
124 {
125 int res;
126 struct zsock_pollfd fds[1];
127
128 /*
129 * Fill up the remote q and then poll until write space is available.
130 * But rather than reading, close the other end of the channel
131 */
132
133 res = zsock_socketpair(AF_UNIX, SOCK_STREAM, 0, fixture->sv);
134 zassert_not_equal(res, -1, "socketpair() failed: %d", errno);
135
136 for (size_t i = 0; i < CONFIG_NET_SOCKETPAIR_BUFFER_SIZE; ++i) {
137 res = zsock_send(fixture->sv[0], "x", 1, 0);
138 zassert_equal(res, 1, "send failed: %d", res);
139 }
140
141 memset(fds, 0, sizeof(fds));
142 fds[0].fd = fixture->sv[0];
143 fds[0].events |= ZSOCK_POLLOUT;
144
145 memset(&ctx, 0, sizeof(ctx));
146 ctx.fd = &fixture->sv[1];
147 ctx.delay = K_MSEC(1000);
148
149 LOG_DBG("scheduling work");
150 k_work_init(&work, close_fun);
151 k_work_submit(&work);
152
153 res = zsock_poll(fds, 1, -1);
154 zassert_equal(res, 1, "poll() failed: %d", res);
155 zassert_equal(fds[0].revents & ZSOCK_POLLHUP, ZSOCK_POLLHUP, "POLLHUP not set");
156
157 res = zsock_send(fixture->sv[0], "x", 1, 0);
158 zassert_equal(res, -1, "send(): expected: -1 actual: %d", res);
159 zassert_equal(errno, EPIPE, "errno: expected: EPIPE actual: %d", errno);
160 }
161
162 /*
163 * Data available immediately
164 * - even with a timeout value of 0 us, poll should return immediately with
165 * a value of 1 (for either read or write cases)
166 * - even with a timeout value of 0us, poll should return immediately with
167 * a value of 2 if both read and write are available
168 */
ZTEST_USER_F(net_socketpair,test_poll_immediate_data)169 ZTEST_USER_F(net_socketpair, test_poll_immediate_data)
170 {
171 int res;
172 struct zsock_pollfd fds[2];
173
174 memset(fds, 0, sizeof(fds));
175 fds[0].fd = fixture->sv[0];
176 fds[0].events |= ZSOCK_POLLOUT;
177 res = zsock_poll(fds, 1, 0);
178 zassert_not_equal(res, -1, "poll() failed: %d", errno);
179 zassert_equal(res, 1, "poll(): expected: 1 actual: %d", res);
180 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, 0, "POLLOUT not set");
181
182 res = zsock_send(fixture->sv[0], "x", 1, 0);
183 zassert_not_equal(res, -1, "send() failed: %d", errno);
184 zassert_equal(res, 1, "write(): expected: 1 actual: %d", res);
185
186 memset(fds, 0, sizeof(fds));
187 fds[0].fd = fixture->sv[1];
188 fds[0].events |= ZSOCK_POLLIN;
189 res = zsock_poll(fds, 1, 0);
190 zassert_not_equal(res, -1, "poll() failed: %d", errno);
191 zassert_equal(res, 1, "poll(): expected: 1 actual: %d", res);
192 zassert_not_equal(fds[0].revents & ZSOCK_POLLIN, 0, "POLLIN not set");
193
194 memset(fds, 0, sizeof(fds));
195 fds[0].fd = fixture->sv[0];
196 fds[0].events |= ZSOCK_POLLOUT;
197 fds[1].fd = fixture->sv[1];
198 fds[1].events |= ZSOCK_POLLIN;
199 res = zsock_poll(fds, 2, 0);
200 zassert_not_equal(res, -1, "poll() failed: %d", errno);
201 zassert_equal(res, 2, "poll(): expected: 1 actual: %d", res);
202 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, 0, "POLLOUT not set");
203 zassert_not_equal(fds[1].revents & ZSOCK_POLLIN, 0, "POLLIN not set");
204 }
205
rw_fun(struct k_work * w)206 static void rw_fun(struct k_work *w)
207 {
208 (void)w;
209
210 int res;
211 char c;
212
213 if (!(K_TIMEOUT_EQ(ctx.delay, K_NO_WAIT)
214 || K_TIMEOUT_EQ(ctx.delay, K_FOREVER))) {
215 k_sleep(ctx.delay);
216 }
217
218 if (ctx.should_write) {
219 LOG_DBG("about to write 1 byte");
220 res = zsock_send(*ctx.fd, "x", 1, 0);
221 if (-1 == res) {
222 LOG_DBG("send() failed: %d", errno);
223 } else {
224 LOG_DBG("wrote 1 byte");
225 }
226 } else {
227 LOG_DBG("about to read 1 byte");
228 res = zsock_recv(*ctx.fd, &c, 1, 0);
229 if (-1 == res) {
230 LOG_DBG("recv() failed: %d", errno);
231 } else {
232 LOG_DBG("read 1 byte");
233 }
234 }
235 }
236
237 /*
238 * Data only available but after some short period
239 * - say there is a timeout value of 5 s, poll should return immediately
240 * with the a value of 1 (for either read or write cases)
241 */
ZTEST_F(net_socketpair,test_poll_delayed_data)242 ZTEST_F(net_socketpair, test_poll_delayed_data)
243 {
244 int res;
245 struct zsock_pollfd fds[1];
246
247 memset(fds, 0, sizeof(fds));
248 fds[0].fd = fixture->sv[0];
249 fds[0].events |= ZSOCK_POLLIN;
250
251 memset(&ctx, 0, sizeof(ctx));
252 ctx.fd = &fixture->sv[1];
253 ctx.should_write = true;
254 ctx.delay = K_MSEC(100);
255
256 LOG_DBG("scheduling work");
257 k_work_init(&work, rw_fun);
258 k_work_submit(&work);
259
260 res = zsock_poll(fds, 1, 5000);
261 zassert_not_equal(res, -1, "poll() failed: %d", errno);
262 zassert_equal(res, 1, "poll(): expected: 1 actual: %d", res);
263 zassert_not_equal(fds[0].revents & ZSOCK_POLLIN, 0, "POLLIN not set");
264
265 for (size_t i = 0; i < CONFIG_NET_SOCKETPAIR_BUFFER_SIZE; ++i) {
266 res = zsock_send(fixture->sv[0], "x", 1, 0);
267 zassert_equal(res, 1, "send() failed: %d", res);
268 }
269
270 memset(fds, 0, sizeof(fds));
271 fds[0].fd = fixture->sv[0];
272 fds[0].events |= ZSOCK_POLLOUT;
273
274 memset(&ctx, 0, sizeof(ctx));
275 ctx.fd = &fixture->sv[1];
276 ctx.should_write = false;
277 ctx.delay = K_MSEC(100);
278
279 LOG_DBG("scheduling work");
280 k_work_init(&work, rw_fun);
281 k_work_submit(&work);
282
283 res = zsock_poll(fds, 1, 5000);
284 zassert_not_equal(res, -1, "poll() failed: %d", errno);
285 zassert_equal(res, 1, "poll(): expected: 1 actual: %d", res);
286 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, 0, "POLLOUT was not set");
287 }
288
289 /*
290 * Verify that POLLIN is correctly signalled
291 * - right after socket creation, POLLIN should not be reported
292 * - after data is written to a remote socket, POLLIN should be reported, even
293 * if the poll was called after the data was written
294 * - after reading data from a remote socket, POLLIN shouldn't be reported
295 */
ZTEST_USER_F(net_socketpair,test_poll_signalling_POLLIN)296 ZTEST_USER_F(net_socketpair, test_poll_signalling_POLLIN)
297 {
298 int res;
299 char c;
300 int64_t timestamp, delta;
301 struct zsock_pollfd fds[1];
302
303 memset(fds, 0, sizeof(fds));
304 fds[0].fd = fixture->sv[1];
305 fds[0].events |= ZSOCK_POLLIN;
306 res = zsock_poll(fds, 1, 0);
307 zassert_not_equal(res, -1, "poll failed: %d", errno);
308 zassert_equal(res, 0, "poll: expected: 0 actual: %d", res);
309 zassert_not_equal(fds[0].revents & ZSOCK_POLLIN, ZSOCK_POLLIN, "POLLIN set");
310
311 res = zsock_send(fixture->sv[0], "x", 1, 0);
312 zassert_equal(res, 1, "send failed: %d", res);
313
314 timestamp = k_uptime_get();
315
316 memset(fds, 0, sizeof(fds));
317 fds[0].fd = fixture->sv[1];
318 fds[0].events |= ZSOCK_POLLIN;
319 res = zsock_poll(fds, 1, 1000);
320 zassert_not_equal(res, -1, "poll failed: %d", errno);
321 zassert_equal(res, 1, "poll: expected: 1 actual: %d", res);
322 zassert_not_equal(fds[0].revents & ZSOCK_POLLIN, 0, "POLLIN not set");
323
324 delta = k_uptime_delta(×tamp);
325 zassert_true(delta < 100, "poll did not exit immediately");
326
327 res = zsock_recv(fixture->sv[1], &c, 1, 0);
328 zassert_equal(res, 1, "recv failed: %d", res);
329
330 memset(fds, 0, sizeof(fds));
331 fds[0].fd = fixture->sv[1];
332 fds[0].events |= ZSOCK_POLLIN;
333 res = zsock_poll(fds, 1, 0);
334 zassert_not_equal(res, -1, "poll failed: %d", errno);
335 zassert_equal(res, 0, "poll: expected: 0 actual: %d", res);
336 zassert_not_equal(fds[0].revents & ZSOCK_POLLIN, ZSOCK_POLLIN, "POLLIN set");
337 }
338
339 /*
340 * Verify that POLLOUT is correctly signalled
341 * - right after socket creation, POLLOUT should be reported
342 * - after remote buffer is filled up, POLLOUT shouldn't be reported
343 * - after reading data from a remote socket, POLLOUT should be reported
344 * again
345 */
ZTEST_USER_F(net_socketpair,test_poll_signalling_POLLOUT)346 ZTEST_USER_F(net_socketpair, test_poll_signalling_POLLOUT)
347 {
348 int res;
349 char c;
350 int64_t timestamp, delta;
351 struct zsock_pollfd fds[1];
352
353 timestamp = k_uptime_get();
354
355 memset(fds, 0, sizeof(fds));
356 fds[0].fd = fixture->sv[0];
357 fds[0].events |= ZSOCK_POLLOUT;
358 res = zsock_poll(fds, 1, 1000);
359 zassert_not_equal(res, -1, "poll failed: %d", errno);
360 zassert_equal(res, 1, "poll: expected: 1 actual: %d", res);
361 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, 0, "POLLOUT not set");
362
363 delta = k_uptime_delta(×tamp);
364 zassert_true(delta < 100, "poll did not exit immediately");
365
366 /* Fill up the remote buffer */
367 for (size_t i = 0; i < CONFIG_NET_SOCKETPAIR_BUFFER_SIZE; ++i) {
368 res = zsock_send(fixture->sv[0], "x", 1, 0);
369 zassert_equal(res, 1, "send() failed: %d", res);
370 }
371
372 memset(fds, 0, sizeof(fds));
373 fds[0].fd = fixture->sv[0];
374 fds[0].events |= ZSOCK_POLLOUT;
375 res = zsock_poll(fds, 1, 0);
376 zassert_not_equal(res, -1, "poll failed: %d", errno);
377 zassert_equal(res, 0, "poll: expected: 0 actual: %d", res);
378 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, ZSOCK_POLLOUT, "POLLOUT is set");
379
380 res = zsock_recv(fixture->sv[1], &c, 1, 0);
381 zassert_equal(res, 1, "recv() failed: %d", res);
382
383 timestamp = k_uptime_get();
384
385 memset(fds, 0, sizeof(fds));
386 fds[0].fd = fixture->sv[0];
387 fds[0].events |= ZSOCK_POLLOUT;
388 res = zsock_poll(fds, 1, 1000);
389 zassert_not_equal(res, -1, "poll failed: %d", errno);
390 zassert_equal(res, 1, "poll: expected: 1 actual: %d", res);
391 zassert_not_equal(fds[0].revents & ZSOCK_POLLOUT, 0, "POLLOUT not set");
392
393 delta = k_uptime_delta(×tamp);
394 zassert_true(delta < 100, "poll did not exit immediately");
395 }
396