aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml9
-rw-r--r--core/caddy.go23
-rw-r--r--middleware/etcd/cname_test.go27
-rw-r--r--middleware/etcd/group_test.go27
-rw-r--r--middleware/etcd/multi_test.go27
-rw-r--r--middleware/etcd/other_test.go27
-rw-r--r--middleware/etcd/setup_test.go28
-rw-r--r--middleware/etcd/stub_test.go1
-rw-r--r--middleware/file/wildcard_test.go1
-rw-r--r--server/server.go52
-rw-r--r--test/etcd_test.go11
-rw-r--r--test/server_test.go53
-rw-r--r--test/tests.go40
13 files changed, 191 insertions, 135 deletions
diff --git a/.travis.yml b/.travis.yml
index a9154fe68..5f16201cf 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,12 @@
language: go
-sudo: false
go:
- 1.5
- 1.6
+before_script:
+ - go get github.com/coreos/etcd
+ - go get github.com/coreos/go-etcd/etcd
+ - go build -o $HOME/gopath/src/github.com/coreos/etcd/etcd.run github.com/coreos/etcd
+ - $HOME/gopath/src/github.com/coreos/etcd/etcd.run &
+ - sleep 2
script:
- - go test -race -bench=. ./...
+ - go test -tags etcd -race -bench=. ./...
diff --git a/core/caddy.go b/core/caddy.go
index e76fa28f1..df84e679a 100644
--- a/core/caddy.go
+++ b/core/caddy.go
@@ -26,6 +26,7 @@ import (
"strings"
"sync"
"sync/atomic"
+ "testing"
"time"
"github.com/miekg/coredns/core/https"
@@ -236,6 +237,7 @@ func startServers(groupings bindingGroup) error {
// start the server
// TODO(miek): for now will always be nil, so we will run ListenAndServe()
+ // TODO(miek): this is also why graceful restarts don't work.
if ln != nil {
//errChan <- s.Serve(ln)
} else {
@@ -386,3 +388,24 @@ type Input interface {
// that could be loaded again later if requested.
IsFile() bool
}
+
+// TestServer returns a test server.
+// The port can be retreived with ... . The testserver itself can be stopped
+// with Stop(). It just takes a normal Corefile input, but doesn't use the port.
+func TestServer(t *testing.T, corefile string) (*server.Server, error) {
+
+ cdyfile := CaddyfileInput{Contents: []byte(corefile)}
+ configs, err := loadConfigs(path.Base(cdyfile.Path()), bytes.NewReader(cdyfile.Body()))
+ if err != nil {
+ return nil, err
+ }
+ groupings, err := arrangeBindings(configs)
+ if err != nil {
+ return nil, err
+ }
+ t.Logf("Starting %d servers", len(groupings))
+
+ group := groupings[0]
+ s, err := server.New(group.BindAddr.String(), group.Configs, time.Second)
+ return s, err
+}
diff --git a/middleware/etcd/cname_test.go b/middleware/etcd/cname_test.go
index 33e42aac7..147498d64 100644
--- a/middleware/etcd/cname_test.go
+++ b/middleware/etcd/cname_test.go
@@ -31,36 +31,17 @@ func TestCnameLookup(t *testing.T) {
}
resp := rec.Msg()
- if resp.Rcode != tc.Rcode {
- t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
+ if !coretest.Header(t, tc, resp) {
t.Logf("%v\n", resp)
continue
}
-
- if len(resp.Answer) != len(tc.Answer) {
- t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Ns) != len(tc.Ns) {
- t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Extra) != len(tc.Extra) {
- t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
- t.Logf("%v\n", resp)
- continue
- }
-
- if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
+ if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
- if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
+ if !coretest.Section(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
-
}
- if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
+ if !coretest.Section(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp)
}
}
diff --git a/middleware/etcd/group_test.go b/middleware/etcd/group_test.go
index d7098c0c7..e37159f3f 100644
--- a/middleware/etcd/group_test.go
+++ b/middleware/etcd/group_test.go
@@ -37,36 +37,17 @@ func TestGroupLookup(t *testing.T) {
sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(coretest.RRSet(resp.Extra))
- if resp.Rcode != tc.Rcode {
- t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
+ if !coretest.Header(t, tc, resp) {
t.Logf("%v\n", resp)
continue
}
-
- if len(resp.Answer) != len(tc.Answer) {
- t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Ns) != len(tc.Ns) {
- t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Extra) != len(tc.Extra) {
- t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
- t.Logf("%v\n", resp)
- continue
- }
-
- if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
+ if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
- if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
+ if !coretest.Section(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
-
}
- if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
+ if !coretest.Section(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp)
}
}
diff --git a/middleware/etcd/multi_test.go b/middleware/etcd/multi_test.go
index cae43f18a..980b17a53 100644
--- a/middleware/etcd/multi_test.go
+++ b/middleware/etcd/multi_test.go
@@ -40,36 +40,17 @@ func TestMultiLookup(t *testing.T) {
sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(coretest.RRSet(resp.Extra))
- if resp.Rcode != tc.Rcode {
- t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
+ if !coretest.Header(t, tc, resp) {
t.Logf("%v\n", resp)
continue
}
-
- if len(resp.Answer) != len(tc.Answer) {
- t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Ns) != len(tc.Ns) {
- t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Extra) != len(tc.Extra) {
- t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
- t.Logf("%v\n", resp)
- continue
- }
-
- if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
+ if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
- if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
+ if !coretest.Section(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
-
}
- if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
+ if !coretest.Section(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp)
}
}
diff --git a/middleware/etcd/other_test.go b/middleware/etcd/other_test.go
index da1cc7d74..ac0db7d3e 100644
--- a/middleware/etcd/other_test.go
+++ b/middleware/etcd/other_test.go
@@ -39,36 +39,17 @@ func TestOtherLookup(t *testing.T) {
sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(coretest.RRSet(resp.Extra))
- if resp.Rcode != tc.Rcode {
- t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
+ if !coretest.Header(t, tc, resp) {
t.Logf("%v\n", resp)
continue
}
-
- if len(resp.Answer) != len(tc.Answer) {
- t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Ns) != len(tc.Ns) {
- t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Extra) != len(tc.Extra) {
- t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
- t.Logf("%v\n", resp)
- continue
- }
-
- if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
+ if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
- if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
+ if !coretest.Section(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
-
}
- if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
+ if !coretest.Section(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp)
}
}
diff --git a/middleware/etcd/setup_test.go b/middleware/etcd/setup_test.go
index acc062f1d..8fbfd1b5f 100644
--- a/middleware/etcd/setup_test.go
+++ b/middleware/etcd/setup_test.go
@@ -18,7 +18,6 @@ import (
coretest "github.com/miekg/coredns/middleware/testing"
etcdc "github.com/coreos/etcd/client"
- "github.com/miekg/dns"
"golang.org/x/net/context"
)
@@ -79,36 +78,17 @@ func TestLookup(t *testing.T) {
sort.Sort(coretest.RRSet(resp.Ns))
sort.Sort(coretest.RRSet(resp.Extra))
- if resp.Rcode != tc.Rcode {
- t.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode])
+ if !coretest.Header(t, tc, resp) {
t.Logf("%v\n", resp)
continue
}
-
- if len(resp.Answer) != len(tc.Answer) {
- t.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Ns) != len(tc.Ns) {
- t.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns))
- t.Logf("%v\n", resp)
- continue
- }
- if len(resp.Extra) != len(tc.Extra) {
- t.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra))
- t.Logf("%v\n", resp)
- continue
- }
-
- if !coretest.CheckSection(t, tc, coretest.Answer, resp.Answer) {
+ if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
- if !coretest.CheckSection(t, tc, coretest.Ns, resp.Ns) {
+ if !coretest.Section(t, tc, coretest.Ns, resp.Ns) {
t.Logf("%v\n", resp)
-
}
- if !coretest.CheckSection(t, tc, coretest.Extra, resp.Extra) {
+ if !coretest.Section(t, tc, coretest.Extra, resp.Extra) {
t.Logf("%v\n", resp)
}
}
diff --git a/middleware/etcd/stub_test.go b/middleware/etcd/stub_test.go
index 789809a50..37bd840a7 100644
--- a/middleware/etcd/stub_test.go
+++ b/middleware/etcd/stub_test.go
@@ -5,6 +5,7 @@ package etcd
import "testing"
func TestStubLookup(t *testing.T) {
+ // MOVE THIS TO etcd_Test.go in the main directory
// e.updateStubZones()
}
diff --git a/middleware/file/wildcard_test.go b/middleware/file/wildcard_test.go
index 703938a4e..896889208 100644
--- a/middleware/file/wildcard_test.go
+++ b/middleware/file/wildcard_test.go
@@ -73,7 +73,6 @@ func TestLookupWildcard(t *testing.T) {
t.Logf("%v\n", resp)
continue
}
-
if !coretest.Section(t, tc, coretest.Answer, resp.Answer) {
t.Logf("%v\n", resp)
}
diff --git a/server/server.go b/server/server.go
index 1816fd1dc..e752d4287 100644
--- a/server/server.go
+++ b/server/server.go
@@ -29,9 +29,12 @@ import (
// the same address and the listener may be stopped for
// graceful termination (POSIX only).
type Server struct {
- Addr string // Address we listen on
- mux *dns.ServeMux
- server [2]*dns.Server
+ Addr string // Address we listen on
+ mux *dns.ServeMux
+ server [2]*dns.Server // by convention 0 is tcp and 1 is udp
+ tcp net.Listener
+ udp net.PacketConn
+
tls bool // whether this server is serving all HTTPS hosts or not
TLSConfig *tls.Config
OnDemandTLS bool // whether this server supports on-demand TLS (load certs at handshake-time)
@@ -132,6 +135,16 @@ func New(addr string, configs []Config, gracefulTimeout time.Duration) (*Server,
return s, nil
}
+// LocalAddr return the addresses where the server is bound to. The TCP listener
+// address is the first returned, the UDP conn address the second.
+func (s *Server) LocalAddr() (net.Addr, net.Addr) {
+ s.listenerMu.Lock()
+ tcp := s.tcp.Addr()
+ udp := s.udp.LocalAddr()
+ s.listenerMu.Unlock()
+ return tcp, udp
+}
+
// Serve starts the server with an existing listener. It blocks until the
// server stops.
/*
@@ -155,18 +168,28 @@ func (s *Server) ListenAndServe() error {
return err
}
- // TODO(miek): going out on a limb here, let's assume that listening
- // on the part for tcp and udp results in the same error. We can only
- // return the error from the udp listener, disregarding whatever
- // happenend to the tcp one.
+ l, err := net.Listen("tcp", s.Addr)
+ if err != nil {
+ return err
+ }
+ pc, err := net.ListenPacket("udp", s.Addr)
+ if err != nil {
+ return err
+ }
+
+ s.listenerMu.Lock()
+ s.server[0] = &dns.Server{Listener: l, Net: "tcp", Handler: s.mux}
+ s.tcp = l
+ s.server[1] = &dns.Server{PacketConn: pc, Net: "udp", Handler: s.mux}
+ s.udp = pc
+ s.listenerMu.Unlock()
+
go func() {
- s.server[0] = &dns.Server{Addr: s.Addr, Net: "tcp", Handler: s.mux}
- s.server[0].ListenAndServe()
+ s.server[0].ActivateAndServe()
}()
close(s.startChan) // unblock anyone waiting for this to start listening
- s.server[1] = &dns.Server{Addr: s.Addr, Net: "udp", Handler: s.mux}
- return s.server[1].ListenAndServe()
+ return s.server[1].ActivateAndServe()
}
// setup prepares the server s to begin listening; it should be
@@ -244,14 +267,11 @@ func (s *Server) Stop() (err error) {
if s.listener != nil {
err = s.listener.Close()
}
- s.listenerMu.Unlock()
- // Don't know if the above is still valid.
for _, s1 := range s.server {
- if err := s1.Shutdown(); err != nil {
- return err
- }
+ err = s1.Shutdown()
}
+ s.listenerMu.Unlock()
return
}
diff --git a/test/etcd_test.go b/test/etcd_test.go
new file mode 100644
index 000000000..96be524e4
--- /dev/null
+++ b/test/etcd_test.go
@@ -0,0 +1,11 @@
+// +build etcd
+
+package test
+
+import "testing"
+
+// This test starts two coredns servers (and needs etcd). Configure a stubzones in both (that will loop) and
+// will then test if we detect this loop.
+func TestEtcdStubForwarding(t *testing.T) {
+ // TODO(miek)
+}
diff --git a/test/server_test.go b/test/server_test.go
new file mode 100644
index 000000000..6020e76d3
--- /dev/null
+++ b/test/server_test.go
@@ -0,0 +1,53 @@
+package test
+
+import (
+ "testing"
+
+ "github.com/miekg/dns"
+)
+
+// Start 2 tests server, server A will proxy to B, server B is an CH server.
+func TestProxyToChaosServer(t *testing.T) {
+ corefile := `.:0 {
+ chaos CoreDNS-001 miek@miek.nl
+}
+`
+ chaos, tcpCH, udpCH, err := testServer(t, corefile)
+ if err != nil {
+ t.Fatalf("Could get server: %s", err)
+ }
+ defer chaos.Stop()
+
+ corefileProxy := `.:0 {
+ proxy . ` + udpCH + `
+}
+`
+ proxy, _, udp, err := testServer(t, corefileProxy)
+ if err != nil {
+ t.Fatalf("Could get server: %s", err)
+ }
+ defer proxy.Stop()
+
+ chaosTest(t, udpCH, "udp")
+ chaosTest(t, tcpCH, "tcp")
+
+ chaosTest(t, udp, "udp")
+ // chaosTest(t, tcp, "tcp"), commented out because we use the original transport to reach the
+ // proxy and we only forward to the udp port.
+}
+
+func chaosTest(t *testing.T, server, net string) {
+ m := testMsg("version.bind.", dns.TypeTXT, nil)
+ m.Question[0].Qclass = dns.ClassCHAOS
+
+ r, err := testExchange(m, server, net)
+ if err != nil {
+ t.Fatalf("Could not send message: %s", err)
+ }
+ if r.Rcode != dns.RcodeSuccess || len(r.Answer) == 0 {
+ t.Fatalf("Expected successful reply on %s, got %s", net, dns.RcodeToString[r.Rcode])
+ }
+ if r.Answer[0].String() != `version.bind. 0 CH TXT "CoreDNS-001"` {
+ t.Fatalf("Expected version.bind. reply, got %s", r.Answer[0].String())
+ }
+}
diff --git a/test/tests.go b/test/tests.go
new file mode 100644
index 000000000..2b11a5ac9
--- /dev/null
+++ b/test/tests.go
@@ -0,0 +1,40 @@
+package test
+
+import (
+ "testing"
+ "time"
+
+ "github.com/miekg/coredns/core"
+ "github.com/miekg/coredns/middleware"
+ "github.com/miekg/coredns/server"
+
+ "github.com/miekg/dns"
+)
+
+func testMsg(zone string, typ uint16, o *dns.OPT) *dns.Msg {
+ m := new(dns.Msg)
+ m.SetQuestion(zone, typ)
+ if o != nil {
+ m.Extra = []dns.RR{o}
+ }
+ return m
+}
+
+func testExchange(m *dns.Msg, server, net string) (*dns.Msg, error) {
+ c := new(dns.Client)
+ c.Net = net
+ return middleware.Exchange(c, m, server)
+}
+
+// testServer returns a test server and the tcp and udp listeners addresses.
+func testServer(t *testing.T, corefile string) (*server.Server, string, string, error) {
+ srv, err := core.TestServer(t, corefile)
+ if err != nil {
+ return nil, "", "", err
+ }
+ go srv.ListenAndServe()
+
+ time.Sleep(1 * time.Second)
+ tcp, udp := srv.LocalAddr()
+ return srv, tcp.String(), udp.String(), nil
+}