"""Tests fuer die puren Helfer aus makemkv_daten. Bewusst OHNE Dateisystem, DB und fcntl — deshalb laufen sie auch auf Windows und nicht nur in der Ampel. Geprueft wird genau das, was ohne Container und ohne echte Disc entscheidbar ist: das Zeilenformat der KEYDB.cfg, die Plausibilitaetspruefung beim Hochladen, die Namenshaerte der AACS-Dumps und das Zusammenfuehren der settings.conf. """ from makemkv_daten import ( ist_aacs_dump, keydb_pruefen, settings_conf_zusammenfuehren, zaehle_disc_eintraege, ) # Echte Beispielzeilen im libaacs-Format: 40 Hex-Zeichen Disc-Kennung, dann # "= Titel". Zweite Zeile mit 0x-Praefix, weil die oeffentlichen Dateien beide # Schreibweisen mischen (Fundstelle steht im Modul-Docstring von makemkv_daten). _GUELTIG = """; KEYDB.cfg — Beispiel 0123456789ABCDEF0123456789ABCDEF01234567 = Akira 0xFEDCBA9876543210FEDCBA9876543210FEDCBA98 = Blade Runner | V | 00112233445566778899AABBCCDDEEFF """ def test_zaehle_disc_eintraege_zaehlt_nur_echte_disc_zeilen(): # Kommentar- und Leerzeilen duerfen NICHT mitgezaehlt werden, sonst meldet # das UI "da liegt was drin", obwohl die Datei keinen Schluessel enthaelt. assert zaehle_disc_eintraege(_GUELTIG) == 2 def test_zaehle_disc_eintraege_ohne_disc_zeile_ist_null(): nur_kommentare = "; nur ein Kommentar\n\n;noch einer\n" assert zaehle_disc_eintraege(nur_kommentare) == 0 assert zaehle_disc_eintraege("") == 0 def test_zaehle_disc_eintraege_akzeptiert_0x_praefix_einzeln(): assert zaehle_disc_eintraege("0x0123456789abcdef0123456789abcdef01234567 = Tenet") == 1 def test_zaehle_disc_eintraege_lehnt_zu_kurze_kennung_ab(): # 39 statt 40 Hex-Zeichen: das ist keine Disc-Kennung, sondern Tippfehler # oder eine abgeschnittene Datei — darf nicht als Eintrag durchgehen. assert zaehle_disc_eintraege("0123456789ABCDEF0123456789ABCDEF0123456 = Kurz") == 0 def test_keydb_pruefen_meldet_leere_datei(): assert keydb_pruefen("") != "" assert keydb_pruefen(" \n\n ") != "" def test_keydb_pruefen_erkennt_html(): # Haeufigster Bedienfehler: statt der Datei landet die HTML-Fehlerseite # eines Downloads im Feld. MakeMKV wuerde dann still weiter meckern. fehler = keydb_pruefen("\n404 Not Found\n") assert "HTML" in fehler def test_keydb_pruefen_meldet_datei_ohne_disc_zeile(): # Text ist da, aber keine einzige Disc-Kennung — z. B. eine Liesmich-Datei. assert keydb_pruefen("Das hier ist irgendein Text ohne Schluessel.\n") != "" def test_keydb_pruefen_laesst_gueltige_datei_durch(): # "" heisst laut Vertrag: alles in Ordnung, darf geschrieben werden. assert keydb_pruefen(_GUELTIG) == "" def test_ist_aacs_dump_erkennt_echten_namen(): # So heisst der Dump, den MakeMKV am 25.07.2026 fuer Akira UHD abgelegt hat # (Meldung 3332) — dieser Name MUSS zum Download durchkommen. assert ist_aacs_dump("MKB20_v76_UHD_AKIRA_C02B.tgz") is True def test_ist_aacs_dump_blockt_pfad_tricks(): # Der Download-Endpunkt haengt den Namen an das Datenverzeichnis — ein # durchgelassenes ".." oder ein Pfadtrenner waere ein Ausbruch. assert ist_aacs_dump("../x.tgz") is False assert ist_aacs_dump("../../etc/passwd.tgz") is False assert ist_aacs_dump("unter/ordner.tgz") is False assert ist_aacs_dump("unter\\ordner.tgz") is False assert ist_aacs_dump(".versteckt.tgz") is False def test_ist_aacs_dump_lehnt_andere_endungen_ab(): # Nur die Dumps sollen abholbar sein — nicht settings.conf, nicht # _private_data.tar und schon gar nicht die KEYDB.cfg selbst. assert ist_aacs_dump("KEYDB.cfg") is False assert ist_aacs_dump("settings.conf") is False assert ist_aacs_dump("_private_data.tar") is False assert ist_aacs_dump("") is False def test_settings_conf_ersetzt_alten_key_und_behaelt_den_rest(): # Regression: bis 25.07.2026 wurde die Datei komplett ueberschrieben. Mit # dem jetzt persistenten Datenverzeichnis waere app_UpdateEnable vor jedem # Rip weg gewesen. alt = 'app_UpdateEnable = "1"\napp_Key = "T-alt"\napp_DestinationDir = "/tmp"\n' neu = settings_conf_zusammenfuehren(alt, "T-neu") assert 'app_Key = "T-neu"' in neu assert "T-alt" not in neu assert 'app_UpdateEnable = "1"' in neu assert 'app_DestinationDir = "/tmp"' in neu def test_settings_conf_leerer_key_entfernt_die_zeile(): # Ein bewusst geleerter Key darf nicht heimlich weiterwirken. neu = settings_conf_zusammenfuehren('app_Key = "T-alt"\napp_UpdateEnable = "1"\n', "") assert "app_Key" not in neu assert 'app_UpdateEnable = "1"' in neu def test_settings_conf_aus_dem_nichts_endet_mit_zeilenumbruch(): # Erster Start: es gibt noch keine settings.conf. MakeMKV erwartet eine # Datei mit abschliessendem Zeilenumbruch. assert settings_conf_zusammenfuehren("", "T-neu") == 'app_Key = "T-neu"\n' assert settings_conf_zusammenfuehren("", "") == ""