package ausgabe import ( "flag" "os" "path/filepath" "strings" "testing" "time" ) var aktualisieren = flag.Bool("update", false, "Golden-Dateien neu schreiben") // Die Beispielausgabe aus der Vorgabe. var mockPhasen = []Phase{ {Titel: "Prüfungen", Status: "ERLEDIGT", Detail: "VMID 120 frei · local-zfs · vmbr0 VLAN 20"}, {Titel: "Klonen", Status: "ERLEDIGT", Detail: "full clone 9013 → 120 · Disk auf 40G"}, {Titel: "cloud-init", Status: "ERLEDIGT", Detail: "user florian · SSH-Key · Profile base, docker"}, {Titel: "Start", Status: "ERLEDIGT", Detail: "VM 120 läuft"}, {Titel: "Guest-Agent", Status: "ERLEDIGT", Detail: "antwortet nach 18s"}, {Titel: "Provisionierung", Status: "LAEUFT", Detail: "cloud-init läuft", Laufzeit: 72 * time.Second}, } var mockBox = Box{ Ok: true, Titel: "web01 bereit", Dauer: "1m 54s", Zeilen: [][2]string{ {"VMID", "120"}, {"IP", "10.0.20.15"}, {"Profile", "base, docker"}, {"SSH", "ssh florian@10.0.20.15"}, }, } func mockAusgabe(s Stil) string { zeilen := []string{s.Kopf("1.0", "Server rz1 · Node pve01 · Debian 13 (Template 9013)", false), ""} zeilen = append(zeilen, s.PhasenZeilen(mockPhasen, 0)...) zeilen = append(zeilen, "") zeilen = append(zeilen, s.BoxZeilen(mockBox)...) return strings.Join(zeilen, "\n") + "\n" } func golden(t *testing.T, name, ist string) { t.Helper() pfad := filepath.Join("testdata", name) if *aktualisieren { if err := os.WriteFile(pfad, []byte(ist), 0o644); err != nil { t.Fatal(err) } } soll, err := os.ReadFile(pfad) if err != nil { t.Fatal(err) } if ist != string(soll) { t.Errorf("%s weicht ab.\n--- soll\n%s\n--- ist\n%s", name, soll, ist) } } // Ohne Farbe muss die Ausgabe zeichengenau dem Mockup der Vorgabe entsprechen. // mockup.txt ist von Hand aus der Vorgabe übernommen und wird nie mit -update überschrieben. func TestMockupZeichengenau(t *testing.T) { soll, err := os.ReadFile(filepath.Join("testdata", "mockup.txt")) if err != nil { t.Fatal(err) } if ist := mockAusgabe(Stil{}); ist != string(soll) { t.Errorf("weicht vom Mockup ab.\n--- soll\n%s\n--- ist\n%s", soll, ist) } } func TestFarbenUndAscii(t *testing.T) { golden(t, "mockup-24bit.golden", mockAusgabe(Stil{Farbe: Echtfarben})) golden(t, "mockup-256.golden", mockAusgabe(Stil{Farbe: Farben256})) golden(t, "mockup-ascii.golden", mockAusgabe(Stil{ASCII: true})) } func TestFehlerUndDryRun(t *testing.T) { s := Stil{} zeilen := []string{s.Kopf("1.0", "Server rz1 · Node pve01 · Debian 13", true), ""} zeilen = append(zeilen, s.PhasenZeilen([]Phase{ {Titel: "Prüfungen", Status: "ERLEDIGT", Detail: "VMID 120 frei"}, {Titel: "Template", Status: "UEBERSPRUNGEN", Detail: "vorhanden (9013)"}, {Titel: "Klonen", Status: "FEHLER", Ursache: "Storage local-zfs ist voll.", Hinweis: "Anderen Storage wählen."}, }, 0)...) zeilen = append(zeilen, "") zeilen = append(zeilen, s.AufrufZeilen([]Aufruf{ {Methode: "POST", Pfad: "/nodes/pve01/qemu/9013/clone", Parameter: map[string]any{"newid": 120, "full": 1, "name": "web01"}}, {Methode: "PUT", Pfad: "/nodes/pve01/qemu/120/config", Parameter: map[string]any{"sshkeys": strings.Repeat("A", 80), "description": "Zeile 1\nZeile 2"}}, })...) zeilen = append(zeilen, "") zeilen = append(zeilen, s.BoxZeilen(Box{ Titel: "web01 fehlgeschlagen", Dauer: "12s", Zeilen: [][2]string{{"Phase", "Klonen"}, {"Ursache", "Storage local-zfs ist voll."}, {"Hinweis", "Anderen Storage wählen und die VM mit einem sehr langen Hinweis neu ausrollen."}}, })...) golden(t, "fehler-dryrun.golden", strings.Join(zeilen, "\n")+"\n") } func TestDauer(t *testing.T) { for d, soll := range map[time.Duration]string{ 0: "0s", 18 * time.Second: "18s", 72 * time.Second: "1m 12s", 65 * time.Second: "1m 05s", 3780 * time.Second: "1h 03m", 1499 * time.Millisecond: "1s", } { if ist := Dauer(d); ist != soll { t.Errorf("Dauer(%v) = %q, soll %q", d, ist, soll) } } } func TestXterm256(t *testing.T) { // Teal #2DD4BF → 43 (#00d7af), Paper #E6EDF3 → 254 (Graustufe #e4e4e4), Rot #F87171 → 203 (#ff5f5f). for f, soll := range map[rgb]int{teal: 43, paper: 254, rot: 203} { if ist := xterm256(f); ist != soll { t.Errorf("xterm256(%v) = %d, soll %d", f, ist, soll) } } }