From 4330014fce5ab2ac1a6e58cd330762318a34f8d9 Mon Sep 17 00:00:00 2001 From: Artem Boldariev Date: Thu, 27 Apr 2023 20:17:18 +0300 Subject: [PATCH] PROXY Stream: add unit test suite This commit adds a specialised test suite for the PROXY Stream transport by reusing most of the testing code from other unit tests for other stream-based transports. --- tests/isc/Makefile.am | 13 +++ tests/isc/netmgr_common.c | 82 +++++++++++++++-- tests/isc/netmgr_common.h | 15 ++-- tests/isc/proxystream_test.c | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+), 12 deletions(-) create mode 100644 tests/isc/proxystream_test.c diff --git a/tests/isc/Makefile.am b/tests/isc/Makefile.am index 18654c2c7d..5bdf2fb3dc 100644 --- a/tests/isc/Makefile.am +++ b/tests/isc/Makefile.am @@ -35,6 +35,7 @@ check_PROGRAMS = \ netaddr_test \ parse_test \ proxyheader_test \ + proxystream_test \ quota_test \ radix_test \ random_test \ @@ -112,6 +113,18 @@ proxyheader_test_SOURCES = \ proxyheader_test.c \ proxyheader_test_data.h +proxystream_test_CPPFLAGS = \ + $(AM_CPPFLAGS) + +proxystream_test_LDADD = \ + $(LDADD) + +proxystream_test_SOURCES = \ + proxystream_test.c \ + netmgr_common.h \ + netmgr_common.c \ + stream_shutdown.c + random_test_LDADD = \ $(LDADD) \ -lm diff --git a/tests/isc/netmgr_common.c b/tests/isc/netmgr_common.c index 200ff98845..3caa4f5374 100644 --- a/tests/isc/netmgr_common.c +++ b/tests/isc/netmgr_common.c @@ -102,19 +102,33 @@ atomic_bool check_listener_quota = false; bool allow_send_back = false; bool noanswer = false; bool stream_use_TLS = false; +bool stream_use_PROXY = false; bool stream = false; in_port_t stream_port = 0; isc_nm_recv_cb_t connect_readcb = NULL; +isc_nm_proxyheader_info_t proxy_info_data; +isc_nm_proxyheader_info_t *proxy_info = NULL; +isc_sockaddr_t proxy_src; +isc_sockaddr_t proxy_dst; + int setup_netmgr_test(void **state) { + struct in_addr in; tcp_connect_addr = (isc_sockaddr_t){ .length = 0 }; isc_sockaddr_fromin6(&tcp_connect_addr, &in6addr_loopback, 0); tcp_listen_addr = (isc_sockaddr_t){ .length = 0 }; isc_sockaddr_fromin6(&tcp_listen_addr, &in6addr_loopback, stream_port); + RUNTIME_CHECK(inet_pton(AF_INET, "1.2.3.4", &in) == 1); + isc_sockaddr_fromin(&proxy_src, &in, 1234); + RUNTIME_CHECK(inet_pton(AF_INET, "4.3.2.1", &in) == 1); + isc_sockaddr_fromin(&proxy_dst, &in, 4321); + isc_nm_proxyheader_info_init(&proxy_info_data, &proxy_src, &proxy_dst, + NULL); + esends = NSENDS * workers; atomic_store(&nsends, esends); @@ -214,6 +228,8 @@ teardown_netmgr_test(void **state ISC_ATTR_UNUSED) { isc_refcount_destroy(&active_ssends); isc_refcount_destroy(&active_sreads); + proxy_info = NULL; + return (0); } @@ -358,6 +374,10 @@ connect_connect_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { return; } + if (stream_use_PROXY) { + assert_true(isc_nm_is_proxy_handle(handle)); + } + /* We are finished, initiate the shutdown */ if (have_expected_cconnects(atomic_fetch_add(&cconnects, 1) + 1)) { do_cconnects_shutdown(loopmgr); @@ -493,6 +513,10 @@ stream_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult, void *cbarg) { do_saccepts_shutdown(loopmgr); } + if (stream_use_PROXY) { + assert_true(isc_nm_is_proxy_handle(handle)); + } + isc_refcount_increment0(&active_sreads); isc_nmhandle_attach(handle, &readhandle); @@ -563,12 +587,41 @@ tls_connect(isc_nm_t *nm) { tcp_tlsctx_client_sess_cache, T_CONNECT); } +isc_nm_proxyheader_info_t * +get_proxyheader_info(void) { + if (proxy_info != NULL) { + return (proxy_info); + } + + /* + * There is 50% chance to get the info: so we can test LOCAL headers, + * too. + */ + if (isc_random_uniform(2)) { + return (&proxy_info_data); + } + + return (NULL); +} + +static void +proxystream_connect(isc_nm_t *nm) { + isc_nm_proxystreamconnect(nm, &tcp_connect_addr, &tcp_listen_addr, + connect_connect_cb, NULL, T_CONNECT, + get_proxyheader_info()); +} + stream_connect_function get_stream_connect_function(void) { if (stream_use_TLS) { return (tls_connect); + } else if (stream_use_PROXY) { + return (proxystream_connect); + } else { + return (tcp_connect); } - return (tcp_connect); + + UNREACHABLE(); } isc_result_t @@ -582,12 +635,19 @@ stream_listen(isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, accept_cbarg, backlog, quota, tcp_listen_tlsctx, sockp); return (result); + } else if (stream_use_PROXY) { + result = isc_nm_listenproxystream( + listen_nm, ISC_NM_LISTEN_ALL, &tcp_listen_addr, + accept_cb, accept_cbarg, backlog, quota, sockp); + return (result); + } else { + result = isc_nm_listentcp(listen_nm, ISC_NM_LISTEN_ALL, + &tcp_listen_addr, accept_cb, + accept_cbarg, backlog, quota, sockp); + return (result); } - result = isc_nm_listentcp(listen_nm, ISC_NM_LISTEN_ALL, - &tcp_listen_addr, accept_cb, accept_cbarg, - backlog, quota, sockp); - return (result); + UNREACHABLE(); } void @@ -600,9 +660,17 @@ stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout) { tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache, timeout); return; + } else if (stream_use_PROXY) { + isc_nm_proxystreamconnect(connect_nm, &tcp_connect_addr, + &tcp_listen_addr, cb, cbarg, timeout, + get_proxyheader_info()); + return; + } else { + isc_nm_tcpconnect(connect_nm, &tcp_connect_addr, + &tcp_listen_addr, cb, cbarg, timeout); + return; } - isc_nm_tcpconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr, cb, - cbarg, timeout); + UNREACHABLE(); } void diff --git a/tests/isc/netmgr_common.h b/tests/isc/netmgr_common.h index 5e8eec620e..28195a2e95 100644 --- a/tests/isc/netmgr_common.h +++ b/tests/isc/netmgr_common.h @@ -23,11 +23,12 @@ * Pick unused port outside the ephemeral port range, so we don't clash with * connected sockets. */ -#define UDP_TEST_PORT 9153 -#define TCP_TEST_PORT 9154 -#define TLS_TEST_PORT 9155 -#define TCPDNS_TEST_PORT 9156 -#define TLSDNS_TEST_PORT 9157 +#define UDP_TEST_PORT 9153 +#define TCP_TEST_PORT 9154 +#define TLS_TEST_PORT 9155 +#define TCPDNS_TEST_PORT 9156 +#define TLSDNS_TEST_PORT 9157 +#define PROXYSTREAM_TEST_PORT 9158 typedef void (*stream_connect_function)(isc_nm_t *nm); typedef void (*connect_func)(isc_nm_t *); @@ -129,6 +130,7 @@ extern atomic_bool check_listener_quota; extern bool allow_send_back; extern bool noanswer; extern bool stream_use_TLS; +extern bool stream_use_PROXY; extern bool stream; extern in_port_t stream_port; @@ -283,6 +285,9 @@ stream_listen(isc_nm_accept_cb_t accept_cb, void *accept_cbarg, int backlog, void stream_connect(isc_nm_cb_t cb, void *cbarg, unsigned int timeout); +isc_nm_proxyheader_info_t * +get_proxyheader_info(void); + int stream_noop_setup(void **state ISC_ATTR_UNUSED); void diff --git a/tests/isc/proxystream_test.c b/tests/isc/proxystream_test.c new file mode 100644 index 0000000000..1991bdb4ab --- /dev/null +++ b/tests/isc/proxystream_test.c @@ -0,0 +1,165 @@ +/* + * Copyright (C) Internet Systems Consortium, Inc. ("ISC") + * + * SPDX-License-Identifier: MPL-2.0 + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, you can obtain one at https://mozilla.org/MPL/2.0/. + * + * See the COPYRIGHT file distributed with this work for additional + * information regarding copyright ownership. + */ + +#include /* IWYU pragma: keep */ +#include +#include +#include +#include +#include + +/* + * As a workaround, include an OpenSSL header file before including cmocka.h, + * because OpenSSL 3.1.0 uses __attribute__(malloc), conflicting with a + * redefined malloc in cmocka.h. + */ +#include + +#define UNIT_TESTING +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uv_wrap.h" +#define KEEP_BEFORE + +#include "netmgr/tcp.c" +#include "netmgr_common.h" + +#include + +/* TCP */ +ISC_LOOP_TEST_IMPL(proxystream_noop) { + stream_noop(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_noresponse) { + stream_noresponse(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_shutdownconnect) { + stream_shutdownconnect(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_shutdownread) { + stream_shutdownread(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_timeout_recovery) { + stream_timeout_recovery(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_one) { + stream_recv_one(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_two) { + stream_recv_two(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_send) { + stream_recv_send(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_send_sendback) { + allow_send_back = true; + stream_recv_send(arg); + return; +} + +/* TCP Quota */ + +ISC_LOOP_TEST_IMPL(proxystream_recv_one_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_one(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_two_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_two(arg); + return; +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_send_quota) { + atomic_store(&check_listener_quota, true); + stream_recv_send(arg); +} + +ISC_LOOP_TEST_IMPL(proxystream_recv_send_quota_sendback) { + atomic_store(&check_listener_quota, true); + allow_send_back = true; + stream_recv_send(arg); +} + +ISC_TEST_LIST_START + +/* Stream */ +ISC_TEST_ENTRY_CUSTOM(proxystream_noop, stream_noop_setup, stream_noop_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_noresponse, stream_noresponse_setup, + stream_noresponse_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_shutdownconnect, stream_shutdownconnect_setup, + stream_shutdownconnect_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_shutdownread, stream_shutdownread_setup, + stream_shutdownread_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_timeout_recovery, + stream_timeout_recovery_setup, + stream_timeout_recovery_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_one, stream_recv_one_setup, + stream_recv_one_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_two, stream_recv_two_setup, + stream_recv_two_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_send, stream_recv_send_setup, + stream_recv_send_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_send_sendback, stream_recv_send_setup, + stream_recv_send_teardown) + +/* Stream Quota */ +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_one_quota, stream_recv_one_setup, + stream_recv_one_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_two_quota, stream_recv_two_setup, + stream_recv_two_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_send_quota, stream_recv_send_setup, + stream_recv_send_teardown) +ISC_TEST_ENTRY_CUSTOM(proxystream_recv_send_quota_sendback, + stream_recv_send_setup, stream_recv_send_teardown) + +ISC_TEST_LIST_END + +static int +proxystream_setup(void **state ISC_ATTR_UNUSED) { + stream_port = PROXYSTREAM_TEST_PORT; + stream_use_TLS = false; + stream_use_PROXY = true; + stream = true; + + return (0); +} + +ISC_TEST_MAIN_CUSTOM(proxystream_setup, NULL)