checker-delegation/checker/helpers_test.go

136 lines
3.9 KiB
Go

package checker
import (
"reflect"
"testing"
"github.com/miekg/dns"
)
func TestDiffStringSets(t *testing.T) {
cases := []struct {
name string
want, got []string
missing, extra []string
}{
{
name: "identical",
want: []string{"a.example.", "b.example."},
got: []string{"a.example.", "b.example."},
missing: nil, extra: nil,
},
{
name: "case and trailing dot are normalized",
want: []string{"A.Example."},
got: []string{"a.example"},
missing: nil, extra: nil,
},
{
name: "missing and extra reported",
want: []string{"a.example.", "b.example."},
got: []string{"b.example.", "c.example."},
missing: []string{"a.example"},
extra: []string{"c.example"},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
gotMissing, gotExtra := diffStringSets(tc.want, tc.got)
if !reflect.DeepEqual(gotMissing, tc.missing) {
t.Errorf("missing: got %v want %v", gotMissing, tc.missing)
}
if !reflect.DeepEqual(gotExtra, tc.extra) {
t.Errorf("extra: got %v want %v", gotExtra, tc.extra)
}
})
}
}
func TestIsInBailiwick(t *testing.T) {
cases := []struct {
host, zone string
want bool
}{
{"ns1.example.com.", "example.com.", true},
{"ns1.example.com", "example.com", true},
{"example.com.", "example.com.", true},
{"ns1.other.com.", "example.com.", false},
{"ns1.notexample.com.", "example.com.", false}, // suffix-but-not-subdomain trap
{"NS1.Example.COM", "example.com", true},
}
for _, tc := range cases {
if got := isInBailiwick(tc.host, tc.zone); got != tc.want {
t.Errorf("isInBailiwick(%q,%q)=%v want %v", tc.host, tc.zone, got, tc.want)
}
}
}
func TestHostPort(t *testing.T) {
cases := []struct {
host, port, want string
}{
{"192.0.2.1", "53", "192.0.2.1:53"},
{"2001:db8::1", "53", "[2001:db8::1]:53"},
{"ns1.example.com.", "53", "ns1.example.com:53"},
}
for _, tc := range cases {
if got := hostPort(tc.host, tc.port); got != tc.want {
t.Errorf("hostPort(%q,%q)=%q want %q", tc.host, tc.port, got, tc.want)
}
}
}
func TestNormalizeNSList(t *testing.T) {
in := []*dns.NS{
{Ns: "B.example.COM"},
nil, // must be skipped
{Ns: "a.example.com."},
}
want := []string{"a.example.com.", "b.example.com."}
got := normalizeNSList(in)
if !reflect.DeepEqual(got, want) {
t.Errorf("normalizeNSList: got %v want %v", got, want)
}
}
func TestDiffDS(t *testing.T) {
a := &dns.DS{KeyTag: 1, Algorithm: 8, DigestType: 2, Digest: "AAAA"}
b := &dns.DS{KeyTag: 2, Algorithm: 8, DigestType: 2, Digest: "BBBB"}
c := &dns.DS{KeyTag: 1, Algorithm: 8, DigestType: 2, Digest: "aaaa"} // case-insensitive digest
missing, extra := diffDS([]*dns.DS{a, b}, []*dns.DS{c})
if len(missing) != 1 || missing[0] != b {
t.Errorf("missing: got %v want [b]", missing)
}
if len(extra) != 0 {
t.Errorf("extra: got %v want []", extra)
}
}
func TestDSMatchesAnyKey(t *testing.T) {
// Build a DNSKEY and derive its DS, so we know they match.
key := &dns.DNSKEY{
Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeDNSKEY, Class: dns.ClassINET},
Flags: 257,
Protocol: 3,
Algorithm: dns.RSASHA256,
// A throwaway public key; ToDS only needs the wire form to be deterministic.
PublicKey: "AwEAAcMnWBKLuvG/LwnPVykcmpvnntwxfshHlHRhlY0F3oz8AMcuF8gw" +
"2Ge56vG9oqVxTzHl4Ss2dEqCQOjFlOVo+pa3JwIO1lUzbQ==",
}
matchingDS := key.ToDS(dns.SHA256)
if matchingDS == nil {
t.Fatal("could not derive DS from DNSKEY")
}
other := &dns.DS{KeyTag: 9999, Algorithm: 99, DigestType: 99, Digest: "DEAD"}
if !dsMatchesAnyKey([]*dns.DS{matchingDS, other}, []*dns.DNSKEY{key}) {
t.Error("expected match between key and its derived DS")
}
if dsMatchesAnyKey([]*dns.DS{other}, []*dns.DNSKEY{key}) {
t.Error("unexpected match against unrelated DS")
}
if dsMatchesAnyKey(nil, []*dns.DNSKEY{key}) {
t.Error("no DS records: must not match")
}
}