package catalog import ( "strings" "testing" ) func TestCatalog(t *testing.T) { c := Default() for _, scope := range []string{ScopeTop, ScopeOptions, ScopeView, "zone:primary", "zone:secondary", "zone:forward", "zone:hint", "zone:stub", "zone:static-stub", "zone:mirror", "zone:redirect", "zone:in-view"} { if len(c.List(scope)) == 0 { t.Errorf("scope %s is empty", scope) } } type want struct { scope, name, kind string multiple bool status string managed bool } cases := []want{ {ScopeOptions, "recursion", KindBool, false, "", false}, {ScopeOptions, "allow-recursion", KindACL, false, "", false}, {ScopeOptions, "dnssec-validation", KindEnum, false, "", false}, {ScopeOptions, "check-names", KindRaw, true, "", false}, {ScopeOptions, "directory", KindString, false, "", false}, {ScopeOptions, "max-cache-ttl", KindDuration, false, "", false}, {ScopeOptions, "sortlist", KindACL, false, "deprecated", false}, {ScopeOptions, "dns64", KindRaw, true, "", false}, {ScopeOptions, "listen-on", KindRaw, true, "", false}, {ScopeView, "match-clients", KindACL, false, "", true}, {ScopeView, "recursion", KindBool, false, "", false}, {ScopeView, "server", KindRaw, true, "", false}, {"zone:primary", "allow-update", KindACL, false, "", false}, {"zone:primary", "file", KindString, false, "", true}, {"zone:primary", "notify", KindEnum, false, "", false}, {"zone:secondary", "primaries", KindRaw, false, "", false}, {"zone:forward", "forward", KindEnum, false, "", false}, {"zone:in-view", "in-view", KindWord, false, "", true}, {ScopeTop, "logging", KindRaw, false, "", false}, {ScopeTop, "controls", KindRaw, true, "", false}, {ScopeTop, "acl", KindRaw, true, "", true}, {ScopeTop, "view", KindRaw, true, "", true}, {ScopeTop, "include", KindString, true, "", false}, {ScopeTop, "remote-servers", KindRaw, true, "", false}, } for _, w := range cases { st, ok := c.Lookup(w.scope, w.name) if !ok { t.Errorf("%s/%s missing", w.scope, w.name) continue } if st.Kind != w.kind || st.Multiple != w.multiple || st.Status != w.status || st.Managed != w.managed { t.Errorf("%s/%s = kind %s multiple %v status %q managed %v; want %+v (grammar %q)", w.scope, w.name, st.Kind, st.Multiple, st.Status, st.Managed, w, st.Grammar) } } if _, ok := c.Lookup("zone:forward", "allow-update"); ok { t.Error("allow-update is not valid in forward zones") } if _, ok := c.Lookup(ScopeOptions, "frobnicate"); ok { t.Error("unknown option found") } st, _ := c.Lookup(ScopeOptions, "dnssec-validation") if strings.Join(st.Choices, ",") != "yes,no,auto" { t.Errorf("dnssec-validation choices = %v", st.Choices) } st, _ = c.Lookup(ScopeOptions, "allow-recursion") if st.Description == "" || len(st.Tags) == 0 { t.Error("description missing") } st, _ = c.Lookup(ScopeOptions, "dns64") if !strings.Contains(st.Grammar, "break-dnssec") { t.Errorf("nested grammar missing: %q", st.Grammar) } types := strings.Join(c.ZoneTypes(), ",") if types != "forward,hint,in-view,mirror,primary,redirect,secondary,static-stub,stub" { t.Errorf("zone types = %s", types) } } func TestWrapList(t *testing.T) { c := Default() for _, tc := range []struct{ scope, name, in, want string }{ {ScopeOptions, "allow-transfer", "10.0.10.53", "{ 10.0.10.53; }"}, {ScopeOptions, "allow-transfer", "localhost 10.0.10.53 key xfer ! key old !10.0.0.1", "{ localhost; 10.0.10.53; key xfer; ! key old; !10.0.0.1; }"}, {ScopeOptions, "forwarders", "1.1.1.1 port 853 tls cf 9.9.9.9", "{ 1.1.1.1 port 853 tls cf; 9.9.9.9; }"}, {ScopeOptions, "allow-transfer", "localhost; 10.0.10.53", "{ localhost; 10.0.10.53; }"}, {ScopeOptions, "allow-transfer", "port 5353 key xfer, !10.0.0.1", "port 5353 { key xfer; !10.0.0.1; }"}, {ScopeOptions, "allow-transfer", "{ any; }", "{ any; }"}, {ScopeOptions, "allow-query", "10.0.0.0/8 192.168.1.0/24", "{ 10.0.0.0/8; 192.168.1.0/24; }"}, {ScopeOptions, "forwarders", "1.1.1.1 9.9.9.9", "{ 1.1.1.1; 9.9.9.9; }"}, {ScopeOptions, "listen-on", "port 53 10.0.10.5", "port 53 { 10.0.10.5; }"}, {ScopeOptions, "recursion", "yes", "yes"}, {ScopeOptions, "directory", `"/var/cache/bind"`, `"/var/cache/bind"`}, } { st, ok := c.Lookup(tc.scope, tc.name) if !ok { t.Fatalf("%s not found", tc.name) } if got := st.WrapList(tc.in); got != tc.want { t.Errorf("%s %q = %q, want %q", tc.name, tc.in, got, tc.want) } } }