Commit c0f7610af0 for bind
commit c0f7610af04c73570464312e1d868f22f635ac66
Author: Štěpán Balážik <stepan@isc.org>
Date: Tue Sep 8 19:33:57 2026 +0200
Replace QnameHandler with a matcher
QnameHandler existed only to match on a list of QNAMEs; its users now
declare `Qname(...)` themselves.
Assisted-by: Claude:claude-fable-5
diff --git a/bin/tests/system/isctest/asyncserver/handlers.py b/bin/tests/system/isctest/asyncserver/handlers.py
index 797da2a90f..6acdd1964d 100644
--- a/bin/tests/system/isctest/asyncserver/handlers.py
+++ b/bin/tests/system/isctest/asyncserver/handlers.py
@@ -187,13 +187,12 @@ class IgnoreAllQueries(ResponseHandler):
yield ResponseDrop()
-class QnameHandler(ResponseHandler):
+class QnameQtypeHandler(ResponseHandler):
"""
- Base class used for deriving custom QNAME handlers.
+ Handle queries for which both of the following conditions are true:
- The derived class must specify a list of `qnames` that it wants to handle.
- Queries for exactly these QNAMEs will then be passed to the
- `get_response()` method in the derived class.
+ - the query's QNAME is present in `self.qnames`,
+ - the query's QTYPE is present in `self.qtypes`.
"""
@property
@@ -204,28 +203,6 @@ class QnameHandler(ResponseHandler):
"""
raise NotImplementedError
- def __init__(self) -> None:
- self._qnames: list[dns.name.Name] = [dns.name.from_text(d) for d in self.qnames]
-
- def __str__(self) -> str:
- return f"{self.__class__.__name__}(QNAMEs: {', '.join(self.qnames)})"
-
- def match(self, qctx: QueryContext) -> bool:
- """
- Handle queries whose QNAME matches any of the QNAMEs handled by this
- class.
- """
- return qctx.qname in self._qnames
-
-
-class QnameQtypeHandler(QnameHandler):
- """
- 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 qtypes(self) -> list[dns.rdatatype.RdataType]:
@@ -235,7 +212,7 @@ class QnameQtypeHandler(QnameHandler):
raise NotImplementedError
def __init__(self) -> None:
- super().__init__()
+ 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:
@@ -246,7 +223,7 @@ class QnameQtypeHandler(QnameHandler):
Handle queries whose QNAME and QTYPE match any of the QNAMEs and
QTYPEs handled by this class.
"""
- return qctx.qtype in self._qtypes and super().match(qctx)
+ return qctx.qtype in self._qtypes and qctx.qname in self._qnames
class _UnsetEdnsType:
diff --git a/bin/tests/system/isctest/asyncserver/matchers.py b/bin/tests/system/isctest/asyncserver/matchers.py
index 27ece151a7..60a8151f41 100644
--- a/bin/tests/system/isctest/asyncserver/matchers.py
+++ b/bin/tests/system/isctest/asyncserver/matchers.py
@@ -11,6 +11,8 @@
import abc
+import dns.name
+
from .context import QueryContext
@@ -106,3 +108,21 @@ class Always(Matcher):
def match(self, qctx: QueryContext) -> bool:
return True
+
+
+class Qname(Matcher):
+ """
+ Match queries whose QNAME is one of the given names.
+ """
+
+ def __init__(self, *qnames: str | dns.name.Name) -> None:
+ self.qnames = [
+ name if isinstance(name, dns.name.Name) else dns.name.from_text(name)
+ for name in qnames
+ ]
+
+ def match(self, qctx: QueryContext) -> bool:
+ return qctx.qname in self.qnames
+
+ def __str__(self) -> str:
+ return f"QNAME in [{', '.join(str(name) for name in self.qnames)}]"
diff --git a/bin/tests/system/qpcache_rrsig_any/ans3/ans.py b/bin/tests/system/qpcache_rrsig_any/ans3/ans.py
index 8f47757163..c0a6e34153 100644
--- a/bin/tests/system/qpcache_rrsig_any/ans3/ans.py
+++ b/bin/tests/system/qpcache_rrsig_any/ans3/ans.py
@@ -19,7 +19,8 @@ import dns.rrset
from isctest.asyncserver import AsyncDnsServer, QueryContext, ResponseHandler
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import QnameHandler, StaticResponseHandler
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname
def rrsig_covering(
@@ -35,7 +36,7 @@ def rrsig_covering(
)
-class RrsigCoversRrsigHandler(QnameHandler, StaticResponseHandler):
+class RrsigCoversRrsigHandler(StaticResponseHandler):
"""
An RRSIG covering RRSIG only trips the QP-cache RRSIG-pairing assertion when
a second RRSIG header shares the owner name, so serve two ordinary RRSIGs
@@ -43,11 +44,11 @@ class RrsigCoversRrsigHandler(QnameHandler, StaticResponseHandler):
RRSIG-covers-RRSIG record is cached harmlessly.
"""
- qnames = ["rrsig.attacker.test."]
+ matcher = Qname("rrsig.attacker.test.")
answer = [
- rrsig_covering(qnames[0], dns.rdatatype.A),
- rrsig_covering(qnames[0], dns.rdatatype.AAAA),
- rrsig_covering(qnames[0], dns.rdatatype.RRSIG),
+ rrsig_covering(matcher.qnames[0], dns.rdatatype.A),
+ rrsig_covering(matcher.qnames[0], dns.rdatatype.AAAA),
+ rrsig_covering(matcher.qnames[0], dns.rdatatype.RRSIG),
]
diff --git a/bin/tests/system/reclimit/reclimit_ans.py b/bin/tests/system/reclimit/reclimit_ans.py
index 3c35d0b489..230a57b210 100644
--- a/bin/tests/system/reclimit/reclimit_ans.py
+++ b/bin/tests/system/reclimit/reclimit_ans.py
@@ -29,16 +29,16 @@ from isctest.asyncserver import (
ResponseHandler,
)
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import QnameHandler
+from isctest.asyncserver.matchers import Qname
-class ReclimitStateHandler(QnameHandler):
+class ReclimitStateHandler(ResponseHandler):
"""
Handler for the "count." and "reset." queries that also holds the state
shared by all the handlers in one server.
"""
- qnames = ["count.", "reset."]
+ matcher = Qname("count.", "reset.")
def __init__(self, indirect_send_response_default: bool = True) -> None:
self._indirect_send_response_default = indirect_send_response_default
@@ -128,8 +128,8 @@ def ns(owner: str | dns.name.Name, target: str | dns.name.Name) -> dns.rrset.RRs
)
-class DirectExampleHandler(ReclimitHandler, QnameHandler):
- qnames = ["direct.example.org", "direct.example.net"]
+class DirectExampleHandler(ReclimitHandler):
+ matcher = Qname("direct.example.org", "direct.example.net")
def __init__(
self, state_handler: ReclimitStateHandler, local_ns_number: int
@@ -145,8 +145,8 @@ class DirectExampleHandler(ReclimitHandler, QnameHandler):
yield DnsResponseSend(qctx.response)
-class IndirectExampleOrgHandler(ReclimitHandler, QnameHandler):
- qnames = [f"indirect{i}.example.org" for i in range(1, 9)]
+class IndirectExampleOrgHandler(ReclimitHandler):
+ matcher = Qname(*[f"indirect{i}.example.org" for i in range(1, 9)])
def __init__(
self, state_handler: ReclimitStateHandler, local_ns_number: int
diff --git a/bin/tests/system/resend_loop/ans3/ans.py b/bin/tests/system/resend_loop/ans3/ans.py
index 393ba43d99..8ace998757 100644
--- a/bin/tests/system/resend_loop/ans3/ans.py
+++ b/bin/tests/system/resend_loop/ans3/ans.py
@@ -22,10 +22,10 @@ from isctest.asyncserver import AsyncDnsServer, QueryContext
from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
- QnameHandler,
QnameQtypeHandler,
StaticResponseHandler,
)
+from isctest.asyncserver.matchers import Qname
def rrset(
@@ -78,8 +78,8 @@ class ExampleCookieHandler(DomainHandler):
yield DnsResponseSend(qctx.response)
-class TestDotComServFailHandler(QnameHandler, StaticResponseHandler):
- qnames = ["test.com."]
+class TestDotComServFailHandler(StaticResponseHandler):
+ matcher = Qname("test.com.")
authoritative = False
rcode = dns.rcode.SERVFAIL
diff --git a/bin/tests/system/resolver/ans2/ans.py b/bin/tests/system/resolver/ans2/ans.py
index 1c9aebe22a..1421340f61 100644
--- a/bin/tests/system/resolver/ans2/ans.py
+++ b/bin/tests/system/resolver/ans2/ans.py
@@ -22,10 +22,10 @@ from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
IgnoreAllQueries,
- QnameHandler,
QnameQtypeHandler,
StaticResponseHandler,
)
+from isctest.asyncserver.matchers import Qname
from ..resolver_ans import (
DelegationHandler,
@@ -58,28 +58,28 @@ def _cname_rrsets(
)
-class Cname1Handler(QnameHandler, StaticResponseHandler):
- qnames = ["cname1.example.com."]
+class Cname1Handler(StaticResponseHandler):
+ matcher = Qname("cname1.example.com.")
# Data for the "cname + other data / 1" test
- answer = _cname_rrsets(qnames[0])
+ answer = _cname_rrsets(matcher.qnames[0])
authoritative = False
-class Cname2Handler(QnameHandler, StaticResponseHandler):
- qnames = ["cname2.example.com."]
+class Cname2Handler(StaticResponseHandler):
+ matcher = Qname("cname2.example.com.")
# Data for the "cname + other data / 2" test: same RRs in opposite order
- answer = tuple(reversed(_cname_rrsets(qnames[0])))
+ answer = tuple(reversed(_cname_rrsets(matcher.qnames[0])))
authoritative = False
-class ExampleOrgHandler(QnameHandler):
- qnames = [
+class ExampleOrgHandler(ResponseHandler):
+ matcher = Qname(
"www.example.org",
"badcname.example.org",
"goodcname.example.org",
"foo.baddname.example.org",
"foo.gooddname.example.org",
- ]
+ )
async def get_responses(
self, qctx: QueryContext
@@ -94,8 +94,8 @@ class ExampleOrgHandler(QnameHandler):
yield DnsResponseSend(qctx.response, authoritative=True)
-class NoResponseExampleUdpHandler(QnameHandler, IgnoreAllQueries):
- qnames = ["noresponse.exampleudp.net."]
+class NoResponseExampleUdpHandler(IgnoreAllQueries):
+ matcher = Qname("noresponse.exampleudp.net.")
class RootNsHandler(QnameQtypeHandler):
@@ -117,8 +117,8 @@ class RootNsHandler(QnameQtypeHandler):
yield DnsResponseSend(qctx.response, authoritative=True)
-class ZoneVersionHandler(QnameHandler):
- qnames = ["zoneversion."]
+class ZoneVersionHandler(ResponseHandler):
+ matcher = Qname("zoneversion.")
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 e4c92b1fa0..a819b6c1f6 100644
--- a/bin/tests/system/resolver/ans3/ans.py
+++ b/bin/tests/system/resolver/ans3/ans.py
@@ -20,10 +20,10 @@ from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
IgnoreAllQueries,
- QnameHandler,
QnameQtypeHandler,
StaticResponseHandler,
)
+from isctest.asyncserver.matchers import Qname
from ..resolver_ans import (
DelegationHandler,
@@ -44,14 +44,14 @@ class ApexNSHandler(QnameQtypeHandler, StaticResponseHandler):
additional = [rrset(f"ns.{qnames[0]}", dns.rdatatype.A, "10.53.0.3")]
-class AttackDnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["www.example.attack.example.net", "isc.attack.example.net."]
+class AttackDnameHandler(StaticResponseHandler):
+ matcher = Qname("www.example.attack.example.net", "isc.attack.example.net.")
answer = [rrset("attack.example.net.", dns.rdatatype.DNAME, "org.")]
-class BadCnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["badcname.example.net."]
- answer = [rrset(qnames[0], dns.rdatatype.CNAME, "badcname.example.org.")]
+class BadCnameHandler(StaticResponseHandler):
+ matcher = Qname("badcname.example.net.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "badcname.example.org.")]
class BadGoodDnameNsHandler(QnameQtypeHandler, StaticResponseHandler):
@@ -60,9 +60,9 @@ class BadGoodDnameNsHandler(QnameQtypeHandler, StaticResponseHandler):
authority = [soa_rrset("example.net.")]
-class CnameSubHandler(QnameHandler, StaticResponseHandler):
- qnames = ["cname.sub.example.org."]
- answer = [rrset(qnames[0], dns.rdatatype.CNAME, "ok.sub.example.org.")]
+class CnameSubHandler(StaticResponseHandler):
+ matcher = Qname("cname.sub.example.org.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "ok.sub.example.org.")]
class ExampleOrgHandler(QnameQtypeHandler, StaticResponseHandler):
@@ -71,33 +71,33 @@ class ExampleOrgHandler(QnameQtypeHandler, StaticResponseHandler):
answer = [rrset(qnames[0], qtypes[0], "1.2.3.4")]
-class FooBadDnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["foo.baddname.example.net."]
+class FooBadDnameHandler(StaticResponseHandler):
+ matcher = Qname("foo.baddname.example.net.")
answer = [
rrset("baddname.example.net.", dns.rdatatype.DNAME, "baddname.example.org.")
]
-class FooBarSubTld1Handler(QnameHandler, StaticResponseHandler):
- qnames = ["foo.bar.sub.tld1."]
- answer = [rrset(qnames[0], dns.rdatatype.TXT, "baz")]
+class FooBarSubTld1Handler(StaticResponseHandler):
+ matcher = Qname("foo.bar.sub.tld1.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.TXT, "baz")]
-class FooGlueInAnswerHandler(QnameHandler, StaticResponseHandler):
- qnames = ["foo.glue-in-answer.example.org."]
- answer = [rrset(qnames[0], dns.rdatatype.A, "192.0.2.1")]
+class FooGlueInAnswerHandler(StaticResponseHandler):
+ matcher = Qname("foo.glue-in-answer.example.org.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.A, "192.0.2.1")]
-class FooGoodDnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["foo.gooddname.example.net."]
+class FooGoodDnameHandler(StaticResponseHandler):
+ matcher = Qname("foo.gooddname.example.net.")
answer = [
rrset("gooddname.example.net.", dns.rdatatype.DNAME, "gooddname.example.org.")
]
-class GoodCnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["goodcname.example.net."]
- answer = [rrset(qnames[0], dns.rdatatype.CNAME, "goodcname.example.org.")]
+class GoodCnameHandler(StaticResponseHandler):
+ matcher = Qname("goodcname.example.net.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.CNAME, "goodcname.example.org.")]
class IscHandler(QnameQtypeHandler, StaticResponseHandler):
@@ -138,26 +138,26 @@ class LongCnameHandler(ResponseHandler):
yield DnsResponseSend(qctx.response)
-class NodataHandler(QnameHandler, StaticResponseHandler):
- qnames = ["nodata.example.net."]
+class NodataHandler(StaticResponseHandler):
+ matcher = Qname("nodata.example.net.")
-class NoresponseHandler(QnameHandler, IgnoreAllQueries):
- qnames = ["noresponse.example.net."]
+class NoresponseHandler(IgnoreAllQueries):
+ matcher = Qname("noresponse.example.net.")
-class NsHandler(QnameHandler, StaticResponseHandler):
- qnames = ["ns.example.net."]
- answer = [rrset(qnames[0], dns.rdatatype.A, "10.53.0.3")]
+class NsHandler(StaticResponseHandler):
+ matcher = Qname("ns.example.net.")
+ answer = [rrset(matcher.qnames[0], dns.rdatatype.A, "10.53.0.3")]
-class NxdomainHandler(QnameHandler, StaticResponseHandler):
- qnames = ["nxdomain.example.net."]
+class NxdomainHandler(StaticResponseHandler):
+ matcher = Qname("nxdomain.example.net.")
rcode = dns.rcode.NXDOMAIN
-class OkSubHandler(QnameHandler):
- qnames = ["ok.sub.example.org.", "www.ok.sub.example.org."]
+class OkSubHandler(ResponseHandler):
+ matcher = Qname("ok.sub.example.org.", "www.ok.sub.example.org.")
async def get_responses(
self, qctx: QueryContext
@@ -178,20 +178,20 @@ class PartialFormerrHandler(DomainHandler):
yield DnsResponseSend(qctx.response)
-class WwwDnameSubHandler(QnameHandler, StaticResponseHandler):
- qnames = ["www.dname.sub.example.org."]
+class WwwDnameSubHandler(StaticResponseHandler):
+ matcher = Qname("www.dname.sub.example.org.")
answer = [
rrset("dname.sub.example.org.", dns.rdatatype.DNAME, "ok.sub.example.org.")
]
-class WwwGoodDnameHandler(QnameHandler, StaticResponseHandler):
- qnames = ["www.example.gooddname.example.net"]
+class WwwGoodDnameHandler(StaticResponseHandler):
+ matcher = Qname("www.example.gooddname.example.net")
answer = [rrset("gooddname.example.net.", dns.rdatatype.DNAME, "org.")]
-class WwwHandler(QnameHandler):
- qnames = ["www.example.net."]
+class WwwHandler(ResponseHandler):
+ matcher = Qname("www.example.net.")
async def get_responses(
self, qctx: QueryContext
diff --git a/bin/tests/system/resolver/ans8/ans.py b/bin/tests/system/resolver/ans8/ans.py
index 446aa428ed..d11cfc7af6 100644
--- a/bin/tests/system/resolver/ans8/ans.py
+++ b/bin/tests/system/resolver/ans8/ans.py
@@ -15,6 +15,7 @@ import abc
import dns.flags
import dns.message
+import dns.name
import dns.rcode
import dns.rdatatype
@@ -27,10 +28,10 @@ from isctest.asyncserver import (
from isctest.asyncserver.actions import DnsResponseSend
from isctest.asyncserver.handlers import (
DomainHandler,
- QnameHandler,
QnameQtypeHandler,
StaticResponseHandler,
)
+from isctest.asyncserver.matchers import Qname
from ..resolver_ans import rrset
@@ -59,13 +60,14 @@ class HeaderOnlyHandler(ResponseHandler):
yield DnsResponseSend(message, acknowledge_hand_rolled_response=True)
-class RefusedOnTcpHandler(QnameHandler, HeaderOnlyHandler):
- qnames = ["tcpalso.no-questions."]
+class RefusedOnTcpHandler(HeaderOnlyHandler):
flags = dns.flags.QR
rcode = dns.rcode.REFUSED
def match(self, qctx: QueryContext) -> bool:
- return qctx.protocol == DnsProtocol.TCP and super().match(qctx)
+ return qctx.protocol == DnsProtocol.TCP and qctx.qname == dns.name.from_text(
+ "tcpalso.no-questions."
+ )
class TcpFallbackHandler(ResponseHandler):
@@ -91,8 +93,8 @@ class NoQuestionsNSHandler(QnameQtypeHandler, StaticResponseHandler):
additional = [rrset(f"ns.{qnames[0]}", dns.rdatatype.A, "10.53.0.8")]
-class NsNoQuestionsAHandler(QnameHandler):
- qnames = ["ns.no-questions."]
+class NsNoQuestionsAHandler(ResponseHandler):
+ matcher = Qname("ns.no-questions.")
async def get_responses(
self, qctx: QueryContext
@@ -103,14 +105,14 @@ class NsNoQuestionsAHandler(QnameHandler):
yield DnsResponseSend(qctx.response)
-class TcpalsoNoQuestionsHandler(QnameHandler, HeaderOnlyHandler):
- qnames = ["tcpalso.no-questions."]
+class TcpalsoNoQuestionsHandler(HeaderOnlyHandler):
+ matcher = Qname("tcpalso.no-questions.")
flags = dns.flags.QR | dns.flags.TC
rcode = dns.rcode.REFUSED
-class TruncatedNoQuestionsHandler(QnameHandler, HeaderOnlyHandler):
- qnames = ["truncated.no-questions."]
+class TruncatedNoQuestionsHandler(HeaderOnlyHandler):
+ matcher = Qname("truncated.no-questions.")
flags = dns.flags.QR | dns.flags.AA | dns.flags.TC
diff --git a/bin/tests/system/resolver/resolver_ans.py b/bin/tests/system/resolver/resolver_ans.py
index d81a67e0d6..cd1d3b1d6a 100644
--- a/bin/tests/system/resolver/resolver_ans.py
+++ b/bin/tests/system/resolver/resolver_ans.py
@@ -19,9 +19,10 @@ 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 DomainHandler, QnameHandler
+from isctest.asyncserver.handlers import DomainHandler
+from isctest.asyncserver.matchers import Qname
def rrset(
@@ -84,8 +85,8 @@ class DelegationHandler(DomainHandler):
yield DnsResponseSend(qctx.response, authoritative=False)
-class Gl6412AHandler(QnameHandler):
- qnames = ["a.gl6412.", "a.a.gl6412."]
+class Gl6412AHandler(ResponseHandler):
+ matcher = Qname("a.gl6412.", "a.a.gl6412.")
async def get_responses(
self, qctx: QueryContext
@@ -94,8 +95,8 @@ class Gl6412AHandler(QnameHandler):
yield DnsResponseSend(qctx.response)
-class Gl6412Handler(QnameHandler):
- qnames = ["gl6412."]
+class Gl6412Handler(ResponseHandler):
+ matcher = Qname("gl6412.")
async def get_responses(
self, qctx: QueryContext
@@ -112,8 +113,8 @@ class Gl6412Handler(QnameHandler):
yield DnsResponseSend(qctx.response)
-class Gl6412Ns2Handler(QnameHandler):
- qnames = ["ns2.gl6412."]
+class Gl6412Ns2Handler(ResponseHandler):
+ matcher = Qname("ns2.gl6412.")
async def get_responses(
self, qctx: QueryContext
@@ -126,8 +127,8 @@ class Gl6412Ns2Handler(QnameHandler):
yield DnsResponseSend(qctx.response)
-class Gl6412Ns3Handler(QnameHandler):
- qnames = ["ns3.gl6412."]
+class Gl6412Ns3Handler(ResponseHandler):
+ matcher = Qname("ns3.gl6412.")
async def get_responses(
self, qctx: QueryContext
diff --git a/bin/tests/system/serve_stale/ans2/ans.py b/bin/tests/system/serve_stale/ans2/ans.py
index add5b14d9e..417fb9944d 100644
--- a/bin/tests/system/serve_stale/ans2/ans.py
+++ b/bin/tests/system/serve_stale/ans2/ans.py
@@ -14,11 +14,8 @@ import dns.rdatatype
from isctest.asyncserver import ControllableAsyncDnsServer, ResponseHandler
from isctest.asyncserver.commands import ToggleResponsesCommand
-from isctest.asyncserver.handlers import (
- QnameHandler,
- QnameQtypeHandler,
- StaticResponseHandler,
-)
+from isctest.asyncserver.handlers import QnameQtypeHandler, StaticResponseHandler
+from isctest.asyncserver.matchers import Qname
from ..serve_stale_ans import (
a_handler,
@@ -34,8 +31,8 @@ from ..serve_stale_ans import (
)
-class NxdomainExampleHandler(QnameHandler, StaticResponseHandler):
- qnames = ["nxdomain.example."]
+class NxdomainExampleHandler(StaticResponseHandler):
+ matcher = Qname("nxdomain.example.")
rcode = dns.rcode.NXDOMAIN
authority = [soa("example.", ttl=2)]
@@ -43,13 +40,13 @@ class NxdomainExampleHandler(QnameHandler, StaticResponseHandler):
# A negative answer that stays fresh for the whole run of a test, so that a
# resolver refreshing it can only be doing so because it wrongly considers
# the cached entry stale.
-class LongttlNodataExampleHandler(QnameHandler, StaticResponseHandler):
- qnames = ["longttl-nodata.example."]
+class LongttlNodataExampleHandler(StaticResponseHandler):
+ matcher = Qname("longttl-nodata.example.")
authority = [soa("example.", ttl=600, minimum=600)]
-class LongttlNxdomainExampleHandler(QnameHandler, StaticResponseHandler):
- qnames = ["longttl-nxdomain.example."]
+class LongttlNxdomainExampleHandler(StaticResponseHandler):
+ matcher = Qname("longttl-nxdomain.example.")
rcode = dns.rcode.NXDOMAIN
authority = [soa("example.", ttl=600, minimum=600)]
@@ -67,8 +64,8 @@ class OthertypeExampleCaaHandler(QnameQtypeHandler, StaticResponseHandler):
]
-class SourceStaleFallbackHandler(QnameHandler, StaticResponseHandler):
- qnames = ["source.stale."]
+class SourceStaleFallbackHandler(StaticResponseHandler):
+ matcher = Qname("source.stale.")
def handlers() -> list[ResponseHandler]:
diff --git a/bin/tests/system/serve_stale/ans8/ans.py b/bin/tests/system/serve_stale/ans8/ans.py
index 1573dee6d6..3307160389 100644
--- a/bin/tests/system/serve_stale/ans8/ans.py
+++ b/bin/tests/system/serve_stale/ans8/ans.py
@@ -13,7 +13,8 @@ import dns.rcode
from isctest.asyncserver import ControllableAsyncDnsServer, ResponseHandler
from isctest.asyncserver.commands import SwitchControlCommand
-from isctest.asyncserver.handlers import QnameHandler, StaticResponseHandler
+from isctest.asyncserver.handlers import StaticResponseHandler
+from isctest.asyncserver.matchers import Qname
from ..serve_stale_ans import (
a_handler,
@@ -26,8 +27,8 @@ from ..serve_stale_ans import (
ANS8_ADDR = "10.53.0.8"
-class TargetStaleFallbackHandler(QnameHandler, StaticResponseHandler):
- qnames = ["target.stale."]
+class TargetStaleFallbackHandler(StaticResponseHandler):
+ matcher = Qname("target.stale.")
def handlers(www_address: str) -> list[ResponseHandler]:
diff --git a/bin/tests/system/statistics/ans4/ans.py b/bin/tests/system/statistics/ans4/ans.py
index 37fea5fcd5..a979d83e23 100644
--- a/bin/tests/system/statistics/ans4/ans.py
+++ b/bin/tests/system/statistics/ans4/ans.py
@@ -17,11 +17,12 @@ import dns.rrset
from isctest.asyncserver import AsyncDnsServer, QueryContext, ResponseHandler
from isctest.asyncserver.actions import DnsResponseSend
-from isctest.asyncserver.handlers import IgnoreAllQueries, QnameHandler
+from isctest.asyncserver.handlers import IgnoreAllQueries
+from isctest.asyncserver.matchers import Qname
-class FooInfoHandler(QnameHandler, IgnoreAllQueries):
- qnames = ["foo.info."]
+class FooInfoHandler(IgnoreAllQueries):
+ matcher = Qname("foo.info.")
class FallbackHandler(ResponseHandler):