package checker import ( "net" "testing" ) func TestLowerFQDN(t *testing.T) { cases := []struct { in, want string }{ {"Example.COM", "example.com."}, {"example.com.", "example.com."}, {"", "."}, {"X", "x."}, {"1.168.192.IN-ADDR.ARPA.", "1.168.192.in-addr.arpa."}, } for _, c := range cases { if got := lowerFQDN(c.in); got != c.want { t.Errorf("lowerFQDN(%q)=%q, want %q", c.in, got, c.want) } } } func TestIsReverseArpa(t *testing.T) { cases := []struct { in string want bool }{ {"1.168.192.in-addr.arpa", true}, {"in-addr.arpa", true}, {"in-addr.arpa.", true}, {"IN-ADDR.ARPA", true}, {"ip6.arpa", true}, {"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", true}, {"example.com", false}, {"arpa", false}, {"in-addr.arpa.example.com", false}, {"", false}, } for _, c := range cases { if got := isReverseArpa(c.in); got != c.want { t.Errorf("isReverseArpa(%q)=%v, want %v", c.in, got, c.want) } } } func TestIsIPv6Arpa(t *testing.T) { cases := []struct { in string want bool }{ {"ip6.arpa", true}, {"IP6.ARPA.", true}, {"0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.", true}, {"1.168.192.in-addr.arpa", false}, {"in-addr.arpa", false}, {"example.com", false}, } for _, c := range cases { if got := isIPv6Arpa(c.in); got != c.want { t.Errorf("isIPv6Arpa(%q)=%v, want %v", c.in, got, c.want) } } } func TestReverseNameToIP_IPv4(t *testing.T) { cases := []struct { in string want string // "" means nil }{ {"42.1.168.192.in-addr.arpa", "192.168.1.42"}, {"42.1.168.192.IN-ADDR.ARPA.", "192.168.1.42"}, {"1.168.192.in-addr.arpa", ""}, // partial: only 3 labels {"a.b.c.d.in-addr.arpa", ""}, // non-numeric {"256.0.0.0.in-addr.arpa", ""}, // out of range parses with strconv but ParseIP fails {"1.2.3.4.5.in-addr.arpa", ""}, // too many {"in-addr.arpa", ""}, // apex, no labels {"example.com", ""}, // unrelated } for _, c := range cases { got := reverseNameToIP(c.in) switch { case c.want == "" && got != nil: t.Errorf("reverseNameToIP(%q)=%v, want nil", c.in, got) case c.want != "" && (got == nil || got.String() != c.want): t.Errorf("reverseNameToIP(%q)=%v, want %s", c.in, got, c.want) } } } func TestReverseNameToIP_IPv6(t *testing.T) { // 2001:db8::1 expanded reverse: // 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. full := "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa" got := reverseNameToIP(full) if got == nil { t.Fatalf("reverseNameToIP(%q) returned nil", full) } want := net.ParseIP("2001:db8::1") if !got.Equal(want) { t.Errorf("reverseNameToIP(%q)=%v, want %v", full, got, want) } // Partial / invalid IPv6 reverse names → nil. partials := []string{ "d.0.1.0.0.2.ip6.arpa", // /24 zone, only 6 nibbles "ip6.arpa", // apex "x.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa", // multi-char label "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.ip6.arpa", // 31 labels } for _, p := range partials { if r := reverseNameToIP(p); r != nil { t.Errorf("reverseNameToIP(%q)=%v, want nil", p, r) } } } func TestIPEqual(t *testing.T) { cases := []struct { addr string ip net.IP want bool }{ {"192.168.1.1", net.ParseIP("192.168.1.1"), true}, {"192.168.1.1", net.ParseIP("192.168.1.2"), false}, {"2001:db8::1", net.ParseIP("2001:0db8:0000::1"), true}, {"::ffff:192.168.1.1", net.ParseIP("192.168.1.1"), true}, {"not-an-ip", net.ParseIP("192.168.1.1"), false}, {"", net.ParseIP("192.168.1.1"), false}, } for _, c := range cases { if got := ipEqual(c.addr, c.ip); got != c.want { t.Errorf("ipEqual(%q,%v)=%v, want %v", c.addr, c.ip, got, c.want) } } } func TestSystemResolverFallback(t *testing.T) { // Force the fallback path: even if /etc/resolv.conf exists, the fallback // kicks in when the file is missing or has zero servers. We can't easily // remove /etc/resolv.conf in a test, so just assert the result is a valid // host:port and that FallbackResolver itself is well-formed. host, port, err := net.SplitHostPort(FallbackResolver) if err != nil { t.Fatalf("FallbackResolver = %q is not host:port: %v", FallbackResolver, err) } if host == "" || port == "" { t.Errorf("FallbackResolver = %q has empty host or port", FallbackResolver) } got := systemResolver() if _, _, err := net.SplitHostPort(got); err != nil { t.Errorf("systemResolver() = %q is not host:port: %v", got, err) } }