]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Migrate digdelv mdig checks to pytest
authorMartin Basti <mbasti@isc.org>
Wed, 22 Jul 2026 22:04:19 +0000 (22:04 +0000)
committerMartin Basti <mbasti@isc.org>
Wed, 29 Jul 2026 11:54:10 +0000 (13:54 +0200)
Move the mdig checks from tests.sh into a new tests_mdig.py module:
the source address and port handling over TCP, the malformed
'+ednsopt=:' option, the +multi +norrcomments output for DNSKEY and
SOA, and the +yaml output structure.  Like tests_dig.py, the module is
skipped entirely when the mdig executable is not available.

Assisted-by: Claude:claude-fable-5
bin/tests/system/digdelv/tests.sh
bin/tests/system/digdelv/tests_mdig.py [new file with mode: 0644]

index 6bf4eafdbbdcda98d6539bede0728938bbb155ad..17c92096ac6836a2ffec274dca6306ccbd8b9912 100644 (file)
@@ -19,10 +19,6 @@ set -e
 status=0
 n=0
 
-mdig_with_opts() {
-  "$MDIG" -p "$PORT" "$@"
-}
-
 # Check if response in file $1 has the correct TTL range.
 # The response record must have RRtype $2 and class IN (CLASS1).
 # Maximum TTL is given by $3.  This works in most cases where TTL is
@@ -63,63 +59,6 @@ NOSPLIT="$(sed <ns2/keydata -e 's/+/[+]/g' -e 's/ //g')"
 HAS_PYYAML=0
 $PYTHON -c "import yaml" 2>/dev/null && HAS_PYYAML=1
 
-if [ -x "$MDIG" ]; then
-  n=$((n + 1))
-  echo_i "checking mdig +tcp works with a source address and port ($n)"
-  ret=0
-  # When running more than once in quick succession with a source address#port,
-  # we can get a "response failed with address not available" error because
-  # the address#port is still busy, but we are not interested in that error,
-  # as we are only looking for the unexpected error case, that's why we ignore
-  # the return code from mdig, but we check for the unexpected error message
-  # using grep. See GitLab #4969.
-  mdig_with_opts -b "10.53.0.3#${EXTRAPORT8}" +tcp @10.53.0.3 example >dig.out.test$n 2>&1 || true
-  grep -F "unexpected error" dig.out.test$n >/dev/null && ret=1
-  if [ $ret -ne 0 ]; then echo_i "failed"; fi
-  status=$((status + ret))
-
-  n=$((n + 1))
-  echo_i "check that mdig handles malformed option '+ednsopt=:' gracefully ($n)"
-  ret=0
-  mdig_with_opts @10.53.0.3 +ednsopt=: a.example >dig.out.test$n 2>&1 && ret=1
-  grep "ednsopt no code point specified" dig.out.test$n >/dev/null || ret=1
-  if [ $ret -ne 0 ]; then echo_i "failed"; fi
-  status=$((status + ret))
-
-  n=$((n + 1))
-  echo_i "checking mdig +multi +norrcomments works for DNSKEY (when default is rrcomments)($n)"
-  ret=0
-  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t DNSKEY example >dig.out.test$n || ret=1
-  grep "; ZSK; alg = $DEFAULT_ALGORITHM ; key id = $KEYID" dig.out.test$n && ret=1
-  if [ $ret -ne 0 ]; then echo_i "failed"; fi
-  status=$((status + ret))
-
-  n=$((n + 1))
-  echo_i "checking mdig +multi +norrcomments works for SOA (when default is rrcomments)($n)"
-  ret=0
-  mdig_with_opts +tcp @10.53.0.3 +multi +norrcomments -t SOA example >dig.out.test$n || ret=1
-  grep "; serial" <dig.out.test$n >/dev/null && ret=1
-  if [ $ret -ne 0 ]; then echo_i "failed"; fi
-  status=$((status + ret))
-
-  if [ $HAS_PYYAML -ne 0 ]; then
-    n=$((n + 1))
-    echo_i "check mdig +yaml output ($n)"
-    ret=0
-    mdig_with_opts +yaml @10.53.0.3 -t any ns2.example >dig.out.test$n 2>&1 || ret=1
-    $PYTHON yamlget.py dig.out.test$n 0 message response_message_data status >yamlget.out.test$n 2>&1 || ret=1
-    read -r value <yamlget.out.test$n
-    [ "$value" = "NOERROR" ] || ret=1
-    $PYTHON yamlget.py dig.out.test$n 0 message response_message_data QUESTION_SECTION 0 >yamlget.out.test$n 2>&1 || ret=1
-    read -r value <yamlget.out.test$n
-    [ "$value" = "ns2.example. IN ANY" ] || ret=1
-    if [ $ret -ne 0 ]; then echo_i "failed"; fi
-    status=$((status + ret))
-  fi
-else
-  echo_i "$MDIG is needed, so skipping these mdig tests"
-fi
-
 if [ -x "$DELV" ]; then
   n=$((n + 1))
   echo_i "checking delv short form works ($n)"
diff --git a/bin/tests/system/digdelv/tests_mdig.py b/bin/tests/system/digdelv/tests_mdig.py
new file mode 100644 (file)
index 0000000..ef5bad4
--- /dev/null
@@ -0,0 +1,81 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0.  If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+"""
+Tests for the mdig tool.
+"""
+
+import os
+
+import pytest
+
+from digdelv.common import ARTIFACTS, needs_pyyaml, parse_yaml
+
+import isctest
+
+pytestmark = [
+    pytest.mark.skipif(
+        not os.access(os.environ.get("MDIG", ""), os.X_OK),
+        reason="mdig executable not available",
+    ),
+    pytest.mark.extra_artifacts(ARTIFACTS),
+]
+
+
+@pytest.fixture(name="mdig")
+def mdig_fixture(named_port):
+    return isctest.run.EnvCmd("MDIG", f"-p {named_port}")
+
+
+def test_tcp_with_source_address_and_port(mdig, ns3):
+    """Check that mdig +tcp works with a source address and port.  When
+    running more than once in quick succession with a source
+    address#port, the query can fail with "response failed with address
+    not available" because the address#port is still busy; that error is
+    not interesting, only the unexpected error case is.  See GL #4969
+    for more information."""
+    extraport8 = os.environ["EXTRAPORT8"]
+    result = mdig(
+        f"-b {ns3.ip}#{extraport8} +tcp @{ns3.ip} example", raise_on_exception=False
+    )
+    assert "unexpected error" not in result.out
+    assert "unexpected error" not in result.err
+
+
+def test_ednsopt_malformed(mdig, ns3):
+    """Check that mdig handles the malformed option '+ednsopt=:'
+    gracefully."""
+    result = mdig(f"@{ns3.ip} +ednsopt=: a.example", raise_on_exception=False)
+    assert result.rc != 0
+    assert "ednsopt no code point specified" in result.err
+
+
+def test_dnskey_norrcomments(mdig, ns3, zsk):
+    """Check that +multi +norrcomments suppresses the DNSKEY comment
+    (the default is rrcomments)."""
+    result = mdig(f"+tcp @{ns3.ip} +multi +norrcomments -t DNSKEY example")
+    assert zsk.rrcomment not in result.out
+
+
+def test_soa_norrcomments(mdig, ns3):
+    """Check that +multi +norrcomments suppresses the SOA field
+    comments."""
+    result = mdig(f"+tcp @{ns3.ip} +multi +norrcomments -t SOA example")
+    assert "; serial" not in result.out
+
+
+@needs_pyyaml
+def test_yaml_output(mdig, ns3):
+    """Check the structure of mdig +yaml output."""
+    result = mdig(f"+yaml @{ns3.ip} -t any ns2.example")
+    response = parse_yaml(result.out)[0]["message"]["response_message_data"]
+    assert response["status"] == "NOERROR"
+    assert response["QUESTION_SECTION"][0] == "ns2.example. IN ANY"