// SPDX-License-Identifier: MIT package checker import ( "context" "strings" "testing" sdk "git.happydns.org/checker-sdk-go/checker" ) func TestMatchesAny(t *testing.T) { if !matchesAny("foo signature has expired bar", []string{"signature has expired"}) { t.Error("expected substring match") } if matchesAny("clean", []string{"missing"}) { t.Error("did not expect a match") } if matchesAny("anything", []string{""}) { t.Error("empty needle must not match") } if matchesAny("anything", nil) { t.Error("nil needles must not match") } } func TestCommonFailuresRule_Match(t *testing.T) { d := &DNSVizData{ Order: []string{"example.com."}, Zones: map[string]ZoneAnalysis{ "example.com.": { Errors: []Finding{ {Code: "X", Description: "An RRSIG signature has expired"}, }, }, }, } r := &commonFailuresRule{} states := r.Evaluate(context.Background(), stubObs{value: d}, nil) if len(states) != 1 { t.Fatalf("expected 1 match, got %+v", states) } if states[0].Code != "dnssec_rrsig_expired" { t.Errorf("expected curated id, got %q", states[0].Code) } if states[0].Status != sdk.StatusCrit { t.Errorf("expected severity Crit, got %v", states[0].Status) } if _, ok := states[0].Meta["hint"].(string); !ok { t.Errorf("expected hint in Meta, got %+v", states[0].Meta) } } func TestCommonFailuresRule_NoMatchEmitsOK(t *testing.T) { d := &DNSVizData{ Order: []string{"example.com."}, Zones: map[string]ZoneAnalysis{ "example.com.": {Errors: []Finding{{Description: "totally unrelated message"}}}, }, } r := &commonFailuresRule{} states := r.Evaluate(context.Background(), stubObs{value: d}, nil) if len(states) != 1 || states[0].Status != sdk.StatusOK { t.Errorf("expected single OK summary, got %+v", states) } } func TestCommonFailuresRule_DedupePerZone(t *testing.T) { // Same scenario surfaced multiple times in a single zone should only emit // one curated state for that (zone, scenario) pair. d := &DNSVizData{ Order: []string{"example.com."}, Zones: map[string]ZoneAnalysis{ "example.com.": { Errors: []Finding{ {Description: "no DS records found"}, {Description: "missing DS at the parent"}, }, }, }, } r := &commonFailuresRule{} states := r.Evaluate(context.Background(), stubObs{value: d}, nil) if len(states) != 1 { t.Fatalf("expected dedup to a single state, got %+v", states) } if states[0].Code != "dnssec_chain_broken_no_ds" { t.Errorf("unexpected curated code: %q", states[0].Code) } } func TestCommonFailuresRule_FirstMatchWins(t *testing.T) { // "rrsig_expired" is listed before generic "expired" patterns; verify a // finding mentioning multiple patterns yields exactly one curated entry. d := &DNSVizData{ Order: []string{"x."}, Zones: map[string]ZoneAnalysis{ "x.": {Errors: []Finding{{Description: "signature has expired and DS does not match"}}}, }, } r := &commonFailuresRule{} states := r.Evaluate(context.Background(), stubObs{value: d}, nil) if len(states) != 1 { t.Fatalf("expected single curated entry, got %d: %+v", len(states), states) } if !strings.HasPrefix(states[0].Code, "dnssec_") { t.Errorf("unexpected code %q", states[0].Code) } } func TestCommonFailures_PatternsLowercase(t *testing.T) { // All catalog patterns are lowercased for substring matching against a // lowercased haystack. A non-lowercase pattern would silently never match. for _, c := range commonFailures { for _, p := range c.Patterns { if p != strings.ToLower(p) { t.Errorf("pattern %q in %q is not lowercase", p, c.ID) } } } }