From 7fbf20da01e9cc2031e92111bc794048a13d5f50 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 16 Jan 2023 19:27:12 +0100 Subject: [PATCH] tests: add test_echo_tcp_sendmmsg_recvmmsg Signed-off-by: Stefan Metzmacher Reviewed-by: Andreas Schneider --- tests/CMakeLists.txt | 1 + tests/test_echo_tcp_sendmmsg_recvmmsg.c | 300 ++++++++++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100644 tests/test_echo_tcp_sendmmsg_recvmmsg.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 2f98af1..175b7cf 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -48,6 +48,7 @@ set(SWRAP_TESTS test_echo_tcp_bind test_echo_tcp_socket_options test_echo_tcp_sendmsg_recvmsg + test_echo_tcp_sendmmsg_recvmmsg test_echo_tcp_write_read test_echo_tcp_writev_readv test_echo_tcp_get_peer_sock_name diff --git a/tests/test_echo_tcp_sendmmsg_recvmmsg.c b/tests/test_echo_tcp_sendmmsg_recvmmsg.c new file mode 100644 index 0000000..e03f629 --- /dev/null +++ b/tests/test_echo_tcp_sendmmsg_recvmmsg.c @@ -0,0 +1,300 @@ +#include +#include +#include +#include + +#include "config.h" +#include "torture.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static int setup_echo_srv_tcp_ipv4(void **state) +{ + torture_setup_echo_srv_tcp_ipv4(state); + + return 0; +} + +#ifdef HAVE_IPV6 +static int setup_echo_srv_tcp_ipv6(void **state) +{ + torture_setup_echo_srv_tcp_ipv6(state); + + return 0; +} +#endif + +static int teardown(void **state) +{ + torture_teardown_echo_srv(state); + + return 0; +} + +static void test_sendmmsg_recvmmsg_ipv4_ignore(void **state) +{ + struct torture_address addr = { + .sa_socklen = sizeof(struct sockaddr_storage), + }; + struct { + struct torture_address reply_addr; + struct iovec s_iov; + struct iovec r_iov; + char send_buf[64]; + char recv_buf[64]; + } tmsgs[10] = {}; + struct mmsghdr s_msgs[10] = {}; + struct mmsghdr r_msgs[10] = {}; + ssize_t ret; + int rc; + int i; + int s; + + (void) state; /* unused */ + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + assert_int_not_equal(s, -1); + + addr.sa.in.sin_family = AF_INET; + addr.sa.in.sin_port = htons(torture_server_port()); + + rc = inet_pton(AF_INET, + torture_server_address(AF_INET), + &addr.sa.in.sin_addr); + assert_int_equal(rc, 1); + + rc = connect(s, &addr.sa.s, addr.sa_socklen); + assert_return_code(rc, errno); + + /* This should be ignored */ + rc = inet_pton(AF_INET, + "127.0.0.1", + &addr.sa.in.sin_addr); + assert_int_equal(rc, 1); + + for (i = 0; i < 10; i++) { + tmsgs[i].reply_addr = (struct torture_address){ + .sa_socklen = sizeof(struct sockaddr_storage), + }; + + snprintf(tmsgs[i].send_buf, sizeof(tmsgs[i].send_buf), "packet.%d", i); + + tmsgs[i].s_iov.iov_base = tmsgs[i].send_buf; + tmsgs[i].s_iov.iov_len = sizeof(tmsgs[i].send_buf); + + s_msgs[i].msg_hdr.msg_name = &addr.sa.s; + s_msgs[i].msg_hdr.msg_namelen = addr.sa_socklen; + s_msgs[i].msg_hdr.msg_iov = &tmsgs[i].s_iov; + s_msgs[i].msg_hdr.msg_iovlen = 1; + + tmsgs[i].r_iov.iov_base = tmsgs[i].recv_buf; + tmsgs[i].r_iov.iov_len = sizeof(tmsgs[i].recv_buf); + + r_msgs[i].msg_hdr.msg_name = &tmsgs[i].reply_addr.sa.s; + r_msgs[i].msg_hdr.msg_namelen = tmsgs[i].reply_addr.sa_socklen; + r_msgs[i].msg_hdr.msg_iov = &tmsgs[i].r_iov; + r_msgs[i].msg_hdr.msg_iovlen = 1; + } + + ret = sendmmsg(s, s_msgs, 10, 0); + assert_int_equal(ret, 10); + + ret = recvmmsg(s, r_msgs, 10, 0, NULL); + assert_int_equal(ret, 10); + + for (i = 0; i < 10; i++) { + assert_int_equal(r_msgs[i].msg_hdr.msg_namelen, 0); + assert_ptr_equal(r_msgs[i].msg_hdr.msg_name, &tmsgs[i].reply_addr.sa.s); + + assert_int_equal(r_msgs[i].msg_len, tmsgs[i].s_iov.iov_len); + assert_memory_equal(tmsgs[i].send_buf, tmsgs[i].recv_buf, sizeof(tmsgs[i].send_buf)); + } + + rc = close(s); + assert_int_equal(rc, 0); +} + +#ifdef HAVE_IPV6 +static void test_sendmmsg_recvmmsg_ipv6(void **state) +{ + struct torture_address addr = { + .sa_socklen = sizeof(struct sockaddr_storage), + }; + struct { + struct torture_address reply_addr; + struct iovec s_iov; + struct iovec r_iov; + char send_buf[64]; + char recv_buf[64]; + } tmsgs[10] = {}; + struct mmsghdr s_msgs[10] = {}; + struct mmsghdr r_msgs[10] = {}; + ssize_t ret; + int rc; + int i; + int s; + + (void) state; /* unused */ + + s = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); + assert_int_not_equal(s, -1); + + addr.sa.in.sin_family = AF_INET6; + addr.sa.in.sin_port = htons(torture_server_port()); + + rc = inet_pton(AF_INET6, + torture_server_address(AF_INET6), + &addr.sa.in6.sin6_addr); + assert_int_equal(rc, 1); + + rc = connect(s, &addr.sa.s, addr.sa_socklen); + assert_return_code(rc, errno); + + for (i = 0; i < 10; i++) { + tmsgs[i].reply_addr = (struct torture_address){ + .sa_socklen = sizeof(struct sockaddr_storage), + }; + + snprintf(tmsgs[i].send_buf, sizeof(tmsgs[i].send_buf), "packet.%d", i); + + tmsgs[i].s_iov.iov_base = tmsgs[i].send_buf; + tmsgs[i].s_iov.iov_len = sizeof(tmsgs[i].send_buf); + + s_msgs[i].msg_hdr.msg_name = &addr.sa.s; + s_msgs[i].msg_hdr.msg_namelen = addr.sa_socklen; + s_msgs[i].msg_hdr.msg_iov = &tmsgs[i].s_iov; + s_msgs[i].msg_hdr.msg_iovlen = 1; + + tmsgs[i].r_iov.iov_base = tmsgs[i].recv_buf; + tmsgs[i].r_iov.iov_len = sizeof(tmsgs[i].recv_buf); + + r_msgs[i].msg_hdr.msg_name = &tmsgs[i].reply_addr.sa.s; + r_msgs[i].msg_hdr.msg_namelen = tmsgs[i].reply_addr.sa_socklen; + r_msgs[i].msg_hdr.msg_iov = &tmsgs[i].r_iov; + r_msgs[i].msg_hdr.msg_iovlen = 1; + } + + ret = sendmmsg(s, s_msgs, 10, 0); + assert_int_equal(ret, 10); + + ret = recvmmsg(s, r_msgs, 10, 0, NULL); + assert_int_equal(ret, 10); + + for (i = 0; i < 10; i++) { + assert_int_equal(r_msgs[i].msg_hdr.msg_namelen, 0); + assert_ptr_equal(r_msgs[i].msg_hdr.msg_name, &tmsgs[i].reply_addr.sa.s); + + assert_int_equal(r_msgs[i].msg_len, tmsgs[i].s_iov.iov_len); + assert_memory_equal(tmsgs[i].send_buf, tmsgs[i].recv_buf, sizeof(tmsgs[i].send_buf)); + } + + rc = close(s); + assert_int_equal(rc, 0); +} +#endif + +static void test_sendmmsg_recvmmsg_ipv4_null(void **state) +{ + struct torture_address addr = { + .sa_socklen = sizeof(struct sockaddr_storage), + }; + struct { + struct torture_address reply_addr; + struct iovec s_iov; + struct iovec r_iov; + char send_buf[64]; + char recv_buf[64]; + } tmsgs[10] = {}; + struct mmsghdr s_msgs[10] = {}; + struct mmsghdr r_msgs[10] = {}; + ssize_t ret; + int rc; + int i; + int s; + + (void) state; /* unused */ + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + assert_int_not_equal(s, -1); + + addr.sa.in.sin_family = AF_INET; + addr.sa.in.sin_port = htons(torture_server_port()); + + rc = inet_pton(AF_INET, + torture_server_address(AF_INET), + &addr.sa.in.sin_addr); + assert_int_equal(rc, 1); + + rc = connect(s, &addr.sa.s, addr.sa_socklen); + assert_return_code(rc, errno); + + for (i = 0; i < 10; i++) { + tmsgs[i].reply_addr = (struct torture_address){ + .sa_socklen = sizeof(struct sockaddr_storage), + }; + + snprintf(tmsgs[i].send_buf, sizeof(tmsgs[i].send_buf), "packet.%d", i); + + tmsgs[i].s_iov.iov_base = tmsgs[i].send_buf; + tmsgs[i].s_iov.iov_len = sizeof(tmsgs[i].send_buf); + + s_msgs[i].msg_hdr.msg_name = NULL; + s_msgs[i].msg_hdr.msg_namelen = 0; + s_msgs[i].msg_hdr.msg_iov = &tmsgs[i].s_iov; + s_msgs[i].msg_hdr.msg_iovlen = 1; + + tmsgs[i].r_iov.iov_base = tmsgs[i].recv_buf; + tmsgs[i].r_iov.iov_len = sizeof(tmsgs[i].recv_buf); + + r_msgs[i].msg_hdr.msg_name = NULL; + r_msgs[i].msg_hdr.msg_namelen = 0; + r_msgs[i].msg_hdr.msg_iov = &tmsgs[i].r_iov; + r_msgs[i].msg_hdr.msg_iovlen = 1; + } + + ret = sendmmsg(s, s_msgs, 10, 0); + assert_int_equal(ret, 10); + + ret = recvmmsg(s, r_msgs, 10, 0, NULL); + assert_int_equal(ret, 10); + + for (i = 0; i < 10; i++) { + assert_int_equal(r_msgs[i].msg_hdr.msg_namelen, 0); + assert_null(r_msgs[i].msg_hdr.msg_name); + + assert_int_equal(r_msgs[i].msg_len, tmsgs[i].s_iov.iov_len); + assert_memory_equal(tmsgs[i].send_buf, tmsgs[i].recv_buf, sizeof(tmsgs[i].send_buf)); + } + + rc = close(s); + assert_int_equal(rc, 0); +} + +int main(void) { + int rc; + + const struct CMUnitTest sendmsg_tests[] = { + cmocka_unit_test_setup_teardown(test_sendmmsg_recvmmsg_ipv4_ignore, + setup_echo_srv_tcp_ipv4, + teardown), + cmocka_unit_test_setup_teardown(test_sendmmsg_recvmmsg_ipv4_null, + setup_echo_srv_tcp_ipv4, + teardown), +#ifdef HAVE_IPV6 + cmocka_unit_test_setup_teardown(test_sendmmsg_recvmmsg_ipv6, + setup_echo_srv_tcp_ipv6, + teardown), +#endif + }; + + rc = cmocka_run_group_tests(sendmsg_tests, NULL, NULL); + + return rc; +} -- 2.34.1