189 lines
5.6 KiB
Go
189 lines
5.6 KiB
Go
// SPDX-License-Identifier: MIT
|
|
|
|
package checker
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
sdk "git.happydns.org/checker-sdk-go/checker"
|
|
)
|
|
|
|
func sampleData() *DNSVizData {
|
|
return &DNSVizData{
|
|
Domain: "example.com",
|
|
Order: []string{"example.com.", "com.", "."},
|
|
Zones: map[string]ZoneAnalysis{
|
|
"example.com.": {
|
|
Status: "BOGUS",
|
|
Errors: []Finding{{Code: "RRSIG_EXPIRED", Description: "signature has expired"}},
|
|
},
|
|
"com.": {Status: "SECURE"},
|
|
".": {Status: "SECURE"},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestOverallStatusRule(t *testing.T) {
|
|
r := &overallStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: sampleData()}, nil)
|
|
if len(states) != 1 {
|
|
t.Fatalf("expected 1 state, got %d", len(states))
|
|
}
|
|
if states[0].Status != sdk.StatusCrit {
|
|
t.Errorf("expected StatusCrit for BOGUS leaf, got %v", states[0].Status)
|
|
}
|
|
if states[0].Subject != "example.com." {
|
|
t.Errorf("subject: got %q", states[0].Subject)
|
|
}
|
|
}
|
|
|
|
func TestOverallStatusRule_FallbackToFirstZone(t *testing.T) {
|
|
d := &DNSVizData{
|
|
Domain: "missing",
|
|
Order: []string{"other.zone."},
|
|
Zones: map[string]ZoneAnalysis{"other.zone.": {Status: "SECURE"}},
|
|
}
|
|
r := &overallStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: d}, nil)
|
|
if states[0].Subject != "other.zone." {
|
|
t.Errorf("expected fallback to first zone, got %q", states[0].Subject)
|
|
}
|
|
if states[0].Status != sdk.StatusOK {
|
|
t.Errorf("expected SECURE -> OK, got %v", states[0].Status)
|
|
}
|
|
}
|
|
|
|
func TestOverallStatusRule_NoZones(t *testing.T) {
|
|
r := &overallStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: &DNSVizData{Domain: "x"}}, nil)
|
|
if states[0].Status != sdk.StatusUnknown {
|
|
t.Errorf("expected Unknown for empty zones, got %v", states[0].Status)
|
|
}
|
|
}
|
|
|
|
func TestOverallStatusRule_LoadError(t *testing.T) {
|
|
r := &overallStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{err: errors.New("nope")}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusError {
|
|
t.Errorf("expected one error state, got %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestPerZoneStatusRule(t *testing.T) {
|
|
r := &perZoneStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: sampleData()}, nil)
|
|
if len(states) != 3 {
|
|
t.Fatalf("expected 3 per-zone states, got %d", len(states))
|
|
}
|
|
subjects := make([]string, len(states))
|
|
for i, s := range states {
|
|
subjects[i] = s.Subject
|
|
}
|
|
want := []string{"example.com.", "com.", "."}
|
|
for i := range want {
|
|
if subjects[i] != want[i] {
|
|
t.Errorf("subjects[%d]=%q, want %q", i, subjects[i], want[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPerZoneStatusRule_NoZones(t *testing.T) {
|
|
r := &perZoneStatusRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: &DNSVizData{}}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusUnknown {
|
|
t.Errorf("expected single Unknown state, got %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestZoneErrorsRule(t *testing.T) {
|
|
r := &zoneErrorsRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: sampleData()}, nil)
|
|
if len(states) != 1 {
|
|
t.Fatalf("expected 1 error state, got %d", len(states))
|
|
}
|
|
if states[0].Status != sdk.StatusCrit {
|
|
t.Errorf("expected Crit, got %v", states[0].Status)
|
|
}
|
|
if states[0].Code != "RRSIG_EXPIRED" {
|
|
t.Errorf("expected the finding code to be used, got %q", states[0].Code)
|
|
}
|
|
}
|
|
|
|
func TestZoneErrorsRule_NoFindings(t *testing.T) {
|
|
d := &DNSVizData{Order: []string{"a."}, Zones: map[string]ZoneAnalysis{"a.": {Status: "SECURE"}}}
|
|
r := &zoneErrorsRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: d}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusOK {
|
|
t.Errorf("expected OK summary state, got %+v", states)
|
|
}
|
|
}
|
|
|
|
func TestZoneWarningsRule(t *testing.T) {
|
|
d := &DNSVizData{
|
|
Order: []string{"a."},
|
|
Zones: map[string]ZoneAnalysis{"a.": {Warnings: []Finding{{Description: "soft"}}}},
|
|
}
|
|
r := &zoneWarningsRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: d}, nil)
|
|
if len(states) != 1 || states[0].Status != sdk.StatusWarn {
|
|
t.Errorf("expected Warn state, got %+v", states)
|
|
}
|
|
// Code falls back to the rule code when finding has none.
|
|
if states[0].Code != "dnsviz_zone_warnings" {
|
|
t.Errorf("expected fallback code, got %q", states[0].Code)
|
|
}
|
|
}
|
|
|
|
func TestEmptyAsUnknown(t *testing.T) {
|
|
if emptyAsUnknown("") != "UNKNOWN" {
|
|
t.Error("empty should map to UNKNOWN")
|
|
}
|
|
if emptyAsUnknown("X") != "X" {
|
|
t.Error("non-empty should pass through")
|
|
}
|
|
}
|
|
|
|
func TestNonEmpty(t *testing.T) {
|
|
if nonEmpty("a", "b") != "a" || nonEmpty("", "b") != "b" {
|
|
t.Error("nonEmpty did not pick non-empty")
|
|
}
|
|
}
|
|
|
|
func TestFindingMeta(t *testing.T) {
|
|
if findingMeta(Finding{}) != nil {
|
|
t.Error("expected nil for empty finding")
|
|
}
|
|
m := findingMeta(Finding{Code: "C", Servers: []string{"a"}})
|
|
if m["code"] != "C" {
|
|
t.Errorf("missing code in meta: %v", m)
|
|
}
|
|
srvs, _ := m["servers"].([]string)
|
|
if len(srvs) != 1 || srvs[0] != "a" {
|
|
t.Errorf("missing servers in meta: %v", m)
|
|
}
|
|
}
|
|
|
|
func TestZoneErrorsRule_ConcatPerZone(t *testing.T) {
|
|
d := &DNSVizData{
|
|
Order: []string{"leaf.", "tld."},
|
|
Zones: map[string]ZoneAnalysis{
|
|
"leaf.": {Errors: []Finding{{Description: "leaf-err"}}},
|
|
"tld.": {Errors: []Finding{{Description: "tld-err"}}},
|
|
},
|
|
}
|
|
r := &zoneErrorsRule{}
|
|
states := r.Evaluate(context.Background(), stubObs{value: d}, nil)
|
|
if len(states) != 2 {
|
|
t.Fatalf("expected 2 states, got %d", len(states))
|
|
}
|
|
// Subjects should both appear, leaf first per Order.
|
|
if states[0].Subject != "leaf." || states[1].Subject != "tld." {
|
|
t.Errorf("subjects out of order: %q,%q", states[0].Subject, states[1].Subject)
|
|
}
|
|
if !strings.Contains(states[0].Message, "leaf-err") {
|
|
t.Errorf("leaf message lost: %q", states[0].Message)
|
|
}
|
|
}
|