Files
weave/server/mdns_client_test.go
T
2014-10-09 14:46:53 +01:00

168 lines
4.2 KiB
Go

package weavedns
import (
"github.com/miekg/dns"
"log"
"net"
"testing"
"time"
)
var (
success_test_name = "test1.weave."
fail_test_name = "test2.weave."
test_addr = net.ParseIP("9.8.7.6")
)
func minimalServer(w dns.ResponseWriter, req *dns.Msg) {
//log.Println("minimalServer received:", req)
if len(req.Answer) > 0 {
return // Only interested in questions.
}
if len(req.Question) != 1 {
return // We only handle single-question messages
}
if req.Question[0].Name != success_test_name {
return // This is not the DNS record you are looking for
}
m := new(dns.Msg)
m.SetReply(req)
hdr := dns.RR_Header{Name: m.Question[0].Name, Rrtype: dns.TypeA,
Class: dns.ClassINET, Ttl: 3600}
a := &dns.A{hdr, test_addr}
m.Answer = append(m.Answer, a)
buf, err := m.Pack()
if err != nil {
log.Fatal(err)
}
if buf == nil {
log.Fatal("Nil buffer")
}
//log.Println("minimalServer sending:", buf)
// This is a bit of a kludge - per the RFC we should send responses from 5353, but that doesn't seem to work
sendconn, err := net.DialUDP("udp", nil, ipv4Addr)
if err != nil {
log.Fatal(err)
}
_, err = sendconn.Write(buf)
sendconn.Close()
if err != nil {
log.Fatal(err)
}
}
func RunLocalMulticastServer() (*dns.Server, error) {
multicast, err := net.ListenMulticastUDP("udp", nil, ipv4Addr)
if err != nil {
return nil, err
}
server := &dns.Server{Listener: nil, PacketConn: multicast, Handler: dns.HandlerFunc(minimalServer)}
go server.ActivateAndServe()
return server, nil
}
func setup(t *testing.T) (*MDNSClient, *dns.Server, error) {
mdnsClient, err := NewMDNSClient()
if err != nil {
t.Fatal(err)
}
err = mdnsClient.Start(nil)
if err != nil {
t.Fatal(err)
}
server, err := RunLocalMulticastServer()
if err != nil {
t.Fatalf("Unable to run test server: %s", err)
}
return mdnsClient, server, err
}
type testContext struct {
received_addr net.IP
received_count int
channel chan *ResponseA
}
func newTestContext() *testContext {
return &testContext{channel: make(chan *ResponseA, 4)}
}
func (c *testContext) checkResponse(t *testing.T, channel_ok bool, resp *ResponseA) {
if !channel_ok {
c.channel = nil
return
}
if resp.err != nil {
t.Fatal(resp.err)
}
log.Printf("Got address response %s addr %s", resp.Name, resp.Addr)
c.received_addr = resp.Addr
c.received_count++
}
func TestSimpleQuery(t *testing.T) {
log.Println("TestSimpleQuery starting")
mdnsClient, server, _ := setup(t)
defer mdnsClient.Shutdown()
defer server.Shutdown()
context := newTestContext()
// First, a test we expect to succeed
mdnsClient.SendQuery(success_test_name, dns.TypeA, context.channel)
for resp := range context.channel {
context.checkResponse(t, true, resp)
}
if !context.received_addr.Equal(test_addr) {
t.Log("Unexpected result for", success_test_name, context.received_addr)
t.Fail()
}
// Now, a test we expect to time out with no responses
context = newTestContext()
mdnsClient.SendQuery("test2.weave.", dns.TypeA, context.channel)
for resp := range context.channel {
context.checkResponse(t, true, resp)
}
if context.received_count > 0 {
t.Log("Unexpected result for test2.weave", context.received_addr)
t.Fail()
}
}
func TestParallelQuery(t *testing.T) {
log.Println("TestParallelQuery starting")
mdnsClient, server, _ := setup(t)
defer mdnsClient.Shutdown()
defer server.Shutdown()
context1 := newTestContext()
context2 := newTestContext()
go mdnsClient.SendQuery(success_test_name, dns.TypeA, context1.channel)
go mdnsClient.SendQuery(success_test_name, dns.TypeA, context2.channel)
timeout := time.After(2 * time.Second)
outerloop:
for context1.channel != nil || context2.channel != nil {
select {
case resp, ok := <-context1.channel:
context1.checkResponse(t, ok, resp)
case resp, ok := <-context2.channel:
context2.checkResponse(t, ok, resp)
case <-timeout:
break outerloop
}
}
if !context1.received_addr.Equal(test_addr) || !context2.received_addr.Equal(test_addr) || context1.received_count != 1 || context2.received_count != 1 {
t.Log("Unexpected result for", success_test_name, context1.received_addr, context2.received_addr, context1.received_count, context2.received_count)
t.Fail()
}
}