Add testing package

This already includes a bunch of helper functions that aid in testing.
Factor out etcd and file testing to use this package.

Fixes: #50
This commit is contained in:
Miek Gieben 2016-03-28 10:49:28 +01:00
parent 5a919198ac
commit 6eae17b0bd
9 changed files with 295 additions and 304 deletions

View file

@ -9,6 +9,7 @@ import (
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -53,14 +54,14 @@ func TestCnameLookup(t *testing.T) {
continue continue
} }
if !checkSection(t, tc, Answer, resp.Answer) { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Ns, resp.Ns) { if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Extra, resp.Extra) { if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
} }
@ -77,20 +78,20 @@ var servicesCname = []*msg.Service{
{Host: "10.240.0.1", Key: "endpoint.region2.skydns.test."}, {Host: "10.240.0.1", Key: "endpoint.region2.skydns.test."},
} }
var dnsTestCasesCname = []dnsTestCase{ var dnsTestCasesCname = []coretest.Case{
{ {
Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{ Answer: []dns.RR{
newSRV("a.server1.dev.region1.skydns.test. 300 IN SRV 10 100 0 cname1.region2.skydns.test."), coretest.SRV("a.server1.dev.region1.skydns.test. 300 IN SRV 10 100 0 cname1.region2.skydns.test."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newCNAME("cname1.region2.skydns.test. 300 IN CNAME cname2.region2.skydns.test."), coretest.CNAME("cname1.region2.skydns.test. 300 IN CNAME cname2.region2.skydns.test."),
newCNAME("cname2.region2.skydns.test. 300 IN CNAME cname3.region2.skydns.test."), coretest.CNAME("cname2.region2.skydns.test. 300 IN CNAME cname3.region2.skydns.test."),
newCNAME("cname3.region2.skydns.test. 300 IN CNAME cname4.region2.skydns.test."), coretest.CNAME("cname3.region2.skydns.test. 300 IN CNAME cname4.region2.skydns.test."),
newCNAME("cname4.region2.skydns.test. 300 IN CNAME cname5.region2.skydns.test."), coretest.CNAME("cname4.region2.skydns.test. 300 IN CNAME cname5.region2.skydns.test."),
newCNAME("cname5.region2.skydns.test. 300 IN CNAME cname6.region2.skydns.test."), coretest.CNAME("cname5.region2.skydns.test. 300 IN CNAME cname6.region2.skydns.test."),
newCNAME("cname6.region2.skydns.test. 300 IN CNAME endpoint.region2.skydns.test."), coretest.CNAME("cname6.region2.skydns.test. 300 IN CNAME endpoint.region2.skydns.test."),
newA("endpoint.region2.skydns.test. 300 IN A 10.240.0.1"), coretest.A("endpoint.region2.skydns.test. 300 IN A 10.240.0.1"),
}, },
}, },
} }

View file

@ -12,6 +12,7 @@ import (
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -33,9 +34,9 @@ func TestGroupLookup(t *testing.T) {
} }
resp := rec.Msg() resp := rec.Msg()
sort.Sort(rrSet(resp.Answer)) sort.Sort(coretest.RRSet(resp.Answer))
sort.Sort(rrSet(resp.Ns)) sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(rrSet(resp.Extra)) sort.Sort(coretest.RRSet(resp.Extra))
if resp.Rcode != tc.Rcode { if resp.Rcode != tc.Rcode {
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
@ -59,14 +60,14 @@ func TestGroupLookup(t *testing.T) {
continue continue
} }
if !checkSection(t, tc, Answer, resp.Answer) { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Ns, resp.Ns) { if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Extra, resp.Extra) { if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
} }
@ -84,29 +85,29 @@ var servicesGroup = []*msg.Service{
{Host: "127.0.0.2", Key: "b.sub.dom1.skydns.test.", Group: "g2"}, {Host: "127.0.0.2", Key: "b.sub.dom1.skydns.test.", Group: "g2"},
} }
var dnsTestCasesGroup = []dnsTestCase{ var dnsTestCasesGroup = []coretest.Case{
// Groups // Groups
{ {
// hits the group 'g1' and only includes those records // hits the group 'g1' and only includes those records
Qname: "dom.skydns.test.", Qtype: dns.TypeA, Qname: "dom.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{ Answer: []dns.RR{
newA("dom.skydns.test. 300 IN A 127.0.0.1"), coretest.A("dom.skydns.test. 300 IN A 127.0.0.1"),
newA("dom.skydns.test. 300 IN A 127.0.0.2"), coretest.A("dom.skydns.test. 300 IN A 127.0.0.2"),
}, },
}, },
{ {
// One has group, the other has not... Include the non-group always. // One has group, the other has not... Include the non-group always.
Qname: "dom2.skydns.test.", Qtype: dns.TypeA, Qname: "dom2.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{ Answer: []dns.RR{
newA("dom2.skydns.test. 300 IN A 127.0.0.1"), coretest.A("dom2.skydns.test. 300 IN A 127.0.0.1"),
newA("dom2.skydns.test. 300 IN A 127.0.0.2"), coretest.A("dom2.skydns.test. 300 IN A 127.0.0.2"),
}, },
}, },
{ {
// The groups differ. // The groups differ.
Qname: "dom1.skydns.test.", Qtype: dns.TypeA, Qname: "dom1.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{ Answer: []dns.RR{
newA("dom1.skydns.test. 300 IN A 127.0.0.1"), coretest.A("dom1.skydns.test. 300 IN A 127.0.0.1"),
}, },
}, },
} }

View file

@ -16,7 +16,7 @@ func (e Etcd) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (i
// are not auth. for *but* do have a stubzone forward for. If we do the stubzone // are not auth. for *but* do have a stubzone forward for. If we do the stubzone
// handler will handle the request. // handler will handle the request.
name := state.Name() name := state.Name()
if len(*e.Stubmap) > 0 { if e.Stubmap != nil && len(*e.Stubmap) > 0 {
for zone, _ := range *e.Stubmap { for zone, _ := range *e.Stubmap {
if strings.HasSuffix(name, zone) { if strings.HasSuffix(name, zone) {
stub := Stub{Etcd: e, Zone: zone} stub := Stub{Etcd: e, Zone: zone}

View file

@ -8,6 +8,8 @@ package etcd
import ( import (
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
"github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -30,87 +32,87 @@ var services = []*msg.Service{
{Host: "b.cname.skydns.test", Key: "a.cname.skydns.test."}, {Host: "b.cname.skydns.test", Key: "a.cname.skydns.test."},
} }
var dnsTestCases = []dnsTestCase{ var dnsTestCases = []testing.Case{
// SRV Test // SRV Test
{ {
Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("a.server1.dev.region1.skydns.test. 300 SRV 10 100 8080 dev.server1.")}, Answer: []dns.RR{testing.SRV("a.server1.dev.region1.skydns.test. 300 SRV 10 100 8080 dev.server1.")},
}, },
// SRV Test (case test) // SRV Test (case test)
{ {
Qname: "a.SERVer1.dEv.region1.skydns.tEst.", Qtype: dns.TypeSRV, Qname: "a.SERVer1.dEv.region1.skydns.tEst.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("a.SERVer1.dEv.region1.skydns.tEst. 300 SRV 10 100 8080 dev.server1.")}, Answer: []dns.RR{testing.SRV("a.SERVer1.dEv.region1.skydns.tEst. 300 SRV 10 100 8080 dev.server1.")},
}, },
// NXDOMAIN Test // NXDOMAIN Test
{ {
Qname: "doesnotexist.skydns.test.", Qtype: dns.TypeA, Qname: "doesnotexist.skydns.test.", Qtype: dns.TypeA,
Rcode: dns.RcodeNameError, Rcode: dns.RcodeNameError,
Ns: []dns.RR{ Ns: []dns.RR{
newSOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0"), testing.SOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0"),
}, },
}, },
// A Test // A Test
{ {
Qname: "a.server1.prod.region1.skydns.test.", Qtype: dns.TypeA, Qname: "a.server1.prod.region1.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{newA("a.server1.prod.region1.skydns.test. 300 A 10.0.0.1")}, Answer: []dns.RR{testing.A("a.server1.prod.region1.skydns.test. 300 A 10.0.0.1")},
}, },
// SRV Test where target is IP address // SRV Test where target is IP address
{ {
Qname: "a.server1.prod.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "a.server1.prod.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("a.server1.prod.region1.skydns.test. 300 SRV 10 100 8080 a.server1.prod.region1.skydns.test.")}, Answer: []dns.RR{testing.SRV("a.server1.prod.region1.skydns.test. 300 SRV 10 100 8080 a.server1.prod.region1.skydns.test.")},
Extra: []dns.RR{newA("a.server1.prod.region1.skydns.test. 300 A 10.0.0.1")}, Extra: []dns.RR{testing.A("a.server1.prod.region1.skydns.test. 300 A 10.0.0.1")},
}, },
// AAAA Test // AAAA Test
{ {
Qname: "b.server6.prod.region1.skydns.test.", Qtype: dns.TypeAAAA, Qname: "b.server6.prod.region1.skydns.test.", Qtype: dns.TypeAAAA,
Answer: []dns.RR{newAAAA("b.server6.prod.region1.skydns.test. 300 AAAA ::1")}, Answer: []dns.RR{testing.AAAA("b.server6.prod.region1.skydns.test. 300 AAAA ::1")},
}, },
// Multiple A Record Test // Multiple A Record Test
{ {
Qname: "server1.prod.region1.skydns.test.", Qtype: dns.TypeA, Qname: "server1.prod.region1.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{ Answer: []dns.RR{
newA("server1.prod.region1.skydns.test. 300 A 10.0.0.1"), testing.A("server1.prod.region1.skydns.test. 300 A 10.0.0.1"),
newA("server1.prod.region1.skydns.test. 300 A 10.0.0.2"), testing.A("server1.prod.region1.skydns.test. 300 A 10.0.0.2"),
}, },
}, },
// Priority Test // Priority Test
{ {
Qname: "priority.skydns.test.", Qtype: dns.TypeSRV, Qname: "priority.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("priority.skydns.test. 300 SRV 333 100 8080 priority.server1.")}, Answer: []dns.RR{testing.SRV("priority.skydns.test. 300 SRV 333 100 8080 priority.server1.")},
}, },
// Subdomain Test // Subdomain Test
{ {
Qname: "sub.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "sub.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{ Answer: []dns.RR{
newSRV("sub.region1.skydns.test. 300 IN SRV 10 33 0 sub.server1."), testing.SRV("sub.region1.skydns.test. 300 IN SRV 10 33 0 sub.server1."),
newSRV("sub.region1.skydns.test. 300 IN SRV 10 33 80 sub.server2."), testing.SRV("sub.region1.skydns.test. 300 IN SRV 10 33 80 sub.server2."),
newSRV("sub.region1.skydns.test. 300 IN SRV 10 33 8080 c.sub.region1.skydns.test."), testing.SRV("sub.region1.skydns.test. 300 IN SRV 10 33 8080 c.sub.region1.skydns.test."),
}, },
Extra: []dns.RR{newA("c.sub.region1.skydns.test. 300 IN A 10.0.0.1")}, Extra: []dns.RR{testing.A("c.sub.region1.skydns.test. 300 IN A 10.0.0.1")},
}, },
// CNAME (unresolvable internal name) // CNAME (unresolvable internal name)
{ {
Qname: "cname.prod.region1.skydns.test.", Qtype: dns.TypeA, Qname: "cname.prod.region1.skydns.test.", Qtype: dns.TypeA,
Ns: []dns.RR{newSOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0")}, Ns: []dns.RR{testing.SOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0")},
}, },
// Wildcard Test // Wildcard Test
{ {
Qname: "*.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "*.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{ Answer: []dns.RR{
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 0 sub.server1."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 0 sub.server1."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 0 unresolvable.skydns.test."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 0 unresolvable.skydns.test."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 80 sub.server2."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 80 sub.server2."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 a.server1.prod.region1.skydns.test."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 a.server1.prod.region1.skydns.test."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 b.server1.prod.region1.skydns.test."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 b.server1.prod.region1.skydns.test."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 b.server6.prod.region1.skydns.test."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 b.server6.prod.region1.skydns.test."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 c.sub.region1.skydns.test."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 c.sub.region1.skydns.test."),
newSRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 dev.server1."), testing.SRV("*.region1.skydns.test. 300 IN SRV 10 12 8080 dev.server1."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"), testing.A("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"),
newA("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"), testing.A("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"),
newAAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"), testing.AAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"),
newA("c.sub.region1.skydns.test. 300 IN A 10.0.0.1"), testing.A("c.sub.region1.skydns.test. 300 IN A 10.0.0.1"),
}, },
}, },
// Wildcard Test // Wildcard Test
@ -118,40 +120,40 @@ var dnsTestCases = []dnsTestCase{
Qname: "prod.*.skydns.test.", Qtype: dns.TypeSRV, Qname: "prod.*.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{ Answer: []dns.RR{
newSRV("prod.*.skydns.test. 300 IN SRV 10 25 0 unresolvable.skydns.test."), testing.SRV("prod.*.skydns.test. 300 IN SRV 10 25 0 unresolvable.skydns.test."),
newSRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 a.server1.prod.region1.skydns.test."), testing.SRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 a.server1.prod.region1.skydns.test."),
newSRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 b.server1.prod.region1.skydns.test."), testing.SRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 b.server1.prod.region1.skydns.test."),
newSRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 b.server6.prod.region1.skydns.test."), testing.SRV("prod.*.skydns.test. 300 IN SRV 10 25 8080 b.server6.prod.region1.skydns.test."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"), testing.A("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"),
newA("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"), testing.A("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"),
newAAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"), testing.AAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"),
}, },
}, },
// Wildcard Test // Wildcard Test
{ {
Qname: "prod.any.skydns.test.", Qtype: dns.TypeSRV, Qname: "prod.any.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{ Answer: []dns.RR{
newSRV("prod.any.skydns.test. 300 IN SRV 10 25 0 unresolvable.skydns.test."), testing.SRV("prod.any.skydns.test. 300 IN SRV 10 25 0 unresolvable.skydns.test."),
newSRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 a.server1.prod.region1.skydns.test."), testing.SRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 a.server1.prod.region1.skydns.test."),
newSRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 b.server1.prod.region1.skydns.test."), testing.SRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 b.server1.prod.region1.skydns.test."),
newSRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 b.server6.prod.region1.skydns.test."), testing.SRV("prod.any.skydns.test. 300 IN SRV 10 25 8080 b.server6.prod.region1.skydns.test."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"), testing.A("a.server1.prod.region1.skydns.test. 300 IN A 10.0.0.1"),
newA("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"), testing.A("b.server1.prod.region1.skydns.test. 300 IN A 10.0.0.2"),
newAAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"), testing.AAAA("b.server6.prod.region1.skydns.test. 300 IN AAAA ::1"),
}, },
}, },
// CNAME loop detection // CNAME loop detection
{ {
Qname: "a.cname.skydns.test.", Qtype: dns.TypeA, Qname: "a.cname.skydns.test.", Qtype: dns.TypeA,
Ns: []dns.RR{newSOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 1407441600 28800 7200 604800 60")}, Ns: []dns.RR{testing.SOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 1407441600 28800 7200 604800 60")},
}, },
// NODATA Test // NODATA Test
{ {
Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeTXT, Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeTXT,
Ns: []dns.RR{newSOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0")}, Ns: []dns.RR{testing.SOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0")},
}, },
} }

View file

@ -3,17 +3,15 @@
package etcd package etcd
// etcd needs to be running on http://127.0.0.1:2379 // etcd needs to be running on http://127.0.0.1:2379
// *and* needs connectivity to the internet for remotely resolving // *and* needs connectivity to the internet for remotely resolving names.
// names.
import ( import (
"sort" "sort"
"testing" "testing"
"golang.org/x/net/context"
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -21,7 +19,7 @@ import (
func TestMultiLookup(t *testing.T) { func TestMultiLookup(t *testing.T) {
etcMulti := etc etcMulti := etc
etcMulti.Zones = []string{"skydns.test.", "miek.nl."} etcMulti.Zones = []string{"skydns.test.", "miek.nl."}
etcMulti.Next = handler() etcMulti.Next = coretest.ErrorHandler()
for _, serv := range servicesMulti { for _, serv := range servicesMulti {
set(t, etcMulti, serv.Key, 0, serv) set(t, etcMulti, serv.Key, 0, serv)
@ -39,9 +37,9 @@ func TestMultiLookup(t *testing.T) {
} }
resp := rec.Msg() resp := rec.Msg()
sort.Sort(rrSet(resp.Answer)) sort.Sort(coretest.RRSet(resp.Answer))
sort.Sort(rrSet(resp.Ns)) sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(rrSet(resp.Extra)) sort.Sort(coretest.RRSet(resp.Extra))
if resp.Rcode != tc.Rcode { if resp.Rcode != tc.Rcode {
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
@ -65,14 +63,14 @@ func TestMultiLookup(t *testing.T) {
continue continue
} }
if !checkSection(t, tc, Answer, resp.Answer) { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Ns, resp.Ns) { if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Extra, resp.Extra) { if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
} }
@ -85,25 +83,16 @@ var servicesMulti = []*msg.Service{
{Host: "dev.server1", Port: 8080, Key: "a.server1.dev.region1.example.org."}, {Host: "dev.server1", Port: 8080, Key: "a.server1.dev.region1.example.org."},
} }
var dnsTestCasesMulti = []dnsTestCase{ var dnsTestCasesMulti = []coretest.Case{
{ {
Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV, Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("a.server1.dev.region1.skydns.test. 300 SRV 10 100 8080 dev.server1.")}, Answer: []dns.RR{coretest.SRV("a.server1.dev.region1.skydns.test. 300 SRV 10 100 8080 dev.server1.")},
}, },
{ {
Qname: "a.server1.dev.region1.miek.nl.", Qtype: dns.TypeSRV, Qname: "a.server1.dev.region1.miek.nl.", Qtype: dns.TypeSRV,
Answer: []dns.RR{newSRV("a.server1.dev.region1.miek.nl. 300 SRV 10 100 8080 dev.server1.")}, Answer: []dns.RR{coretest.SRV("a.server1.dev.region1.miek.nl. 300 SRV 10 100 8080 dev.server1.")},
}, },
{ {
Qname: "a.server1.dev.region1.example.org.", Qtype: dns.TypeSRV, Rcode: dns.RcodeServerFailure, Qname: "a.server1.dev.region1.example.org.", Qtype: dns.TypeSRV, Rcode: dns.RcodeServerFailure,
}, },
} }
func handler() middleware.Handler {
return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeServerFailure)
w.WriteMsg(m)
return dns.RcodeServerFailure, nil
})
}

View file

@ -14,6 +14,7 @@ import (
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
) )
@ -35,9 +36,9 @@ func TestOtherLookup(t *testing.T) {
} }
resp := rec.Msg() resp := rec.Msg()
sort.Sort(rrSet(resp.Answer)) sort.Sort(coretest.RRSet(resp.Answer))
sort.Sort(rrSet(resp.Ns)) sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(rrSet(resp.Extra)) sort.Sort(coretest.RRSet(resp.Extra))
if resp.Rcode != tc.Rcode { if resp.Rcode != tc.Rcode {
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
@ -61,14 +62,14 @@ func TestOtherLookup(t *testing.T) {
continue continue
} }
if !checkSection(t, tc, Answer, resp.Answer) { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Ns, resp.Ns) { if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Extra, resp.Extra) { if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
} }
@ -98,57 +99,57 @@ var servicesOther = []*msg.Service{
{Host: "10.11.11.10", Key: "https.multiport.http.skydns.test.", Port: 443}, {Host: "10.11.11.10", Key: "https.multiport.http.skydns.test.", Port: 443},
} }
var dnsTestCasesOther = []dnsTestCase{ var dnsTestCasesOther = []coretest.Case{
// MX Tests // MX Tests
{ {
// NODATA as this is not an Mail: true record. // NODATA as this is not an Mail: true record.
Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeMX, Qname: "a.server1.dev.region1.skydns.test.", Qtype: dns.TypeMX,
Ns: []dns.RR{ Ns: []dns.RR{
newSOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0"), coretest.SOA("skydns.test. 300 SOA ns.dns.skydns.test. hostmaster.skydns.test. 0 0 0 0 0"),
}, },
}, },
{ {
Qname: "a.mail.skydns.test.", Qtype: dns.TypeMX, Qname: "a.mail.skydns.test.", Qtype: dns.TypeMX,
Answer: []dns.RR{newMX("a.mail.skydns.test. 300 IN MX 50 mx.skydns.test.")}, Answer: []dns.RR{coretest.MX("a.mail.skydns.test. 300 IN MX 50 mx.skydns.test.")},
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.ipaddr.skydns.test. 300 IN A 172.16.1.1"), coretest.A("a.ipaddr.skydns.test. 300 IN A 172.16.1.1"),
newCNAME("mx.skydns.test. 300 IN CNAME a.ipaddr.skydns.test."), coretest.CNAME("mx.skydns.test. 300 IN CNAME a.ipaddr.skydns.test."),
}, },
}, },
{ {
Qname: "mx2.skydns.test.", Qtype: dns.TypeMX, Qname: "mx2.skydns.test.", Qtype: dns.TypeMX,
Answer: []dns.RR{ Answer: []dns.RR{
newMX("mx2.skydns.test. 300 IN MX 10 a.ipaddr.skydns.test."), coretest.MX("mx2.skydns.test. 300 IN MX 10 a.ipaddr.skydns.test."),
newMX("mx2.skydns.test. 300 IN MX 10 b.ipaddr.skydns.test."), coretest.MX("mx2.skydns.test. 300 IN MX 10 b.ipaddr.skydns.test."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.ipaddr.skydns.test. 300 A 172.16.1.1"), coretest.A("a.ipaddr.skydns.test. 300 A 172.16.1.1"),
newA("b.ipaddr.skydns.test. 300 A 172.16.1.2"), coretest.A("b.ipaddr.skydns.test. 300 A 172.16.1.2"),
}, },
}, },
// Txt // Txt
{ {
Qname: "a1.txt.skydns.test.", Qtype: dns.TypeTXT, Qname: "a1.txt.skydns.test.", Qtype: dns.TypeTXT,
Answer: []dns.RR{ Answer: []dns.RR{
newTXT("a1.txt.skydns.test. 300 IN TXT \"abc\""), coretest.TXT("a1.txt.skydns.test. 300 IN TXT \"abc\""),
}, },
}, },
{ {
Qname: "a2.txt.skydns.test.", Qtype: dns.TypeTXT, Qname: "a2.txt.skydns.test.", Qtype: dns.TypeTXT,
Answer: []dns.RR{ Answer: []dns.RR{
newTXT("a2.txt.skydns.test. 300 IN TXT \"abc abc\""), coretest.TXT("a2.txt.skydns.test. 300 IN TXT \"abc abc\""),
}, },
}, },
{ {
Qname: "txt.skydns.test.", Qtype: dns.TypeTXT, Qname: "txt.skydns.test.", Qtype: dns.TypeTXT,
Answer: []dns.RR{ Answer: []dns.RR{
newTXT("txt.skydns.test. 300 IN TXT \"abc abc\""), coretest.TXT("txt.skydns.test. 300 IN TXT \"abc abc\""),
newTXT("txt.skydns.test. 300 IN TXT \"abc\""), coretest.TXT("txt.skydns.test. 300 IN TXT \"abc\""),
}, },
}, },
// Duplicate IP address test // Duplicate IP address test
{ {
Qname: "multiport.http.skydns.test.", Qtype: dns.TypeA, Qname: "multiport.http.skydns.test.", Qtype: dns.TypeA,
Answer: []dns.RR{newA("multiport.http.skydns.test. 300 IN A 10.11.11.10")}, Answer: []dns.RR{coretest.A("multiport.http.skydns.test. 300 IN A 10.11.11.10")},
}, },
} }

View file

@ -3,8 +3,7 @@
package etcd package etcd
// etcd needs to be running on http://127.0.0.1:2379 // etcd needs to be running on http://127.0.0.1:2379
// *and* needs connectivity to the internet for remotely resolving // *and* needs connectivity to the internet for remotely resolving names.
// names.
import ( import (
"encoding/json" "encoding/json"
@ -16,6 +15,7 @@ import (
"github.com/miekg/coredns/middleware/etcd/msg" "github.com/miekg/coredns/middleware/etcd/msg"
"github.com/miekg/coredns/middleware/etcd/singleflight" "github.com/miekg/coredns/middleware/etcd/singleflight"
"github.com/miekg/coredns/middleware/proxy" "github.com/miekg/coredns/middleware/proxy"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
etcdc "github.com/coreos/etcd/client" etcdc "github.com/coreos/etcd/client"
@ -28,14 +28,6 @@ var (
ctx context.Context ctx context.Context
) )
type Section int
const (
Answer Section = iota
Ns
Extra
)
func init() { func init() {
ctx, _ = context.WithTimeout(context.Background(), etcdTimeout) ctx, _ = context.WithTimeout(context.Background(), etcdTimeout)
@ -67,12 +59,6 @@ func delete(t *testing.T, e Etcd, k string) {
e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false}) e.Client.Delete(ctx, path, &etcdc.DeleteOptions{Recursive: false})
} }
type rrSet []dns.RR
func (p rrSet) Len() int { return len(p) }
func (p rrSet) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p rrSet) Less(i, j int) bool { return p[i].String() < p[j].String() }
func TestLookup(t *testing.T) { func TestLookup(t *testing.T) {
for _, serv := range services { for _, serv := range services {
set(t, etc, serv.Key, 0, serv) set(t, etc, serv.Key, 0, serv)
@ -90,9 +76,9 @@ func TestLookup(t *testing.T) {
} }
resp := rec.Msg() resp := rec.Msg()
sort.Sort(rrSet(resp.Answer)) sort.Sort(coretest.RRSet(resp.Answer))
sort.Sort(rrSet(resp.Ns)) sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(rrSet(resp.Extra)) sort.Sort(coretest.RRSet(resp.Extra))
if resp.Rcode != tc.Rcode { if resp.Rcode != tc.Rcode {
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
@ -116,134 +102,15 @@ func TestLookup(t *testing.T) {
continue continue
} }
if !checkSection(t, tc, Answer, resp.Answer) { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Ns, resp.Ns) { if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
if !checkSection(t, tc, Extra, resp.Extra) { if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
} }
} }
} }
type dnsTestCase struct {
Qname string
Qtype uint16
Rcode int
Answer []dns.RR
Ns []dns.RR
Extra []dns.RR
}
func newA(rr string) *dns.A { r, _ := dns.NewRR(rr); return r.(*dns.A) }
func newAAAA(rr string) *dns.AAAA { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) }
func newCNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) }
func newSRV(rr string) *dns.SRV { r, _ := dns.NewRR(rr); return r.(*dns.SRV) }
func newSOA(rr string) *dns.SOA { r, _ := dns.NewRR(rr); return r.(*dns.SOA) }
func newNS(rr string) *dns.NS { r, _ := dns.NewRR(rr); return r.(*dns.NS) }
func newPTR(rr string) *dns.PTR { r, _ := dns.NewRR(rr); return r.(*dns.PTR) }
func newTXT(rr string) *dns.TXT { r, _ := dns.NewRR(rr); return r.(*dns.TXT) }
func newMX(rr string) *dns.MX { r, _ := dns.NewRR(rr); return r.(*dns.MX) }
func checkSection(t *testing.T, tc dnsTestCase, sect Section, rr []dns.RR) bool {
section := []dns.RR{}
switch sect {
case 0:
section = tc.Answer
case 1:
section = tc.Ns
case 2:
section = tc.Extra
}
for i, a := range rr {
if a.Header().Name != section[i].Header().Name {
t.Errorf("rr %d should have a Header Name of %q, but has %q", i, section[i].Header().Name, a.Header().Name)
return false
}
// 303 signals: don't care what the ttl is.
if section[i].Header().Ttl != 303 && a.Header().Ttl != section[i].Header().Ttl {
t.Errorf("rr %d should have a Header TTL of %d, but has %d", i, section[i].Header().Ttl, a.Header().Ttl)
return false
}
if a.Header().Rrtype != section[i].Header().Rrtype {
t.Errorf("rr %d should have a header rr type of %d, but has %d", i, section[i].Header().Rrtype, a.Header().Rrtype)
return false
}
switch x := a.(type) {
case *dns.SRV:
if x.Priority != section[i].(*dns.SRV).Priority {
t.Errorf("rr %d should have a Priority of %d, but has %d", i, section[i].(*dns.SRV).Priority, x.Priority)
return false
}
if x.Weight != section[i].(*dns.SRV).Weight {
t.Errorf("rr %d should have a Weight of %d, but has %d", i, section[i].(*dns.SRV).Weight, x.Weight)
return false
}
if x.Port != section[i].(*dns.SRV).Port {
t.Errorf("rr %d should have a Port of %d, but has %d", i, section[i].(*dns.SRV).Port, x.Port)
return false
}
if x.Target != section[i].(*dns.SRV).Target {
t.Errorf("rr %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target)
return false
}
case *dns.A:
if x.A.String() != section[i].(*dns.A).A.String() {
t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String())
return false
}
case *dns.AAAA:
if x.AAAA.String() != section[i].(*dns.AAAA).AAAA.String() {
t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.AAAA).AAAA.String(), x.AAAA.String())
return false
}
case *dns.TXT:
for j, txt := range x.Txt {
if txt != section[i].(*dns.TXT).Txt[j] {
t.Errorf("rr %d should have a Txt of %q, but has %q", i, section[i].(*dns.TXT).Txt[j], txt)
return false
}
}
case *dns.SOA:
tt := section[i].(*dns.SOA)
if x.Ns != tt.Ns {
t.Errorf("SOA nameserver should be %q, but is %q", x.Ns, tt.Ns)
return false
}
case *dns.PTR:
tt := section[i].(*dns.PTR)
if x.Ptr != tt.Ptr {
t.Errorf("PTR ptr should be %q, but is %q", x.Ptr, tt.Ptr)
return false
}
case *dns.CNAME:
tt := section[i].(*dns.CNAME)
if x.Target != tt.Target {
t.Errorf("CNAME target should be %q, but is %q", x.Target, tt.Target)
return false
}
case *dns.MX:
tt := section[i].(*dns.MX)
if x.Mx != tt.Mx {
t.Errorf("MX Mx should be %q, but is %q", x.Mx, tt.Mx)
return false
}
if x.Preference != tt.Preference {
t.Errorf("MX Preference should be %q, but is %q", x.Preference, tt.Preference)
return false
}
case *dns.NS:
tt := section[i].(*dns.NS)
if x.Ns != tt.Ns {
t.Errorf("NS nameserver should be %q, but is %q", x.Ns, tt.Ns)
return false
}
}
}
return true
}

View file

@ -6,66 +6,61 @@ import (
"testing" "testing"
"github.com/miekg/coredns/middleware" "github.com/miekg/coredns/middleware"
coretest "github.com/miekg/coredns/middleware/testing"
"github.com/miekg/dns" "github.com/miekg/dns"
"golang.org/x/net/context" "golang.org/x/net/context"
) )
var dnsTestCases = []dnsTestCase{ var dnsTestCases = []coretest.Case{
{ {
Qname: "miek.nl.", Qtype: dns.TypeSOA, Qname: "miek.nl.", Qtype: dns.TypeSOA,
Answer: []dns.RR{ Answer: []dns.RR{
newSOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
}, },
}, },
{ {
Qname: "miek.nl.", Qtype: dns.TypeAAAA, Qname: "miek.nl.", Qtype: dns.TypeAAAA,
Answer: []dns.RR{ Answer: []dns.RR{
newAAAA("miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"), coretest.AAAA("miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"),
}, },
}, },
{ {
Qname: "miek.nl.", Qtype: dns.TypeMX, Qname: "miek.nl.", Qtype: dns.TypeMX,
Answer: []dns.RR{ Answer: []dns.RR{
newMX("miek.nl. 1800 IN MX 1 aspmx.l.google.com."), coretest.MX("miek.nl. 1800 IN MX 1 aspmx.l.google.com."),
newMX("miek.nl. 1800 IN MX 10 aspmx2.googlemail.com."), coretest.MX("miek.nl. 1800 IN MX 10 aspmx2.googlemail.com."),
newMX("miek.nl. 1800 IN MX 10 aspmx3.googlemail.com."), coretest.MX("miek.nl. 1800 IN MX 10 aspmx3.googlemail.com."),
newMX("miek.nl. 1800 IN MX 5 alt1.aspmx.l.google.com."), coretest.MX("miek.nl. 1800 IN MX 5 alt1.aspmx.l.google.com."),
newMX("miek.nl. 1800 IN MX 5 alt2.aspmx.l.google.com."), coretest.MX("miek.nl. 1800 IN MX 5 alt2.aspmx.l.google.com."),
}, },
}, },
{ {
Qname: "www.miek.nl.", Qtype: dns.TypeA, Qname: "www.miek.nl.", Qtype: dns.TypeA,
Answer: []dns.RR{ Answer: []dns.RR{
newCNAME("www.miek.nl. 1800 IN CNAME a.miek.nl."), coretest.CNAME("www.miek.nl. 1800 IN CNAME a.miek.nl."),
}, },
Extra: []dns.RR{ Extra: []dns.RR{
newA("a.miek.nl. 1800 IN A 139.162.196.78"), coretest.A("a.miek.nl. 1800 IN A 139.162.196.78"),
newAAAA("a.miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"), coretest.AAAA("a.miek.nl. 1800 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735"),
}, },
}, },
{ {
Qname: "a.miek.nl.", Qtype: dns.TypeSRV, Qname: "a.miek.nl.", Qtype: dns.TypeSRV,
Ns: []dns.RR{ Ns: []dns.RR{
newSOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
}, },
}, },
{ {
Qname: "b.miek.nl.", Qtype: dns.TypeA, Qname: "b.miek.nl.", Qtype: dns.TypeA,
Rcode: dns.RcodeNameError, Rcode: dns.RcodeNameError,
Ns: []dns.RR{ Ns: []dns.RR{
newSOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"), coretest.SOA("miek.nl. 1800 IN SOA linode.atoom.net. miek.miek.nl. 1282630057 14400 3600 604800 14400"),
}, },
}, },
} }
type rrSet []dns.RR
func (p rrSet) Len() int { return len(p) }
func (p rrSet) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p rrSet) Less(i, j int) bool { return p[i].String() < p[j].String() }
const testzone = "miek.nl." const testzone = "miek.nl."
func TestLookup(t *testing.T) { func TestLookup(t *testing.T) {
@ -74,7 +69,7 @@ func TestLookup(t *testing.T) {
t.Fatalf("expect no error when reading zone, got %q", err) t.Fatalf("expect no error when reading zone, got %q", err)
} }
fm := File{Next: handler(), Zones: Zones{Z: map[string]*Zone{testzone: zone}, Names: []string{testzone}}} fm := File{Next: coretest.ErrorHandler(), Zones: Zones{Z: map[string]*Zone{testzone: zone}, Names: []string{testzone}}}
ctx := context.TODO() ctx := context.TODO()
for _, tc := range dnsTestCases { for _, tc := range dnsTestCases {
@ -89,9 +84,9 @@ func TestLookup(t *testing.T) {
} }
resp := rec.Msg() resp := rec.Msg()
sort.Sort(rrSet(resp.Answer)) sort.Sort(coretest.RRSet(resp.Answer))
sort.Sort(rrSet(resp.Ns)) sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(rrSet(resp.Extra)) sort.Sort(coretest.RRSet(resp.Extra))
if resp.Rcode != tc.Rcode { if resp.Rcode != tc.Rcode {
t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
@ -114,27 +109,19 @@ func TestLookup(t *testing.T) {
t.Logf("%v\n", resp) t.Logf("%v\n", resp)
continue continue
} }
}
}
type dnsTestCase struct { if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
Qname string t.Logf("%v\n", resp)
Qtype uint16
Rcode int
Answer []dns.RR
Ns []dns.RR
Extra []dns.RR
} }
if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
func newA(rr string) *dns.A { r, _ := dns.NewRR(rr); return r.(*dns.A) } }
func newAAAA(rr string) *dns.AAAA { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) } if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
func newCNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) } t.Logf("%v\n", resp)
func newSRV(rr string) *dns.SRV { r, _ := dns.NewRR(rr); return r.(*dns.SRV) } }
func newSOA(rr string) *dns.SOA { r, _ := dns.NewRR(rr); return r.(*dns.SOA) } }
func newNS(rr string) *dns.NS { r, _ := dns.NewRR(rr); return r.(*dns.NS) } }
func newPTR(rr string) *dns.PTR { r, _ := dns.NewRR(rr); return r.(*dns.PTR) }
func newTXT(rr string) *dns.TXT { r, _ := dns.NewRR(rr); return r.(*dns.TXT) }
func newMX(rr string) *dns.MX { r, _ := dns.NewRR(rr); return r.(*dns.MX) }
const dbMiekNL = ` const dbMiekNL = `
$TTL 30M $TTL 30M
@ -163,12 +150,3 @@ a IN A 139.162.196.78
IN AAAA 2a01:7e00::f03c:91ff:fef1:6735 IN AAAA 2a01:7e00::f03c:91ff:fef1:6735
www IN CNAME a www IN CNAME a
archive IN CNAME a` archive IN CNAME a`
func handler() middleware.Handler {
return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeServerFailure)
w.WriteMsg(m)
return dns.RcodeServerFailure, nil
})
}

View file

@ -0,0 +1,152 @@
package testing
import (
"testing"
"github.com/miekg/coredns/middleware"
"github.com/miekg/dns"
"golang.org/x/net/context"
)
type Section int
const (
Answer Section = iota
Ns
Extra
)
type RRSet []dns.RR
func (p RRSet) Len() int { return len(p) }
func (p RRSet) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p RRSet) Less(i, j int) bool { return p[i].String() < p[j].String() }
type Case struct {
Qname string
Qtype uint16
Rcode int
Answer []dns.RR
Ns []dns.RR
Extra []dns.RR
}
func A(rr string) *dns.A { r, _ := dns.NewRR(rr); return r.(*dns.A) }
func AAAA(rr string) *dns.AAAA { r, _ := dns.NewRR(rr); return r.(*dns.AAAA) }
func CNAME(rr string) *dns.CNAME { r, _ := dns.NewRR(rr); return r.(*dns.CNAME) }
func SRV(rr string) *dns.SRV { r, _ := dns.NewRR(rr); return r.(*dns.SRV) }
func SOA(rr string) *dns.SOA { r, _ := dns.NewRR(rr); return r.(*dns.SOA) }
func NS(rr string) *dns.NS { r, _ := dns.NewRR(rr); return r.(*dns.NS) }
func PTR(rr string) *dns.PTR { r, _ := dns.NewRR(rr); return r.(*dns.PTR) }
func TXT(rr string) *dns.TXT { r, _ := dns.NewRR(rr); return r.(*dns.TXT) }
func MX(rr string) *dns.MX { r, _ := dns.NewRR(rr); return r.(*dns.MX) }
func CheckSection(t *testing.T, tc Case, sect Section, rr []dns.RR) bool {
section := []dns.RR{}
switch sect {
case 0:
section = tc.Answer
case 1:
section = tc.Ns
case 2:
section = tc.Extra
}
for i, a := range rr {
if a.Header().Name != section[i].Header().Name {
t.Errorf("rr %d should have a Header Name of %q, but has %q", i, section[i].Header().Name, a.Header().Name)
return false
}
// 303 signals: don't care what the ttl is.
if section[i].Header().Ttl != 303 && a.Header().Ttl != section[i].Header().Ttl {
t.Errorf("rr %d should have a Header TTL of %d, but has %d", i, section[i].Header().Ttl, a.Header().Ttl)
return false
}
if a.Header().Rrtype != section[i].Header().Rrtype {
t.Errorf("rr %d should have a header rr type of %d, but has %d", i, section[i].Header().Rrtype, a.Header().Rrtype)
return false
}
switch x := a.(type) {
case *dns.SRV:
if x.Priority != section[i].(*dns.SRV).Priority {
t.Errorf("rr %d should have a Priority of %d, but has %d", i, section[i].(*dns.SRV).Priority, x.Priority)
return false
}
if x.Weight != section[i].(*dns.SRV).Weight {
t.Errorf("rr %d should have a Weight of %d, but has %d", i, section[i].(*dns.SRV).Weight, x.Weight)
return false
}
if x.Port != section[i].(*dns.SRV).Port {
t.Errorf("rr %d should have a Port of %d, but has %d", i, section[i].(*dns.SRV).Port, x.Port)
return false
}
if x.Target != section[i].(*dns.SRV).Target {
t.Errorf("rr %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target)
return false
}
case *dns.A:
if x.A.String() != section[i].(*dns.A).A.String() {
t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String())
return false
}
case *dns.AAAA:
if x.AAAA.String() != section[i].(*dns.AAAA).AAAA.String() {
t.Errorf("rr %d should have a Address of %q, but has %q", i, section[i].(*dns.AAAA).AAAA.String(), x.AAAA.String())
return false
}
case *dns.TXT:
for j, txt := range x.Txt {
if txt != section[i].(*dns.TXT).Txt[j] {
t.Errorf("rr %d should have a Txt of %q, but has %q", i, section[i].(*dns.TXT).Txt[j], txt)
return false
}
}
case *dns.SOA:
tt := section[i].(*dns.SOA)
if x.Ns != tt.Ns {
t.Errorf("SOA nameserver should be %q, but is %q", x.Ns, tt.Ns)
return false
}
case *dns.PTR:
tt := section[i].(*dns.PTR)
if x.Ptr != tt.Ptr {
t.Errorf("PTR ptr should be %q, but is %q", x.Ptr, tt.Ptr)
return false
}
case *dns.CNAME:
tt := section[i].(*dns.CNAME)
if x.Target != tt.Target {
t.Errorf("CNAME target should be %q, but is %q", x.Target, tt.Target)
return false
}
case *dns.MX:
tt := section[i].(*dns.MX)
if x.Mx != tt.Mx {
t.Errorf("MX Mx should be %q, but is %q", x.Mx, tt.Mx)
return false
}
if x.Preference != tt.Preference {
t.Errorf("MX Preference should be %q, but is %q", x.Preference, tt.Preference)
return false
}
case *dns.NS:
tt := section[i].(*dns.NS)
if x.Ns != tt.Ns {
t.Errorf("NS nameserver should be %q, but is %q", x.Ns, tt.Ns)
return false
}
}
}
return true
}
func ErrorHandler() middleware.Handler {
return middleware.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeServerFailure)
w.WriteMsg(m)
return dns.RcodeServerFailure, nil
})
}