From f5753c6a8cac5a57a042b0388f38abeff5d1f37d Mon Sep 17 00:00:00 2001 From: radhitya Date: Thu, 18 Jun 2026 12:42:29 +0700 Subject: migration to new dns library --- internal/resolver/resolver_test.go | 150 +++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 47 deletions(-) (limited to 'internal/resolver/resolver_test.go') diff --git a/internal/resolver/resolver_test.go b/internal/resolver/resolver_test.go index 0bd0402..54f727e 100644 --- a/internal/resolver/resolver_test.go +++ b/internal/resolver/resolver_test.go @@ -2,54 +2,53 @@ package resolver import ( "context" - "net" + "io" + "net/netip" "testing" "time" - "github.com/miekg/dns" + "codeberg.org/miekg/dns" + "codeberg.org/miekg/dns/dnsutil" + "codeberg.org/miekg/dns/rdata" ) func startTestServer(t *testing.T, addr string, handler dns.Handler) *dns.Server { t.Helper() + ready := make(chan struct{}) srv := &dns.Server{ Addr: addr, Net: "udp", Handler: handler, UDPSize: 4096, + NotifyStartedFunc: func(ctx context.Context) { + close(ready) + }, } go func() { - if err := srv.ListenAndServe(); err != nil { - } + _ = srv.ListenAndServe() }() + <-ready return srv } func TestLookupDirectAnswer(t *testing.T) { - mux := dns.NewServeMux() - mux.HandleFunc(".", func(w dns.ResponseWriter, req *dns.Msg) { - resp := new(dns.Msg) - resp.SetReply(req) - resp.Authoritative = true - if req.Question[0].Name == "example.com." && - req.Question[0].Qtype == dns.TypeA { + srv := startTestServer(t, "127.0.0.1:15353", + dns.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) { + resp := new(dns.Msg) + dnsutil.SetReply(resp, req) + resp.Authoritative = true resp.Answer = append(resp.Answer, &dns.A{ - Hdr: dns.RR_Header{ - Name: "example.com.", - Rrtype: dns.TypeA, - Class: dns.ClassINET, - Ttl: 60, + Hdr: dns.Header{ + Name: "example.com.", + Class: dns.ClassINET, + TTL: 60, }, - A: net.IPv4(127, 0, 0, 1), + A: rdata.A{Addr: netip.AddrFrom4([4]byte{127, 0, 0, 1})}, }) - } else { - resp.Rcode = dns.RcodeNameError - } - w.WriteMsg(resp) - }) - - srv := startTestServer(t, "127.0.0.1:15353", mux) - defer srv.Shutdown() - time.Sleep(50 * time.Millisecond) + io.Copy(w, resp) + })) + defer srv.Shutdown(context.Background()) + time.Sleep(100 * time.Millisecond) r := New( WithRootAddresses([]string{"127.0.0.1:15353"}), @@ -73,23 +72,21 @@ func TestLookupDirectAnswer(t *testing.T) { if !ok { t.Fatal("expected A record") } - if !a.A.Equal(net.IPv4(127, 0, 0, 1)) { - t.Fatalf("expected 127.0.0.1, got %s", a.A) + if a.A.Addr != netip.AddrFrom4([4]byte{127, 0, 0, 1}) { + t.Fatalf("expected 127.0.0.1, got %s", a.A.Addr) } } func TestLookupNXDOMAIN(t *testing.T) { - mux := dns.NewServeMux() - mux.HandleFunc(".", func(w dns.ResponseWriter, req *dns.Msg) { - resp := new(dns.Msg) - resp.SetReply(req) - resp.Rcode = dns.RcodeNameError - w.WriteMsg(resp) - }) - - srv := startTestServer(t, "127.0.0.1:15354", mux) - defer srv.Shutdown() - time.Sleep(50 * time.Millisecond) + srv := startTestServer(t, "127.0.0.1:15354", + dns.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) { + resp := new(dns.Msg) + dnsutil.SetReply(resp, req) + resp.Rcode = dns.RcodeNameError + io.Copy(w, resp) + })) + defer srv.Shutdown(context.Background()) + time.Sleep(100 * time.Millisecond) r := New( WithRootAddresses([]string{"127.0.0.1:15354"}), @@ -111,16 +108,16 @@ func TestNextServersWithGlue(t *testing.T) { msg := new(dns.Msg) msg.Authoritative = false msg.Ns = append(msg.Ns, &dns.NS{ - Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeNS, Ttl: 300}, - Ns: "ns1.example.com.", + Hdr: dns.Header{Name: "example.com.", Class: dns.ClassINET, TTL: 300}, + NS: rdata.NS{Ns: "ns1.example.com."}, }) msg.Extra = append(msg.Extra, &dns.A{ - Hdr: dns.RR_Header{Name: "ns1.example.com.", Rrtype: dns.TypeA, Ttl: 300}, - A: net.ParseIP("192.0.2.1").To4(), + Hdr: dns.Header{Name: "ns1.example.com.", Class: dns.ClassINET, TTL: 300}, + A: rdata.A{Addr: netip.MustParseAddr("192.0.2.1")}, }) msg.Extra = append(msg.Extra, &dns.AAAA{ - Hdr: dns.RR_Header{Name: "ns1.example.com.", Rrtype: dns.TypeAAAA, Ttl: 300}, - AAAA: net.ParseIP("2001:db8::1"), + Hdr: dns.Header{Name: "ns1.example.com.", Class: dns.ClassINET, TTL: 300}, + AAAA: rdata.AAAA{Addr: netip.MustParseAddr("2001:db8::1")}, }) r := &Resolver{} @@ -137,8 +134,8 @@ func TestNextServersNoGlue(t *testing.T) { msg := new(dns.Msg) msg.Authoritative = false msg.Ns = append(msg.Ns, &dns.NS{ - Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeNS, Ttl: 300}, - Ns: "ns1.example.com.", + Hdr: dns.Header{Name: "example.com.", Class: dns.ClassINET, TTL: 300}, + NS: rdata.NS{Ns: "ns1.example.com."}, }) r := &Resolver{maxDelegations: 30, timeout: time.Second, retries: 1} @@ -147,3 +144,62 @@ func TestNextServersNoGlue(t *testing.T) { t.Fatal("expected error when no glue and no roots") } } + +func TestLookupCNAME(t *testing.T) { + callCount := 0 + srv := startTestServer(t, "127.0.0.1:15355", + dns.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) { + callCount++ + resp := new(dns.Msg) + dnsutil.SetReply(resp, req) + resp.Authoritative = true + resp.Answer = append(resp.Answer, + &dns.CNAME{ + Hdr: dns.Header{Name: "alias.example.com.", Class: dns.ClassINET, TTL: 60}, + CNAME: rdata.CNAME{Target: "real.example.com."}, + }, + ) + if callCount > 1 { + resp.Answer = append(resp.Answer, + &dns.A{ + Hdr: dns.Header{Name: "real.example.com.", Class: dns.ClassINET, TTL: 60}, + A: rdata.A{Addr: netip.AddrFrom4([4]byte{127, 0, 0, 1})}, + }, + ) + } + io.Copy(w, resp) + })) + defer srv.Shutdown(context.Background()) + time.Sleep(100 * time.Millisecond) + + r := New( + WithRootAddresses([]string{"127.0.0.1:15355"}), + WithTimeout(time.Second), + ) + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + resp, err := r.Lookup(ctx, "alias.example.com.", dns.TypeA) + if err != nil { + t.Fatalf("CNAME lookup failed: %v", err) + } + if resp.Rcode != dns.RcodeSuccess { + t.Fatalf("expected NOERROR, got %d", resp.Rcode) + } + hasCNAME := false + hasA := false + for _, rr := range resp.Answer { + if _, ok := rr.(*dns.CNAME); ok { + hasCNAME = true + } + if _, ok := rr.(*dns.A); ok { + hasA = true + } + } + if !hasCNAME { + t.Fatal("expected CNAME record in answer") + } + if !hasA { + t.Fatal("expected A record (CNAME target) in answer") + } +} -- cgit v1.2.3