tests: Add test for ephemeral port binding in listen()
authorAndreas Schneider <asn@samba.org>
Wed, 4 Nov 2015 10:22:25 +0000 (11:22 +0100)
committerAndreas Schneider <asn@samba.org>
Wed, 4 Nov 2015 14:11:26 +0000 (15:11 +0100)
Signed-off-by: Andreas Schneider <asn@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
tests/CMakeLists.txt
tests/test_tcp_listen.c [new file with mode: 0644]

index 96791772ea4bb9179e71f079d896fff36f6ccd41..aecf6b849760b3709e46e085c78e55411d55c1bf 100644 (file)
@@ -20,6 +20,7 @@ target_link_libraries(${TORTURE_LIBRARY}
 
 set(SWRAP_TESTS
     test_ioctl
+    test_tcp_listen
     test_echo_tcp_socket
     test_echo_tcp_connect
     test_echo_tcp_bind
diff --git a/tests/test_tcp_listen.c b/tests/test_tcp_listen.c
new file mode 100644 (file)
index 0000000..5641c47
--- /dev/null
@@ -0,0 +1,115 @@
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "config.h"
+#include "torture.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#ifdef HAVE_RPC_RPC_H
+#include <rpc/rpc.h>
+#endif
+
+static int setup(void **state)
+{
+       torture_setup_socket_dir(state);
+
+       return 0;
+}
+
+static int teardown(void **state)
+{
+       torture_teardown_socket_dir(state);
+
+       return 0;
+}
+
+static void test_listen_unbound_ipv4(void **state)
+{
+       struct torture_address addr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
+       int rc;
+       int s1;
+       int s2;
+
+       (void) state; /* unused */
+
+       s1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s1, errno);
+
+       rc = listen(s1, SOMAXCONN);
+       assert_return_code(rc, errno);
+
+       rc = getsockname(s1, &addr.sa.s, &addr.sa_socklen);
+       assert_return_code(rc, errno);
+       assert_int_equal(addr.sa_socklen, sizeof(struct sockaddr_in));
+       assert_in_range(ntohs(addr.sa.in.sin_port), 1024, 65535);
+
+       s2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s2, errno);
+
+       rc = connect(s2, &addr.sa.s, addr.sa_socklen);
+       assert_return_code(rc, errno);
+
+       close(s1);
+       close(s2);
+}
+
+#ifdef HAVE_IPV6
+static void test_listen_unbound_ipv6(void **state)
+{
+       struct torture_address addr = {
+               .sa_socklen = sizeof(struct sockaddr_storage),
+       };
+       int rc;
+       int s1;
+       int s2;
+
+       (void) state; /* unused */
+
+       s1 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s1, errno);
+
+       rc = listen(s1, SOMAXCONN);
+       assert_return_code(rc, errno);
+
+       rc = getsockname(s1, &addr.sa.s, &addr.sa_socklen);
+       assert_return_code(rc, errno);
+       assert_int_equal(addr.sa_socklen, sizeof(struct sockaddr_in6));
+       assert_in_range(ntohs(addr.sa.in6.sin6_port), 1024, 65535);
+
+       s2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
+       assert_return_code(s2, errno);
+
+       rc = connect(s2, &addr.sa.s, addr.sa_socklen);
+       assert_return_code(rc, errno);
+
+       close(s1);
+       close(s2);
+}
+#endif /* HAVE_IPV6 */
+
+int main(void) {
+       int rc;
+
+       const struct CMUnitTest tcp_listen_tests[] = {
+               cmocka_unit_test(test_listen_unbound_ipv4),
+#ifdef HAVE_IPV6
+               cmocka_unit_test(test_listen_unbound_ipv6),
+#endif /* HAVE_IPV6 */
+       };
+
+       rc = cmocka_run_group_tests(tcp_listen_tests, setup, teardown);
+
+       return rc;
+}