Commit c469d23734 for bind
commit c469d237349345372e8b987f4efa97555cae207e
Author: Štěpán Balážik <stepan@isc.org>
Date: Tue Sep 8 19:34:32 2026 +0200
Replace QnameQtypeHandler with a matcher
QnameQtypeHandler existed only to match on a QNAME and a QTYPE; its
users now declare `Qname(...) & Qtype(...)` themselves.
Assisted-by: Claude:claude-fable-5
diff --git a/bin/tests/system/cyclic_glue/ans5/ans.py b/bin/tests/system/cyclic_glue/ans5/ans.py
index 0d5867ef92..86d7d0e90e 100644
--- a/bin/tests/system/cyclic_glue/ans5/ans.py
+++ b/bin/tests/system/cyclic_glue/ans5/ans.py
@@ -16,7 +16,8 @@ import dns.rdatatype
import dns.rrset
from isctest.asyncserver import AsyncDnsServer
-from isctest.asyncserver.handlers import QnameQtypeHandler, StaticResponseHandler
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
def rrset(
@@ -36,9 +37,8 @@ def a(owner: str, address: str) -> dns.rrset.RRset:
return rrset(owner, dns.rdatatype.A, address)
-class BrokenFooHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["a.foo.test."]
- qtypes = [dns.rdatatype.A]
+class BrokenFooHandler(StaticResponseHandler):
+ matcher = Qname("a.foo.test.") & Qtype(dns.rdatatype.A)
authority = [
ns("foo.test.", "ns.foo.test."),
ns("foo.test.", "ns.bar.test."),
@@ -55,9 +55,8 @@ class BrokenFooHandler(QnameQtypeHandler, StaticResponseHandler):
]
-class BrokenBarHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["a.bar.test."]
- qtypes = [dns.rdatatype.A]
+class BrokenBarHandler(StaticResponseHandler):
+ matcher = Qname("a.bar.test.") & Qtype(dns.rdatatype.A)
authority = [
ns("bar.test.", "ns.bar.test."),
# This NS is valid but outside the bar.test domain.
diff --git a/bin/tests/system/dnssec_wildcard/ans1/ans.py b/bin/tests/system/dnssec_wildcard/ans1/ans.py
index 843d1935dd..e9f362880c 100644
--- a/bin/tests/system/dnssec_wildcard/ans1/ans.py
+++ b/bin/tests/system/dnssec_wildcard/ans1/ans.py
@@ -15,9 +15,9 @@ import dns.name
import dns.rdatatype
import dns.rrset
-from isctest.asyncserver import AsyncDnsServer, QueryContext
+from isctest.asyncserver import AsyncDnsServer, QueryContext, ResponseHandler
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import QnameQtypeHandler
+from isctest.asyncserver.matchers import Qname, Qtype
def append_forged_a_rrset_to_additional(qctx: QueryContext, owner_name: str) -> None:
@@ -53,9 +53,8 @@ def append_forged_a_rrset_to_additional(qctx: QueryContext, owner_name: str) ->
# from a wildcard record.
-class WildcardAdditionalHandler(QnameQtypeHandler):
- qnames = ["svc.f043.test."]
- qtypes = [dns.rdatatype.MX]
+class WildcardAdditionalHandler(ResponseHandler):
+ matcher = Qname("svc.f043.test.") & Qtype(dns.rdatatype.MX)
async def get_responses(
self, qctx: QueryContext
@@ -64,9 +63,8 @@ class WildcardAdditionalHandler(QnameQtypeHandler):
yield DnsResponseSend(qctx.response)
-class ParentWildcardHandler(QnameQtypeHandler):
- qnames = ["q.f045.test."]
- qtypes = [dns.rdatatype.MX]
+class ParentWildcardHandler(ResponseHandler):
+ matcher = Qname("q.f045.test.") & Qtype(dns.rdatatype.MX)
async def get_responses(
self, qctx: QueryContext
diff --git a/bin/tests/system/filters/ans6/ans.py b/bin/tests/system/filters/ans6/ans.py
index f2cacb3171..ef77810bfe 100644
--- a/bin/tests/system/filters/ans6/ans.py
+++ b/bin/tests/system/filters/ans6/ans.py
@@ -15,7 +15,8 @@ import dns.rdatatype
import dns.rrset
from isctest.asyncserver import AsyncDnsServer, QueryContext
-from isctest.asyncserver.handlers import QnameQtypeHandler, StaticResponseHandler
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
DNS64_TRIGGER = "nodata.test."
@@ -36,15 +37,14 @@ def aaaa() -> dns.rrset.RRset:
return rrset(DNS64_TRIGGER, dns.rdatatype.AAAA, "2001:db8::1")
-class NodataOnceHandler(QnameQtypeHandler, StaticResponseHandler):
+class NodataOnceHandler(StaticResponseHandler):
"""
Answer only the first AAAA query, with NODATA, so the DNS64 resolver looks
up an A record; the delayed A lookup lets filter-a re-enter and re-query
AAAA (answered by AaaaHandler), triggering the bug.
"""
- qnames = [DNS64_TRIGGER]
- qtypes = [dns.rdatatype.AAAA]
+ matcher = Qname(DNS64_TRIGGER) & Qtype(dns.rdatatype.AAAA)
authority = [soa()]
def __init__(self) -> None:
@@ -58,15 +58,13 @@ class NodataOnceHandler(QnameQtypeHandler, StaticResponseHandler):
return super().match(qctx)
-class AaaaHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [DNS64_TRIGGER]
- qtypes = [dns.rdatatype.AAAA]
+class AaaaHandler(StaticResponseHandler):
+ matcher = Qname(DNS64_TRIGGER) & Qtype(dns.rdatatype.AAAA)
answer = [aaaa()]
-class DelayedAHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [DNS64_TRIGGER]
- qtypes = [dns.rdatatype.A]
+class DelayedAHandler(StaticResponseHandler):
+ matcher = Qname(DNS64_TRIGGER) & Qtype(dns.rdatatype.A)
answer = [a()]
delay = 2.0
diff --git a/bin/tests/system/forward/ans6/ans.py b/bin/tests/system/forward/ans6/ans.py
index cdff896a69..89c08d0018 100644
--- a/bin/tests/system/forward/ans6/ans.py
+++ b/bin/tests/system/forward/ans6/ans.py
@@ -24,11 +24,8 @@ from isctest.asyncserver import (
)
from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.commands import ToggleResponsesCommand
-from isctest.asyncserver.handlers import (
- DomainHandler,
- QnameQtypeHandler,
- StaticResponseHandler,
-)
+from isctest.asyncserver.handlers import DomainHandler, StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
SLD = "sld.tld."
NS1 = f"ns1.{SLD}"
@@ -56,16 +53,14 @@ def soa(owner: dns.name.Name | str) -> dns.rrset.RRset:
return rrset(owner, dns.rdatatype.SOA, ". . 0 0 0 0 0")
-class Ns1AHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [NS1]
- qtypes = [dns.rdatatype.A]
+class Ns1AHandler(StaticResponseHandler):
+ matcher = Qname(NS1) & Qtype(dns.rdatatype.A)
answer = [a(NS1)]
edns = None
-class Ns1AaaaHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [NS1]
- qtypes = [dns.rdatatype.AAAA]
+class Ns1AaaaHandler(StaticResponseHandler):
+ matcher = Qname(NS1) & Qtype(dns.rdatatype.AAAA)
answer = [aaaa(NS1)]
edns = None
diff --git a/bin/tests/system/fwdfirst/ans3/ans.py b/bin/tests/system/fwdfirst/ans3/ans.py
index da2624995f..ad4ee7f321 100644
--- a/bin/tests/system/fwdfirst/ans3/ans.py
+++ b/bin/tests/system/fwdfirst/ans3/ans.py
@@ -15,7 +15,8 @@ import dns.rdatatype
import dns.rrset
from isctest.asyncserver import AsyncDnsServer
-from isctest.asyncserver.handlers import QnameQtypeHandler, StaticResponseHandler
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
VICTIM = "victim.sibling.hack."
POISON_ADDRESS = "6.6.6.6"
@@ -27,9 +28,8 @@ def a(name: str) -> dns.rrset.RRset:
)
-class PoisonedAHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [VICTIM]
- qtypes = [dns.rdatatype.A]
+class PoisonedAHandler(StaticResponseHandler):
+ matcher = Qname(VICTIM) & Qtype(dns.rdatatype.A)
answer = [a(VICTIM)]
diff --git a/bin/tests/system/isctest/asyncserver/handlers.py b/bin/tests/system/isctest/asyncserver/handlers.py
index 559790e7b1..9f6f18a0d3 100644
--- a/bin/tests/system/isctest/asyncserver/handlers.py
+++ b/bin/tests/system/isctest/asyncserver/handlers.py
@@ -188,45 +188,6 @@ class IgnoreAllQueries(ResponseHandler):
yield ResponseDrop()
-class QnameQtypeHandler(ResponseHandler):
- """
- Handle queries for which both of the following conditions are true:
-
- - the query's QNAME is present in `self.qnames`,
- - the query's QTYPE is present in `self.qtypes`.
- """
-
- @property
- @abc.abstractmethod
- def qnames(self) -> list[str]:
- """
- A list of QNAMEs handled by this class.
- """
- raise NotImplementedError
-
- @property
- @abc.abstractmethod
- def qtypes(self) -> list[dns.rdatatype.RdataType]:
- """
- A list of QTYPEs handled by this class.
- """
- raise NotImplementedError
-
- def __init__(self) -> None:
- self._qnames: list[dns.name.Name] = [dns.name.from_text(d) for d in self.qnames]
- self._qtypes: list[dns.rdatatype.RdataType] = self.qtypes
-
- def __str__(self) -> str:
- return f"{self.__class__.__name__}(QNAMEs: {', '.join(self.qnames)}; QTYPEs: {', '.join(map(str, self.qtypes))})"
-
- def match(self, qctx: QueryContext) -> bool:
- """
- Handle queries whose QNAME and QTYPE match any of the QNAMEs and
- QTYPEs handled by this class.
- """
- return qctx.qtype in self._qtypes and qctx.qname in self._qnames
-
-
class _UnsetEdnsType:
pass
diff --git a/bin/tests/system/mismatchtcp/ans2/ans.py b/bin/tests/system/mismatchtcp/ans2/ans.py
index 650b209f7d..d80a0dfc51 100644
--- a/bin/tests/system/mismatchtcp/ans2/ans.py
+++ b/bin/tests/system/mismatchtcp/ans2/ans.py
@@ -11,14 +11,19 @@
from collections.abc import AsyncGenerator
+import dns.name
import dns.rdatatype
-from isctest.asyncserver import AsyncDnsServer, DnsProtocol, QueryContext
+from isctest.asyncserver import (
+ AsyncDnsServer,
+ DnsProtocol,
+ QueryContext,
+ ResponseHandler,
+)
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import QnameQtypeHandler
-class MismatchedIdOnUdpHandler(QnameQtypeHandler):
+class MismatchedIdOnUdpHandler(ResponseHandler):
"""
Simulate Kaminsky-style off-path spoofing: answer every UDP query for
trigger.example./A with the correct response prepared from zone data,
@@ -28,11 +33,12 @@ class MismatchedIdOnUdpHandler(QnameQtypeHandler):
the correct answer.
"""
- qnames = ["trigger.example."]
- qtypes = [dns.rdatatype.A]
-
def match(self, qctx: QueryContext) -> bool:
- return qctx.protocol == DnsProtocol.UDP and super().match(qctx)
+ return (
+ qctx.qname == dns.name.from_text("trigger.example.")
+ and qctx.qtype == dns.rdatatype.A
+ and qctx.protocol == DnsProtocol.UDP
+ )
async def get_responses(
self, qctx: QueryContext
diff --git a/bin/tests/system/nsupdate/ans11/ans.py b/bin/tests/system/nsupdate/ans11/ans.py
index 114b518cda..13a27573c9 100644
--- a/bin/tests/system/nsupdate/ans11/ans.py
+++ b/bin/tests/system/nsupdate/ans11/ans.py
@@ -16,11 +16,8 @@ import dns.rdatatype
import dns.rrset
from isctest.asyncserver import AsyncDnsServer
-from isctest.asyncserver.handlers import (
- AxfrHandler,
- QnameQtypeHandler,
- StaticResponseHandler,
-)
+from isctest.asyncserver.handlers import AxfrHandler, StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
ZONE = "sigaxfr.nil."
NS_NAME = "ns.sigaxfr.nil."
@@ -60,13 +57,12 @@ def sig() -> dns.rrset.RRset:
)
-class SoaHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [ZONE]
- qtypes = [dns.rdatatype.SOA]
+class SoaHandler(StaticResponseHandler):
+ matcher = Qname(ZONE) & Qtype(dns.rdatatype.SOA)
answer = [soa()]
-class SigAxfrHandler(QnameQtypeHandler, AxfrHandler):
+class SigAxfrHandler(AxfrHandler):
"""
Serve an AXFR carrying two legacy SIG (24) rdatas at one owner whose
body "covered type" fields differ (A, MX); per RFC 3755 SIG has no
@@ -74,8 +70,7 @@ class SigAxfrHandler(QnameQtypeHandler, AxfrHandler):
in a single opaque rdataset.
"""
- qnames = [ZONE]
- qtypes = [dns.rdatatype.AXFR]
+ matcher = Qname(ZONE) & Qtype(dns.rdatatype.AXFR)
initial_soa = soa()
zone_contents = [
rrset(ZONE, dns.rdatatype.NS, NS_NAME),
diff --git a/bin/tests/system/resend_loop/ans3/ans.py b/bin/tests/system/resend_loop/ans3/ans.py
index 8ace998757..6dc750c644 100644
--- a/bin/tests/system/resend_loop/ans3/ans.py
+++ b/bin/tests/system/resend_loop/ans3/ans.py
@@ -20,12 +20,8 @@ import dns.rrset
from isctest.asyncserver import AsyncDnsServer, QueryContext
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import (
- DomainHandler,
- QnameQtypeHandler,
- StaticResponseHandler,
-)
-from isctest.asyncserver.matchers import Qname
+from isctest.asyncserver.handlers import DomainHandler, StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
def rrset(
@@ -37,16 +33,14 @@ def rrset(
return dns.rrset.from_text(qname, ttl, dns.rdataclass.IN, rtype, rdata)
-class RootNsHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["."]
- qtypes = [dns.rdatatype.NS]
+class RootNsHandler(StaticResponseHandler):
+ matcher = Qname(".") & Qtype(dns.rdatatype.NS)
answer = [rrset(".", dns.rdatatype.NS, "a.root-servers.nil.")]
additional = [rrset("a.root-servers.nil.", dns.rdatatype.A, "10.53.0.3")]
-class ExampleNsHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["example."]
- qtypes = [dns.rdatatype.NS]
+class ExampleNsHandler(StaticResponseHandler):
+ matcher = Qname("example.") & Qtype(dns.rdatatype.NS)
answer = [rrset("example.", dns.rdatatype.NS, "ns.example.")]
additional = [rrset("ns.example.", dns.rdatatype.A, "10.53.0.3")]
diff --git a/bin/tests/system/resolver/ans2/ans.py b/bin/tests/system/resolver/ans2/ans.py
index 1421340f61..7f8e446b3f 100644
--- a/bin/tests/system/resolver/ans2/ans.py
+++ b/bin/tests/system/resolver/ans2/ans.py
@@ -22,10 +22,9 @@ from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
IgnoreAllQueries,
- QnameQtypeHandler,
StaticResponseHandler,
)
-from isctest.asyncserver.matchers import Qname
+from isctest.asyncserver.matchers import Qname, Qtype
from ..resolver_ans import (
DelegationHandler,
@@ -39,12 +38,10 @@ from ..resolver_ans import (
)
-class BadGoodDnameNsHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = [
- "baddname.example.org.",
- "gooddname.example.org.",
- ]
- qtypes = [dns.rdatatype.NS]
+class BadGoodDnameNsHandler(StaticResponseHandler):
+ matcher = Qname("baddname.example.org.", "gooddname.example.org.") & Qtype(
+ dns.rdatatype.NS
+ )
answer = [rrset("example.org.", dns.rdatatype.NS, "a.root-servers.nil.")]
authoritative = True
@@ -98,16 +95,10 @@ class NoResponseExampleUdpHandler(IgnoreAllQueries):
matcher = Qname("noresponse.exampleudp.net.")
-class RootNsHandler(QnameQtypeHandler):
- qnames = [
- "example.com.",
- "com.",
- "example.org.",
- "org.",
- "net.",
- ]
-
- qtypes = [dns.rdatatype.NS]
+class RootNsHandler(ResponseHandler):
+ matcher = Qname("example.com.", "com.", "example.org.", "org.", "net.") & Qtype(
+ dns.rdatatype.NS
+ )
async def get_responses(
self, qctx: QueryContext
diff --git a/bin/tests/system/resolver/ans3/ans.py b/bin/tests/system/resolver/ans3/ans.py
index a819b6c1f6..e53ac71796 100644
--- a/bin/tests/system/resolver/ans3/ans.py
+++ b/bin/tests/system/resolver/ans3/ans.py
@@ -20,10 +20,9 @@ from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
IgnoreAllQueries,
- QnameQtypeHandler,
StaticResponseHandler,
)
-from isctest.asyncserver.matchers import Qname
+from isctest.asyncserver.matchers import Qname, Qtype
from ..resolver_ans import (
DelegationHandler,
@@ -37,11 +36,18 @@ from ..resolver_ans import (
)
-class ApexNSHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["example.net."]
- qtypes = [dns.rdatatype.NS]
- answer = [rrset(qnames[0], dns.rdatatype.NS, f"ns.{qnames[0]}")]
- additional = [rrset(f"ns.{qnames[0]}", dns.rdatatype.A, "10.53.0.3")]
+class ApexNSHandler(StaticResponseHandler):
+ matcher = Qname("example.net.") & Qtype(dns.rdatatype.NS)
+ answer = [
+ rrset(
+ matcher.of(Qname).qnames[0],
+ dns.rdatatype.NS,
+ f"ns.{matcher.of(Qname).qnames[0]}",
+ )
+ ]
+ additional = [
+ rrset(f"ns.{matcher.of(Qname).qnames[0]}", dns.rdatatype.A, "10.53.0.3")
+ ]
class AttackDnameHandler(StaticResponseHandler):
@@ -54,9 +60,10 @@ class BadCnameHandler(StaticResponseHandler):
answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "badcname.example.org.")]
-class BadGoodDnameNsHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["baddname.example.net.", "gooddname.example.net."]
- qtypes = [dns.rdatatype.NS]
+class BadGoodDnameNsHandler(StaticResponseHandler):
+ matcher = Qname("baddname.example.net.", "gooddname.example.net.") & Qtype(
+ dns.rdatatype.NS
+ )
authority = [soa_rrset("example.net.")]
@@ -65,10 +72,11 @@ class CnameSubHandler(StaticResponseHandler):
answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "ok.sub.example.org.")]
-class ExampleOrgHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["example.org."]
- qtypes = [dns.rdatatype.A]
- answer = [rrset(qnames[0], qtypes[0], "1.2.3.4")]
+class ExampleOrgHandler(StaticResponseHandler):
+ matcher = Qname("example.org.") & Qtype(dns.rdatatype.A)
+ answer = [
+ rrset(matcher.of(Qname).qnames[0], matcher.of(Qtype).qtypes[0], "1.2.3.4")
+ ]
class FooBadDnameHandler(StaticResponseHandler):
@@ -100,10 +108,11 @@ class GoodCnameHandler(StaticResponseHandler):
answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "goodcname.example.org.")]
-class IscHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["isc.org."]
- qtypes = [dns.rdatatype.A]
- answer = [rrset(qnames[0], qtypes[0], "1.2.3.4")]
+class IscHandler(StaticResponseHandler):
+ matcher = Qname("isc.org.") & Qtype(dns.rdatatype.A)
+ answer = [
+ rrset(matcher.of(Qname).qnames[0], matcher.of(Qtype).qtypes[0], "1.2.3.4")
+ ]
class LameExampleOrgDelegation(DelegationHandler):
@@ -111,12 +120,11 @@ class LameExampleOrgDelegation(DelegationHandler):
server_number = 3
-class LargeReferralHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["large-referral.example.net."]
- qtypes = [dns.rdatatype.NS]
+class LargeReferralHandler(StaticResponseHandler):
+ matcher = Qname("large-referral.example.net.") & Qtype(dns.rdatatype.NS)
authority = [
rrset_from_list(
- qnames[0],
+ matcher.of(Qname).qnames[0],
dns.rdatatype.NS,
[f"ns{i}.fake.redirect.com." for i in range(1, 1000)],
)
diff --git a/bin/tests/system/resolver/ans8/ans.py b/bin/tests/system/resolver/ans8/ans.py
index d11cfc7af6..b5506aedca 100644
--- a/bin/tests/system/resolver/ans8/ans.py
+++ b/bin/tests/system/resolver/ans8/ans.py
@@ -26,12 +26,8 @@ from isctest.asyncserver import (
ResponseHandler,
)
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import (
- DomainHandler,
- QnameQtypeHandler,
- StaticResponseHandler,
-)
-from isctest.asyncserver.matchers import Qname
+from isctest.asyncserver.handlers import DomainHandler, StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
from ..resolver_ans import rrset
@@ -86,11 +82,18 @@ class FormerrToAllHandler(DomainHandler, StaticResponseHandler):
rcode = dns.rcode.FORMERR
-class NoQuestionsNSHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["no-questions."]
- qtypes = [dns.rdatatype.NS]
- answer = [rrset(qnames[0], dns.rdatatype.NS, f"ns.{qnames[0]}")]
- additional = [rrset(f"ns.{qnames[0]}", dns.rdatatype.A, "10.53.0.8")]
+class NoQuestionsNSHandler(StaticResponseHandler):
+ matcher = Qname("no-questions.") & Qtype(dns.rdatatype.NS)
+ answer = [
+ rrset(
+ matcher.of(Qname).qnames[0],
+ dns.rdatatype.NS,
+ f"ns.{matcher.of(Qname).qnames[0]}",
+ )
+ ]
+ additional = [
+ rrset(f"ns.{matcher.of(Qname).qnames[0]}", dns.rdatatype.A, "10.53.0.8")
+ ]
class NsNoQuestionsAHandler(ResponseHandler):
diff --git a/bin/tests/system/serve_stale/ans2/ans.py b/bin/tests/system/serve_stale/ans2/ans.py
index 417fb9944d..e01d93841f 100644
--- a/bin/tests/system/serve_stale/ans2/ans.py
+++ b/bin/tests/system/serve_stale/ans2/ans.py
@@ -14,8 +14,8 @@ import dns.rdatatype
from isctest.asyncserver import ControllableAsyncDnsServer, ResponseHandler
from isctest.asyncserver.commands import ToggleResponsesCommand
-from isctest.asyncserver.handlers import QnameQtypeHandler, StaticResponseHandler
-from isctest.asyncserver.matchers import Qname
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname, Qtype
from ..serve_stale_ans import (
a_handler,
@@ -51,9 +51,8 @@ class LongttlNxdomainExampleHandler(StaticResponseHandler):
authority = [soa("example.", ttl=600, minimum=600)]
-class OthertypeExampleCaaHandler(QnameQtypeHandler, StaticResponseHandler):
- qnames = ["othertype.example."]
- qtypes = [dns.rdatatype.CAA]
+class OthertypeExampleCaaHandler(StaticResponseHandler):
+ matcher = Qname("othertype.example.") & Qtype(dns.rdatatype.CAA)
answer = [
rrset(
"othertype.example.",
diff --git a/bin/tests/system/srtt/srtt_ans.py b/bin/tests/system/srtt/srtt_ans.py
index 0433604e64..55f9d88bd1 100644
--- a/bin/tests/system/srtt/srtt_ans.py
+++ b/bin/tests/system/srtt/srtt_ans.py
@@ -17,12 +17,12 @@ import dns.rdataclass
import dns.rdatatype
import dns.rrset
-from isctest.asyncserver import QueryContext
+from isctest.asyncserver import QueryContext, ResponseHandler
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import QnameQtypeHandler
+from isctest.asyncserver.matchers import Qname, Qtype
-class DelayedQnameRangeHandler(QnameQtypeHandler):
+class DelayedQnameRangeHandler(ResponseHandler):
"""
Respond to queries for QNAMEs "foo1.example." through "foo<N>.example."
with QTYPE=A, where <N> must be defined by the subclass. Every response is
@@ -30,11 +30,10 @@ class DelayedQnameRangeHandler(QnameQtypeHandler):
by the subclass.
"""
- @property
- def qnames(self) -> list[str]:
- return [f"foo{x}.example." for x in range(1, self.max_qname + 1)]
-
- qtypes = [dns.rdatatype.A]
+ def __init__(self) -> None:
+ self.matcher = Qname(
+ *(f"foo{x}.example." for x in range(1, self.max_qname + 1))
+ ) & Qtype(dns.rdatatype.A)
@property
@abc.abstractmethod