From 8fed1b64618a1625dd1efc2d7cd8983284b1f4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 8 Feb 2022 21:32:10 +0100 Subject: [PATCH] Add XFR max-transfer-time-out and max-tranfer-idle-out system tests Extend the timeouts system test to ensure that the maximum outgoing transfer time (max-transfer-time-out) and maximum outgoing transfer idle time (max-transfer-idle-out) works as expected. This is done by lowering the limits to 5/1 minutes and testing that the connection has been dropped while sleeping between the individual XFR messages. --- bin/tests/system/run.sh.in | 1 + bin/tests/system/timeouts/conftest.py | 10 +++ bin/tests/system/timeouts/ns1/named.conf.in | 2 + bin/tests/system/timeouts/tests-tcp.py | 73 +++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/bin/tests/system/run.sh.in b/bin/tests/system/run.sh.in index 9c529d0286..c8467e6b94 100644 --- a/bin/tests/system/run.sh.in +++ b/bin/tests/system/run.sh.in @@ -88,6 +88,7 @@ if ! $do_run; then LOG_DRIVER_FLAGS="--verbose yes --color-tests yes" \ LOG_FLAGS="$log_flags" \ TEST_LARGE_MAP="${TEST_LARGE_MAP}" \ + CI_ENABLE_ALL_TESTS="${CI_ENABLE_ALL_TESTS}" \ make -e check exit $? fi diff --git a/bin/tests/system/timeouts/conftest.py b/bin/tests/system/timeouts/conftest.py index 0ce749b3fd..d92d87f72c 100644 --- a/bin/tests/system/timeouts/conftest.py +++ b/bin/tests/system/timeouts/conftest.py @@ -20,6 +20,9 @@ def pytest_configure(config): config.addinivalue_line( "markers", "dnspython2: mark tests that need dnspython >= 2.0.0" ) + config.addinivalue_line( + "markers", "long: mark tests that take a long time to run" + ) def pytest_collection_modifyitems(config, items): @@ -46,6 +49,13 @@ def pytest_collection_modifyitems(config, items): if "dnspython2" in item.keywords: item.add_marker(skip_dnspython2) + skip_long_tests = pytest.mark.skip( + reason="need CI_ENABLE_ALL_TESTS environment variable") + if not os.environ.get("CI_ENABLE_ALL_TESTS"): + for item in items: + if "long" in item.keywords: + item.add_marker(skip_long_tests) + @pytest.fixture def port(request): diff --git a/bin/tests/system/timeouts/ns1/named.conf.in b/bin/tests/system/timeouts/ns1/named.conf.in index c9a7a6b42e..4b422e22b2 100644 --- a/bin/tests/system/timeouts/ns1/named.conf.in +++ b/bin/tests/system/timeouts/ns1/named.conf.in @@ -30,6 +30,8 @@ options { tcp-initial-timeout 20; tcp-idle-timeout 50; tcp-keepalive-timeout 70; + max-transfer-time-out 5; /* minutes */ + max-transfer-idle-out 1; /* minutes */ }; zone "." { diff --git a/bin/tests/system/timeouts/tests-tcp.py b/bin/tests/system/timeouts/tests-tcp.py index e1f19608c8..a1c94839ea 100644 --- a/bin/tests/system/timeouts/tests-tcp.py +++ b/bin/tests/system/timeouts/tests-tcp.py @@ -220,3 +220,76 @@ def test_send_timeout(port): (response, rtime) = dns.query.receive_tcp(sock, timeout()) except ConnectionError as e: raise EOFError from e + + +@pytest.mark.dnspython +@pytest.mark.dnspython2 +@pytest.mark.long +def test_max_transfer_idle_out(port): + import dns.query + import dns.rdataclass + import dns.rdatatype + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.connect(("10.53.0.1", port)) + + name = dns.name.from_text("example.") + msg = create_msg("example.", "AXFR") + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + + # Receive the initial DNS message with SOA + (response, rtime) = dns.query.receive_tcp(sock, timeout(), + one_rr_per_rrset=True) + soa = response.get_rrset(dns.message.ANSWER, name, + dns.rdataclass.IN, dns.rdatatype.SOA) + assert soa is not None + + time.sleep(61) # max-transfer-idle-out is 1 minute + + with pytest.raises(ConnectionResetError): + # Process queued TCP messages + while True: + (response, rtime) = \ + dns.query.receive_tcp(sock, timeout(), + one_rr_per_rrset=True) + soa = response.get_rrset(dns.message.ANSWER, name, + dns.rdataclass.IN, dns.rdatatype.SOA) + if soa is not None: + break + assert soa is None + + +@pytest.mark.dnspython +@pytest.mark.dnspython2 +@pytest.mark.long +def test_max_transfer_time_out(port): + import dns.query + import dns.rdataclass + import dns.rdatatype + + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.connect(("10.53.0.1", port)) + + name = dns.name.from_text("example.") + msg = create_msg("example.", "AXFR") + (sbytes, stime) = dns.query.send_tcp(sock, msg, timeout()) + + # Receive the initial DNS message with SOA + (response, rtime) = dns.query.receive_tcp(sock, timeout(), + one_rr_per_rrset=True) + soa = response.get_rrset(dns.message.ANSWER, name, + dns.rdataclass.IN, dns.rdatatype.SOA) + assert soa is not None + + # The loop should timeout at the 5 minutes (max-transfer-time-out) + with pytest.raises(EOFError): + while True: + time.sleep(1) + (response, rtime) = \ + dns.query.receive_tcp(sock, timeout(), + one_rr_per_rrset=True) + soa = response.get_rrset(dns.message.ANSWER, name, + dns.rdataclass.IN, dns.rdatatype.SOA) + if soa is not None: + break + assert soa is None