Files
rippy/rippy-windows/test/messung.rip.test.ts
HitonabiandClaude Fable 5 844bca37ff
Ampel / ampel (push) Failing after 1m22s
feat(v5): Etappe W-2 — Rippen: Parser, makemkvcon-Lauf, Werkzeug-Katalog
rip/parser.ts: die reine Textverarbeitung mit allen bezahlten Fallen aus
dem Docker-Zweig — quelle() (dev:G: statt dev:\.\G:, der 404-Verwandte),
textVon() (UTF-8 streng, sonst cp1252 — nie wieder 'Öffnen'), parseMsg
(Regex statt split — Meldungen mit Komma), PRGV (-1 vs. echtes 0 %),
TINFO/SINFO (Sprache aus Attr 3/4, NICHT 28/29), laengsterTitel mit
Play-All-Schutz, episodenTitel, KRITISCHE_CODES (sprachfeste NUMMERN).

rip/makemkv.ts: Kommandobau + Lauf — ZeilenLeser (binaer, halbe Zeilen,
je Zeile dekodiert), RipAuswertung (pur), rippen() mit AbortSignal,
Lesefehler-Flag AUCH bei Rueckgabewert 0. werkzeuge/katalog.ts: die
Suchreihenfolge samt %VAR%-Gross/Klein-Falle und Registry-Rueckfall.
ablauf/rippen.ts: ein Rip je Laufwerk, Status-Push, 'erst nachsehen,
dann rippen' (unbekannt heisst trotzdem rippen). Fenster: Rippen-Knopf,
Fortschrittsbalken, Abbrechen; Auswurf waehrend des Rips abgelehnt.

Gemessen am echten System (30.08.2026): Katalog findet
makemkvcon64 (Program Files x86), HandBrakeCLI und flac (beide im
rc11-Werkzeugordner LOCALAPPDATA\Rippy\tools). NEUER BEFUND: Nach dem
abgebrochenen rc11-Rip vom Mittag sieht MakeMKV GAR KEIN Laufwerk mehr
(MSG 5042, leere DRV-Liste, mit und ohne --noscan), waehrend die
Storage-IOCTLs sauber antworten — MakeMKV spricht SCSI direkt. 5042 ist
jetzt ein KRITISCHER_CODE mit Klartext-Abhilfe. Der volle Rip-Beweis
(messung.rip.test.ts liegt bereit) braucht deshalb erst eine Hand am
Geraet: Disc neu einlegen oder USB ab-/anstecken.

96 Tests gruen, Smoke gruen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 18:12:44 +02:00

69 lines
2.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// DER W-2-BEWEIS: ein voller, verlustfreier Rip der eingelegten Disc am
// echten Laufwerk — dauert 3090 Minuten. Läuft nur auf Verlangen:
//
// RIPPY_MESSUNG_RIP=1 RIPPY_MESSUNG_ZIEL=<ordner> \
// npx vitest run test/messung.rip.test.ts --reporter=verbose
//
// Fortschritt wird in 5-%-Schritten geloggt; das Ergebnis nennt Dateien
// und Größen. Das Protokoll wandert in den SAVEPOINT (beweisen statt
// behaupten).
import { statSync } from 'node:fs'
import { describe, expect, it } from 'vitest'
const messen = process.env.RIPPY_MESSUNG_RIP === '1' && process.platform === 'win32'
const zielWurzel = process.env.RIPPY_MESSUNG_ZIEL ?? ''
describe.skipIf(!messen)('Voller Rip am echten Laufwerk', () => {
it('rippt die eingelegte Disc verlustfrei', { timeout: 3 * 60 * 60 * 1000 }, async () => {
expect(zielWurzel.length, 'RIPPY_MESSUNG_ZIEL fehlt').toBeGreaterThan(0)
const { finden } = await import('../src/kern/werkzeuge/katalog')
const { rippen } = await import('../src/kern/rip/makemkv')
const { win32Api } = await import('../src/kern/laufwerk/win32')
const { listOptischeLaufwerke } = await import('../src/kern/laufwerk/disc')
const programm = finden('makemkv')
expect(programm.length).toBeGreaterThan(0)
const geraete = listOptischeLaufwerke(win32Api())
expect(geraete.length).toBeGreaterThan(0)
const start = Date.now()
let letzteStufe = -5
const ergebnis = await rippen({
programm,
geraetepfad: geraete[0],
zielOrdner: zielWurzel,
titel: 'all',
aufFortschritt: (prozent) => {
if (prozent >= letzteStufe + 5) {
letzteStufe = prozent
const minuten = ((Date.now() - start) / 60000).toFixed(1)
console.log(`RIP-FORTSCHRITT ${prozent}% nach ${minuten}min`)
}
},
aufMeldung: (code, text) => {
// Nur die tragenden Meldungen — sonst wird das Protokoll unlesbar.
if (code >= 5000 || text.includes('errors') || text.includes('gesichert') || text.includes('saved')) {
console.log(`RIP-MSG ${code}: ${text}`)
}
},
})
const minuten = ((Date.now() - start) / 60000).toFixed(1)
if (ergebnis.status === 'success') {
console.log(`RIP-ERGEBNIS success nach ${minuten}min · lesefehler=${ergebnis.lesefehler}`)
for (const datei of ergebnis.dateien) {
console.log(`RIP-DATEI ${datei} · ${(statSync(datei).size / 1e9).toFixed(2)} GB`)
}
} else {
console.log(`RIP-ERGEBNIS ${ergebnis.status} nach ${minuten}min: ${'fehler' in ergebnis ? ergebnis.fehler : ''}`)
}
expect(ergebnis.status).toBe('success')
})
})
describe.skipIf(messen)('Rip-Messung übersprungen', () => {
it('läuft nur mit RIPPY_MESSUNG_RIP=1 unter Windows', () => {
expect(true).toBe(true)
})
})