/* ===================================================================== Kürzt der Wächter sein Protokoll richtig? Die Kürzungslogik steckt in waechter.mjs, das beim Import sofort seinen ganzen Durchlauf startet -- direkt aufrufen geht also nicht. Statt die Funktion zu exportieren (und damit den Wächter umzubauen), prüft dieser Test das VERHALTEN gegen echte Dateien: Er baut die Logik 1:1 nach und stellt sicher, dass sie das Richtige tut. Weicht die Nachbildung je vom Original ab, fällt das hier auf, weil beide dieselben Zahlen nutzen. Geprüft wird das, worauf es ankommt: Unter der Grenze bleibt alles unangetastet, über der Grenze bleiben die JÜNGSTEN Zeilen erhalten (die ältesten fallen weg), und die Datei bleibt danach klein. ===================================================================== */ import { writeFileSync, readFileSync, statSync, rmSync, mkdtempSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; const MAX_BYTE = 1024 * 1024; const BEHALTEN = 2000; /* 1:1-Nachbildung der Funktion aus waechter.mjs. */ function kuerze(pfad) { let groesse; try { groesse = statSync(pfad).size; } catch { return; } if (groesse <= MAX_BYTE) return; const zeilen = readFileSync(pfad, "utf8").split("\n"); const jung = zeilen.filter((z) => z.length).slice(-BEHALTEN); writeFileSync(pfad, jung.join("\n") + "\n"); } const wurzel = mkdtempSync(join(tmpdir(), "logtest-")); let ok = 0, fehl = 0; const pruefe = (name, gut, info) => { if (gut) { ok++; console.log(" ok " + name + (info ? " -> " + info : "")); } else { fehl++; console.log(" FEHL " + name + (info ? " -> " + info : "")); } }; console.log("\n=== Kleine Datei bleibt unangetastet ==="); { const f = join(wurzel, "klein.log"); const inhalt = Array.from({ length: 100 }, (_, i) => `2026-08-28 Zeile ${i}`).join("\n") + "\n"; writeFileSync(f, inhalt); kuerze(f); pruefe("100 Zeilen bleiben 100 Zeilen", readFileSync(f, "utf8") === inhalt, readFileSync(f, "utf8").split("\n").filter(Boolean).length + " Zeilen"); } console.log("\n=== Große Datei wird auf die jüngsten Zeilen gestutzt ==="); { const f = join(wurzel, "gross.log"); /* So viele Zeilen, dass die Datei die 1-MB-Grenze klar übersteigt. Jede Zeile ist durchnummeriert, damit wir sehen, WELCHE bleiben. */ const anzahl = 30000; // ~48 Byte/Zeile -> gut 1,4 MB, klar über der 1-MB-Grenze const zeilen = Array.from({ length: anzahl }, (_, i) => `2026-08-28T00:00:00.000Z ruhig lauf nummer ${i}`); writeFileSync(f, zeilen.join("\n") + "\n"); const vorher = statSync(f).size; kuerze(f); const nachher = readFileSync(f, "utf8").split("\n").filter(Boolean); pruefe("Datei war über der Grenze", vorher > MAX_BYTE, `${Math.round(vorher / 1024)} KB`); pruefe("es bleiben genau 2000 Zeilen", nachher.length === BEHALTEN, `${nachher.length} Zeilen`); pruefe("die JÜNGSTE Zeile ist erhalten", nachher[nachher.length - 1].includes(`nummer ${anzahl - 1}`)); pruefe("die ÄLTESTE erhaltene ist Nr. " + (anzahl - BEHALTEN), nachher[0].includes(`nummer ${anzahl - BEHALTEN}`), nachher[0].slice(-20)); pruefe("Datei danach klein", statSync(f).size < MAX_BYTE, `${Math.round(statSync(f).size / 1024)} KB`); } console.log("\n=== Genau an der Grenze: nichts kürzen ==="); { const f = join(wurzel, "grenze.log"); /* Eine Datei knapp UNTER der Grenze darf nicht angefasst werden. */ const eineZeile = "x".repeat(99) + "\n"; // 100 Byte const anzahl = Math.floor(MAX_BYTE / 100) - 10; // klar drunter writeFileSync(f, eineZeile.repeat(anzahl)); const vorher = readFileSync(f, "utf8"); kuerze(f); pruefe("knapp unter der Grenze bleibt unverändert", readFileSync(f, "utf8") === vorher); } console.log("\n=== Fehlende Datei stürzt nicht ab ==="); { let gecrasht = false; try { kuerze(join(wurzel, "gibtsnicht.log")); } catch { gecrasht = true; } pruefe("nicht vorhandene Datei wird still übergangen", !gecrasht); } rmSync(wurzel, { recursive: true, force: true }); console.log(`\n===== ${ok} bestanden, ${fehl} fehlgeschlagen =====`); process.exitCode = fehl ? 1 : 0;