dnscontrol/providers/bind/prettyzone_test.go
Craig Peterson 1ea80d5347 Nameserver overhaul (#17)
* go changes to support nameservers_from

* clear nameservers before giving to dsp.

* work

* work

* nameserver updates.

* remove unused

* name.com stinks at NS records.

* whitespace

* removing web(belongs in own repo). First sketch of DSP vs NAMESERVER_FROM

* add DEFAULTS to replace defaultDsps.

* initial gcloud provider. Simple records work.

* namedotcom can do subdomain ns records now.

* fix for mx and txt

* kill dsp acronym
2016-12-16 13:10:27 -07:00

298 lines
7.5 KiB
Go

package bind
import (
"bytes"
"fmt"
"log"
"math/rand"
"testing"
"github.com/miekg/dns"
"github.com/miekg/dns/dnsutil"
)
func parseAndRegen(t *testing.T, buf *bytes.Buffer, expected string) {
// Take a zonefile, parse it, then generate a zone. We should
// get back the same string.
// This is used after any WriteZoneFile test as an extra verification step.
// Parse the output:
var parsed []dns.RR
for x := range dns.ParseZone(buf, "bosun.org", "bosun.org.zone") {
if x.Error != nil {
log.Fatalf("Error in zonefile: %v", x.Error)
} else {
parsed = append(parsed, x.RR)
}
}
// Generate it back:
buf2 := &bytes.Buffer{}
WriteZoneFile(buf2, parsed, "bosun.org.", 300)
// Compare:
if buf2.String() != expected {
t.Fatalf("Regenerated zonefile does not match: got=(\n%v\n)\nexpected=(\n%v\n)\n", buf2.String(), expected)
}
}
// func WriteZoneFile
func TestWriteZoneFileSimple(t *testing.T) {
r1, _ := dns.NewRR("bosun.org. 300 IN A 192.30.252.153")
r2, _ := dns.NewRR("bosun.org. 300 IN A 192.30.252.154")
r3, _ := dns.NewRR("www.bosun.org. 300 IN CNAME bosun.org.")
buf := &bytes.Buffer{}
WriteZoneFile(buf, []dns.RR{r1, r2, r3}, "bosun.org.", 300)
expected := `$TTL 300
@ IN A 192.30.252.153
IN A 192.30.252.154
www IN CNAME bosun.org.
`
if buf.String() != expected {
t.Log(buf.String())
t.Log(expected)
t.Fatalf("Zone file does not match.")
}
parseAndRegen(t, buf, expected)
}
func TestWriteZoneFileMx(t *testing.T) {
//exhibits explicit ttls and long name
r1, _ := dns.NewRR(`bosun.org. 300 IN TXT "aaa"`)
r2, _ := dns.NewRR(`bosun.org. 300 IN TXT "bbb"`)
r2.(*dns.TXT).Txt[0] = `b"bb`
r3, _ := dns.NewRR("bosun.org. 300 IN MX 1 ASPMX.L.GOOGLE.COM.")
r4, _ := dns.NewRR("bosun.org. 300 IN MX 5 ALT1.ASPMX.L.GOOGLE.COM.")
r5, _ := dns.NewRR("bosun.org. 300 IN MX 10 ASPMX3.GOOGLEMAIL.COM.")
r6, _ := dns.NewRR("bosun.org. 300 IN A 198.252.206.16")
r7, _ := dns.NewRR("*.bosun.org. 600 IN A 198.252.206.16")
r8, _ := dns.NewRR(`_domainkey.bosun.org. 300 IN TXT "vvvv"`)
r9, _ := dns.NewRR(`google._domainkey.bosun.org. 300 IN TXT "\"foo\""`)
buf := &bytes.Buffer{}
WriteZoneFile(buf, []dns.RR{r1, r2, r3, r4, r5, r6, r7, r8, r9}, "bosun.org", 300)
if buf.String() != testdataZFMX {
t.Log(buf.String())
t.Log(testdataZFMX)
t.Fatalf("Zone file does not match.")
}
parseAndRegen(t, buf, testdataZFMX)
}
var testdataZFMX = `$TTL 300
@ IN A 198.252.206.16
IN MX 1 ASPMX.L.GOOGLE.COM.
IN MX 5 ALT1.ASPMX.L.GOOGLE.COM.
IN MX 10 ASPMX3.GOOGLEMAIL.COM.
IN TXT "aaa"
IN TXT "b\"bb"
* 600 IN A 198.252.206.16
_domainkey IN TXT "vvvv"
google._domainkey IN TXT "\"foo\""
`
func TestWriteZoneFileOrder(t *testing.T) {
var records []dns.RR
for i, td := range []string{
"@",
"@",
"@",
"stackoverflow.com.",
"*",
"foo",
"bar.foo",
"hip.foo",
"mup",
"a.mup",
"bzt.mup",
"aaa.bzt.mup",
"zzz.bzt.mup",
"nnn.mup",
"zt.mup",
"zap",
} {
name := dnsutil.AddOrigin(td, "stackoverflow.com.")
r, _ := dns.NewRR(fmt.Sprintf("%s 300 IN A 1.2.3.%d", name, i))
records = append(records, r)
}
buf := &bytes.Buffer{}
WriteZoneFile(buf, records, "stackoverflow.com.", 300)
// Compare
if buf.String() != testdataOrder {
t.Log("Found:")
t.Log(buf.String())
t.Log("Expected:")
t.Log(testdataOrder)
t.Fatalf("Zone file does not match.")
}
parseAndRegen(t, buf, testdataOrder)
// Now shuffle the list many times and make sure it still works:
for iteration := 5; iteration > 0; iteration-- {
// Randomize the list:
perm := rand.Perm(len(records))
for i, v := range perm {
records[i], records[v] = records[v], records[i]
//fmt.Println(i, v)
}
// Generate
buf := &bytes.Buffer{}
WriteZoneFile(buf, records, "stackoverflow.com.", 300)
// Compare
if buf.String() != testdataOrder {
t.Log(buf.String())
t.Log(testdataOrder)
t.Fatalf("Zone file does not match.")
}
parseAndRegen(t, buf, testdataOrder)
}
}
var testdataOrder = `$TTL 300
@ IN A 1.2.3.0
IN A 1.2.3.1
IN A 1.2.3.2
IN A 1.2.3.3
* IN A 1.2.3.4
foo IN A 1.2.3.5
bar.foo IN A 1.2.3.6
hip.foo IN A 1.2.3.7
mup IN A 1.2.3.8
a.mup IN A 1.2.3.9
bzt.mup IN A 1.2.3.10
aaa.bzt.mup IN A 1.2.3.11
zzz.bzt.mup IN A 1.2.3.12
nnn.mup IN A 1.2.3.13
zt.mup IN A 1.2.3.14
zap IN A 1.2.3.15
`
// func formatLine
func TestFormatLine(t *testing.T) {
tests := []struct {
lengths []int
fields []string
expected string
}{
{[]int{2, 2, 0}, []string{"a", "b", "c"}, "a b c"},
{[]int{2, 2, 0}, []string{"aaaaa", "b", "c"}, "aaaaa b c"},
}
for _, ts := range tests {
actual := formatLine(ts.lengths, ts.fields)
if actual != ts.expected {
t.Errorf("\"%s\" != \"%s\"", actual, ts.expected)
}
}
}
// func zoneLabelLess
func TestZoneLabelLess(t *testing.T) {
/*
The zone should sort in prefix traversal order:
@
*
foo
bar.foo
hip.foo
mup
a.mup
bzt.mup
aaa.bzt.mup
zzz.bzt.mup
nnn.mup
zt.mup
zap
*/
var tests = []struct {
e1, e2 string
expected bool
}{
{"@", "@", false},
{"@", "*", true},
{"@", "b", true},
{"*", "@", false},
{"*", "*", false},
{"*", "b", true},
{"foo", "foo", false},
{"foo", "bar", false},
{"bar", "foo", true},
{"a.mup", "mup", false},
{"mup", "a.mup", true},
{"a.mup", "a.mup", false},
{"a.mup", "bzt.mup", true},
{"a.mup", "aa.mup", true},
{"zt.mup", "aaa.bzt.mup", false},
{"aaa.bzt.mup", "mup", false},
{"nnn.mup", "aaa.bzt.mup", false},
{`www\.miek.nl`, `www.miek.nl`, false},
}
for _, test := range tests {
actual := zoneLabelLess(test.e1, test.e2)
if test.expected != actual {
t.Errorf("%v: expected (%v) got (%v)\n", test.e1, test.e2, actual)
}
actual = zoneLabelLess(test.e2, test.e1)
// The reverse should work too:
var expected bool
if test.e1 == test.e2 {
expected = false
} else {
expected = !test.expected
}
if expected != actual {
t.Errorf("%v: expected (%v) got (%v)\n", test.e1, test.e2, actual)
}
}
}
func TestZoneRrtypeLess(t *testing.T) {
/*
In zonefiles we want to list SOAs, then NSs, then all others.
*/
var tests = []struct {
e1, e2 uint16
expected bool
}{
{dns.TypeSOA, dns.TypeSOA, false},
{dns.TypeSOA, dns.TypeA, true},
{dns.TypeSOA, dns.TypeTXT, true},
{dns.TypeSOA, dns.TypeNS, true},
{dns.TypeNS, dns.TypeSOA, false},
{dns.TypeNS, dns.TypeA, true},
{dns.TypeNS, dns.TypeTXT, true},
{dns.TypeNS, dns.TypeNS, false},
{dns.TypeA, dns.TypeSOA, false},
{dns.TypeA, dns.TypeA, false},
{dns.TypeA, dns.TypeTXT, true},
{dns.TypeA, dns.TypeNS, false},
{dns.TypeMX, dns.TypeSOA, false},
{dns.TypeMX, dns.TypeA, false},
{dns.TypeMX, dns.TypeTXT, true},
{dns.TypeMX, dns.TypeNS, false},
}
for _, test := range tests {
actual := zoneRrtypeLess(test.e1, test.e2)
if test.expected != actual {
t.Errorf("%v: expected (%v) got (%v)\n", test.e1, test.e2, actual)
}
actual = zoneRrtypeLess(test.e2, test.e1)
// The reverse should work too:
var expected bool
if test.e1 == test.e2 {
expected = false
} else {
expected = !test.expected
}
if expected != actual {
t.Errorf("%v: expected (%v) got (%v)\n", test.e1, test.e2, actual)
}
}
}