more compliance

pull/18/head
Hugo Landau 10 years ago
parent 444da5c251
commit 0c11a32c1c

@ -315,7 +315,7 @@ func (v *Value) findSubdomainByName(subdomain string) (*Value, error) {
return nil, fmt.Errorf("subdomain part not found: %s", head) return nil, fmt.Errorf("subdomain part not found: %s", head)
} }
type rawValue struct { type rawValue_old struct {
IP interface{} `json:"ip"` IP interface{} `json:"ip"`
IP6 interface{} `json:"ip6"` IP6 interface{} `json:"ip6"`
NS interface{} `json:"ns"` NS interface{} `json:"ns"`
@ -363,10 +363,10 @@ func (ef ErrorFunc) addWarning(err error) {
// continues and recovers as much as possible; errFunc is called for all errors // continues and recovers as much as possible; errFunc is called for all errors
// and warnings if specified. // and warnings if specified.
func ParseValue(name, jsonValue string, resolve ResolveFunc, errFunc ErrorFunc) (value *Value) { func ParseValue(name, jsonValue string, resolve ResolveFunc, errFunc ErrorFunc) (value *Value) {
rv := &rawValue{} var rv interface{}
v := &Value{} v := &Value{}
err := json.Unmarshal([]byte(jsonValue), rv) err := json.Unmarshal([]byte(jsonValue), &rv)
if err != nil { if err != nil {
errFunc.add(err) errFunc.add(err)
return return
@ -381,14 +381,20 @@ func ParseValue(name, jsonValue string, resolve ResolveFunc, errFunc ErrorFunc)
mergedNames := map[string]struct{}{} mergedNames := map[string]struct{}{}
mergedNames[name] = struct{}{} mergedNames[name] = struct{}{}
rv.parse(v, resolve, errFunc, 0, 0, "", "", mergedNames) parse(rv, v, resolve, errFunc, 0, 0, "", "", mergedNames)
v.IsTopLevel = true v.IsTopLevel = true
value = v value = v
return return
} }
func (rv *rawValue) parse(v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, subdomain, relname string, mergedNames map[string]struct{}) { func parse(rv interface{}, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, subdomain, relname string, mergedNames map[string]struct{}) {
rvm, ok := rv.(map[string]interface{})
if !ok {
errFunc.add(fmt.Errorf("value is not an object"))
return
}
if depth > depthLimit { if depth > depthLimit {
errFunc.add(fmt.Errorf("depth limit exceeded")) errFunc.add(fmt.Errorf("depth limit exceeded"))
return return
@ -401,24 +407,28 @@ func (rv *rawValue) parse(v *Value, resolve ResolveFunc, errFunc ErrorFunc, dept
v = &Value{} v = &Value{}
} }
ok, _ := rv.parseDelegate(v, resolve, errFunc, depth, mergeDepth, relname, mergedNames) ok, _ = parseDelegate(rvm, v, resolve, errFunc, depth, mergeDepth, relname, mergedNames)
if ok { if ok {
return return
} }
rv.parseImport(v, resolve, errFunc, depth, mergeDepth, relname, mergedNames) parseImport(rvm, v, resolve, errFunc, depth, mergeDepth, relname, mergedNames)
rv.parseIP(v, errFunc, rv.IP, false) if ip, ok := rvm["ip"]; ok {
rv.parseIP(v, errFunc, rv.IP6, true) parseIP(rvm, v, errFunc, ip, false)
rv.parseNS(v, errFunc, relname) }
rv.parseAlias(v, errFunc, relname) if ip6, ok := rvm["ip6"]; ok {
rv.parseTranslate(v, errFunc, relname) parseIP(rvm, v, errFunc, ip6, true)
rv.parseHostmaster(v, errFunc) }
rv.parseDS(v, errFunc) parseNS(rvm, v, errFunc, relname)
rv.parseTXT(v, errFunc) parseAlias(rvm, v, errFunc, relname)
rv.parseService(v, errFunc, relname) parseTranslate(rvm, v, errFunc, relname)
rv.parseMX(v, errFunc, relname) parseHostmaster(rvm, v, errFunc)
rv.parseTLSA(v, errFunc) parseDS(rvm, v, errFunc)
rv.parseMap(v, resolve, errFunc, depth, mergeDepth, relname) parseTXT(rvm, v, errFunc)
parseService(rvm, v, errFunc, relname)
parseMX(rvm, v, errFunc, relname)
parseTLSA(rvm, v, errFunc)
parseMap(rvm, v, resolve, errFunc, depth, mergeDepth, relname)
v.moveEmptyMapItems() v.moveEmptyMapItems()
if subdomain != "" { if subdomain != "" {
@ -464,8 +474,8 @@ func (v *Value) qualify(name, suffix, apexSuffix string) (string, bool) {
return s, true return s, true
} }
func (rv *rawValue) parseMerge(mergeValue string, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, subdomain, relname string, mergedNames map[string]struct{}) error { func parseMerge(rv map[string]interface{}, mergeValue string, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, subdomain, relname string, mergedNames map[string]struct{}) error {
rv2 := &rawValue{} var rv2 interface{}
if mergeDepth > mergeDepthLimit { if mergeDepth > mergeDepthLimit {
err := fmt.Errorf("merge depth limit exceeded") err := fmt.Errorf("merge depth limit exceeded")
@ -473,30 +483,32 @@ func (rv *rawValue) parseMerge(mergeValue string, v *Value, resolve ResolveFunc,
return err return err
} }
err := json.Unmarshal([]byte(mergeValue), rv2) err := json.Unmarshal([]byte(mergeValue), &rv2)
if err != nil { if err != nil {
err = fmt.Errorf("couldn't parse JSON to be merged: %v", err) err = fmt.Errorf("couldn't parse JSON to be merged: %v", err)
errFunc.add(err) errFunc.add(err)
return err return err
} }
rv2.parse(v, resolve, errFunc, depth, mergeDepth, subdomain, relname, mergedNames) parse(rv2, v, resolve, errFunc, depth, mergeDepth, subdomain, relname, mergedNames)
return nil return nil
} }
func (rv *rawValue) parseIP(v *Value, errFunc ErrorFunc, ipi interface{}, ipv6 bool) { func parseIP(rv map[string]interface{}, v *Value, errFunc ErrorFunc, ipi interface{}, ipv6 bool) {
if ipi != nil { if ipv6 {
if ipv6 { v.IP6 = nil
v.IP6 = nil } else {
} else { v.IP = nil
v.IP = nil }
}
if ipi == nil {
return
} }
if ipa, ok := ipi.([]interface{}); ok { if ipa, ok := ipi.([]interface{}); ok {
for _, ip := range ipa { for _, ip := range ipa {
if ips, ok := ip.(string); ok { if ips, ok := ip.(string); ok {
rv.addIP(v, errFunc, ips, ipv6) addIP(rv, v, errFunc, ips, ipv6)
} }
} }
@ -504,11 +516,11 @@ func (rv *rawValue) parseIP(v *Value, errFunc ErrorFunc, ipi interface{}, ipv6 b
} }
if ip, ok := ipi.(string); ok { if ip, ok := ipi.(string); ok {
rv.addIP(v, errFunc, ip, ipv6) addIP(rv, v, errFunc, ip, ipv6)
} }
} }
func (rv *rawValue) addIP(v *Value, errFunc ErrorFunc, ips string, ipv6 bool) { func addIP(rv map[string]interface{}, v *Value, errFunc ErrorFunc, ips string, ipv6 bool) {
pip := net.ParseIP(ips) pip := net.ParseIP(ips)
if pip == nil || (pip.To4() == nil) != ipv6 { if pip == nil || (pip.To4() == nil) != ipv6 {
errFunc.add(fmt.Errorf("malformed IP: %s", ips)) errFunc.add(fmt.Errorf("malformed IP: %s", ips))
@ -522,54 +534,70 @@ func (rv *rawValue) addIP(v *Value, errFunc ErrorFunc, ips string, ipv6 bool) {
} }
} }
func (rv *rawValue) parseNS(v *Value, errFunc ErrorFunc, relname string) { func parseNS(rv map[string]interface{}, v *Value, errFunc ErrorFunc, relname string) {
// "dns" takes precedence // "dns" takes precedence
if rv.DNS != nil { if dns, ok := rv["dns"]; ok && dns != nil {
rv.NS = rv.DNS rv["ns"] = dns
} }
if rv.NS == nil { ns, ok := rv["ns"]
if !ok || ns == nil {
return return
} }
v.NS = nil v.NS = nil
if rv.nsSet == nil { if _, ok := rv["_nsSet"]; !ok {
rv.nsSet = map[string]struct{}{} rv["_nsSet"] = map[string]struct{}{}
} }
switch rv.NS.(type) { switch ns.(type) {
case []interface{}: case []interface{}:
for _, si := range rv.NS.([]interface{}) { for _, si := range ns.([]interface{}) {
s, ok := si.(string) s, ok := si.(string)
if !ok { if !ok {
continue continue
} }
rv.addNS(v, s, relname) addNS(rv, v, errFunc, s, relname)
} }
return return
case string: case string:
s := rv.NS.(string) s := ns.(string)
rv.addNS(v, s, relname) addNS(rv, v, errFunc, s, relname)
return return
default: default:
errFunc.add(fmt.Errorf("unknown NS field format")) errFunc.add(fmt.Errorf("unknown NS field format"))
} }
} }
func (rv *rawValue) addNS(v *Value, s, relname string) { func addNS(rv map[string]interface{}, v *Value, errFunc ErrorFunc, s, relname string) {
if _, ok := rv.nsSet[s]; !ok { if !util.ValidateOwnerName(s) {
errFunc.add(fmt.Errorf("malformed domain name in NS field"))
}
if _, ok := (rv["_nsSet"].(map[string]struct{}))[s]; !ok {
v.NS = append(v.NS, s) v.NS = append(v.NS, s)
rv.nsSet[s] = struct{}{} (rv["_nsSet"].(map[string]struct{}))[s] = struct{}{}
} }
} }
func (rv *rawValue) parseAlias(v *Value, errFunc ErrorFunc, relname string) { func parseAlias(rv map[string]interface{}, v *Value, errFunc ErrorFunc, relname string) {
if rv.Alias == nil { alias, ok := rv["alias"]
if !ok {
return
}
if alias == nil {
v.Alias = ""
v.HasAlias = false
return return
} }
if s, ok := rv.Alias.(string); ok { if s, ok := alias.(string); ok {
if !util.ValidateOwnerName(s) {
errFunc.add(fmt.Errorf("malformed alias name"))
return
}
v.Alias = s v.Alias = s
v.HasAlias = true v.HasAlias = true
return return
@ -578,12 +606,23 @@ func (rv *rawValue) parseAlias(v *Value, errFunc ErrorFunc, relname string) {
errFunc.add(fmt.Errorf("unknown alias field format")) errFunc.add(fmt.Errorf("unknown alias field format"))
} }
func (rv *rawValue) parseTranslate(v *Value, errFunc ErrorFunc, relname string) { func parseTranslate(rv map[string]interface{}, v *Value, errFunc ErrorFunc, relname string) {
if rv.Translate == nil { translate, ok := rv["translate"]
if !ok {
return
}
if translate == nil {
v.Translate = ""
v.HasTranslate = false
return return
} }
if s, ok := rv.Translate.(string); ok { if s, ok := translate.(string); ok {
if !util.ValidateOwnerName(s) {
errFunc.add(fmt.Errorf("malformed translate name"))
return
}
v.Translate = s v.Translate = s
v.HasTranslate = true v.HasTranslate = true
return return
@ -610,15 +649,16 @@ func isAllString(x []interface{}) bool {
return true return true
} }
func (rv *rawValue) parseImportImpl(val *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}, delegate bool) (bool, error) { func parseImportImpl(rv map[string]interface{}, val *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}, delegate bool) (bool, error) {
var err error var err error
succeeded := false succeeded := false
src := rv.Import xname := "import"
if delegate { if delegate {
src = rv.Delegate xname = "delegate"
} }
if src == nil { src, ok := rv[xname]
if !ok || src == nil {
return false, nil return false, nil
} }
@ -665,7 +705,7 @@ func (rv *rawValue) parseImportImpl(val *Value, resolve ResolveFunc, errFunc Err
mergedNames[k] = struct{}{} mergedNames[k] = struct{}{}
err = rv.parseMerge(dv, val, resolve, errFunc, depth, mergeDepth+1, subs, relname, mergedNames) err = parseMerge(rv, dv, val, resolve, errFunc, depth, mergeDepth+1, subs, relname, mergedNames)
if err != nil { if err != nil {
errFunc.add(err) errFunc.add(err)
continue continue
@ -690,21 +730,22 @@ func (rv *rawValue) parseImportImpl(val *Value, resolve ResolveFunc, errFunc Err
return succeeded, err return succeeded, err
} }
func (rv *rawValue) parseImport(v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}) error { func parseImport(rv map[string]interface{}, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}) error {
_, err := rv.parseImportImpl(v, resolve, errFunc, depth, mergeDepth, relname, mergedNames, false) _, err := parseImportImpl(rv, v, resolve, errFunc, depth, mergeDepth, relname, mergedNames, false)
return err return err
} }
func (rv *rawValue) parseDelegate(v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}) (bool, error) { func parseDelegate(rv map[string]interface{}, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string, mergedNames map[string]struct{}) (bool, error) {
return rv.parseImportImpl(v, resolve, errFunc, depth, mergeDepth, relname, mergedNames, true) return parseImportImpl(rv, v, resolve, errFunc, depth, mergeDepth, relname, mergedNames, true)
} }
func (rv *rawValue) parseHostmaster(v *Value, errFunc ErrorFunc) { func parseHostmaster(rv map[string]interface{}, v *Value, errFunc ErrorFunc) {
if rv.Hostmaster == nil { hm, ok := rv["email"]
if !ok || hm == nil {
return return
} }
if s, ok := rv.Hostmaster.(string); ok { if s, ok := hm.(string); ok {
if !util.ValidateEmail(s) { if !util.ValidateEmail(s) {
errFunc.add(fmt.Errorf("malformed e. mail address in email field")) errFunc.add(fmt.Errorf("malformed e. mail address in email field"))
return return
@ -717,14 +758,15 @@ func (rv *rawValue) parseHostmaster(v *Value, errFunc ErrorFunc) {
errFunc.add(fmt.Errorf("unknown email field format")) errFunc.add(fmt.Errorf("unknown email field format"))
} }
func (rv *rawValue) parseDS(v *Value, errFunc ErrorFunc) { func parseDS(rv map[string]interface{}, v *Value, errFunc ErrorFunc) {
if rv.DS == nil { rds, ok := rv["ds"]
if !ok || rds == nil {
return return
} }
v.DS = nil v.DS = nil
if dsa, ok := rv.DS.([]interface{}); ok { if dsa, ok := rds.([]interface{}); ok {
for _, ds1 := range dsa { for _, ds1 := range dsa {
if ds, ok := ds1.([]interface{}); ok { if ds, ok := ds1.([]interface{}); ok {
if len(ds) < 4 { if len(ds) < 4 {
@ -780,14 +822,15 @@ func (rv *rawValue) parseDS(v *Value, errFunc ErrorFunc) {
errFunc.add(fmt.Errorf("malformed DS field format")) errFunc.add(fmt.Errorf("malformed DS field format"))
} }
func (rv *rawValue) parseTLSA(v *Value, errFunc ErrorFunc) { func parseTLSA(rv map[string]interface{}, v *Value, errFunc ErrorFunc) {
if rv.TLSA == nil { tlsa, ok := rv["tls"]
if !ok || tlsa == nil {
return return
} }
v.TLSA = nil v.TLSA = nil
if tlsaa, ok := rv.TLSA.([]interface{}); ok { if tlsaa, ok := tlsa.([]interface{}); ok {
for _, tlsa1 := range tlsaa { for _, tlsa1 := range tlsaa {
if tlsa, ok := tlsa1.([]interface{}); ok { if tlsa, ok := tlsa1.([]interface{}); ok {
// Format: ["443", "tcp", 1, 2, 3, "base64 certificate data"] // Format: ["443", "tcp", 1, 2, 3, "base64 certificate data"]
@ -868,12 +911,13 @@ func (rv *rawValue) parseTLSA(v *Value, errFunc ErrorFunc) {
errFunc.add(fmt.Errorf("Malformed TLSA field format")) errFunc.add(fmt.Errorf("Malformed TLSA field format"))
} }
func (rv *rawValue) parseTXT(v *Value, errFunc ErrorFunc) { func parseTXT(rv map[string]interface{}, v *Value, errFunc ErrorFunc) {
if rv.TXT == nil { rtxt, ok := rv["txt"]
if !ok || rtxt == nil {
return return
} }
if txta, ok := rv.TXT.([]interface{}); ok { if txta, ok := rtxt.([]interface{}); ok {
// ["...", "..."] or [["...", "..."], ["...", "..."]] // ["...", "..."] or [["...", "..."], ["...", "..."]]
for _, vv := range txta { for _, vv := range txta {
if sa, ok := vv.([]interface{}); ok { if sa, ok := vv.([]interface{}); ok {
@ -896,7 +940,7 @@ func (rv *rawValue) parseTXT(v *Value, errFunc ErrorFunc) {
} }
} else { } else {
// "..." // "..."
if s, ok := rv.TXT.(string); ok { if s, ok := rtxt.(string); ok {
v.TXT = append(v.TXT, segmentizeTXT(s)) v.TXT = append(v.TXT, segmentizeTXT(s))
} else { } else {
errFunc.add(fmt.Errorf("malformed TXT value")) errFunc.add(fmt.Errorf("malformed TXT value"))
@ -934,14 +978,15 @@ func segmentizeTXT(txt string) (a []string) {
return return
} }
func (rv *rawValue) parseMX(v *Value, errFunc ErrorFunc, relname string) { func parseMX(rv map[string]interface{}, v *Value, errFunc ErrorFunc, relname string) {
if rv.MX == nil { rmx, ok := rv["mx"]
if !ok || rmx == nil {
return return
} }
if sa, ok := rv.MX.([]interface{}); ok { if sa, ok := rmx.([]interface{}); ok {
for _, s := range sa { for _, s := range sa {
rv.parseSingleMX(s, v, errFunc, relname) parseSingleMX(rv, s, v, errFunc, relname)
} }
return return
} }
@ -949,7 +994,7 @@ func (rv *rawValue) parseMX(v *Value, errFunc ErrorFunc, relname string) {
errFunc.add(fmt.Errorf("malformed MX value")) errFunc.add(fmt.Errorf("malformed MX value"))
} }
func (rv *rawValue) parseSingleMX(s interface{}, v *Value, errFunc ErrorFunc, relname string) { func parseSingleMX(rv map[string]interface{}, s interface{}, v *Value, errFunc ErrorFunc, relname string) {
sa, ok := s.([]interface{}) sa, ok := s.([]interface{})
if !ok { if !ok {
errFunc.add(fmt.Errorf("malformed MX value")) errFunc.add(fmt.Errorf("malformed MX value"))
@ -982,8 +1027,9 @@ func (rv *rawValue) parseSingleMX(s interface{}, v *Value, errFunc ErrorFunc, re
return return
} }
func (rv *rawValue) parseService(v *Value, errFunc ErrorFunc, relname string) { func parseService(rv map[string]interface{}, v *Value, errFunc ErrorFunc, relname string) {
if rv.Service == nil { rsvc, ok := rv["service"]
if !ok || rsvc == nil {
return return
} }
@ -993,9 +1039,9 @@ func (rv *rawValue) parseService(v *Value, errFunc ErrorFunc, relname string) {
oldServices := v.Service oldServices := v.Service
v.Service = nil v.Service = nil
if sa, ok := rv.Service.([]interface{}); ok { if sa, ok := rsvc.([]interface{}); ok {
for _, s := range sa { for _, s := range sa {
rv.parseSingleService(s, v, errFunc, relname, servicesUsed) parseSingleService(rv, s, v, errFunc, relname, servicesUsed)
} }
} else { } else {
errFunc.add(fmt.Errorf("malformed service value")) errFunc.add(fmt.Errorf("malformed service value"))
@ -1008,7 +1054,7 @@ func (rv *rawValue) parseService(v *Value, errFunc ErrorFunc, relname string) {
} }
} }
func (rv *rawValue) parseSingleService(svc interface{}, v *Value, errFunc ErrorFunc, relname string, servicesUsed map[string]struct{}) { func parseSingleService(rv map[string]interface{}, svc interface{}, v *Value, errFunc ErrorFunc, relname string, servicesUsed map[string]struct{}) {
svca, ok := svc.([]interface{}) svca, ok := svc.([]interface{})
if !ok { if !ok {
errFunc.add(fmt.Errorf("malformed service value")) errFunc.add(fmt.Errorf("malformed service value"))
@ -1075,45 +1121,40 @@ func (rv *rawValue) parseSingleService(svc interface{}, v *Value, errFunc ErrorF
return return
} }
func (rv *rawValue) parseMap(v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string) { func parseMap(rv map[string]interface{}, v *Value, resolve ResolveFunc, errFunc ErrorFunc, depth, mergeDepth int, relname string) {
if rv.Map == nil { rmap, ok := rv["map"]
if !ok || rmap == nil {
return return
} }
m := map[string]json.RawMessage{} m, ok := rmap.(map[string]interface{})
if !ok {
err := json.Unmarshal(rv.Map, &m) errFunc.add(fmt.Errorf("Map value must be an object"))
if err != nil {
errFunc.add(fmt.Errorf("Couldn't unmarshal map: %v", err))
return return
} }
for mk, mv := range m { for mk, mv := range m {
rv2 := &rawValue{} if s, ok := mv.(string); ok {
v2 := &Value{}
var s string
err := json.Unmarshal(mv, &s)
if err == nil {
// deprecated case: "map": { "": "127.0.0.1" } // deprecated case: "map": { "": "127.0.0.1" }
rv2.IP = s mv = map[string]interface{}{"ip": []interface{}{s}}
} else { m[mk] = mv
// normal case: "map": { "": { ... } }
err = json.Unmarshal(mv, rv2)
if err != nil {
errFunc.add(fmt.Errorf("Couldn't unmarshal map: %v", err))
continue
}
} }
mergedNames := map[string]struct{}{} if mvm, ok := mv.(map[string]interface{}); ok {
rv2.parse(v2, resolve, errFunc, depth+1, mergeDepth, "", relname, mergedNames) v2 := &Value{}
mergedNames := map[string]struct{}{}
parse(mvm, v2, resolve, errFunc, depth+1, mergeDepth, "", relname, mergedNames)
if v.Map == nil { if v.Map == nil {
v.Map = make(map[string]*Value) v.Map = make(map[string]*Value)
} }
v.Map[mk] = v2
v.Map[mk] = v2 } else {
errFunc.add(fmt.Errorf("Value in map object must be an object or string"))
continue
}
} }
} }

@ -26,7 +26,15 @@ func TestSuite(t *testing.T) {
continue continue
} }
v := ncdomain.ParseValue(k, jsonValue, resolve, nil) errCount := 0
errFunc := func(err error, isWarning bool) {
if !isWarning {
errCount++
}
//fmt.Printf("Error: %v\n", err)
}
v := ncdomain.ParseValue(k, jsonValue, resolve, errFunc)
if v == nil { if v == nil {
// TODO // TODO
continue continue
@ -46,6 +54,10 @@ func TestSuite(t *testing.T) {
if rrstr != ti.Records { if rrstr != ti.Records {
t.Errorf("Didn't match: %s\n%+v\n !=\n%+v\n\n%#v\n\n%#v", ti.ID, rrstr, ti.Records, v, rrs) t.Errorf("Didn't match: %s\n%+v\n !=\n%+v\n\n%#v\n\n%#v", ti.ID, rrstr, ti.Records, v, rrs)
} }
if errCount != ti.NumErrors {
t.Errorf("Error count didn't match: %d != %d (%s)\n", errCount, ti.NumErrors, ti.ID)
}
} }
} }
} }

@ -9,11 +9,13 @@ import "path/filepath"
import "io" import "io"
import "bufio" import "bufio"
import "testing" import "testing"
import "strconv"
type TestItem struct { type TestItem struct {
ID string ID string
Names map[string]string Names map[string]string
Records string Records string
NumErrors int
} }
func stripTag(L string) string { func stripTag(L string) string {
@ -100,10 +102,19 @@ func SuiteReader(t *testing.T) <-chan TestItem {
} }
} }
if L != "OUT" { if !strings.HasPrefix(L, "OUT") {
t.Fatalf("invalid test suite file") t.Fatalf("invalid test suite file")
} }
numErrors := 0
if len(L) > 4 {
n, err := strconv.ParseUint(L[4:], 10, 31)
if err != nil {
t.Fatalf("invalid error count")
}
numErrors = int(n)
}
records := []string{} records := []string{}
for { for {
L, ok = <-lineChan L, ok = <-lineChan
@ -120,9 +131,10 @@ func SuiteReader(t *testing.T) <-chan TestItem {
// process records // process records
ti := TestItem{ ti := TestItem{
ID: id, ID: id,
Names: m, Names: m,
Records: strings.Join(records, "\n"), Records: strings.Join(records, "\n"),
NumErrors: numErrors,
} }
testItemChan <- ti testItemChan <- ti

@ -126,6 +126,7 @@ var re_hostName = regexp.MustCompilePOSIX(`^(([a-z0-9_][a-z0-9_-]{0,62}\.)*[a-z_
var re_label = regexp.MustCompilePOSIX(`^[a-z_][a-z0-9_-]*$`) var re_label = regexp.MustCompilePOSIX(`^[a-z_][a-z0-9_-]*$`)
var re_serviceName = regexp.MustCompilePOSIX(`^[a-z_][a-z0-9_-]*$`) var re_serviceName = regexp.MustCompilePOSIX(`^[a-z_][a-z0-9_-]*$`)
var re_domainNameLabel = regexp.MustCompilePOSIX(`^(xn--)?[a-z0-9]+(-[a-z0-9]+)*$`) var re_domainNameLabel = regexp.MustCompilePOSIX(`^(xn--)?[a-z0-9]+(-[a-z0-9]+)*$`)
var re_ownerName = regexp.MustCompilePOSIX(`^(|@|([a-z0-9_-]{1,63}\.)*[a-z0-9_-]{1,63}(\.@?)?)$`)
func ValidateHostName(name string) bool { func ValidateHostName(name string) bool {
name = dns.Fqdn(name) name = dns.Fqdn(name)
@ -144,6 +145,10 @@ func ValidateDomainNameLabel(name string) bool {
return len(name) <= 63 && re_domainNameLabel.MatchString(name) return len(name) <= 63 && re_domainNameLabel.MatchString(name)
} }
func ValidateOwnerName(name string) bool {
return len(name) <= 255 && re_ownerName.MatchString(name)
}
func ValidateEmail(email string) bool { func ValidateEmail(email string) bool {
addr, err := mail.ParseAddress(email) addr, err := mail.ParseAddress(email)
if addr == nil || err != nil { if addr == nil || err != nil {

Loading…
Cancel
Save