diff options
Diffstat (limited to 'tests/pytests/conn_flood.py')
-rw-r--r-- | tests/pytests/conn_flood.py | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/tests/pytests/conn_flood.py b/tests/pytests/conn_flood.py new file mode 100644 index 0000000..88bbfa5 --- /dev/null +++ b/tests/pytests/conn_flood.py @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +"""Test opening as many connections as possible. + +Due to resource-intensity of this test, it's filename doesn't contain +"test" on purpose, so it doesn't automatically get picked up by pytest +(to allow easy parallel testing). + +To execute this test, pass the filename of this file to pytest directly. +Also, make sure not to use parallel execution (-n). +""" + +import resource +import time + +import pytest + +from kresd import Kresd +import utils + + +MAX_SOCKETS = 10000 # upper bound of how many connections to open +MAX_ITERATIONS = 10 # number of iterations to run the test + +# we can't use softlimit itself since kresd already has open sockets, +# so use lesser value +RESERVED_NOFILE = 40 # 40 is empirical value + + +@pytest.mark.parametrize('sock_func_name', [ + 'ip_tcp_socket', + 'ip6_tcp_socket', + 'ip_tls_socket', + 'ip6_tls_socket', +]) +def test_conn_flood(tmpdir, sock_func_name): + def create_sockets(make_sock, nsockets): + sockets = [] + next_ping = time.time() + 4 # less than tcp idle timeout / 2 + while True: + additional_sockets = 0 + while time.time() < next_ping: + nsock_to_init = min(100, nsockets - len(sockets)) + if not nsock_to_init: + return sockets + sockets.extend([make_sock() for _ in range(nsock_to_init)]) + additional_sockets += nsock_to_init + + # large number of connections can take a lot of time to open + # send some valid data to avoid TCP idle timeout for already open sockets + next_ping = time.time() + 4 + for s in sockets: + utils.ping_alive(s) + + # break when no more than 20% additional sockets are created + if additional_sockets / len(sockets) < 0.2: + return sockets + + max_num_of_open_files = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - RESERVED_NOFILE + nsockets = min(max_num_of_open_files, MAX_SOCKETS) + + # create kresd instance with verbose=False + ip = '127.0.0.1' + ip6 = '::1' + with Kresd(tmpdir, ip=ip, ip6=ip6, verbose=False) as kresd: + make_sock = getattr(kresd, sock_func_name) # function for creating sockets + sockets = create_sockets(make_sock, nsockets) + print("\nEstablished {} connections".format(len(sockets))) + + print("Start sending data") + for i in range(MAX_ITERATIONS): + for s in sockets: + utils.ping_alive(s) + print("Iteration {} done...".format(i)) + + print("Close connections") + for s in sockets: + s.close() + + # check in kresd is alive + print("Check upstream is still alive") + sock = make_sock() + utils.ping_alive(sock) + + print("OK!") |