checker-ptr/checker/collect_test.go

160 lines
4.4 KiB
Go

package checker
import (
"encoding/json"
"net"
"testing"
sdk "git.happydns.org/checker-sdk-go/checker"
)
func TestLooksGeneric(t *testing.T) {
v4 := net.ParseIP("203.0.113.42")
v6 := net.ParseIP("2001:db8::1")
cases := []struct {
name string
host string
ip net.IP
want bool
}{
{"dotted ip embedded", "host-203.0.113.42.example.net", v4, true},
{"hyphenated ip embedded", "203-0-113-42.isp.example.net", v4, true},
{"dhcp pattern", "dhcp-10-20-30.isp.example.net", v4, true},
{"pool pattern", "pool.10.20.30.isp.example.net", v4, true},
{"dyn pattern", "dyn-203-0-113.isp.example.net", v4, true},
{"clean hostname", "mail.example.com", v4, false},
{"hostname with single digit suffix (not generic)", "host1.example.com", v4, false},
{"static-www should not match", "static-www.example.com", v4, false},
{"v6 short prefix only", "ipv6-2001-db8.example.net", v6, false},
{"v6 dash-grouped embedded", "host-2001-0db8-0000-0000-0000-0000-0000-0001.isp.example.net", v6, true},
{"v6 flat hex embedded", "h20010db8000000000000000000000001.isp.example.net", v6, true},
{"v6 dotted nibble embedded", "host.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.example.net", v6, true},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
if got := looksGeneric(tc.host, tc.ip); got != tc.want {
t.Errorf("looksGeneric(%q, %s) = %v, want %v", tc.host, tc.ip, got, tc.want)
}
})
}
}
func TestIPEqual(t *testing.T) {
v4 := net.ParseIP("1.2.3.4")
if !ipEqual("1.2.3.4", v4) {
t.Error("expected 1.2.3.4 to equal itself")
}
if !ipEqual("::ffff:1.2.3.4", v4) {
t.Error("expected v4-mapped v6 to equal v4")
}
if ipEqual("1.2.3.5", v4) {
t.Error("different addresses should not be equal")
}
if ipEqual("not-an-ip", v4) {
t.Error("invalid input must not be equal")
}
}
func TestResolvePTRInputs_FromDomainSubdomain(t *testing.T) {
opts := sdk.CheckerOptions{
"domain_name": "3.2.1.in-addr.arpa",
"subdomain": "4",
}
owner, target, ttl, err := resolvePTRInputs(opts)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if owner != "4.3.2.1.in-addr.arpa." {
t.Errorf("owner = %q, want 4.3.2.1.in-addr.arpa.", owner)
}
if target != "" {
t.Errorf("target = %q, want empty", target)
}
if ttl != 0 {
t.Errorf("ttl = %d, want 0", ttl)
}
}
func TestResolvePTRInputs_ApexSubdomain(t *testing.T) {
opts := sdk.CheckerOptions{
"domain_name": "4.3.2.1.in-addr.arpa.",
"subdomain": "@",
}
owner, _, _, err := resolvePTRInputs(opts)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if owner != "4.3.2.1.in-addr.arpa." {
t.Errorf("owner = %q, want 4.3.2.1.in-addr.arpa.", owner)
}
}
func TestResolvePTRInputs_ExpectedTarget(t *testing.T) {
opts := sdk.CheckerOptions{
"domain_name": "3.2.1.in-addr.arpa",
"subdomain": "4",
"expected_target": "Mail.Example.COM",
}
_, target, _, err := resolvePTRInputs(opts)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if target != "mail.example.com." {
t.Errorf("target = %q, want mail.example.com.", target)
}
}
func TestResolvePTRInputs_MissingDomain(t *testing.T) {
if _, _, _, err := resolvePTRInputs(sdk.CheckerOptions{}); err == nil {
t.Fatal("expected error for missing domain_name")
}
}
func TestResolvePTRInputs_FromService(t *testing.T) {
rec := map[string]any{
"Hdr": map[string]any{
"Name": "4",
"Rrtype": 12,
"Class": 1,
"Ttl": 3600,
},
"Ptr": "Mail.Example.COM.",
}
svc, _ := json.Marshal(map[string]any{"Record": rec})
envelope, _ := json.Marshal(map[string]any{
"_svctype": "svcs.PTR",
"_domain": "3.2.1.in-addr.arpa",
"Service": json.RawMessage(svc),
})
opts := sdk.CheckerOptions{"service": json.RawMessage(envelope)}
owner, target, ttl, err := resolvePTRInputs(opts)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if owner != "4.3.2.1.in-addr.arpa." {
t.Errorf("owner = %q, want 4.3.2.1.in-addr.arpa.", owner)
}
if target != "mail.example.com." {
t.Errorf("target = %q, want mail.example.com.", target)
}
if ttl != 3600 {
t.Errorf("ttl = %d, want 3600", ttl)
}
}
func TestResolvePTRInputs_WrongServiceType(t *testing.T) {
envelope, _ := json.Marshal(map[string]any{
"_svctype": "svcs.A",
"_domain": "example.com",
"Service": json.RawMessage(`{"Record":null}`),
})
opts := sdk.CheckerOptions{"service": json.RawMessage(envelope)}
if _, _, _, err := resolvePTRInputs(opts); err == nil {
t.Fatal("expected error for non-PTR service type")
}
}