2 * Unix SMB/CIFS implementation.
4 * Copyright (C) 2022 Andrew Bartlett <abartlet@samba.org>
5 * Copyright (C) 2021 Andreas Schneider <asn@samba.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/network.h"
28 #include "socketpair_tcp.h"
31 enum socket_pair_selector
{
37 struct tevent_context
*ev
;
41 /* for tstream tests */
45 struct timeval endtime
;
50 /* If this is too large, we get EPIPE rather than EAGAIN */
51 static const uint8_t TEST_STRING
[128] = { 0 };
53 static int sigpipe_setup(void **state
)
55 BlockSignals(true, SIGPIPE
);
59 static int setup_socketpair_tcp_context(void **state
)
62 struct socket_pair
*sp
= talloc_zero(NULL
, struct socket_pair
);
65 /* Set up a socketpair over TCP to test with */
66 assert_return_code(socketpair_tcp(fd
), errno
);
68 sp
->socket_server
= fd
[SOCKET_SERVER
];
69 sp
->socket_client
= fd
[SOCKET_CLIENT
];
71 sp
->ev
= tevent_context_init(sp
);
72 assert_non_null(sp
->ev
);
78 static int setup_socketpair_context(void **state
)
81 struct socket_pair
*sp
= talloc_zero(NULL
, struct socket_pair
);
84 /* Set up a socketpair over TCP to test with */
85 assert_return_code(socketpair(AF_UNIX
, SOCK_STREAM
, 0, fd
), errno
);
87 sp
->socket_server
= fd
[SOCKET_SERVER
];
88 sp
->socket_client
= fd
[SOCKET_CLIENT
];
90 sp
->ev
= tevent_context_init(sp
);
91 assert_non_null(sp
->ev
);
97 static int teardown_socketpair_context(void **state
)
99 struct socket_pair
*sp
= *state
;
100 struct socket_pair sp_save
= *sp
;
105 * Close these after the TALLOC_FREE() to allow clean shutdown
106 * of epoll() in tstream
108 if (sp_save
.socket_client
!= -1) {
109 close(sp_save
.socket_client
);
111 if (sp_save
.socket_server
!= -1) {
112 close(sp_save
.socket_server
);
118 /* Test socket behaviour */
119 static void test_simple_socketpair(void **state
) {
121 struct socket_pair
*sp
= *state
;
123 char buf
[sizeof(TEST_STRING
)];
125 assert_int_equal(write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
)),
126 sizeof(TEST_STRING
));
127 assert_int_equal(read(sp
->socket_client
, buf
, sizeof(buf
)),
133 /* Test socket behaviour */
134 static void test_read_client_after_close_server_socket(void **state
) {
136 struct socket_pair
*sp
= *state
;
138 char buf
[sizeof(TEST_STRING
)];
140 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
141 assert_return_code(rc
, errno
);
142 assert_int_equal(rc
, sizeof(TEST_STRING
));
144 assert_return_code(close(sp
->socket_server
), 0);
146 rc
= read(sp
->socket_client
, buf
, sizeof(buf
));
148 assert_return_code(rc
, errno
);
149 assert_int_equal(rc
, sizeof(buf
));
152 static void test_write_server_after_close_client_socket(void **state
) {
154 struct socket_pair
*sp
= *state
;
157 assert_return_code(close(sp
->socket_client
), 0);
158 sp
->socket_client
= -1;
160 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
161 assert_return_code(rc
, errno
);
162 assert_int_equal(rc
, sizeof(TEST_STRING
));
165 static void test_fill_socket(int sock
)
171 rc
= write(sock
, TEST_STRING
, sizeof(TEST_STRING
));
172 if (rc
== -1 && errno
== EAGAIN
) {
174 * This makes sure we write until we get a whole second
175 * only with EAGAIN every 50 ms (20 times)
177 * Otherwise the tests are not reliable...
186 /* try again next time */
190 assert_int_equal(rc
, -1);
191 assert_int_equal(errno
, EAGAIN
);
194 static void test_big_write_server(void **state
) {
196 struct socket_pair
*sp
= *state
;
199 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
200 assert_return_code(rc
, errno
);
201 assert_int_equal(rc
, sizeof(TEST_STRING
));
203 rc
= set_blocking(sp
->socket_server
, 0);
204 assert_return_code(rc
, errno
);
206 test_fill_socket(sp
->socket_server
);
209 static void test_big_write_server_close_write(void **state
) {
211 struct socket_pair
*sp
= *state
;
214 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
215 assert_return_code(rc
, errno
);
216 assert_int_equal(rc
, sizeof(TEST_STRING
));
218 rc
= set_blocking(sp
->socket_server
, 0);
219 assert_return_code(rc
, errno
);
221 test_fill_socket(sp
->socket_server
);
223 assert_return_code(close(sp
->socket_client
), 0);
224 sp
->socket_client
= -1;
226 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
227 assert_int_equal(errno
, ECONNRESET
);
231 static void test_big_write_server_shutdown_wr_write(void **state
) {
233 struct socket_pair
*sp
= *state
;
236 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
237 assert_return_code(rc
, errno
);
238 assert_int_equal(rc
, sizeof(TEST_STRING
));
240 rc
= set_blocking(sp
->socket_server
, 0);
241 assert_return_code(rc
, errno
);
243 test_fill_socket(sp
->socket_server
);
245 assert_return_code(shutdown(sp
->socket_client
, SHUT_WR
), 0);
246 sp
->socket_client
= -1;
248 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
249 assert_int_equal(rc
, -1);
250 assert_int_equal(errno
, EAGAIN
);
253 static void test_big_write_server_shutdown_rd_write(void **state
) {
255 struct socket_pair
*sp
= *state
;
258 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
259 assert_return_code(rc
, errno
);
260 assert_int_equal(rc
, sizeof(TEST_STRING
));
262 rc
= set_blocking(sp
->socket_server
, 0);
263 assert_return_code(rc
, errno
);
265 test_fill_socket(sp
->socket_server
);
267 assert_return_code(shutdown(sp
->socket_client
, SHUT_RD
), 0);
268 sp
->socket_client
= -1;
270 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
271 assert_int_equal(rc
, -1);
272 assert_int_equal(errno
, EAGAIN
);
275 static void test_call_writev_done(struct tevent_req
*subreq
)
277 struct socket_pair
*sp
=
278 tevent_req_callback_data(subreq
,
282 rc
= tstream_writev_recv(subreq
, &sp
->sys_errno
);
288 static void test_tstream_server_spin_client_shutdown(struct socket_pair
*sp
)
292 rc
= shutdown(sp
->socket_client
, SHUT_WR
);
293 assert_return_code(rc
, errno
);
295 * It should only take a few additional loop to realise that this socket is
298 sp
->max_loops
= sp
->num_loops
+ 2;
299 sp
->expected_errno
= ECONNRESET
;
302 static void test_tstream_server_spin_client_write(struct socket_pair
*sp
)
307 sp
->endtime
= timeval_current_ofs_msec(timeout
);
309 rc
= write(sp
->socket_client
, TEST_STRING
, sizeof(TEST_STRING
));
310 assert_return_code(rc
, errno
);
311 sp
->expected_errno
= ETIMEDOUT
;
314 static void test_tstream_server_spin_client_tcp_user_timeout(struct socket_pair
*sp
)
319 rc
= setsockopt(sp
->socket_server
, IPPROTO_TCP
, TCP_USER_TIMEOUT
, &timeout
, sizeof(timeout
));
320 assert_return_code(rc
, errno
);
322 rc
= write(sp
->socket_client
, TEST_STRING
, sizeof(TEST_STRING
));
323 assert_return_code(rc
, errno
);
324 sp
->expected_errno
= ETIMEDOUT
;
328 static void test_tstream_server_spin_client_both_timer(struct tevent_context
*ev
,
329 struct tevent_timer
*te
,
330 struct timeval current_time
,
333 struct socket_pair
*sp
=
334 talloc_get_type_abort(private_data
,
337 test_tstream_server_spin_client_shutdown(sp
);
340 static void test_tstream_server_spin_client_both(struct socket_pair
*sp
)
342 struct tevent_timer
*te
= NULL
;
343 struct timeval endtime
;
345 test_tstream_server_spin_client_write(sp
);
347 endtime
= timeval_current_ofs_msec(2500);
349 te
= tevent_add_timer(sp
->ev
,
352 test_tstream_server_spin_client_both_timer
,
355 sp
->expected_errno
= ENXIO
;
358 static void test_tstream_server_spin(struct socket_pair
*sp
,
359 void (*client_fn
)(struct socket_pair
*sp
))
361 struct tstream_context
*stream
= NULL
;
362 struct tevent_req
*req
= NULL
;
366 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
367 assert_return_code(rc
, errno
);
368 assert_int_equal(rc
, sizeof(TEST_STRING
));
370 rc
= set_blocking(sp
->socket_server
, 0);
371 assert_return_code(rc
, errno
);
373 test_fill_socket(sp
->socket_server
);
376 * by default we don't expect more then 2 loop iterations
377 * for a timeout of 5 seconds.
383 rc
= write(sp
->socket_server
, TEST_STRING
, sizeof(TEST_STRING
));
384 assert_int_equal(rc
, -1);
385 assert_int_equal(errno
, EAGAIN
);
387 /* OK, so we now know the socket is in CLOSE_WAIT */
389 rc
= tstream_bsd_existing_socket(sp
->ev
, sp
->socket_server
, &stream
);
390 assert_return_code(rc
, errno
);
391 sp
->socket_server
= -1;
393 iov
.iov_base
= discard_const_p(char, TEST_STRING
);
394 iov
.iov_len
= sizeof(TEST_STRING
);
396 req
= tstream_writev_send(stream
, sp
->ev
, stream
, &iov
, 1);
397 assert_non_null(req
);
398 if (!timeval_is_zero(&sp
->endtime
)) {
399 assert_true(tevent_req_set_endtime(req
, sp
->ev
, sp
->endtime
));
401 tevent_req_set_callback(req
, test_call_writev_done
, sp
);
403 while (tevent_req_is_in_progress(req
)) {
404 if (sp
->num_loops
>= sp
->max_loops
) {
405 assert_int_not_equal(sp
->num_loops
, sp
->max_loops
);
406 assert_int_equal(sp
->num_loops
, sp
->max_loops
);
410 rc
= tevent_loop_once(sp
->ev
);
411 assert_int_equal(rc
, 0);
414 assert_int_equal(sp
->rc
, -1);
415 assert_int_equal(sp
->sys_errno
, sp
->expected_errno
);
420 * We need two names to run this with the two different setup
423 static void test_tstream_disconnected_tcp_client_spin(void **state
)
425 struct socket_pair
*sp
= *state
;
426 test_tstream_server_spin(sp
, test_tstream_server_spin_client_shutdown
);
429 static void test_tstream_disconnected_unix_client_spin(void **state
)
431 struct socket_pair
*sp
= *state
;
432 test_tstream_server_spin(sp
, test_tstream_server_spin_client_shutdown
);
435 static void test_tstream_more_tcp_client_spin(void **state
)
437 struct socket_pair
*sp
= *state
;
438 test_tstream_server_spin(sp
, test_tstream_server_spin_client_write
);
441 static void test_tstream_more_unix_client_spin(void **state
)
443 struct socket_pair
*sp
= *state
;
444 test_tstream_server_spin(sp
, test_tstream_server_spin_client_write
);
447 static void test_tstream_more_disconnect_tcp_client_spin(void **state
)
449 struct socket_pair
*sp
= *state
;
450 test_tstream_server_spin(sp
, test_tstream_server_spin_client_both
);
453 static void test_tstream_more_disconnect_unix_client_spin(void **state
)
455 struct socket_pair
*sp
= *state
;
456 test_tstream_server_spin(sp
, test_tstream_server_spin_client_both
);
459 static void test_tstream_more_tcp_user_timeout_spin(void **state
)
461 struct socket_pair
*sp
= *state
;
462 if (socket_wrapper_enabled()) {
465 test_tstream_server_spin(sp
, test_tstream_server_spin_client_tcp_user_timeout
);
469 const struct CMUnitTest tests
[] = {
470 cmocka_unit_test_setup_teardown(test_simple_socketpair
,
471 setup_socketpair_tcp_context
,
472 teardown_socketpair_context
),
473 cmocka_unit_test_setup_teardown(test_read_client_after_close_server_socket
,
474 setup_socketpair_tcp_context
,
475 teardown_socketpair_context
),
476 cmocka_unit_test_setup_teardown(test_write_server_after_close_client_socket
,
477 setup_socketpair_tcp_context
,
478 teardown_socketpair_context
),
479 cmocka_unit_test_setup_teardown(test_big_write_server
,
480 setup_socketpair_tcp_context
,
481 teardown_socketpair_context
),
482 cmocka_unit_test_setup_teardown(test_big_write_server_close_write
,
483 setup_socketpair_tcp_context
,
484 teardown_socketpair_context
),
485 cmocka_unit_test_setup_teardown(test_big_write_server_shutdown_wr_write
,
486 setup_socketpair_tcp_context
,
487 teardown_socketpair_context
),
488 cmocka_unit_test_setup_teardown(test_big_write_server_shutdown_rd_write
,
489 setup_socketpair_tcp_context
,
490 teardown_socketpair_context
),
491 cmocka_unit_test_setup_teardown(test_tstream_disconnected_tcp_client_spin
,
492 setup_socketpair_tcp_context
,
493 teardown_socketpair_context
),
494 cmocka_unit_test_setup_teardown(test_tstream_disconnected_unix_client_spin
,
495 setup_socketpair_context
,
496 teardown_socketpair_context
),
497 cmocka_unit_test_setup_teardown(test_tstream_more_tcp_client_spin
,
498 setup_socketpair_tcp_context
,
499 teardown_socketpair_context
),
500 cmocka_unit_test_setup_teardown(test_tstream_more_unix_client_spin
,
501 setup_socketpair_context
,
502 teardown_socketpair_context
),
503 cmocka_unit_test_setup_teardown(test_tstream_more_disconnect_tcp_client_spin
,
504 setup_socketpair_tcp_context
,
505 teardown_socketpair_context
),
506 cmocka_unit_test_setup_teardown(test_tstream_more_disconnect_unix_client_spin
,
507 setup_socketpair_context
,
508 teardown_socketpair_context
),
509 cmocka_unit_test_setup_teardown(test_tstream_more_tcp_user_timeout_spin
,
510 setup_socketpair_tcp_context
,
511 teardown_socketpair_context
),
514 cmocka_set_message_output(CM_OUTPUT_SUBUNIT
);
516 return cmocka_run_group_tests(tests
, sigpipe_setup
, NULL
);