dns/serve_mux_test.go
Tom Thorogood 068c7e7c81 Rework and optimise ServeMux (#754)
* Avoid using pointer to sync.RWMutex in ServeMux

* Initialize ServeMux.z only when needed.

This means the zero ServeMux is now valid and empty.

* Add benchmark for ServeMux.match

* Use strings.ToLower once in ServeMux.match

strings.ToLower has a special path for ASCII-only (which q always should
be), and avoids all allocations if the string is already lowercase
(which most DNS labels should be).

* Move NextLabel into for clause in ServeMux.match

* Make ServeMux.ServeDNS easier to read

* Fix the documentation of ServeMux.ServeDNS

* Invoke HandleFailed directly in ServeMux.ServeDNS

* Bail early in ServeMux.match if Handle never called

* Fix typo in ServeMux.match

* Improve documentation of ServeMux

This just splits the massive wall of text up so it's easier to follow.

* Fix typo in ServeMux.HandleRemove documentation

* Replace strings.ToLower with once-allocating version

strings.ToLower allocates twice for uppercase ASCII which causes an
overall regression for this changeset. By writing our own custom version
here we can avoid that allocation.

When https://go-review.googlesource.com/c/go/+/137575 lands in a go
release this can be removed.
2018-09-27 07:48:02 +01:00

73 lines
1.6 KiB
Go

package dns
import "testing"
func TestDotAsCatchAllWildcard(t *testing.T) {
mux := NewServeMux()
mux.Handle(".", HandlerFunc(HelloServer))
mux.Handle("example.com.", HandlerFunc(AnotherHelloServer))
handler := mux.match("www.miek.nl.", TypeTXT)
if handler == nil {
t.Error("wildcard match failed")
}
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")
}
}
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")
}
}
func TestRootServer(t *testing.T) {
mux := NewServeMux()
mux.Handle(".", HandlerFunc(HelloServer))
handler := mux.match(".", TypeNS)
if handler == nil {
t.Error("root match failed")
}
}
func BenchmarkMuxMatch(b *testing.B) {
mux := NewServeMux()
mux.Handle("_udp.example.com.", HandlerFunc(HelloServer))
bench := func(q string) func(*testing.B) {
return func(b *testing.B) {
for n := 0; n < b.N; n++ {
handler := mux.match(q, TypeSRV)
if handler == nil {
b.Fatal("couldn't find match")
}
}
}
}
b.Run("lowercase", bench("_dns._udp.example.com."))
b.Run("uppercase", bench("_DNS._UDP.EXAMPLE.COM."))
}