software steht so weit.
jetzt build + docker build und testen
This commit is contained in:
1 parent
42f0c0accb
commit
ca6cdcca63
90 files changed
+10298
-480
No files matched your search
@@ -0,0 +1,153 @@
|
||||
package checkmk
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var now = time.Date(2026, 10, 2, 12, 0, 0, 0, time.UTC)
|
||||
|
||||
func lines(out string) map[string]string {
|
||||
m := map[string]string{}
|
||||
for _, l := range strings.Split(strings.TrimSpace(out), "\n") {
|
||||
start := strings.Index(l, `"`)
|
||||
end := strings.Index(l[start+1:], `"`)
|
||||
m[l[start+1:start+1+end]] = l
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func TestTenants(t *testing.T) {
|
||||
out := Render(State{Tenants: []Tenant{
|
||||
{ID: "kunde_schmidt", Commercial: true, Status: "active", ValidUntil: now.AddDate(0, 0, 74)},
|
||||
{ID: "meier_gmbh", Commercial: true, Status: "active", ValidUntil: now.AddDate(0, 0, 25)},
|
||||
{ID: "bald", Commercial: true, Status: "active", ValidUntil: now.AddDate(0, 0, 12)},
|
||||
{ID: "alt_ag", Commercial: true, Status: "expired", ValidUntil: now.AddDate(0, 0, -1)},
|
||||
{ID: "homelab", Commercial: false, Status: "active", ValidUntil: now.AddDate(0, 0, -100)},
|
||||
}}, now)
|
||||
l := lines(out)
|
||||
want := map[string]string{
|
||||
"Sultan_Tenant_kunde_schmidt": `0 "Sultan_Tenant_kunde_schmidt" days_left=74;30;14 OK - Abo aktiv bis 2026-12-15 (74 Tage verbleibend)`,
|
||||
"Sultan_Tenant_meier_gmbh": `1 "Sultan_Tenant_meier_gmbh" days_left=25;30;14 WARN - Abo laeuft in 25 Tagen ab! Verlaengerung erforderlich.`,
|
||||
"Sultan_Tenant_bald": `2 "Sultan_Tenant_bald" days_left=12;30;14 CRIT - Abo laeuft in 12 Tagen ab! Verlaengerung erforderlich.`,
|
||||
"Sultan_Tenant_alt_ag": `2 "Sultan_Tenant_alt_ag" days_left=0;30;14 CRIT - Abo seit 1 Tagen abgelaufen! Status: expired`,
|
||||
}
|
||||
for svc, w := range want {
|
||||
if l[svc] != w {
|
||||
t.Errorf("%s:\n got: %s\nwant: %s", svc, l[svc], w)
|
||||
}
|
||||
}
|
||||
if _, ok := l["Sultan_Tenant_homelab"]; ok {
|
||||
t.Error("Community-Mandant mit Vertragsfrist (5c: keine)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPayment(t *testing.T) {
|
||||
out := Render(State{Tenants: []Tenant{
|
||||
{ID: "a", Commercial: true, Status: "active", ValidUntil: now.AddDate(1, 0, 0), DunningLevel: 0},
|
||||
{ID: "b", Commercial: true, Status: "active", ValidUntil: now.AddDate(1, 0, 0), DunningLevel: 1, OverdueSince: now.AddDate(0, 0, -9)},
|
||||
{ID: "c", Commercial: true, Status: "active", ValidUntil: now.AddDate(1, 0, 0), DunningLevel: 2, OverdueSince: now.AddDate(0, 0, -26)},
|
||||
{ID: "d", Commercial: true, Status: "suspended_payment", ValidUntil: now.AddDate(1, 0, 0), DunningLevel: 3, OverdueSince: now.AddDate(0, 0, -40)},
|
||||
{ID: "h", Commercial: false, Status: "active", ValidUntil: now},
|
||||
}}, now)
|
||||
l := lines(out)
|
||||
for svc, prefix := range map[string]string{
|
||||
"Sultan_Payment_a": `0 "Sultan_Payment_a" dunning_level=0;1;2 OK - keine offene Zahlung`,
|
||||
"Sultan_Payment_b": `1 "Sultan_Payment_b" dunning_level=1;1;2 WARN - Mahnstufe 1 (Zahlung seit 9 Tagen offen)`,
|
||||
"Sultan_Payment_c": `2 "Sultan_Payment_c" dunning_level=2;1;2 CRIT - Mahnstufe 2 (Zahlung seit 26 Tagen offen)`,
|
||||
"Sultan_Payment_d": `2 "Sultan_Payment_d" dunning_level=3;1;2 CRIT - Mahnstufe 3 (Zahlung seit 40 Tagen offen) - Kunde offline`,
|
||||
} {
|
||||
if l[svc] != prefix {
|
||||
t.Errorf("%s:\n got: %s\nwant: %s", svc, l[svc], prefix)
|
||||
}
|
||||
}
|
||||
if _, ok := l["Sultan_Payment_h"]; ok {
|
||||
t.Error("Community-Mandant mit Mahnwesen")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNodes(t *testing.T) {
|
||||
out := Render(State{Nodes: []Node{
|
||||
{ID: "online", Status: "online", LeaseUntil: now.Add(48 * time.Hour)},
|
||||
{ID: "wartung", Status: "online", MaintenanceActive: true, MaintenanceUntil: now.Add(90 * time.Minute), MaintenanceReason: "Kernel 6.12", LeaseUntil: now.Add(time.Hour)},
|
||||
{ID: "kurz-weg", Status: "offline", OfflineSince: now.Add(-5 * time.Minute), LeaseUntil: now.Add(time.Hour)},
|
||||
{ID: "lange-weg", Status: "offline", OfflineSince: now.Add(-20 * time.Minute)},
|
||||
{ID: "abgezogen", Status: "drained"},
|
||||
}}, now)
|
||||
l := lines(out)
|
||||
want := map[string]string{
|
||||
"Sultan_Node_online": `0 "Sultan_Node_online" lease_hours_left=48 OK - online`,
|
||||
"Sultan_Node_wartung": `1 "Sultan_Node_wartung" lease_hours_left=1 WARN - Wartung bis 2026-10-02 13:30 UTC (Kernel 6.12)`,
|
||||
"Sultan_Node_kurz-weg": `1 "Sultan_Node_kurz-weg" lease_hours_left=1 WARN - offline seit 5 min`,
|
||||
"Sultan_Node_lange-weg": `2 "Sultan_Node_lange-weg" lease_hours_left=0 CRIT - offline seit 20 min`,
|
||||
"Sultan_Node_abgezogen": `0 "Sultan_Node_abgezogen" lease_hours_left=0 OK - drained`,
|
||||
}
|
||||
for svc, w := range want {
|
||||
if l[svc] != w {
|
||||
t.Errorf("%s:\n got: %s\nwant: %s", svc, l[svc], w)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Angemeldete Wartung: auch offline nur WARN (geplant), nicht CRIT.
|
||||
func TestNodeOfflineDuringMaintenance(t *testing.T) {
|
||||
out := Render(State{Nodes: []Node{{ID: "pi", Status: "offline", OfflineSince: now.Add(-time.Hour), MaintenanceActive: true}}}, now)
|
||||
if !strings.HasPrefix(strings.TrimSpace(out), `1 "Sultan_Node_pi"`) || !strings.Contains(out, "Wartung unbefristet") {
|
||||
t.Errorf("out = %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestViolations(t *testing.T) {
|
||||
for n, want := range map[int]string{
|
||||
0: `0 "Sultan_Policy_Violations" violations_24h=0;1 OK - keine Policy-Verstoesse in 24 h`,
|
||||
3: `1 "Sultan_Policy_Violations" violations_24h=3;1 WARN - 3 Policy-Verstoesse in 24 h (siehe Server-Log)`,
|
||||
} {
|
||||
if got := strings.TrimSpace(Render(State{Violations24h: n}, now)); got != want {
|
||||
t.Errorf("%d:\n got: %s\nwant: %s", n, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOutputIsSortedAndASCII(t *testing.T) {
|
||||
out := Render(State{
|
||||
Tenants: []Tenant{{ID: "b", Commercial: true, Status: "active", ValidUntil: now.AddDate(1, 0, 0)}, {ID: "a", Commercial: true, Status: "active", ValidUntil: now.AddDate(1, 0, 0)}},
|
||||
Nodes: []Node{{ID: "y", Status: "online"}, {ID: "x", Status: "online", MaintenanceActive: true, MaintenanceReason: "Grün & Ölwechsel\nzweite Zeile"}},
|
||||
}, now)
|
||||
if strings.Index(out, "Sultan_Tenant_a") > strings.Index(out, "Sultan_Tenant_b") || strings.Index(out, "Sultan_Node_x") > strings.Index(out, "Sultan_Node_y") {
|
||||
t.Errorf("nicht sortiert:\n%s", out)
|
||||
}
|
||||
for _, r := range out {
|
||||
if r > 127 {
|
||||
t.Fatalf("Nicht-ASCII-Zeichen %q in:\n%s", r, out)
|
||||
}
|
||||
}
|
||||
if strings.Count(out, "\n") != len(lines(out)) {
|
||||
t.Errorf("Zeilenumbruch aus dem Grund in der Ausgabe:\n%s", out)
|
||||
}
|
||||
if !strings.Contains(out, "Gruen & Oelwechsel zweite Zeile") {
|
||||
t.Errorf("Umlaute nicht umschrieben:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestShortOfflineInSeconds(t *testing.T) {
|
||||
out := Render(State{Nodes: []Node{{ID: "pi", Status: "offline", OfflineSince: now.Add(-45 * time.Second)}}}, now)
|
||||
if !strings.Contains(out, "offline seit 45 s") {
|
||||
t.Errorf("out = %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
// Wartungsende in der Zeitzone des Servers (wie auf der Lander-Seite).
|
||||
func TestMaintenanceUntilInLocation(t *testing.T) {
|
||||
berlin, err := time.LoadLocation("Europe/Berlin")
|
||||
if err != nil {
|
||||
t.Skip("Zeitzonendaten fehlen")
|
||||
}
|
||||
out := Render(State{
|
||||
Location: berlin,
|
||||
Nodes: []Node{{ID: "pi", Status: "online", MaintenanceActive: true, MaintenanceUntil: now.Add(90 * time.Minute)}},
|
||||
}, now)
|
||||
if !strings.Contains(out, "Wartung bis 2026-10-02 15:30 CEST") {
|
||||
t.Errorf("out = %s", out)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user