From a30954ea71bb8498abaf127a8565d4fa226165cc Mon Sep 17 00:00:00 2001 From: Ville Vesilehto Date: Mon, 15 Sep 2025 20:17:35 +0300 Subject: [PATCH] test(view): improve test coverage (#7543) Cover edge cases in config parser. Add rudimentary View/Filter tests. Improves test coverage from 44% to 82%. Signed-off-by: Ville Vesilehto --- plugin/view/metadata_test.go | 22 +++++++++++ plugin/view/setup_test.go | 25 +++++++++++++ plugin/view/view_test.go | 71 ++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+) create mode 100644 plugin/view/metadata_test.go create mode 100644 plugin/view/view_test.go diff --git a/plugin/view/metadata_test.go b/plugin/view/metadata_test.go new file mode 100644 index 000000000..bd3cc13e6 --- /dev/null +++ b/plugin/view/metadata_test.go @@ -0,0 +1,22 @@ +package view + +import ( + "context" + "testing" + + "github.com/coredns/coredns/plugin/metadata" + "github.com/coredns/coredns/request" +) + +func TestMetadata_PublishesViewName(t *testing.T) { + v := &View{viewName: "myview"} + ctx := metadata.ContextWithMetadata(context.Background()) + st := request.Request{} + ctx = v.Metadata(ctx, st) + + if f := metadata.ValueFunc(ctx, "view/name"); f == nil { + t.Fatalf("metadata value func is nil") + } else if got := f(); got != "myview" { + t.Fatalf("metadata value: got %q, want %q", got, "myview") + } +} diff --git a/plugin/view/setup_test.go b/plugin/view/setup_test.go index 7c7838070..309d85cb8 100644 --- a/plugin/view/setup_test.go +++ b/plugin/view/setup_test.go @@ -1,9 +1,14 @@ package view import ( + "context" + "errors" "testing" "github.com/coredns/caddy" + ptest "github.com/coredns/coredns/plugin/test" + + "github.com/miekg/dns" ) func TestSetup(t *testing.T) { @@ -17,6 +22,8 @@ func TestSetup(t *testing.T) { {"view example {\n expr name() == 'example.com.'\n expr name() == 'example2.com.'\n}", false, 2}, {"view", true, 0}, {"view example {\n expr invalid expression\n}", true, 0}, + {"view x {\n foo bar\n}\n", true, 0}, + {"view a { }\nview b { }\n", true, 0}, } for i, test := range tests { @@ -36,3 +43,21 @@ func TestSetup(t *testing.T) { } } } + +func TestServeDNS_DelegatesToNext(t *testing.T) { + v := &View{} + wantCode := 123 + wantErr := errors.New("boom") + v.Next = ptest.NextHandler(wantCode, wantErr) + + rr := new(dns.Msg) + rr.SetQuestion("example.com.", dns.TypeA) + w := &ptest.ResponseWriter{} + gotCode, gotErr := v.ServeDNS(context.Background(), w, rr) + if gotCode != wantCode { + t.Fatalf("rcode: got %d, want %d", gotCode, wantCode) + } + if gotErr != wantErr { + t.Fatalf("error: got %v, want %v", gotErr, wantErr) + } +} diff --git a/plugin/view/view_test.go b/plugin/view/view_test.go new file mode 100644 index 000000000..1f080cd11 --- /dev/null +++ b/plugin/view/view_test.go @@ -0,0 +1,71 @@ +package view + +import ( + "context" + "testing" + + "github.com/coredns/coredns/plugin/pkg/expression" + ptest "github.com/coredns/coredns/plugin/test" + "github.com/coredns/coredns/request" + + "github.com/expr-lang/expr" + "github.com/expr-lang/expr/vm" + "github.com/miekg/dns" +) + +func TestFilter_NoPrograms(t *testing.T) { + v := &View{viewName: "test"} + st := makeState(t, "example.com.") + if !v.Filter(context.Background(), st) { + t.Fatalf("expected true when no programs are configured") + } +} + +func TestFilter_ErrorPaths(t *testing.T) { + st := makeState(t, "example.com.") + + tests := []struct { + expr string + expected bool + }{ + {"name() == 'example.com.'", true}, + {"name() == 'notexample.com.'", false}, + {"1", false}, + {"incidr('invalid', '1.2.3.0/24')", false}, + } + + for i, tc := range tests { + v := &View{progs: []*vm.Program{compileExpr(t, tc.expr)}} + got := v.Filter(context.Background(), st) + if got != tc.expected { + t.Fatalf("case %d expr %q: expected %v, got %v", i, tc.expr, tc.expected, got) + } + } +} + +func TestView_Names(t *testing.T) { + v := &View{viewName: "v1"} + if v.ViewName() != "v1" { + t.Fatalf("ViewName() expected %q, got %q", "v1", v.ViewName()) + } + if v.Name() != "view" { + t.Fatalf("Name() expected %q, got %q", "view", v.Name()) + } +} + +func compileExpr(t *testing.T, e string) *vm.Program { + t.Helper() + prog, err := expr.Compile(e, expr.Env(expression.DefaultEnv(context.Background(), nil)), expr.DisableBuiltin("type")) + if err != nil { + t.Fatalf("compile failed for %q: %v", e, err) + } + return prog +} + +func makeState(t *testing.T, qname string) *request.Request { + t.Helper() + m := new(dns.Msg) + m.SetQuestion(dns.Fqdn(qname), dns.TypeA) + w := &ptest.ResponseWriter{} + return &request.Request{W: w, Req: m} +}