zettio/weave#362 - improve the unit tests for the TCP server by checking if we get all the responses with TCP when a previous UDP query resulted in a truncated response.

This commit is contained in:
Alvaro Saurin committed 2015-02-23 13:17:54 +01:00
1 parent bf88ed8d96
commit 9c7ffd9b81
3 files changed
+96 -45

No files matched your search

+18 -22
View File
@@ -21,34 +21,31 @@ func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
}
type DNSServer struct {
config *dns.ClientConfig
zone Zone
iface *net.Interface
udpPort int
udpSrv *dns.Server
tcpPort int
tcpSrv *dns.Server
config *dns.ClientConfig
zone Zone
iface *net.Interface
port int
udpSrv *dns.Server
tcpSrv *dns.Server
}
// Creates a new DNS server with a given config
func NewDNSServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, udpPort int, tcpPort int) (*DNSServer, error) {
func NewDNSServerWithConfig(config *dns.ClientConfig, zone Zone, iface *net.Interface, port int) (*DNSServer, error) {
return &DNSServer{
config: config,
zone: zone,
iface: iface,
udpPort: udpPort,
tcpPort: tcpPort,
config: config,
zone: zone,
iface: iface,
port: port,
}, nil
}
// Creates a new DNS server
func NewDNSServer(zone Zone, iface *net.Interface, udpPort int, tcpPort int) (*DNSServer, error) {
func NewDNSServer(zone Zone, iface *net.Interface, port int) (*DNSServer, error) {
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
return nil, err
}
return NewDNSServerWithConfig(config, zone, iface, udpPort, tcpPort)
return NewDNSServerWithConfig(config, zone, iface, port)
}
// Start the DNS server
@@ -75,19 +72,18 @@ func (s *DNSServer) Start() error {
err = mdnsServer.Start(s.iface)
checkFatal(err)
udpAddress := fmt.Sprintf(":%d", s.udpPort)
s.udpSrv = &dns.Server{Addr: udpAddress, Net: "udp", Handler: LocalServeMux}
tcpAddress := fmt.Sprintf(":%d", s.tcpPort)
s.tcpSrv = &dns.Server{Addr: tcpAddress, Net: "tcp", Handler: LocalServeMux}
address := fmt.Sprintf(":%d", s.port)
s.udpSrv = &dns.Server{Addr: address, Net: "udp", Handler: LocalServeMux}
s.tcpSrv = &dns.Server{Addr: address, Net: "tcp", Handler: LocalServeMux}
go func() {
Info.Printf("Listening for DNS on %s (UDP)", udpAddress)
Info.Printf("Listening for DNS on %s (UDP)", address)
err = s.udpSrv.ListenAndServe()
checkFatal(err)
}()
go func() {
Info.Printf("Listening for DNS on %s (TCP)", tcpAddress)
Info.Printf("Listening for DNS on %s (TCP)", address)
err = s.tcpSrv.ListenAndServe()
checkFatal(err)
}()
+75 -18
View File
@@ -3,7 +3,7 @@ package nameserver
import (
"fmt"
"github.com/miekg/dns"
"github.com/zettio/weave/common"
. "github.com/zettio/weave/common"
wt "github.com/zettio/weave/testing"
"net"
"testing"
@@ -16,7 +16,7 @@ const (
testRDNSnonlocal = "8.8.8.8.in-addr.arpa."
)
func TestDNSServer(t *testing.T) {
func TestUDPDNSServer(t *testing.T) {
const (
port = 17625
successTestName = "test1.weave.local."
@@ -27,7 +27,7 @@ func TestDNSServer(t *testing.T) {
dnsAddr := fmt.Sprintf("localhost:%d", port)
testCIDR1 := testAddr1 + "/24"
common.InitDefaultLogging(true)
InitDefaultLogging(true)
var zone = new(ZoneDb)
ip, _, _ := net.ParseCIDR(testCIDR1)
zone.AddRecord(containerID, successTestName, ip)
@@ -41,17 +41,14 @@ func TestDNSServer(t *testing.T) {
wt.AssertNoErr(t, err)
config := &dns.ClientConfig{Servers: []string{"127.0.0.1"}, Port: fallbackPort}
srv, err := NewDNSServerWithConfig(config, zone, nil, port, port)
srv, err := NewDNSServerWithConfig(config, zone, nil, port)
wt.AssertNoErr(t, err)
defer srv.Stop()
go srv.Start()
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
// Create a regular UDP client and a TCP client
c := new(dns.Client)
c.UDPSize = UDPBufSize
tc := new(dns.Client)
tc.Net = "tcp"
m := new(dns.Msg)
m.SetQuestion(successTestName, dns.TypeA)
m.RecursionDesired = true
@@ -63,16 +60,6 @@ func TestDNSServer(t *testing.T) {
wt.AssertType(t, r.Answer[0], (*dns.A)(nil), "DNS record")
wt.AssertEqualString(t, r.Answer[0].(*dns.A).A.String(), testAddr1, "IP address")
// Retry the query with the TCP client
tr, _, err := tc.Exchange(m, dnsAddr)
wt.AssertNoErr(t, err)
wt.AssertStatus(t, tr.Rcode, dns.RcodeSuccess, "DNS response code (TCP)")
wt.AssertEqualInt(t, len(tr.Answer), 1, "Number of answers (TCP)")
wt.AssertType(t, tr.Answer[0], (*dns.A)(nil), "DNS record (TCP)")
wt.AssertEqualString(t, tr.Answer[0].(*dns.A).A.String(), testAddr1, "IP address (TCP)")
// TODO: look for some way of testing the TCP fallback for truncated responses: it seems there is
// TODO: no client lib in Go that can do that...
m.SetQuestion(failTestName, dns.TypeA)
r, _, err = c.Exchange(m, dnsAddr)
wt.AssertNoErr(t, err)
@@ -129,6 +116,76 @@ func TestDNSServer(t *testing.T) {
// needs two servers, each listening on its own address
}
func TestTCPDNSServer(t *testing.T) {
const (
port = 17625
localTestName = "test1.weave.local."
testAddr1 = "10.0.2.1"
)
dnsAddr := fmt.Sprintf("localhost:%d", port)
InitDefaultLogging(true)
var zone = new(ZoneDb)
// Insert a bunch of IPs for the same name
ansCount := 0
for i := 0; i < 255; i++ {
for j := 0; j < 10; j++ {
ip := net.ParseIP(fmt.Sprintf("10.0.%d.%d", i, j))
ansCount += 1
err := zone.AddRecord(containerID, localTestName, ip)
wt.AssertNoErr(t, err)
}
}
// Run another DNS server for fallback
s, fallbackAddr, err := RunLocalUDPServer("127.0.0.1:0")
wt.AssertNoErr(t, err)
defer s.Shutdown()
_, fallbackPort, err := net.SplitHostPort(fallbackAddr)
wt.AssertNoErr(t, err)
config := &dns.ClientConfig{Servers: []string{"127.0.0.1"}, Port: fallbackPort}
srv, err := NewDNSServerWithConfig(config, zone, nil, port)
wt.AssertNoErr(t, err)
defer srv.Stop()
go srv.Start()
time.Sleep(100 * time.Millisecond) // Allow sever goroutine to start
// Create a regular UDP client and a TCP client
uc := new(dns.Client)
uc.UDPSize = UDPBufSize
tc := new(dns.Client)
tc.Net = "tcp"
m := new(dns.Msg)
m.SetQuestion(localTestName, dns.TypeA)
m.RecursionDesired = false
Debug.Printf("Using UDP for quering about %s", localTestName)
r, _, err := uc.Exchange(m, dnsAddr)
wt.AssertNoErr(t, err)
if len(r.Answer) > 1 { // TODO: remove this when we have proper support for multiple responses (zettio/weave#338)
wt.AssertStatus(t, r.Rcode, dns.RcodeBadTrunc, "DNS response code")
if len(r.Answer) == ansCount {
wt.Fatalf(t, "%d answers received, but we expected less than that", len(r.Answer))
}
} else {
Debug.Println("... multiple reponses not supported (yet)")
wt.AssertStatus(t, r.Rcode, dns.RcodeSuccess, "DNS response code")
}
Debug.Println("Using TCP for the same query")
tr, _, err := tc.Exchange(m, dnsAddr)
wt.AssertNoErr(t, err)
wt.AssertStatus(t, tr.Rcode, dns.RcodeSuccess, "DNS response code (TCP)")
if len(r.Answer) > 1 { // TODO: remove this when we have proper support for multiple responses (zettio/weave#338)
wt.AssertEqualInt(t, len(tr.Answer), ansCount, "Number of answers (TCP)")
}
wt.AssertType(t, tr.Answer[0], (*dns.A)(nil), "DNS record (TCP)") // assume they are all the same...
}
func fallbackHandler(w dns.ResponseWriter, req *dns.Msg) {
m := new(dns.Msg)
m.SetReply(req)
+3 -5
View File
@@ -18,8 +18,7 @@ func main() {
justVersion bool
ifaceName string
apiPath string
udpPort int
tcpPort int
dnsPort int
httpPort int
wait int
watch bool
@@ -30,8 +29,7 @@ func main() {
flag.StringVar(&ifaceName, "iface", "", "name of interface to use for multicast")
flag.StringVar(&apiPath, "api", "unix:///var/run/docker.sock", "Path to Docker API socket")
flag.IntVar(&wait, "wait", 0, "number of seconds to wait for interface to be created and come up")
flag.IntVar(&udpPort, "udpport", 53, "UDP port to listen to DNS requests")
flag.IntVar(&tcpPort, "tcpport", 53, "TCP port to listen to DNS requests")
flag.IntVar(&dnsPort, "dnsport", 53, "port to listen to DNS requests")
flag.IntVar(&httpPort, "httpport", 6785, "port to listen to HTTP requests")
flag.BoolVar(&watch, "watch", true, "watch the docker socket for container events")
flag.BoolVar(&debug, "debug", false, "output debugging info to stderr")
@@ -66,7 +64,7 @@ func main() {
}
go weavedns.ListenHttp(weavedns.LOCAL_DOMAIN, zone, httpPort)
srv, err := weavedns.NewDNSServer(zone, iface, udpPort, tcpPort)
srv, err := weavedns.NewDNSServer(zone, iface, dnsPort)
if err != nil {
Error.Fatal("Failed to start server", err)
}