// Tests des freien Platzes (kern/dienste/speicher.ts, 5.5.0): der nächste // vorhandene Elternpfad, die Messung mit nachgebautem statfs, das Urteil // vor dem Rip. Der echte statfs-Aufruf ist am 01.09.2026 gemessen (siehe // Kopf der Datei) — hier zählt die Rechnung. Die Pfade stehen mit // Schrägstrichen: dirname versteht sie auf Windows UND auf dem Linux-Runner // der CI gleich. import { describe, expect, it } from 'vitest' import { platzMessen, platzUrteil, vorhandenerPfad } from '../src/kern/dienste/speicher' describe('vorhandenerPfad', () => { it('nimmt den Ordner selbst, wenn es ihn gibt', () => { expect(vorhandenerPfad('X:/rippy/ablage', (p) => p === 'X:/rippy/ablage')).toBe('X:/rippy/ablage') }) it('geht hoch bis zum ersten vorhandenen Elternpfad — die Ablage darf noch fehlen', () => { const da = new Set(['X:/', 'X:/rippy']) expect(vorhandenerPfad('X:/rippy/ablage/Filme', (p) => da.has(p))).toBe('X:/rippy') }) it('bleibt an der Wurzel stehen, wenn nichts existiert (Windows: Q:/ — auf dem Linux-Runner endet dirname bei „.")', () => { expect(vorhandenerPfad('Q:/gibt/es/nicht', () => false)).toBe(process.platform === 'win32' ? 'Q:/' : '.') }) }) describe('platzMessen', () => { it('rechnet bavail × bsize und blocks × bsize', () => { const platz = platzMessen('X:/rippy', () => ({ bavail: 1000, bsize: 4096, blocks: 5000 }), () => true) expect(platz).toEqual({ pfad: 'X:/rippy', ok: true, freiBytes: 4_096_000, gesamtBytes: 20_480_000, fehler: '' }) }) it('ein leerer Pfad ist nicht messbar — und sagt es (R2)', () => { const platz = platzMessen(' ', () => ({ bavail: 1, bsize: 1, blocks: 1 })) expect(platz.ok).toBe(false) expect(platz.fehler).toBe('kein Pfad') }) it('ein Fehler der Messung wird zum Grund, nie zu einer erfundenen Null', () => { const platz = platzMessen( 'Z:/weg', () => { throw new Error('ENOENT: no such file or directory') }, () => true, ) expect(platz.ok).toBe(false) expect(platz.freiBytes).toBe(0) expect(platz.fehler).toContain('ENOENT') }) }) describe('platzUrteil', () => { const GB = 1e9 it('reicht: Roh plus 25 % plus 2 GB Luft passen', () => { expect(platzUrteil(60 * GB, 40 * GB, true)).toEqual({ text: '', hart: false }) }) it('knapp: der Rip passt, die Kompression nicht mehr sicher', () => { const urteil = platzUrteil(45 * GB, 40 * GB, true) expect(urteil.hart).toBe(false) expect(urteil.text.startsWith('Knapp')).toBe(true) expect(urteil.text).toContain('45,0 GB frei') }) it('zu wenig: nicht einmal der verlustfreie Rip passt', () => { const urteil = platzUrteil(30 * GB, 40 * GB, false) expect(urteil.hart).toBe(true) expect(urteil.text.startsWith('Zu wenig Platz')).toBe(true) }) it('ohne Kompression zählt nur Roh plus Luft', () => { expect(platzUrteil(43 * GB, 40 * GB, false).text).toBe('') expect(platzUrteil(43 * GB, 40 * GB, true).text.startsWith('Knapp')).toBe(true) }) })