2013-05-13 00:09:52 +10:00
|
|
|
// Copyright 2011 Miek Gieben. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2011-07-06 03:49:13 +10:00
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
2014-02-15 08:53:00 +11:00
|
|
|
"fmt"
|
|
|
|
"net"
|
2013-06-22 17:55:30 +10:00
|
|
|
"runtime"
|
2014-03-01 02:57:10 +11:00
|
|
|
"sync"
|
2011-07-06 03:49:13 +10:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func HelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-10 05:23:25 +11:00
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
2012-11-20 02:15:03 +11:00
|
|
|
w.WriteMsg(m)
|
2011-07-06 03:49:13 +10:00
|
|
|
}
|
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
func AnotherHelloServer(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
|
|
|
|
m.Extra = make([]RR, 1)
|
2012-12-10 05:23:25 +11:00
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello example"}}
|
2012-11-20 02:15:03 +11:00
|
|
|
w.WriteMsg(m)
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
func RunLocalUDPServer(laddr string) (*Server, string, error) {
|
|
|
|
pc, err := net.ListenPacket("udp", laddr)
|
2014-08-29 13:11:49 +10:00
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
server := &Server{PacketConn: pc}
|
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
pc.Close()
|
|
|
|
}()
|
|
|
|
return server, pc.LocalAddr().String(), nil
|
|
|
|
}
|
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
func RunLocalTCPServer(laddr string) (*Server, string, error) {
|
|
|
|
l, err := net.Listen("tcp", laddr)
|
|
|
|
if err != nil {
|
|
|
|
return nil, "", err
|
|
|
|
}
|
|
|
|
server := &Server{Listener: l}
|
|
|
|
go func() {
|
|
|
|
server.ActivateAndServe()
|
|
|
|
l.Close()
|
|
|
|
}()
|
|
|
|
return server, l.Addr().String(), nil
|
|
|
|
}
|
|
|
|
|
2011-07-06 03:49:13 +10:00
|
|
|
func TestServing(t *testing.T) {
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2012-08-25 08:46:35 +10:00
|
|
|
HandleFunc("example.com.", AnotherHelloServer)
|
2014-08-29 13:11:49 +10:00
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
2014-08-29 13:11:49 +10:00
|
|
|
if err != nil {
|
2014-08-29 22:27:53 +10:00
|
|
|
t.Fatalf("Unable to run test server: %s", err)
|
2014-08-29 13:11:49 +10:00
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err := c.Exchange(m, addrstr)
|
2014-07-17 20:14:50 +10:00
|
|
|
if err != nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Log("failed to exchange miek.nl", err)
|
2014-08-19 07:06:29 +10:00
|
|
|
t.Fatal()
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2012-12-10 05:23:25 +11:00
|
|
|
txt := r.Extra[0].(*TXT).Txt[0]
|
2012-08-25 08:46:35 +10:00
|
|
|
if txt != "Hello world" {
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Log("Unexpected result for miek.nl", txt, "!= Hello world")
|
|
|
|
t.Fail()
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
2014-07-17 20:14:50 +10:00
|
|
|
|
2012-08-25 08:46:35 +10:00
|
|
|
m.SetQuestion("example.com.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
2014-07-17 20:14:50 +10:00
|
|
|
if err != nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Log("failed to exchange example.com", err)
|
2014-08-19 07:06:29 +10:00
|
|
|
t.Fatal()
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2012-12-10 05:23:25 +11:00
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
2012-08-25 08:46:35 +10:00
|
|
|
if txt != "Hello example" {
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Log("Unexpected result for example.com", txt, "!= Hello example")
|
|
|
|
t.Fail()
|
2012-08-25 08:46:35 +10:00
|
|
|
}
|
2014-07-17 20:14:50 +10:00
|
|
|
|
2013-10-19 21:52:15 +11:00
|
|
|
// Test Mixes cased as noticed by Ask.
|
2013-07-25 16:55:59 +10:00
|
|
|
m.SetQuestion("eXaMplE.cOm.", TypeTXT)
|
2014-08-29 13:11:49 +10:00
|
|
|
r, _, err = c.Exchange(m, addrstr)
|
2014-07-17 20:14:50 +10:00
|
|
|
if err != nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Log("failed to exchange eXaMplE.cOm", err)
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Fail()
|
2014-07-17 20:14:50 +10:00
|
|
|
}
|
2013-07-25 16:55:59 +10:00
|
|
|
txt = r.Extra[0].(*TXT).Txt[0]
|
|
|
|
if txt != "Hello example" {
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Log("Unexpected result for example.com", txt, "!= Hello example")
|
|
|
|
t.Fail()
|
2013-07-25 16:55:59 +10:00
|
|
|
}
|
2011-07-06 03:49:13 +10:00
|
|
|
}
|
2011-07-07 03:21:19 +10:00
|
|
|
|
2014-01-29 18:56:21 +11:00
|
|
|
func BenchmarkServe(b *testing.B) {
|
2011-07-24 07:43:43 +10:00
|
|
|
b.StopTimer()
|
2011-07-07 03:21:19 +10:00
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
2013-06-22 17:55:30 +10:00
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
|
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Unable to run test server: %s", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2012-05-26 18:28:32 +10:00
|
|
|
c := new(Client)
|
2011-07-24 07:43:43 +10:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
2011-07-07 03:21:19 +10:00
|
|
|
|
2011-07-24 07:43:43 +10:00
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2011-07-24 07:43:43 +10:00
|
|
|
}
|
2013-06-22 17:55:30 +10:00
|
|
|
runtime.GOMAXPROCS(a)
|
2011-07-07 03:21:19 +10:00
|
|
|
}
|
2012-09-17 16:56:27 +10:00
|
|
|
|
2014-07-09 16:23:54 +10:00
|
|
|
func benchmarkServe6(b *testing.B) {
|
2014-07-09 00:15:08 +10:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServer)
|
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("[::1]:0")
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Unable to run test server: %s", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
|
|
|
|
2014-07-09 00:15:08 +10:00
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
|
|
|
|
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2014-07-09 00:15:08 +10:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2013-06-28 05:29:10 +10:00
|
|
|
func HelloServerCompress(w ResponseWriter, req *Msg) {
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Extra = make([]RR, 1)
|
|
|
|
m.Extra[0] = &TXT{Hdr: RR_Header{Name: m.Question[0].Name, Rrtype: TypeTXT, Class: ClassINET, Ttl: 0}, Txt: []string{"Hello world"}}
|
|
|
|
m.Compress = true
|
|
|
|
w.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
2014-01-29 18:52:23 +11:00
|
|
|
func BenchmarkServeCompress(b *testing.B) {
|
2013-06-28 05:29:10 +10:00
|
|
|
b.StopTimer()
|
|
|
|
HandleFunc("miek.nl.", HelloServerCompress)
|
|
|
|
a := runtime.GOMAXPROCS(4)
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
b.Fatalf("Unable to run test server: %s", err)
|
|
|
|
}
|
|
|
|
defer s.Shutdown()
|
2013-06-28 05:29:10 +10:00
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("miek.nl", TypeSOA)
|
|
|
|
b.StartTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
2014-08-29 22:27:53 +10:00
|
|
|
c.Exchange(m, addrstr)
|
2013-06-28 05:29:10 +10:00
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(a)
|
|
|
|
}
|
|
|
|
|
2012-09-17 16:56:27 +10:00
|
|
|
func TestDotAsCatchAllWildcard(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle(".", HandlerFunc(HelloServer))
|
|
|
|
mux.Handle("example.com.", HandlerFunc(AnotherHelloServer))
|
|
|
|
|
2012-09-18 16:19:06 +10:00
|
|
|
handler := mux.match("www.miek.nl.", TypeTXT)
|
2012-09-17 16:56:27 +10:00
|
|
|
if handler == nil {
|
|
|
|
t.Error("wildcard match failed")
|
|
|
|
}
|
|
|
|
|
2012-09-18 16:19:06 +10:00
|
|
|
handler = mux.match("www.example.com.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("example.com match failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("a.www.example.com.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("a.www.example.com match failed")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("boe.", TypeTXT)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("boe. match failed")
|
2012-09-17 16:56:27 +10:00
|
|
|
}
|
|
|
|
}
|
2013-05-12 23:56:12 +10:00
|
|
|
|
2013-12-14 20:37:53 +11:00
|
|
|
func TestCaseFolding(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle("_udp.example.com.", HandlerFunc(HelloServer))
|
|
|
|
|
|
|
|
handler := mux.match("_dns._udp.example.com.", TypeSRV)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("case sensitive characters folded")
|
|
|
|
}
|
|
|
|
|
|
|
|
handler = mux.match("_DNS._UDP.EXAMPLE.COM.", TypeSRV)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("case insensitive characters not folded")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-12 23:56:12 +10:00
|
|
|
func TestRootServer(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
|
|
|
mux.Handle(".", HandlerFunc(HelloServer))
|
|
|
|
|
|
|
|
handler := mux.match(".", TypeNS)
|
|
|
|
if handler == nil {
|
|
|
|
t.Error("root match failed")
|
|
|
|
}
|
|
|
|
}
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-03-01 02:57:10 +11:00
|
|
|
type maxRec struct {
|
|
|
|
max int
|
|
|
|
sync.RWMutex
|
|
|
|
}
|
|
|
|
|
|
|
|
var M = new(maxRec)
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-02-15 19:03:40 +11:00
|
|
|
func HelloServerLargeResponse(resp ResponseWriter, req *Msg) {
|
2014-02-15 08:53:00 +11:00
|
|
|
m := new(Msg)
|
|
|
|
m.SetReply(req)
|
|
|
|
m.Authoritative = true
|
2014-03-01 02:57:10 +11:00
|
|
|
m1 := 0
|
|
|
|
M.RLock()
|
|
|
|
m1 = M.max
|
|
|
|
M.RUnlock()
|
|
|
|
for i := 0; i < m1; i++ {
|
2014-02-15 08:53:00 +11:00
|
|
|
aRec := &A{
|
|
|
|
Hdr: RR_Header{
|
|
|
|
Name: req.Question[0].Name,
|
|
|
|
Rrtype: TypeA,
|
|
|
|
Class: ClassINET,
|
|
|
|
Ttl: 0,
|
|
|
|
},
|
|
|
|
A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)).To4(),
|
|
|
|
}
|
|
|
|
m.Answer = append(m.Answer, aRec)
|
|
|
|
}
|
|
|
|
resp.WriteMsg(m)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestServingLargeResponses(t *testing.T) {
|
|
|
|
mux := NewServeMux()
|
2014-02-15 19:03:40 +11:00
|
|
|
mux.HandleFunc("example.", HelloServerLargeResponse)
|
2014-02-15 08:53:00 +11:00
|
|
|
|
2014-08-29 22:27:53 +10:00
|
|
|
s, addrstr, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Unable to run test server: %s", err)
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-08-29 22:27:53 +10:00
|
|
|
defer s.Shutdown()
|
|
|
|
s.Handler = mux
|
2014-02-15 08:53:00 +11:00
|
|
|
|
|
|
|
// Create request
|
|
|
|
m := new(Msg)
|
|
|
|
m.SetQuestion("web.service.example.", TypeANY)
|
|
|
|
|
|
|
|
c := new(Client)
|
|
|
|
c.Net = "udp"
|
2014-03-01 02:57:10 +11:00
|
|
|
M.Lock()
|
|
|
|
M.max = 2
|
|
|
|
M.Unlock()
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 08:53:00 +11:00
|
|
|
if err != nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Logf("failed to exchange: %s", err.Error())
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Fail()
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
|
|
|
// This must fail
|
2014-03-01 02:57:10 +11:00
|
|
|
M.Lock()
|
|
|
|
M.max = 20
|
|
|
|
M.Unlock()
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 08:53:00 +11:00
|
|
|
if err == nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Logf("failed to fail exchange, this should generate packet error")
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Fail()
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-02-15 09:14:41 +11:00
|
|
|
// But this must work again
|
|
|
|
c.UDPSize = 7000
|
2014-08-29 22:27:53 +10:00
|
|
|
_, _, err = c.Exchange(m, addrstr)
|
2014-02-15 09:14:41 +11:00
|
|
|
if err != nil {
|
2014-08-19 18:39:04 +10:00
|
|
|
t.Logf("failed to exchange: %s", err.Error())
|
2014-07-18 03:48:28 +10:00
|
|
|
t.Fail()
|
2014-02-15 09:14:41 +11:00
|
|
|
}
|
2014-02-15 08:53:00 +11:00
|
|
|
}
|
2014-08-19 18:39:04 +10:00
|
|
|
|
2014-08-20 06:46:00 +10:00
|
|
|
// TODO(miek): These tests should actually fail when the server does
|
|
|
|
// not shut down.
|
2014-08-29 22:37:32 +10:00
|
|
|
// (asergeyev) I put err check logic which is not yet in use but IMO
|
|
|
|
// this test will not change as shutdown internals improve.
|
2014-08-19 19:25:41 +10:00
|
|
|
func TestShutdownTCP(t *testing.T) {
|
2014-08-29 22:27:53 +10:00
|
|
|
s, _, err := RunLocalTCPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Unable to run test server: %s", err)
|
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
|
|
|
t.Error("Could not shutdown test TCP server, %s", err)
|
|
|
|
}
|
2014-08-19 19:25:41 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestShutdownUDP(t *testing.T) {
|
2014-08-29 22:27:53 +10:00
|
|
|
s, _, err := RunLocalUDPServer("127.0.0.1:0")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Unable to run test server: %s", err)
|
|
|
|
}
|
|
|
|
err = s.Shutdown()
|
|
|
|
if err != nil {
|
|
|
|
t.Error("Could not shutdown test UDP server, %s", err)
|
|
|
|
}
|
2014-08-19 18:39:04 +10:00
|
|
|
}
|