]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add system test for minimal-responses behaviour
authorColin Vidal <colin@isc.org>
Mon, 23 Feb 2026 13:27:44 +0000 (14:27 +0100)
committerColin Vidal <colin@isc.org>
Mon, 30 Mar 2026 18:41:13 +0000 (20:41 +0200)
Add the 'minimalresponses' system test in order to cover the multiple
combinations of server 'minimal-responses' configurations and contexts
(resolver, auth only, etc.) when filling the ANSWER, AUTHORITY and
ADDITIONAL sections.

13 files changed:
bin/tests/system/minimalresponses/README [new file with mode: 0644]
bin/tests/system/minimalresponses/common.py [new file with mode: 0644]
bin/tests/system/minimalresponses/ns1/named.conf.j2 [new file with mode: 0644]
bin/tests/system/minimalresponses/ns1/root.db [new file with mode: 0644]
bin/tests/system/minimalresponses/ns2/example2.db [new file with mode: 0644]
bin/tests/system/minimalresponses/ns2/named.conf.j2 [new file with mode: 0644]
bin/tests/system/minimalresponses/ns3/named.conf.j2 [new file with mode: 0644]
bin/tests/system/minimalresponses/ns4/example4.db [new file with mode: 0644]
bin/tests/system/minimalresponses/ns4/named.conf.j2 [new file with mode: 0644]
bin/tests/system/minimalresponses/tests_minimalresponses_no.py [new file with mode: 0644]
bin/tests/system/minimalresponses/tests_minimalresponses_noauth.py [new file with mode: 0644]
bin/tests/system/minimalresponses/tests_minimalresponses_noauthrec.py [new file with mode: 0644]
bin/tests/system/minimalresponses/tests_minimalresponses_yes.py [new file with mode: 0644]

diff --git a/bin/tests/system/minimalresponses/README b/bin/tests/system/minimalresponses/README
new file mode 100644 (file)
index 0000000..9c2c255
--- /dev/null
@@ -0,0 +1,15 @@
+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.
+
+ns1 is the root
+ns2 is auth only
+ns3 is resolver only
+ns4 is both auth and resolver
diff --git a/bin/tests/system/minimalresponses/common.py b/bin/tests/system/minimalresponses/common.py
new file mode 100644 (file)
index 0000000..9dad7c9
--- /dev/null
@@ -0,0 +1,121 @@
+# 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.
+
+# pylint: disable=global-statement
+
+from re import compile as Re
+
+from dns.rcode import NOERROR, REFUSED
+
+import isctest
+
+EXAMPLE2_NS = "example2. 300 IN NS ns.example2."
+AEXAMPLE2_A = "a.example2. 300 IN A 10.53.0.20"
+NSEXAMPLE2_A = "ns.example2. 300 IN A 10.53.0.2"
+
+EXAMPLE4_NS = "example4. 300 IN NS ns.example4."
+AEXAMPLE4_A = "a.example4. 300 IN A 10.53.0.40"
+NSEXAMPLE4_A = "ns.example4. 300 IN A 10.53.0.4"
+
+AROOTSERVER_NS = ". 999999 IN NS a.root-servers.nil."
+
+INPUTPARAMS = "ns, qname, qtype, rd, cached, rcode, answer, authority, additional"
+
+# `minimal-responses yes` and `minimal-responses no-auth` behaves the same,
+# hence they share the same input.
+# The only case AUTHORITY and ADDITIONAL are provided are when strictly needed:
+#   - either from an authoritative server for delegation
+#     (cases with ns1, both AUTHORITY and glues in ADDITIONAL);
+#   - either from a resolver with RD=0 and no cache,
+#      so the resolver can only return the root hints (AUTHORITY only).
+INPUTS_YES_NOAUTH = [
+    ("ns1", "a.example2", "A", True, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", True, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    ("ns2", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns2", "a.example4", "A", True, False, REFUSED, None, None, None),
+    ("ns3", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns3", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example4", "A", True, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example4", "A", True, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns1", "a.example2", "A", False, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", False, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    ("ns2", "a.example2", "A", False, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns2", "a.example4", "A", False, False, REFUSED, None, None, None),
+    ("ns3", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example4", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", False, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns4", "a.example4", "A", False, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example4", "A", False, True, NOERROR, AEXAMPLE4_A, None, None),
+    # Resolver always provides glues with associated NS for qtype=NS
+    ("ns3", "example2", "NS", True, False, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "example2", "NS", False, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", True, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+]
+
+TESTSERVERS = None
+
+FLUSHED_PATTERN = Re("flushing cache.*succeeded")
+
+
+def check(ns, qname, qtype, rd, cached, rcode, answer, authority, additional):
+    ns = TESTSERVERS[ns]
+    msg = isctest.query.create(qname, qtype, rd=rd)
+    if cached:
+        cachingmsg = isctest.query.create(qname, qtype, rd=True)
+        isctest.query.udp(cachingmsg, ns.ip)
+    else:
+        with ns.watch_log_from_here() as watcher:
+            ns.rndc("flush")
+            watcher.wait_for_line(FLUSHED_PATTERN)
+    res = isctest.query.udp(msg, ns.ip)
+    isctest.check.rcode(res, rcode)
+    if answer:
+        assert len(res.answer) == 1
+        # Clamp the answer TTL to 300 to match the expected answer
+        # (In case the server would be a bit slow to process the
+        # query, and we would end up with a TTL of ~299)
+        res.answer[0].ttl = 300
+        assert str(res.answer[0]) == answer
+    else:
+        assert len(res.answer) == 0
+    if authority:
+        assert len(res.authority) == 1
+        assert str(res.authority[0]) == authority
+    else:
+        assert len(res.authority) == 0
+    if additional:
+        assert len(res.additional) == 1
+        # Clamp the answer TTL to 300 to match the expected answer
+        # (In case the server would be a bit slow to process the
+        # query, and we would end up with a TTL of ~299)
+        res.additional[0].ttl = 300
+        assert str(res.additional[0]) == additional
+    else:
+        assert len(res.additional) == 0
+
+
+def reconfig(servers, templates, minresp):
+    global TESTSERVERS
+    for server in servers:
+        ns = servers[server]
+        with ns.watch_log_from_here() as watcher:
+            templates.render(f"{server}/named.conf", {"minresp": minresp})
+            ns.rndc("reload")
+            watcher.wait_for_line("running")
+    TESTSERVERS = servers
diff --git a/bin/tests/system/minimalresponses/ns1/named.conf.j2 b/bin/tests/system/minimalresponses/ns1/named.conf.j2
new file mode 100644 (file)
index 0000000..4a4a414
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+{% set minresp = minresp | default("yes") %}
+
+options {
+       query-source address 10.53.0.1;
+       notify-source 10.53.0.1;
+       transfer-source 10.53.0.1;
+       port @PORT@;
+       pid-file "named.pid";
+       listen-on { 10.53.0.1; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+       minimal-responses @minresp@;
+};
+
+zone "." {
+       type primary;
+       file "root.db";
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+       inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
diff --git a/bin/tests/system/minimalresponses/ns1/root.db b/bin/tests/system/minimalresponses/ns1/root.db
new file mode 100644 (file)
index 0000000..93d021e
--- /dev/null
@@ -0,0 +1,27 @@
+; 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.
+
+$TTL 300
+.                      IN SOA  gson.nominum.com. a.root.servers.nil. (
+                               2000042100      ; serial
+                               600             ; refresh
+                               600             ; retry
+                               1200            ; expire
+                               600             ; minimum
+                               )
+.                      NS      a.root-servers.nil.
+a.root-servers.nil.    A       10.53.0.1
+
+example2.              NS      ns.example2.
+ns.example2.           A       10.53.0.2
+
+example4.              NS      ns.example4.
+ns.example4.           A       10.53.0.4
diff --git a/bin/tests/system/minimalresponses/ns2/example2.db b/bin/tests/system/minimalresponses/ns2/example2.db
new file mode 100644 (file)
index 0000000..b7fb5fa
--- /dev/null
@@ -0,0 +1,23 @@
+; 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.
+
+$TTL 300       ; 5 minutes
+@                      IN SOA  mname1. . (
+                               2000042407 ; serial
+                               20         ; refresh (20 seconds)
+                               20         ; retry (20 seconds)
+                               1814400    ; expire (3 weeks)
+                               3600       ; minimum (1 hour)
+                               )
+                       NS      ns
+ns                     A       10.53.0.2
+
+a                      A       10.53.0.20
diff --git a/bin/tests/system/minimalresponses/ns2/named.conf.j2 b/bin/tests/system/minimalresponses/ns2/named.conf.j2
new file mode 100644 (file)
index 0000000..d918d43
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+{% set minresp = minresp | default("yes") %}
+
+options {
+       query-source address 10.53.0.2;
+       notify-source 10.53.0.2;
+       transfer-source 10.53.0.2;
+       port @PORT@;
+       pid-file "named.pid";
+       listen-on { 10.53.0.2; };
+       listen-on-v6 { none; };
+       recursion no;
+       notify yes;
+       dnssec-validation no;
+       minimal-responses @minresp@;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+       inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "example2" {
+       type primary;
+       file "example2.db";
+};
diff --git a/bin/tests/system/minimalresponses/ns3/named.conf.j2 b/bin/tests/system/minimalresponses/ns3/named.conf.j2
new file mode 100644 (file)
index 0000000..6756c00
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+{% set minresp = minresp | default("yes") %}
+
+options {
+       query-source address 10.53.0.3;
+       notify-source 10.53.0.3;
+       transfer-source 10.53.0.3;
+       port @PORT@;
+       pid-file "named.pid";
+       listen-on { 10.53.0.3; };
+       listen-on-v6 { none; };
+       recursion yes;
+       notify yes;
+       dnssec-validation no;
+       minimal-responses @minresp@;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+       inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type hint;
+       file "../../_common/root.hint";
+};
+
+
diff --git a/bin/tests/system/minimalresponses/ns4/example4.db b/bin/tests/system/minimalresponses/ns4/example4.db
new file mode 100644 (file)
index 0000000..90e0399
--- /dev/null
@@ -0,0 +1,23 @@
+; 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.
+
+$TTL 300       ; 5 minutes
+@                      IN SOA  mname1. . (
+                               2000042407 ; serial
+                               20         ; refresh (20 seconds)
+                               20         ; retry (20 seconds)
+                               1814400    ; expire (3 weeks)
+                               3600       ; minimum (1 hour)
+                               )
+                       NS      ns
+ns                     A       10.53.0.4
+
+a                      A       10.53.0.40
diff --git a/bin/tests/system/minimalresponses/ns4/named.conf.j2 b/bin/tests/system/minimalresponses/ns4/named.conf.j2
new file mode 100644 (file)
index 0000000..c11a639
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+{% set minresp = minresp | default("yes") %}
+
+options {
+       query-source address 10.53.0.4;
+       notify-source 10.53.0.4;
+       transfer-source 10.53.0.4;
+       port @PORT@;
+       pid-file "named.pid";
+       listen-on { 10.53.0.4; };
+       listen-on-v6 { none; };
+       recursion yes;
+       notify yes;
+       dnssec-validation no;
+       minimal-responses @minresp@;
+};
+
+key rndc_key {
+       secret "1234abcd8765";
+       algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+       inet 10.53.0.4 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+       type hint;
+       file "../../_common/root.hint";
+};
+
+zone "example4" {
+       type primary;
+       file "example4.db";
+};
diff --git a/bin/tests/system/minimalresponses/tests_minimalresponses_no.py b/bin/tests/system/minimalresponses/tests_minimalresponses_no.py
new file mode 100644 (file)
index 0000000..febaf46
--- /dev/null
@@ -0,0 +1,139 @@
+# 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.
+
+from dns.rcode import NOERROR, REFUSED
+
+import pytest
+
+from minimalresponses.common import (
+    AEXAMPLE2_A,
+    AEXAMPLE4_A,
+    AROOTSERVER_NS,
+    EXAMPLE2_NS,
+    EXAMPLE4_NS,
+    INPUTPARAMS,
+    NSEXAMPLE2_A,
+    NSEXAMPLE4_A,
+    check,
+    reconfig,
+)
+
+INPUTS = [
+    # ns1 provides AUTHORITY and ADDITIONAL as it delegate those zone.
+    ("ns1", "a.example2", "A", True, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", True, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    ("ns1", "a.example2", "A", False, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", False, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    # ns2 is authoritative on example2, so it gives us everything it can in any cases.
+    (
+        "ns2",
+        "a.example2",
+        "A",
+        True,
+        False,
+        NOERROR,
+        AEXAMPLE2_A,
+        EXAMPLE2_NS,
+        NSEXAMPLE2_A,
+    ),
+    (
+        "ns2",
+        "a.example2",
+        "A",
+        False,
+        False,
+        NOERROR,
+        AEXAMPLE2_A,
+        EXAMPLE2_NS,
+        NSEXAMPLE2_A,
+    ),
+    ("ns2", "a.example4", "A", True, False, REFUSED, None, None, None),
+    ("ns2", "a.example4", "A", False, False, REFUSED, None, None, None),
+    # ns3 being resolver only and having the answer, no AUTHORITY or ADDITIONAL are added.
+    # However, with RD=0 and no cache, it can't answer, so the root hints are provided
+    # in AUTHORITY.
+    ("ns3", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns3", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns3", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example4", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", False, True, NOERROR, AEXAMPLE4_A, None, None),
+    # ns4 is authoritative on example4, so gives us everything in any cases.
+    # For example2, because it has the answer, it only provide the ANSWER section
+    # (except with no cache and RD=0, where we got the root hint, because it can't do anything else)
+    ("ns4", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        True,
+        True,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    ("ns4", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        True,
+        False,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    ("ns4", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        False,
+        False,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        False,
+        True,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    # Resolver always provides glues with associated NS for qtype=NS
+    ("ns3", "example2", "NS", True, False, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "example2", "NS", False, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", True, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+]
+
+
+@pytest.fixture(scope="module", autouse=True)
+def authsection_init(servers, templates):
+    reconfig(servers, templates, "no")
+
+
+@pytest.mark.parametrize(INPUTPARAMS, INPUTS)
+def test_minimalresponses_no(
+    ns, qname, qtype, rd, cached, rcode, answer, authority, additional
+):
+    check(ns, qname, qtype, rd, cached, rcode, answer, authority, additional)
diff --git a/bin/tests/system/minimalresponses/tests_minimalresponses_noauth.py b/bin/tests/system/minimalresponses/tests_minimalresponses_noauth.py
new file mode 100644 (file)
index 0000000..d1f12ab
--- /dev/null
@@ -0,0 +1,26 @@
+# 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.
+
+import pytest
+
+from minimalresponses.common import INPUTPARAMS, INPUTS_YES_NOAUTH, check, reconfig
+
+
+@pytest.fixture(scope="module", autouse=True)
+def authsection_init(servers, templates):
+    reconfig(servers, templates, "no-auth")
+
+
+@pytest.mark.parametrize(INPUTPARAMS, INPUTS_YES_NOAUTH)
+def test_minimalresponses_noauth(
+    ns, qname, qtype, rd, cached, rcode, answer, authority, additional
+):
+    check(ns, qname, qtype, rd, cached, rcode, answer, authority, additional)
diff --git a/bin/tests/system/minimalresponses/tests_minimalresponses_noauthrec.py b/bin/tests/system/minimalresponses/tests_minimalresponses_noauthrec.py
new file mode 100644 (file)
index 0000000..1465c1b
--- /dev/null
@@ -0,0 +1,111 @@
+# 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.
+
+from dns.rcode import NOERROR, REFUSED
+
+import pytest
+
+from minimalresponses.common import (
+    AEXAMPLE2_A,
+    AEXAMPLE4_A,
+    AROOTSERVER_NS,
+    EXAMPLE2_NS,
+    EXAMPLE4_NS,
+    INPUTPARAMS,
+    NSEXAMPLE2_A,
+    NSEXAMPLE4_A,
+    check,
+    reconfig,
+)
+
+INPUTS = [
+    # ns1 provides AUTHORITY and ADDITIONAL as it delegate those zone.
+    ("ns1", "a.example2", "A", True, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", True, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    ("ns1", "a.example2", "A", False, False, NOERROR, None, EXAMPLE2_NS, NSEXAMPLE2_A),
+    ("ns1", "a.example4", "A", False, False, NOERROR, None, EXAMPLE4_NS, NSEXAMPLE4_A),
+    # ns2 behaves like `minimal-responses no` with RD=0 on `example2.`
+    # (which it makes authority on).
+    # Nothing for `example4.` as it's an authoritative server only,
+    # and doesn't own that zone.
+    # Otherwise, it behaves like `minimal-responses yes`
+    ("ns2", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns2", "a.example4", "A", True, False, REFUSED, None, None, None),
+    (
+        "ns2",
+        "a.example2",
+        "A",
+        False,
+        False,
+        NOERROR,
+        AEXAMPLE2_A,
+        EXAMPLE2_NS,
+        NSEXAMPLE2_A,
+    ),
+    ("ns2", "a.example4", "A", False, False, REFUSED, None, None, None),
+    # ns3 behaviour (as resolver) is common between all variants with RD=1.
+    # With RD=0, it has the same behavior than `minimal-responses no;`
+    ("ns3", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns3", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", True, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns3", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example4", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns3", "a.example4", "A", False, True, NOERROR, AEXAMPLE4_A, None, None),
+    # ns4, with RD=1 has minimal responses (just the answer).
+    # But RD=0 behaves as `minimal-responses no`.
+    ("ns4", "a.example2", "A", True, False, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example4", "A", True, False, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", True, True, NOERROR, AEXAMPLE2_A, None, None),
+    ("ns4", "a.example4", "A", True, True, NOERROR, AEXAMPLE4_A, None, None),
+    ("ns4", "a.example2", "A", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        False,
+        False,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    ("ns4", "a.example2", "A", False, True, NOERROR, AEXAMPLE2_A, None, None),
+    (
+        "ns4",
+        "a.example4",
+        "A",
+        False,
+        True,
+        NOERROR,
+        AEXAMPLE4_A,
+        EXAMPLE4_NS,
+        NSEXAMPLE4_A,
+    ),
+    # Resolver always provides glues with associated NS for qtype=NS
+    ("ns3", "example2", "NS", True, False, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", False, False, NOERROR, None, AROOTSERVER_NS, None),
+    ("ns3", "example2", "NS", False, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+    ("ns3", "example2", "NS", True, True, NOERROR, EXAMPLE2_NS, None, NSEXAMPLE2_A),
+]
+
+
+@pytest.fixture(scope="module", autouse=True)
+def authsection_init(servers, templates):
+    reconfig(servers, templates, "no-auth-recursive")
+
+
+@pytest.mark.parametrize(INPUTPARAMS, INPUTS)
+def test_minimalresponses_noauthrec(
+    ns, qname, qtype, rd, cached, rcode, answer, authority, additional
+):
+    check(ns, qname, qtype, rd, cached, rcode, answer, authority, additional)
diff --git a/bin/tests/system/minimalresponses/tests_minimalresponses_yes.py b/bin/tests/system/minimalresponses/tests_minimalresponses_yes.py
new file mode 100644 (file)
index 0000000..049479c
--- /dev/null
@@ -0,0 +1,26 @@
+# 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.
+
+import pytest
+
+from minimalresponses.common import INPUTPARAMS, INPUTS_YES_NOAUTH, check, reconfig
+
+
+@pytest.fixture(scope="module", autouse=True)
+def authsection_init(servers, templates):
+    reconfig(servers, templates, "yes")
+
+
+@pytest.mark.parametrize(INPUTPARAMS, INPUTS_YES_NOAUTH)
+def test_minimalresponses_yes(
+    ns, qname, qtype, rd, cached, rcode, answer, authority, additional
+):
+    check(ns, qname, qtype, rd, cached, rcode, answer, authority, additional)