checker-dnsviz/checker/report_test.go

170 lines
4.6 KiB
Go

// SPDX-License-Identifier: MIT
package checker
import (
"encoding/json"
"strings"
"testing"
"time"
sdk "git.happydns.org/checker-sdk-go/checker"
)
func TestWorstStatus(t *testing.T) {
if got := worstStatus(nil); got != sdk.StatusOK {
t.Errorf("nil states: got %v, want OK", got)
}
got := worstStatus([]sdk.CheckState{
{Status: sdk.StatusOK},
{Status: sdk.StatusWarn},
{Status: sdk.StatusCrit},
{Status: sdk.StatusInfo},
})
if got != sdk.StatusCrit {
t.Errorf("got %v, want Crit", got)
}
}
func TestTitleAndHint(t *testing.T) {
title, hint := titleAndHint(sdk.CheckState{
Message: "fallback",
Meta: map[string]any{"title": "T", "hint": "H"},
})
if title != "T" || hint != "H" {
t.Errorf("got (%q,%q), want (T,H)", title, hint)
}
// Falls back to message when no title in meta.
title, _ = titleAndHint(sdk.CheckState{Message: "fb"})
if title != "fb" {
t.Errorf("expected fallback to Message, got %q", title)
}
}
func TestGetHTMLReport_EmptyContext(t *testing.T) {
p := &dnsvizProvider{}
out, err := p.GetHTMLReport(sdk.StaticReportContext(nil))
if err != nil {
t.Fatal(err)
}
if !strings.Contains(out, "No DNSViz data and no rule states") {
t.Errorf("expected empty banner, got: %s", out)
}
}
func TestGetHTMLReport_FullDocument(t *testing.T) {
data := &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", Servers: []string{"ns1"}}},
},
"com.": {Status: "SECURE"},
".": {Status: "SECURE"},
},
Raw: []byte(`{"example.com.": {"status": "BOGUS"}}`),
ProbeStderr: "probe-warning",
GrokStderr: "grok-warning",
}
rawJSON, _ := json.Marshal(data)
states := []sdk.CheckState{
{Status: sdk.StatusCrit, Code: "dnssec_rrsig_expired", Subject: "example.com.", Message: "Signature expired",
Meta: map[string]any{"title": "Signature expired", "hint": "Re-sign the zone."}},
{Status: sdk.StatusOK, Code: "dnsviz_overall_status", Message: "ok"},
}
p := &dnsvizProvider{}
out, err := p.GetHTMLReport(sdk.NewReportContext(rawJSON, nil, states))
if err != nil {
t.Fatal(err)
}
wantContains := []string{
"<title>DNSSEC report: example.com</title>",
`class="banner s-CRIT"`,
"Fix these first",
"Re-sign the zone.",
"DNS hierarchy",
"RRSIG_EXPIRED",
"All rule states",
"probe-warning",
"grok-warning",
}
for _, sub := range wantContains {
if !strings.Contains(out, sub) {
t.Errorf("HTML missing %q", sub)
}
}
// Ensure XSS-prone strings are escaped.
xssData := &DNSVizData{
Domain: `<script>alert(1)</script>`,
Order: []string{"x."},
Zones: map[string]ZoneAnalysis{"x.": {Status: "SECURE"}},
}
rawXSS, _ := json.Marshal(xssData)
xssOut, _ := p.GetHTMLReport(sdk.StaticReportContext(rawXSS))
if strings.Contains(xssOut, "<script>alert(1)</script>") {
t.Errorf("unescaped <script> in report: %s", xssOut)
}
}
func TestGetHTMLReport_BadJSON(t *testing.T) {
p := &dnsvizProvider{}
_, err := p.GetHTMLReport(sdk.StaticReportContext(json.RawMessage("not json")))
if err == nil {
t.Fatal("expected error for malformed data")
}
}
func TestExtractMetrics(t *testing.T) {
data := &DNSVizData{
Zones: map[string]ZoneAnalysis{
"example.com.": {Errors: []Finding{{}, {}}, Warnings: []Finding{{}}},
"com.": {},
},
}
rawJSON, _ := json.Marshal(data)
states := []sdk.CheckState{
{Status: sdk.StatusOK},
{Status: sdk.StatusCrit},
{Status: sdk.StatusCrit},
}
p := &dnsvizProvider{}
now := time.Now()
metrics, err := p.ExtractMetrics(sdk.NewReportContext(rawJSON, nil, states), now)
if err != nil {
t.Fatal(err)
}
byName := map[string]float64{}
statusCounts := map[string]float64{}
for _, m := range metrics {
if !m.Timestamp.Equal(now) {
t.Errorf("metric %q has wrong timestamp", m.Name)
}
if m.Name == "dnsviz.findings.count" {
statusCounts[m.Labels["status"]] = m.Value
continue
}
byName[m.Name] = m.Value
}
if byName["dnsviz.zones.count"] != 2 {
t.Errorf("zones.count = %v, want 2", byName["dnsviz.zones.count"])
}
if byName["dnsviz.errors.count"] != 2 {
t.Errorf("errors.count = %v, want 2", byName["dnsviz.errors.count"])
}
if byName["dnsviz.warnings.count"] != 1 {
t.Errorf("warnings.count = %v, want 1", byName["dnsviz.warnings.count"])
}
if statusCounts["CRIT"] != 2 || statusCounts["OK"] != 1 {
t.Errorf("findings counts: %v", statusCounts)
}
}
func TestExtractMetrics_BadJSON(t *testing.T) {
p := &dnsvizProvider{}
_, err := p.ExtractMetrics(sdk.StaticReportContext(json.RawMessage("not json")), time.Now())
if err == nil {
t.Fatal("expected error")
}
}