wip: tighten watcher assertions, document loopback nameservers
check / check (push) Failing after 12s

This commit is contained in:
clawbot
2026-09-03 22:53:50 +00:00
parent 240c1bd393
commit 15f148f066
3 changed files with 277 additions and 25 deletions
+36
View File
@@ -39,6 +39,42 @@ assertions and sensible timeouts, not from mocks.
running at once the gates sum instead of holding, and the resolver's
per-attempt deadlines start expiring
### Transport failures: loopback nameservers, not mocks
The resolver classifies a nameserver that stays silent as
`StatusTimeout` and one that answers SERVFAIL as `StatusError`. The
public network cannot be made to produce either on demand — a
black-holed address is only black-holed on some networks, and build
environments that transparently intercept UDP/53 answer it locally —
so a test built on a chosen remote address asserts on the network it
happens to run on rather than on the resolver.
`internal/resolver/transport_test.go` binds a real nameserver on
`127.0.0.1` instead and points the query at it.
`nameserverAddr` dials an address that already carries a port as
written, so no production behaviour is bypassed to arrange this.
**This is permitted, and it is not a mock.** The rule above bans
substituting `DNSClient` or any other DNS abstraction, which lets the
code under test skip DNS and hands it a manufactured verdict. A
loopback nameserver does the opposite: the resolver dials a real
socket, writes a real query with the real `miekg/dns` client, and
applies its real deadline and its real classification logic to what
comes back. Choosing which nameserver a live query is sent to is not
faking DNS — the resolver is aimed at a nameserver of the caller's
choosing in production too.
The distinction to hold on to: **substituting the client is banned;
choosing the server is not.** A test that reaches for a fake
`DNSClient` to force a classification is still forbidden, no matter
how awkward the alternative looks.
Such a test must stay cheap. The resolver asks for eight record
types and retries each once, so a nameserver silent on every type
costs sixteen query timeouts. `TestQueryNameserverIP_Timeout` is
silent on `A` alone and answers the rest, which is all the resolver
needs to classify the response and keeps the test to two.
### What NOT to do
- **Do not mock `DNSClient`**, the watcher's `DNSResolver` interface,