]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Port TCP request statistics checks to Python
authorŠtěpán Balážik <stepan@isc.org>
Sat, 25 Apr 2026 14:00:38 +0000 (16:00 +0200)
committerŠtěpán Balážik <stepan@isc.org>
Sat, 25 Apr 2026 18:25:41 +0000 (20:25 +0200)
Add a helper that runs `rndc stats` and reads the TCP request counter
from named.stats, then use it to port the resolver and forwarder checks
from the shell script to tests_tcp.py. Record named.stats as an extra
artifact so the generated statistics remain available after test runs.

bin/tests/system/tcp/tests.sh
bin/tests/system/tcp/tests_sh_tcp.py
bin/tests/system/tcp/tests_tcp.py

index 18276c8441b53e9a261e797e1a48231caa41ff54..3e0f203c5e388306b9c7aaf62dd57f339c3de013 100644 (file)
@@ -27,50 +27,6 @@ rndccmd() {
 status=0
 n=0
 
-n=$((n + 1))
-echo_i "initializing TCP statistics ($n)"
-ret=0
-rndccmd 10.53.0.1 stats || ret=1
-rndccmd 10.53.0.2 stats || ret=1
-mv ns1/named.stats ns1/named.stats.test$n
-mv ns2/named.stats ns2/named.stats.test$n
-ntcp10="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
-ntcp20="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
-if [ $ret != 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-n=$((n + 1))
-echo_i "checking TCP request statistics (resolver) ($n)"
-ret=0
-dig_with_opts @10.53.0.3 txt.example. >dig.out.test$n
-sleep 1
-rndccmd 10.53.0.1 stats || ret=1
-rndccmd 10.53.0.2 stats || ret=1
-mv ns1/named.stats ns1/named.stats.test$n
-mv ns2/named.stats ns2/named.stats.test$n
-ntcp11="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
-ntcp21="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
-if [ "$ntcp10" -ge "$ntcp11" ]; then ret=1; fi
-if [ "$ntcp20" -ne "$ntcp21" ]; then ret=1; fi
-if [ $ret != 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
-n=$((n + 1))
-echo_i "checking TCP request statistics (forwarder) ($n)"
-ret=0
-dig_with_opts @10.53.0.4 txt.example. >dig.out.test$n
-sleep 1
-rndccmd 10.53.0.1 stats || ret=1
-rndccmd 10.53.0.2 stats || ret=1
-mv ns1/named.stats ns1/named.stats.test$n
-mv ns2/named.stats ns2/named.stats.test$n
-ntcp12="$(grep "TCP requests received" ns1/named.stats.test$n | tail -1 | awk '{print $1}')"
-ntcp22="$(grep "TCP requests received" ns2/named.stats.test$n | tail -1 | awk '{print $1}')"
-if [ "$ntcp11" -ne "$ntcp12" ]; then ret=1; fi
-if [ "$ntcp21" -ge "$ntcp22" ]; then ret=1; fi
-if [ $ret != 0 ]; then echo_i "failed"; fi
-status=$((status + ret))
-
 # -------- TCP high-water tests ----------
 refresh_tcp_stats() {
   rndccmd 10.53.0.5 status >rndc.out.$n || ret=1
index 0e0c9fc0e5044fd10e19909d42be80bae61ddf07..f2430db9eeec55326aa03ce383bc4cee3c5bfb72 100644 (file)
@@ -17,7 +17,6 @@ pytestmark = pytest.mark.extra_artifacts(
         "rndc.out.*",
         "ans*/ans.run",
         "ans*/ans.run.prev",
-        "ns*/named.stats.*",
     ]
 )
 
index 6a05bc202a95f66f623aae0cbe9149d99621abe3..bcf6a60dc53d3a302752dcfad6f59cb4bb41def5 100644 (file)
@@ -21,9 +21,11 @@ import dns.query
 import dns.rrset
 import pytest
 
+from isctest.instance import NamedInstance
+
 import isctest
 
-pytestmark = pytest.mark.extra_artifacts(["ans*/ans.run"])
+pytestmark = pytest.mark.extra_artifacts(["ans*/ans.run", "ns*/named.stats"])
 
 TIMEOUT: int = 10
 
@@ -34,6 +36,20 @@ def create_socket(host: str, port: int) -> socket.socket:
     return sock
 
 
+def tcp_requests_received(ns: NamedInstance) -> int:
+    ns.rndc("stats")
+    stats_file = ns.directory / "named.stats"
+    last_count: int | None = None
+
+    with open(stats_file, "r", encoding="utf-8") as stats:
+        for line in stats:
+            if "TCP requests received" in line:
+                last_count = int(line.split()[0])
+
+    assert last_count is not None, f"'TCP requests received' not found in {stats_file}"
+    return last_count
+
+
 def tcp_round_trip(
     sock: socket.socket, msg: dns.message.Message
 ) -> dns.message.Message:
@@ -131,3 +147,31 @@ def test_tcp_big(named_port: int) -> None:
             "a.example.", "A", dnssec=False, use_edns=-1, ad=False
         )
         tcp_round_trip(sock, msg)
+
+
+def test_tcp_request_statistics(
+    ns1: NamedInstance, ns2: NamedInstance, ns3: NamedInstance, ns4: NamedInstance
+) -> None:
+    isctest.log.info("initializing TCP statistics")
+    ns1_tcp = tcp_requests_received(ns1)
+    ns2_tcp = tcp_requests_received(ns2)
+
+    isctest.log.info("checking TCP request statistics (resolver)")
+    msg = isctest.query.create("txt.example.", "A")
+    isctest.query.udp(msg, ns3.ip)
+    time.sleep(1)
+
+    ns1_tcp_after_resolver = tcp_requests_received(ns1)
+    ns2_tcp_after_resolver = tcp_requests_received(ns2)
+    assert ns1_tcp < ns1_tcp_after_resolver
+    assert ns2_tcp == ns2_tcp_after_resolver
+
+    isctest.log.info("checking TCP request statistics (forwarder)")
+    msg = isctest.query.create("txt.example.", "A")
+    isctest.query.udp(msg, ns4.ip)
+    time.sleep(1)
+
+    ns1_tcp_after_forwarder = tcp_requests_received(ns1)
+    ns2_tcp_after_forwarder = tcp_requests_received(ns2)
+    assert ns1_tcp_after_resolver == ns1_tcp_after_forwarder
+    assert ns2_tcp_after_resolver < ns2_tcp_after_forwarder