aboutsummaryrefslogtreecommitdiff
path: root/plugin/autopath/autopath_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/autopath/autopath_test.go')
-rw-r--r--plugin/autopath/autopath_test.go166
1 files changed, 166 insertions, 0 deletions
diff --git a/plugin/autopath/autopath_test.go b/plugin/autopath/autopath_test.go
new file mode 100644
index 000000000..a00bbf0a6
--- /dev/null
+++ b/plugin/autopath/autopath_test.go
@@ -0,0 +1,166 @@
+package autopath
+
+import (
+ "testing"
+
+ "github.com/coredns/coredns/plugin"
+ "github.com/coredns/coredns/plugin/pkg/dnsrecorder"
+ "github.com/coredns/coredns/plugin/test"
+
+ "github.com/miekg/dns"
+ "golang.org/x/net/context"
+)
+
+var autopathTestCases = []test.Case{
+ {
+ // search path expansion.
+ Qname: "b.example.org.", Qtype: dns.TypeA,
+ Answer: []dns.RR{
+ test.CNAME("b.example.org. 3600 IN CNAME b.com."),
+ test.A("b.com." + defaultA),
+ },
+ },
+ {
+ // No search path expansion
+ Qname: "a.example.com.", Qtype: dns.TypeA,
+ Answer: []dns.RR{
+ test.A("a.example.com." + defaultA),
+ },
+ },
+}
+
+func newTestAutoPath() *AutoPath {
+ ap := new(AutoPath)
+ ap.Zones = []string{"."}
+ ap.Next = nextHandler(map[string]int{
+ "b.example.org.": dns.RcodeNameError,
+ "b.com.": dns.RcodeSuccess,
+ "a.example.com.": dns.RcodeSuccess,
+ })
+
+ ap.search = []string{"example.org.", "example.com.", "com.", ""}
+ return ap
+}
+
+func TestAutoPath(t *testing.T) {
+ ap := newTestAutoPath()
+ ctx := context.TODO()
+
+ for _, tc := range autopathTestCases {
+ m := tc.Msg()
+
+ rec := dnsrecorder.New(&test.ResponseWriter{})
+ _, err := ap.ServeDNS(ctx, rec, m)
+ if err != nil {
+ t.Errorf("expected no error, got %v\n", err)
+ continue
+ }
+
+ // No sorting here as we want to check if the CNAME sits *before* the
+ // test of the answer.
+ resp := rec.Msg
+
+ if !test.Header(t, tc, resp) {
+ t.Logf("%v\n", resp)
+ continue
+ }
+ if !test.Section(t, tc, test.Answer, resp.Answer) {
+ t.Logf("%v\n", resp)
+ }
+ if !test.Section(t, tc, test.Ns, resp.Ns) {
+ t.Logf("%v\n", resp)
+ }
+ if !test.Section(t, tc, test.Extra, resp.Extra) {
+ t.Logf("%v\n", resp)
+ }
+ }
+}
+
+var autopathNoAnswerTestCases = []test.Case{
+ {
+ // search path expansion, no answer
+ Qname: "c.example.org.", Qtype: dns.TypeA,
+ Answer: []dns.RR{
+ test.CNAME("b.example.org. 3600 IN CNAME b.com."),
+ test.A("b.com." + defaultA),
+ },
+ },
+}
+
+func TestAutoPathNoAnswer(t *testing.T) {
+ ap := newTestAutoPath()
+ ctx := context.TODO()
+
+ for _, tc := range autopathNoAnswerTestCases {
+ m := tc.Msg()
+
+ rec := dnsrecorder.New(&test.ResponseWriter{})
+ rcode, err := ap.ServeDNS(ctx, rec, m)
+ if err != nil {
+ t.Errorf("expected no error, got %v\n", err)
+ continue
+ }
+ if plugin.ClientWrite(rcode) {
+ t.Fatalf("expected no client write, got one for rcode %d", rcode)
+ }
+ }
+}
+
+// nextHandler returns a Handler that returns an answer for the question in the
+// request per the domain->answer map. On success an RR will be returned: "qname 3600 IN A 127.0.0.53"
+func nextHandler(mm map[string]int) test.Handler {
+ return test.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
+ rcode, ok := mm[r.Question[0].Name]
+ if !ok {
+ return dns.RcodeServerFailure, nil
+ }
+
+ m := new(dns.Msg)
+ m.SetReply(r)
+
+ switch rcode {
+ case dns.RcodeNameError:
+ m.Rcode = rcode
+ m.Ns = []dns.RR{soa}
+ w.WriteMsg(m)
+ return m.Rcode, nil
+
+ case dns.RcodeSuccess:
+ m.Rcode = rcode
+ a, _ := dns.NewRR(r.Question[0].Name + defaultA)
+ m.Answer = []dns.RR{a}
+
+ w.WriteMsg(m)
+ return m.Rcode, nil
+ default:
+ panic("nextHandler: unhandled rcode")
+ }
+ })
+}
+
+const defaultA = " 3600 IN A 127.0.0.53"
+
+var soa = func() dns.RR {
+ s, _ := dns.NewRR("example.org. 1800 IN SOA example.org. example.org. 1502165581 14400 3600 604800 14400")
+ return s
+}()
+
+func TestInSearchPath(t *testing.T) {
+ a := AutoPath{search: []string{"default.svc.cluster.local.", "svc.cluster.local.", "cluster.local."}}
+
+ tests := []struct {
+ qname string
+ b bool
+ }{
+ {"google.com", false},
+ {"default.svc.cluster.local.", true},
+ {"a.default.svc.cluster.local.", true},
+ {"a.b.svc.cluster.local.", false},
+ }
+ for i, tc := range tests {
+ got := firstInSearchPath(tc.qname, a.search)
+ if got != tc.b {
+ t.Errorf("Test %d, got %v, expected %v", i, got, tc.b)
+ }
+ }
+}