check / check (push) Canceled after 0s
Each row of the Hostnames table listed a nameserver's record types in the order Go happens to walk the record map, which changed from row to row and on every page load, so two nameservers with the same records looked different. formatRecords now sorts the types by their place in the README's list (A, AAAA, CNAME, MX, TXT, SRV, CAA, NS); any other type comes after them in alphabetical order. Values within a type were already sorted by the resolver. Model: opus-5-5
157 lines
3.7 KiB
Go
157 lines
3.7 KiB
Go
package handlers_test
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"sneak.berlin/go/dnswatcher/internal/handlers"
|
|
)
|
|
|
|
func TestRelTime(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
tests := []struct {
|
|
name string
|
|
dur time.Duration
|
|
want string
|
|
}{
|
|
{"zero", 0, "never"},
|
|
{"seconds", 30 * time.Second, "30s ago"},
|
|
{"minutes", 5 * time.Minute, "5m ago"},
|
|
{"hours", 2*time.Hour + 15*time.Minute, "2h 15m ago"},
|
|
{"days", 48*time.Hour + 3*time.Hour, "2d 3h ago"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var input time.Time
|
|
if tt.dur > 0 {
|
|
input = time.Now().Add(-tt.dur)
|
|
}
|
|
|
|
got := handlers.RelTime(input)
|
|
if got != tt.want {
|
|
t.Errorf(
|
|
"RelTime(%v) = %q, want %q",
|
|
tt.dur, got, tt.want,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExpiryDays(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// 10 days from now.
|
|
future := time.Now().Add(10 * 24 * time.Hour)
|
|
|
|
days := handlers.ExpiryDays(future)
|
|
if days < 9 || days > 10 {
|
|
t.Errorf("expected ~10 days, got %d", days)
|
|
}
|
|
|
|
// Already expired.
|
|
past := time.Now().Add(-24 * time.Hour)
|
|
|
|
days = handlers.ExpiryDays(past)
|
|
if days != 0 {
|
|
t.Errorf("expected 0 for expired, got %d", days)
|
|
}
|
|
}
|
|
|
|
func TestFormatRecords(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := handlers.FormatRecords(nil)
|
|
if got != "-" {
|
|
t.Errorf("expected -, got %q", got)
|
|
}
|
|
|
|
got = handlers.FormatRecords(map[string][]string{
|
|
"A": {"1.2.3.4"},
|
|
})
|
|
|
|
if got != "A: 1.2.3.4" {
|
|
t.Errorf("unexpected format: %q", got)
|
|
}
|
|
}
|
|
|
|
// TestFormatRecordsTypeOrder checks that record types are listed in
|
|
// the README's order (A, AAAA, CNAME, MX, TXT, SRV, CAA, NS), with
|
|
// any other type after them in alphabetical order.
|
|
func TestFormatRecordsTypeOrder(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
got := handlers.FormatRecords(map[string][]string{
|
|
"SOA": {"ns1.example.com. hostmaster.example.com. 1 2 3 4 5"},
|
|
"NS": {"ns1.example.com.", "ns2.example.com."},
|
|
"CAA": {`0 issue "letsencrypt.org"`},
|
|
"DNAME": {"example.net."},
|
|
"TXT": {"v=spf1 -all"},
|
|
"SRV": {"10 5 443 www.example.com."},
|
|
"MX": {"10 mail.example.com."},
|
|
"CNAME": {"www.example.com."},
|
|
"AAAA": {"2001:db8::1"},
|
|
"A": {"192.0.2.1"},
|
|
})
|
|
|
|
want := strings.Join([]string{
|
|
"A: 192.0.2.1",
|
|
"AAAA: 2001:db8::1",
|
|
"CNAME: www.example.com.",
|
|
"MX: 10 mail.example.com.",
|
|
"TXT: v=spf1 -all",
|
|
"SRV: 10 5 443 www.example.com.",
|
|
`CAA: 0 issue "letsencrypt.org"`,
|
|
"NS: ns1.example.com.",
|
|
"NS: ns2.example.com.",
|
|
"DNAME: example.net.",
|
|
"SOA: ns1.example.com. hostmaster.example.com. 1 2 3 4 5",
|
|
}, ", ")
|
|
|
|
if got != want {
|
|
t.Errorf("FormatRecords lists types out of order:\n got %q\nwant %q",
|
|
got, want)
|
|
}
|
|
}
|
|
|
|
// dashboardRow returns the table row of page that contains name.
|
|
func dashboardRow(t *testing.T, page string, name string) string {
|
|
t.Helper()
|
|
|
|
for row := range strings.SplitSeq(page, "<tr") {
|
|
if strings.Contains(row, name) {
|
|
return row
|
|
}
|
|
}
|
|
|
|
t.Fatalf("dashboard has no row containing %q", name)
|
|
|
|
return ""
|
|
}
|
|
|
|
// TestDashboardShowsFailureReasons checks that the dashboard shows the
|
|
// reason in the row of a failed nameserver and of a failed certificate,
|
|
// and not in the row of a nameserver that answered.
|
|
func TestDashboardShowsFailureReasons(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
page := get(t, newHandlersWithFailures(t).HandleDashboard())
|
|
|
|
if !strings.Contains(dashboardRow(t, page, failedNS), nsFailureReason) {
|
|
t.Errorf("row of %s does not show %q", failedNS, nsFailureReason)
|
|
}
|
|
|
|
if strings.Contains(dashboardRow(t, page, answeringNS), nsFailureReason) {
|
|
t.Errorf("row of %s shows %q", answeringNS, nsFailureReason)
|
|
}
|
|
|
|
if !strings.Contains(dashboardRow(t, page, certKey), certFailedReason) {
|
|
t.Errorf("row of %s does not show %q", certKey, certFailedReason)
|
|
}
|
|
}
|