Files
coredns/plugin/pkg/upstream/upstream_test.go

102 lines
3.4 KiB
Go
Raw Normal View History

package upstream
import (
"context"
"errors"
"testing"
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/test"
"github.com/coredns/coredns/request"
"github.com/miekg/dns"
)
// selfReferencing answers every query with a CNAME to the query name itself
// and then asks the upstream for that target, the way a backend does for a
// CNAME-typed service whose target leads back to the backend.
type selfReferencing struct {
up *Upstream
calls int
}
func (s *selfReferencing) Name() string { return "selfref" }
func (s *selfReferencing) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
s.calls++
state := request.Request{W: w, Req: r}
m := new(dns.Msg)
m.SetReply(r)
m.Answer = []dns.RR{test.CNAME(state.QName() + " 5 IN CNAME " + state.QName())}
if resp, err := s.up.Lookup(ctx, state, state.QName(), state.QType()); err == nil && resp != nil {
m.Answer = append(m.Answer, resp.Answer...)
}
w.WriteMsg(m)
return dns.RcodeSuccess, nil
}
func TestLookupDepthIsBounded(t *testing.T) {
h := &selfReferencing{up: New()}
cfg := &dnsserver.Config{Zone: ".", Plugin: []plugin.Plugin{func(plugin.Handler) plugin.Handler { return h }}}
server, err := dnsserver.NewServer("dns://:53", []*dnsserver.Config{cfg})
if err != nil {
t.Fatalf("NewServer: %v", err)
}
ctx := context.WithValue(context.Background(), dnsserver.Key{}, server)
m := new(dns.Msg)
m.SetQuestion("x.example.org.", dns.TypeA)
rec := &test.ResponseWriter{}
server.ServeDNS(ctx, rec, m)
// The client query plus maxDepth nested lookups.
if want := maxDepth + 1; h.calls != want {
t.Fatalf("expected %d invocations of the plugin chain, got %d", want, h.calls)
}
}
func TestLookupReturnsErrMaxDepth(t *testing.T) {
server, err := dnsserver.NewServer("dns://:53", []*dnsserver.Config{{Zone: "."}})
if err != nil {
t.Fatalf("NewServer: %v", err)
}
ctx := context.WithValue(context.Background(), dnsserver.Key{}, server)
ctx = context.WithValue(ctx, depthKey{}, maxDepth)
m := new(dns.Msg)
m.SetQuestion("x.example.org.", dns.TypeA)
state := request.Request{W: &test.ResponseWriter{}, Req: m}
if _, err := New().Lookup(ctx, state, "y.example.org.", dns.TypeA); !errors.Is(err, errMaxDepth) {
t.Fatalf("expected errMaxDepth, got %v", err)
}
}
func TestLookupDoesNotConsumeServerLoopDepth(t *testing.T) {
h := &selfReferencing{up: New()}
cfg := &dnsserver.Config{Zone: ".", Plugin: []plugin.Plugin{func(plugin.Handler) plugin.Handler { return h }}}
server, err := dnsserver.NewServer("dns://:53", []*dnsserver.Config{cfg})
if err != nil {
t.Fatalf("NewServer: %v", err)
}
ctx := context.WithValue(context.Background(), dnsserver.Key{}, server)
ctx = context.WithValue(ctx, dnsserver.LoopKey{}, maxDepth)
m := new(dns.Msg)
m.SetQuestion("x.example.org.", dns.TypeA)
state := request.Request{W: &test.ResponseWriter{}, Req: m}
if _, err := New().Lookup(ctx, state, "y.example.org.", dns.TypeA); err != nil {
t.Fatalf("Lookup unexpectedly used dnsserver.LoopKey: %v", err)
}
}
func TestLookupWithoutServer(t *testing.T) {
m := new(dns.Msg)
m.SetQuestion("x.example.org.", dns.TypeA)
state := request.Request{W: &test.ResponseWriter{}, Req: m}
if _, err := New().Lookup(context.Background(), state, "y.example.org.", dns.TypeA); err == nil {
t.Fatal("expected an error without a server in the context")
}
}