git » spf » commit b567bf7

tests: Tracing function support

author Alberto Bertogli
2019-10-13 14:42:13 UTC
committer Alberto Bertogli
2019-10-14 12:18:21 UTC
parent 8ae8b8e9ee5028d6bafac3b037989c78dc334fd2

tests: Tracing function support

This patch introduces support for a tracing during tests.
For now, it is set to t.Logf for convenience.

spf.go +19 -0
spf_test.go +11 -0
yml_test.go +2 -0

diff --git a/spf.go b/spf.go
index a1f88a3..f4d45a1 100644
--- a/spf.go
+++ b/spf.go
@@ -44,6 +44,7 @@ var (
 	lookupMX   = net.LookupMX
 	lookupIP   = net.LookupIP
 	lookupAddr = net.LookupAddr
+	trace      = func(f string, a ...interface{}) {}
 )
 
 // The Result of an SPF check. Note the values have meaning, we use them in
@@ -109,6 +110,7 @@ var (
 // to determine if `ip` is permitted to send mail for it.
 // Reference: https://tools.ietf.org/html/rfc7208#section-4
 func CheckHost(ip net.IP, domain string) (Result, error) {
+	trace("check host %q %q", ip, domain)
 	r := &resolution{ip, 0, "", nil}
 	return r.Check(domain)
 }
@@ -123,6 +125,7 @@ func CheckHostWithSender(ip net.IP, helo, sender string) (Result, error) {
 		domain = helo
 	}
 
+	trace("check host with sender %q %q %q (%q)", ip, helo, sender, domain)
 	r := &resolution{ip, 0, sender, nil}
 	return r.Check(domain)
 }
@@ -149,19 +152,23 @@ type resolution struct {
 
 func (r *resolution) Check(domain string) (Result, error) {
 	r.count++
+	trace("check %s %d", domain, r.count)
 	txt, err := getDNSRecord(domain)
 	if err != nil {
 		if isTemporary(err) {
+			trace("dns temp error: %v", err)
 			return TempError, err
 		}
 		// Could not resolve the name, it may be missing the record.
 		// https://tools.ietf.org/html/rfc7208#section-2.6.1
+		trace("dns perm error: %v", err)
 		return None, err
 	}
 
 	if txt == "" {
 		// No record => None.
 		// https://tools.ietf.org/html/rfc7208#section-4.6
+		trace("no txt record")
 		return None, nil
 	}
 
@@ -187,6 +194,7 @@ func (r *resolution) Check(domain string) (Result, error) {
 		// Limit the number of resolutions to 10
 		// https://tools.ietf.org/html/rfc7208#section-4.6.4
 		if r.count > 10 {
+			trace("lookup limit reached")
 			return PermError, errLookupLimitReached
 		}
 
@@ -205,32 +213,41 @@ func (r *resolution) Check(domain string) (Result, error) {
 
 		if field == "all" {
 			// https://tools.ietf.org/html/rfc7208#section-5.1
+			trace("%v matched all", result)
 			return result, errMatchedAll
 		} else if strings.HasPrefix(field, "include:") {
 			if ok, res, err := r.includeField(result, field); ok {
+				trace("include ok, %v %v", res, err)
 				return res, err
 			}
 		} else if strings.HasPrefix(field, "a") {
 			if ok, res, err := r.aField(result, field, domain); ok {
+				trace("a ok, %v %v", res, err)
 				return res, err
 			}
 		} else if strings.HasPrefix(field, "mx") {
 			if ok, res, err := r.mxField(result, field, domain); ok {
+				trace("mx ok, %v %v", res, err)
 				return res, err
 			}
 		} else if strings.HasPrefix(field, "ip4:") || strings.HasPrefix(field, "ip6:") {
 			if ok, res, err := r.ipField(result, field); ok {
+				trace("ip ok, %v %v", res, err)
 				return res, err
 			}
 		} else if strings.HasPrefix(field, "ptr") {
 			if ok, res, err := r.ptrField(result, field, domain); ok {
+				trace("ptr ok, %v %v", res, err)
 				return res, err
 			}
 		} else if strings.HasPrefix(field, "exists") {
+			trace("exists, neutral / not supported")
 			return Neutral, errExistsNotSupported
 		} else if strings.HasPrefix(field, "exp=") {
+			trace("exp=, neutral / not supported")
 			return Neutral, errExpNotSupported
 		} else if strings.HasPrefix(field, "redirect=") {
+			trace("redirect, %q", field)
 			// https://tools.ietf.org/html/rfc7208#section-6.1
 			result, err := r.Check(field[len("redirect="):])
 			if result == None {
@@ -239,12 +256,14 @@ func (r *resolution) Check(domain string) (Result, error) {
 			return result, err
 		} else {
 			// http://www.openspf.org/SPF_Record_Syntax
+			trace("permerror, unknown field")
 			return PermError, errUnknownField
 		}
 	}
 
 	// Got to the end of the evaluation without a result => Neutral.
 	// https://tools.ietf.org/html/rfc7208#section-4.7
+	trace("fallback to neutral")
 	return Neutral, nil
 }
 
diff --git a/spf_test.go b/spf_test.go
index 54383ec..c5c482a 100644
--- a/spf_test.go
+++ b/spf_test.go
@@ -13,6 +13,7 @@ var ip6660 = net.ParseIP("2001:db8::0")
 
 func TestBasic(t *testing.T) {
 	dns = NewDNS()
+	trace = t.Logf
 
 	cases := []struct {
 		txt string
@@ -78,6 +79,7 @@ func TestBasic(t *testing.T) {
 
 func TestIPv6(t *testing.T) {
 	dns = NewDNS()
+	trace = t.Logf
 
 	cases := []struct {
 		txt string
@@ -121,6 +123,7 @@ func TestIPv6(t *testing.T) {
 }
 
 func TestNotSupported(t *testing.T) {
+	trace = t.Logf
 	cases := []struct {
 		txt string
 		err error
@@ -145,6 +148,7 @@ func TestInclude(t *testing.T) {
 	// If we got a match on 1.1.1.1, is because include:domain2 did not match.
 	dns = NewDNS()
 	dns.txt["domain"] = []string{"v=spf1 include:domain2 ip4:1.1.1.1"}
+	trace = t.Logf
 
 	cases := []struct {
 		txt string
@@ -172,6 +176,7 @@ func TestInclude(t *testing.T) {
 func TestRecursionLimit(t *testing.T) {
 	dns = NewDNS()
 	dns.txt["domain"] = []string{"v=spf1 include:domain ~all"}
+	trace = t.Logf
 
 	res, err := CheckHost(ip1111, "domain")
 	if res != PermError || err != errLookupLimitReached {
@@ -183,6 +188,7 @@ func TestRedirect(t *testing.T) {
 	dns = NewDNS()
 	dns.txt["domain"] = []string{"v=spf1 redirect=domain2"}
 	dns.txt["domain2"] = []string{"v=spf1 ip4:1.1.1.1 -all"}
+	trace = t.Logf
 
 	res, err := CheckHost(ip1111, "domain")
 	if res != Pass {
@@ -196,6 +202,7 @@ func TestInvalidRedirect(t *testing.T) {
 	// https://tools.ietf.org/html/rfc7208#section-6.1
 	dns = NewDNS()
 	dns.txt["domain"] = []string{"v=spf1 redirect=doesnotexist"}
+	trace = t.Logf
 
 	res, err := CheckHost(ip1111, "doesnotexist")
 	if res != None {
@@ -213,6 +220,7 @@ func TestRedirectOrder(t *testing.T) {
 	// redirect modifier appears before them.
 	dns = NewDNS()
 	dns.txt["faildom"] = []string{"v=spf1 -all"}
+	trace = t.Logf
 
 	dns.txt["domain"] = []string{"v=spf1 redirect=faildom"}
 	res, err := CheckHost(ip1111, "domain")
@@ -232,6 +240,7 @@ func TestNoRecord(t *testing.T) {
 	dns.txt["d1"] = []string{""}
 	dns.txt["d2"] = []string{"loco", "v=spf2"}
 	dns.errors["nospf"] = fmt.Errorf("no such domain")
+	trace = t.Logf
 
 	for _, domain := range []string{"d1", "d2", "d3", "nospf"} {
 		res, err := CheckHost(ip1111, domain)
@@ -252,6 +261,7 @@ func TestDNSTemporaryErrors(t *testing.T) {
 	dns.errors["tmperr"] = dnsError
 	dns.errors["1.1.1.1"] = dnsError
 	dns.mx["tmpmx"] = []*net.MX{{"tmperr", 10}}
+	trace = t.Logf
 
 	cases := []struct {
 		txt string
@@ -285,6 +295,7 @@ func TestDNSPermanentErrors(t *testing.T) {
 	dns.errors["tmperr"] = dnsError
 	dns.errors["1.1.1.1"] = dnsError
 	dns.mx["tmpmx"] = []*net.MX{{"tmperr", 10}}
+	trace = t.Logf
 
 	cases := []struct {
 		txt string
diff --git a/yml_test.go b/yml_test.go
index 48c20a8..e68cd6b 100644
--- a/yml_test.go
+++ b/yml_test.go
@@ -146,6 +146,8 @@ func testRFC(t *testing.T, fname string) {
 		suites = append(suites, s)
 	}
 
+	trace = t.Logf
+
 	for _, suite := range suites {
 		t.Logf("suite: %v", suite.Description)