pytests: import test_conn_flood (test8)

parent 4c42eea6
......@@ -16,7 +16,7 @@ stages:
- build
- test
- coverage
- respdiff
- extended
- deploy
build:linux:amd64:
......@@ -293,9 +293,22 @@ pytests:run:
- linux
- amd64
pytests:extended:
stage: extended
dependencies:
- build:linux:amd64
except:
- master
script:
- PATH="$PREFIX/sbin:$PATH" ./ci/pytests/run-extended.sh
tags:
- docker
- linux
- amd64
.respdiff: &respdiff
stage: respdiff
stage: extended
dependencies: []
only: # trigger job only in repos under our control
- branches@knot/knot-resolver
......@@ -396,7 +409,7 @@ respdiff:iter:udp:linux:amd64:
.resperf: &resperf
stage: respdiff
stage: extended
dependencies: []
only: # trigger job only in repos under our control
- branches@knot/knot-resolver
......
#!/bin/bash
# Execute extended, long-running test suite
python3 -m pytest tests/pytests/conn_flood.py --capture=no
"""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, make_port
import utils
# TODO: test often fails in CI, debug and maybe decrease MAX_SOCKETS?
MAX_SOCKETS = 15000 # upper bound of how many connections to open
MAX_ITERATIONS = 20 # number of iterations to run the test
# we can't use softlimit ifself 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):
buff, _ = utils.get_msgbuff()
sockets = []
next_ping = time.time() + 5 # less than tcp idle timeout
while True:
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)])
# 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
for s in sockets:
s.sendall(buff)
next_ping = time.time() + 5
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'
port = make_port(ip, ip6)
tls_port = make_port(ip, ip6)
with Kresd(tmpdir, port, tls_port, ip, ip6, verbose=False) as kresd:
print("\nEstablishing {} connections".format(nsockets))
make_sock = getattr(kresd, sock_func_name) # function for creating sockets
sockets = create_sockets(make_sock, nsockets)
print("Start sending data")
for i in range(MAX_ITERATIONS):
for s in sockets:
assert 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()
assert utils.ping_alive(sock)
print("OK!")
......@@ -29,7 +29,7 @@ def create_file_from_template(template_path, dest, data):
class Kresd(ContextDecorator):
def __init__(self, workdir, port, tls_port, ip=None, ip6=None, certname=None):
def __init__(self, workdir, port, tls_port, ip=None, ip6=None, certname=None, verbose=True):
if ip is None and ip6 is None:
raise ValueError("IPv4 or IPv6 must be specified!")
self.workdir = str(workdir)
......@@ -40,6 +40,7 @@ class Kresd(ContextDecorator):
self.process = None
self.sockets = []
self.logfile = None
self.verbose = verbose
if certname:
self.tls_cert_path = os.path.join(CERTS_DIR, certname + '.cert.pem')
......@@ -208,6 +209,5 @@ def make_kresd(workdir, certname=None, ip='127.0.0.1', ip6='::1'):
tls_port = make_port(ip, ip6)
with Kresd(workdir, port, tls_port, ip, ip6, certname) as kresd:
yield kresd
# TODO: add verbose option?
# with open(kresd.logfile_path) as log:
# print(log.read()) # display log for debugging purposes
with open(kresd.logfile_path) as log:
print(log.read()) # display log for debugging purposes
verbose(true)
verbose({{ 'true' if kresd.verbose else 'false' }})
{% if kresd.ip %}
net.listen('{{ kresd.ip }}', {{ kresd.port }})
net.listen('{{ kresd.ip }}', {{ kresd.tls_port }}, {tls = true})
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment