An extended zone answers authoritatively only for the records it holds locally; any name with nothing configured falls through to recursive resolution instead of a synthesized NXDOMAIN, so a public domain's records don't need to be duplicated just to override a few of them. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V8c76Xr2BycaHHu5N4buqi
89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
package authoritative
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/owen/vibedns/internal/models"
|
|
)
|
|
|
|
// extendedIndex builds an "extended" zone that overrides a single name
|
|
// (www.example.com) and otherwise carries no data, mimicking a domain whose
|
|
// public records should still be resolved on the internet.
|
|
func extendedIndex(t *testing.T) *Index {
|
|
t.Helper()
|
|
zone := models.Zone{
|
|
ID: 1, Name: "example.com.", Kind: models.ZoneExtended, Enabled: true,
|
|
DefaultTTL: 3600, PrimaryNS: "ns1.example.com.", AdminEmail: "hostmaster@example.com",
|
|
}
|
|
recs := []models.Record{
|
|
{ZoneID: 1, Name: "www", Type: "A", Data: "10.0.0.1", Enabled: true},
|
|
{ZoneID: 1, Name: "www", Type: "AAAA", Data: "2001:db8::1", Enabled: true},
|
|
}
|
|
idx, problems := Build([]models.Zone{zone}, map[int64][]models.Record{1: recs})
|
|
for _, p := range problems {
|
|
t.Fatalf("unexpected build problem: %v", p)
|
|
}
|
|
return idx
|
|
}
|
|
|
|
func TestExtendedZoneOverridesLocalRecord(t *testing.T) {
|
|
idx := extendedIndex(t)
|
|
|
|
resp := query(t, idx, "www.example.com.", dns.TypeA)
|
|
if resp == nil {
|
|
t.Fatal("expected a local answer for the overridden name, got nil (fallthrough)")
|
|
}
|
|
if !resp.Authoritative {
|
|
t.Error("expected the override answer to be authoritative")
|
|
}
|
|
if len(resp.Answer) != 1 {
|
|
t.Fatalf("expected 1 answer, got %d", len(resp.Answer))
|
|
}
|
|
a, ok := resp.Answer[0].(*dns.A)
|
|
if !ok || a.A.String() != "10.0.0.1" {
|
|
t.Errorf("unexpected answer: %v", resp.Answer[0])
|
|
}
|
|
}
|
|
|
|
func TestExtendedZoneFallsThroughForUnknownName(t *testing.T) {
|
|
idx := extendedIndex(t)
|
|
|
|
// No local record for mail.example.com at all: the caller must see nil
|
|
// so it forwards the query upstream, instead of a synthesised NXDOMAIN.
|
|
resp := query(t, idx, "mail.example.com.", dns.TypeA)
|
|
if resp != nil {
|
|
t.Fatalf("expected fallthrough (nil) for an unconfigured name, got %+v", resp)
|
|
}
|
|
}
|
|
|
|
func TestExtendedZoneFallsThroughForApex(t *testing.T) {
|
|
idx := extendedIndex(t)
|
|
|
|
// The apex itself was never configured (no auto SOA/NS synthesis for an
|
|
// extended zone), so even a query at the zone name falls through.
|
|
resp := query(t, idx, "example.com.", dns.TypeMX)
|
|
if resp != nil {
|
|
t.Fatalf("expected fallthrough (nil) for the bare apex, got %+v", resp)
|
|
}
|
|
}
|
|
|
|
func TestExtendedZoneNoDataForOverriddenNameOtherType(t *testing.T) {
|
|
idx := extendedIndex(t)
|
|
|
|
// www.example.com is locally overridden for A/AAAA; a query for a type
|
|
// that was not configured there is answered locally as NODATA rather
|
|
// than forwarded, since the name itself is under local management.
|
|
resp := query(t, idx, "www.example.com.", dns.TypeTXT)
|
|
if resp == nil {
|
|
t.Fatal("expected a local NODATA answer, got nil (fallthrough)")
|
|
}
|
|
if len(resp.Answer) != 0 {
|
|
t.Errorf("expected no answer records, got %d", len(resp.Answer))
|
|
}
|
|
if resp.Rcode != dns.RcodeSuccess {
|
|
t.Errorf("expected NOERROR/NODATA, got %s", dns.RcodeToString[resp.Rcode])
|
|
}
|
|
}
|