From: Artem Boldariev Date: Fri, 23 Jul 2021 10:52:35 +0000 (+0300) Subject: Refactor the DoH quota stress test to make it more reliable X-Git-Tag: v9.17.17~8^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ae26a1ec75b291ed2135f3b14ef0a6bd9941a31a;p=thirdparty%2Fbind9.git Refactor the DoH quota stress test to make it more reliable This commit refactors the DoH quota system test to make it more reliable. The test tries to establish dummy TCP connections to stress the quota one by one instead of in bulk until the BIND instance cannot answer queries anymore. This design is better because the test itself does not need to be aware of the actual quota size. --- diff --git a/bin/tests/system/doth/stress_http_quota.py b/bin/tests/system/doth/stress_http_quota.py index 16806ba31f0..1e56538aa98 100755 --- a/bin/tests/system/doth/stress_http_quota.py +++ b/bin/tests/system/doth/stress_http_quota.py @@ -19,8 +19,6 @@ import time from functools import reduce -# this number should exceed default HTTP quota value -NCONNECTIONS = 320 MULTIDIG_INSTANCES = 10 CONNECT_TRIES = 5 @@ -61,8 +59,7 @@ def get_dig_path(): # A simple class which creates the given number of TCP connections to # the given host in order to stress the BIND's quota facility class TCPConnector: - def __init__(self, nconnections, host, port): - self.number_of_connections = nconnections + def __init__(self, host, port): self.host = host self.port = port self.connections = [] @@ -85,10 +82,6 @@ class TCPConnector: finally: tries -= 1 - def connect_all(self): - for _ in range(1, self.number_of_connections + 1): - self.connect_one() - # Close an established connection (randomly) def disconnect_random(self): pos = random.randint(0, len(self.connections) - 1) @@ -138,7 +131,6 @@ class SubDIG: with open(os.devnull, 'w') as devnull: self.sub_process = subprocess.Popen(self.get_command(), shell=True, stdout=devnull) - jitter() def wait(self, timeout=None): res = None @@ -185,6 +177,13 @@ class MultiDIG: return reduce(lambda a, b: (a and b), map(lambda p: (p.alive()), self.digs)) + def completed(self): + total = 0 + for p in self.digs: + if not p.alive(): + total += 1 + return total + # The test's main logic def run_test(http_secure=True): @@ -195,19 +194,17 @@ def run_test(http_secure=True): assert subdig.wait() == 0, "DIG was expected to succeed" # Let's create a lot of TCP connections to the server stress the # HTTP quota - connector = TCPConnector(NCONNECTIONS, get_http_host(), + connector = TCPConnector(get_http_host(), get_http_port(http_secure=http_secure)) # Let's make queries until the quota kicks in subdig = SubDIG(http_secure=http_secure, extra_args=query_args) subdig.run() while True: + connector.connect_one() subdig = SubDIG(http_secure=http_secure, extra_args=query_args) - connector.connect_all() - time.sleep(2) subdig.run() - if subdig.wait(timeout=2) is None: + if subdig.wait(timeout=5) is None: break - connector.disconnect_all() # At this point quota has kicked in. Additionally, let's create a # bunch of dig processes all trying to make a query against the @@ -218,9 +215,12 @@ def run_test(http_secure=True): # Wait for the dig instance to complete. Not a single instance has # a chance to complete successfully because of the exceeded quota assert subdig.wait(timeout=5) is None,\ - "Single DIG instance has stopped prematurely" - assert subdig.alive(), "Single DIG instance is expected to be alive" - assert multidig.alive(), "Multiple DIG instances are expected to be alive" + "The single DIG instance has stopped prematurely" + assert subdig.alive(), "The single DIG instance is expected to be alive" + assert multidig.alive(), \ + ("The DIG instances from the set are all expected to " + "be alive, but {} of them have completed")\ + .format(multidig.completed()) # Let's close opened connections (in random order) to let all dig # processes to complete connector.disconnect_all()