Files
fancy-dns/internal/zonefile/example_test.go
T
developer e8c5b414d9
build / build-push (push) Failing after 23s
half broken
2026-09-27 17:17:53 +00:00

82 lines
2.8 KiB
Go

package zonefile
import (
"path/filepath"
"slices"
"strings"
"testing"
)
// nameTypeRdata renders every record as "name TYPE rdata", skipping the line
// number and the TTL. The shipped examples are edited by hand, so pinning the
// exact record set is enough; pinning line numbers would make a comment change
// look like a parser bug.
func nameTypeRdata(t *testing.T, z *Zone) []string {
t.Helper()
out := make([]string, 0, len(z.Records))
for _, rec := range z.Records {
parts := strings.SplitN(rec.RR.String(), "\t", 5)
if len(parts) != 5 {
t.Fatalf("record on line %d does not render as 5 tab-separated fields: %q",
rec.Line, rec.Text())
}
out = append(out, parts[0]+" "+parts[3]+" "+parts[4])
}
return out
}
// TestExampleLocalZoneIsOriginIndependent parses deploy/local.example.zone the
// way the product parses it — with the origin taken from the file name, which
// for local.example.zone is "local." — and pins that every name in the example
// is fully qualified anyway.
//
// This is not a style test. The origin a master file is read with is its base
// name, so a relative owner name silently becomes <name>.local. and the zone
// answers for names nobody asked about. The example is what an operator copies,
// and it used to mix relative owners with absolute ones: a file that looked
// right and matched nothing.
func TestExampleLocalZoneIsOriginIndependent(t *testing.T) {
path := filepath.Join("..", "..", "deploy", "local.example.zone")
if got, want := OriginFromPath(path), "local."; got != want {
t.Fatalf("OriginFromPath(%q) = %q, want %q — the example depends on this origin",
path, got, want)
}
z, err := ParseFile(path, OriginFromPath(path))
if err != nil {
t.Fatalf("ParseFile(%s): %v", path, err)
}
got := nameTypeRdata(t, z)
want := []string{
"lan. SOA ns1.lan. hostmaster.lan. 2024010101 3600 600 604800 300",
"lan. NS ns1.lan.",
"lan. NS ns2.lan.",
"ns1.lan. A 192.168.1.2",
"ns2.lan. A 192.168.1.3",
"router.lan. A 192.168.1.1",
"nas.lan. A 192.168.1.10",
"nas.lan. AAAA fd00::10",
"*.lan. A 192.168.1.50",
"*.internal.lan. A 10.0.0.50",
"_ntp._udp.lan. SRV 0 0 123 ns1.lan.",
"_ldap._tcp.lan. SRV 10 0 389 nas.lan.",
`_dmarc._domain.lan. TXT "v=DMARC1; p=reject; rua=mailto:dmarc.lan"`,
`_lan. TXT "internal network, do not use on the open internet"`,
}
if !slices.Equal(got, want) {
t.Errorf("records mismatch\n got: %q\nwant: %q", got, want)
}
if z.DefaultTTL != 300 {
t.Errorf("DefaultTTL = %d, want the $TTL 300", z.DefaultTTL)
}
for _, rec := range z.Records {
if !strings.HasSuffix(rec.Name, ".") {
t.Errorf("record %q is not fully qualified; the example is read with the "+
"origin %q derived from the file name", rec.Name, z.Origin)
}
}
if z.SOA == nil || z.SOA.Serial != 2024010101 {
t.Errorf("SOA = %v, want the serial 2024010101", z.SOA)
}
}