Files
go-pdns/pipe/dsl/dsl_test.go
2015-01-10 02:01:24 +00:00

182 lines
5.8 KiB
Go

package dsl_test
import (
"errors"
"fmt"
"github.com/BytemarkHosting/go-pdns/pipe/backend"
. "github.com/BytemarkHosting/go-pdns/pipe/dsl"
h "github.com/BytemarkHosting/go-pdns/pipe/test_helpers"
"strings"
"testing"
)
func ReplyHandler(x string) func(c *Context) {
return func(c *Context) { c.Reply(x) }
}
func NullHandler(c *Context) {}
var ErrorReplyError = errors.New("Foo")
func ErrorReplyHandler(c *Context) { c.Error = ErrorReplyError }
func SOAQuery() *backend.Query {
q := h.FakeQuery(3)
q.QName = "example.com"
q.QType = "SOA"
return q
}
func AssertTableEntry(t *testing.T, d *DSL, qtype, matcher, msg string) {
table := qtype + "\t:\t" + matcher + "\n"
h.AssertEqualString(t, table, d.String(), msg)
}
func AssertLookup(t *testing.T, d *DSL, q *backend.Query, n int, err error) []*backend.Response {
rsp, rspErr := d.Lookup(q)
if err == nil {
h.RefuteError(t, err, "Lookup shouldn't return error")
} else if rspErr == nil {
t.Logf("Expected error %s but no error was returned", err)
t.FailNow()
} else {
h.AssertEqualString(t, err.Error(), rspErr.Error(), "Expected error not returned")
}
rspStrs := []string{}
for _, r := range rsp {
r.ProtocolVersion = 1
str, err := r.String()
h.RefuteError(t, err, "sanity")
rspStrs = append(rspStrs, str)
}
h.AssertEqualInt(t, n, len(rsp), fmt.Sprintf("One response expected, got:\n%s", strings.Join(rspStrs, "")))
return rsp
}
// Don't test all the autogenerated helpers explicitly, just a common one.
func TestAutogeneratedExampleRegistersCorrectCallbackWhenRun(t *testing.T) {
d := New()
d.SOA(`example\.com`, NullHandler)
AssertTableEntry(t, d, "SOA", `^(?i)example\.com$`, "SOA callback not registered")
}
func TestDefaultTTLFromNewIsOneHour(t *testing.T) {
d := New()
d.SOA(`*`, ReplyHandler("Foo"))
rsp := AssertLookup(t, d, SOAQuery(), 1, nil)
h.AssertEqualString(t, "3600", rsp[0].TTL, "Default TTL not honoured")
}
func TestAlternativeTTLCanBeSpecifiedUsingNewWithTTL(t *testing.T) {
d := NewWithTTL(86400)
d.SOA(`*`, ReplyHandler("Foo"))
rsp := AssertLookup(t, d, SOAQuery(), 1, nil)
h.AssertEqualString(t, "86400", rsp[0].TTL, "Custom TTL not honoured")
}
func TestBeforeCallbackIsCalledIfSpecified(t *testing.T) {
d := New()
d.Before(ReplyHandler("Before"))
d.SOA(`*`, ReplyHandler("SOA 1"))
d.SOA(`*`, ReplyHandler("SOA 2"))
rsp := AssertLookup(t, d, SOAQuery(), 4, nil)
h.AssertEqualString(t, "Before", rsp[0].Content, "First Before not called")
h.AssertEqualString(t, "SOA 1", rsp[1].Content, "First SOA not called")
h.AssertEqualString(t, "Before", rsp[2].Content, "Second Before not called")
h.AssertEqualString(t, "SOA 2", rsp[3].Content, "Second SOA not called")
}
func TestLookupCallbackOrderIsDefined(t *testing.T) {
d := New()
d.SOA(`*`, ReplyHandler("SOA 1"))
d.MX(`*`, ReplyHandler("MX 1"))
d.SOA(`*`, ReplyHandler("SOA 2"))
d.SOA(`*`, ReplyHandler("SOA 3"))
d.AAAA(`*`, ReplyHandler("AAAA 1"))
d.A(`*`, ReplyHandler("AAAA 2"))
rsp := AssertLookup(t, d, h.FakeQuery(1), 6, nil)
msg := "Order is wrong"
h.AssertEqualString(t, "SOA 1", rsp[0].Content, msg)
h.AssertEqualString(t, "SOA 2", rsp[1].Content, msg)
h.AssertEqualString(t, "SOA 3", rsp[2].Content, msg)
h.AssertEqualString(t, "MX 1", rsp[3].Content, msg)
h.AssertEqualString(t, "AAAA 1", rsp[4].Content, msg)
h.AssertEqualString(t, "AAAA 2", rsp[5].Content, msg)
}
func TestOnlyMatchingCallbacksAreRun(t *testing.T) {
d := New()
d.SOA(`example\.com`, ReplyHandler("Good"))
d.SOA(`example\.org`, ReplyHandler("Bad"))
rsp := AssertLookup(t, d, SOAQuery(), 1, nil)
h.AssertEqualString(t, "Good", rsp[0].Content, "Wrong callback run")
}
func TestOnlyCallbacksOfTheRightQTypeAreRun(t *testing.T) {
d := New()
d.SOA(`example\.com`, ReplyHandler("Good"))
d.NS(`example\.com`, ReplyHandler("Bad"))
rsp := AssertLookup(t, d, SOAQuery(), 1, nil)
h.AssertEqualString(t, "Good", rsp[0].Content, "Wrong callback run")
}
func TestCaptureGroupsArePutIntoContextMatches(t *testing.T) {
d := New()
var captures []string
d.SOA(`([a-z]{3})\.([a-z]{3})\.([a-z]{3})\.example\.com`, func(c *Context) {
captures = c.Matches
c.Reply("OK")
})
q := SOAQuery()
q.QName = "BAZ.bar.foo.example.com"
rsp := AssertLookup(t, d, q, 1, nil)
h.AssertEqualInt(t, 3, len(captures), "Wrong number of match groups returned")
h.AssertEqualString(t, "OK", rsp[0].Content, "Wrong callback run?")
// case-insensitive, so we don't mangle these
h.AssertEqualString(t, "BAZ", captures[0], "Part 1 not captured")
h.AssertEqualString(t, "bar", captures[1], "Part 2 not captured")
h.AssertEqualString(t, "foo", captures[2], "Part 3 not captured")
}
func TestBeforeCanModifyCaptureGroups(t *testing.T) {
d := New()
d.Before(func(c *Context) { c.Matches = append(c.Matches, "modify-cg") })
d.SOA(`*`, func(c *Context) { c.Reply(c.Matches[0]) })
rsp := AssertLookup(t, d, SOAQuery(), 1, nil)
h.AssertEqualString(t, "modify-cg", rsp[0].Content, "Capture modification lost")
}
func TestChangesToMatchesInOrdinaryCallbacksDoNotPersist(t *testing.T) {
d := New()
var ok bool
d.SOA(`*`, func(c *Context) { c.Matches = append(c.Matches, "Bad") })
d.SOA(`*`, func(c *Context) { ok = (len(c.Matches) == 0) })
AssertLookup(t, d, SOAQuery(), 0, nil)
h.Assert(t, ok, "Change was persisted")
}
func TestCallbackReturningErrorIsReported(t *testing.T) {
d := New()
d.SOA(`*`, ErrorReplyHandler)
AssertLookup(t, d, SOAQuery(), 0, ErrorReplyError)
}
func TestCallbackReturningErrorBlanksAnswers(t *testing.T) {
d := New()
d.SOA(`*`, ReplyHandler("Foo"))
d.SOA(`*`, ErrorReplyHandler)
AssertLookup(t, d, SOAQuery(), 0, ErrorReplyError)
}
func TestCallbackReturningErrorStopsLaterCallbacksFromRunning(t *testing.T) {
d := New()
ok := true
d.SOA(`*`, ErrorReplyHandler)
d.SOA(`*`, func(c *Context) { ok = false })
AssertLookup(t, d, SOAQuery(), 0, ErrorReplyError)
h.Assert(t, ok, "Later callback was run")
}