testAufraeumen(); $this->testFremdePfadeBleiben(); $this->testTearDownRaeumtAuf(); $this->testUploadHaertung(); } private function testAufraeumen(): void { $probe = new AufraeumProbe(); $tmpDatei = $probe->tempPathOeffentlich('.csv'); file_put_contents($tmpDatei, 'inhalt'); $belegDir = $probe->makeTempDirOeffentlich( \Steuerkram\Config::get('upload_dir') . '/2099/BLG-2099-TEST79' ); file_put_contents($belegDir . '/original.pdf', 'dummy'); mkdir($belegDir . '/unterordner'); file_put_contents($belegDir . '/unterordner/datei.txt', 'tief'); // Schreibgeschütztes Verzeichnis (wie in Test 49) muss trotzdem verschwinden $gesperrt = $probe->makeTempDirOeffentlich( \Steuerkram\Config::get('upload_dir') . '/test_79_gesperrt' ); file_put_contents($gesperrt . '/original.pdf', 'dummy'); chmod($gesperrt, 0500); $this->assert(is_file($tmpDatei), 'Temporäre Datei wurde angelegt'); $this->assert(is_dir($belegDir), 'Belegverzeichnis wurde angelegt'); $probe->cleanupOeffentlich(); $this->assert(!file_exists($tmpDatei), 'Temporäre Datei ist nach dem Aufräumen weg'); $this->assert(!is_dir($belegDir), 'Belegverzeichnis ist samt Inhalt weg'); $this->assert(!is_dir($gesperrt), 'Auch ein schreibgeschütztes Verzeichnis wird entfernt'); $this->assert( is_dir((string)\Steuerkram\Config::get('upload_dir')), 'Das Belegverzeichnis selbst bleibt bestehen' ); $this->assert( !is_dir((string)\Steuerkram\Config::get('upload_dir') . '/2099'), 'Das leere Jahresverzeichnis bleibt nicht als Rückstand liegen' ); } private function testFremdePfadeBleiben(): void { // Sicherheitsnetz: außerhalb von Temp-, Beleg- und Logoverzeichnis wird // nichts gelöscht – ein Tippfehler im Testpfad darf keine Daten kosten. $probe = new AufraeumProbe(); $fremd = dirname(__DIR__) . '/test79_fremd_' . bin2hex(random_bytes(4)) . '.txt'; file_put_contents($fremd, 'nicht anfassen'); $probe->registerTempPathOeffentlich($fremd); ob_start(); $probe->cleanupOeffentlich(); $meldung = (string)ob_get_clean(); $this->assert(is_file($fremd), 'Pfad außerhalb der Testverzeichnisse bleibt unangetastet'); $this->assert(str_contains($meldung, 'Nicht aufgeräumt'), 'Der übersprungene Pfad wird gemeldet'); unlink($fremd); } private function testTearDownRaeumtAuf(): void { $quelltext = (string)file_get_contents(__DIR__ . '/TestCase.php'); $this->assert( (bool)preg_match('/function tearDown\(\).*?cleanupTempPaths\(\)/s', $quelltext), 'tearDown() ruft das Aufräumen auf – auch wenn der Test mit einer Ausnahme abbricht' ); $runner = (string)file_get_contents(__DIR__ . '/run.php'); $this->assert( str_contains($runner, 'datenBestand()') && str_contains($runner, 'registerTempPath'), 'run.php meldet Rückstände, die ein Test nicht angemeldet hat' ); } private function testUploadHaertung(): void { $controller = (string)file_get_contents(dirname(__DIR__) . '/src/Controllers/BelegController.php'); $this->assert( str_contains($controller, 'is_writable($absDir)'), 'upload() prüft, ob das Zielverzeichnis beschreibbar ist' ); $this->assert( (bool)preg_match('/if \(!move_uploaded_file\(/', $controller), 'Ein fehlgeschlagenes move_uploaded_file() wird ausgewertet statt ignoriert' ); $this->assert( substr_count($controller, 'Beleg::releaseBelegNr($belegNr)') >= 2, 'Bei einem Speicherfehler wird die vergebene Belegnummer wieder freigegeben' ); $this->assert( str_contains($controller, 'Bitte die Schreibrechte im Belegverzeichnis prüfen.'), 'Der Nutzer bekommt eine verständliche Meldung statt einer Ausnahme' ); } } /** * Hilfsklasse: macht die geschützten Aufräum-Methoden von TestCase prüfbar. * tearDown() wird bewusst nicht aufgerufen – das würde die Transaktion des * laufenden Tests zurückrollen. */ class AufraeumProbe extends TestCase { public function run(): void { } public function tempPathOeffentlich(string $suffix = ''): string { return $this->tempPath($suffix); } public function makeTempDirOeffentlich(string $pfad): string { return $this->makeTempDir($pfad); } public function registerTempPathOeffentlich(string $pfad): string { return $this->registerTempPath($pfad); } public function cleanupOeffentlich(): void { $this->cleanupTempPaths(); } }