$pluginDir, 'DESKHUB_TESTING' => '1', 'DESKHUB_CATALOG_DEFAULTS' => __DIR__ . '/fixtures/no-catalog.php', 'DESKHUB_SQLITE_PATH' => $db, 'DESKHUB_BOOTSTRAP' => dirname(__DIR__) . '/includes/bootstrap.php']; foreach ($env as $k => $v) putenv("{$k}={$v}"); require_once dirname(__DIR__) . '/includes/bootstrap.php'; $failures = []; $check = function (bool $ok, string $what) use (&$failures): void { if (!$ok) $failures[] = $what; }; $pdo = get_db(); require_once __DIR__ . '/fixtures/paths.php'; $src = plugin_source_dir_or_skip('ueberwachung', 'plugin_ueberwachung_cron'); $zipPath = sys_get_temp_dir() . '/uc-' . bin2hex(random_bytes(3)) . '.zip'; $zip = new ZipArchive(); $zip->open($zipPath, ZipArchive::CREATE); foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($src, FilesystemIterator::SKIP_DOTS)) as $f) { $zip->addFile($f->getPathname(), str_replace('\\', '/', substr($f->getPathname(), strlen($src) + 1))); } $zip->close(); $check(plugin_install_zip($pdo, $zipPath)['ok'], 'Plugin lässt sich installieren'); $check(plugin_set_active($pdo, 'ueberwachung', true, ['hooks.cron', 'ui.menu', 'db.migrations'])['ok'], 'Plugin lässt sich aktivieren'); $check(is_file($pluginDir . '/ueberwachung/cron.php'), 'cron.php liegt im Plugin'); // Ein Ziel, das nicht erreichbar ist (geschlossener Port) $closed = 0; for ($i = 0; $i < 20 && !$closed; $i++) { $p = random_int(20000, 60000); $s = @stream_socket_server("tcp://127.0.0.1:{$p}"); if ($s) { fclose($s); $closed = $p; } } $pdo->prepare("INSERT INTO plugin_ueberwachung_monitors (name, type, target, timeout_sec, created_at) VALUES ('Test', 'port', ?, 2, ?)")->execute(["127.0.0.1:{$closed}", db_now()]); $php = escapeshellarg(PHP_BINARY); $cron = escapeshellarg($pluginDir . '/ueberwachung/cron.php'); exec("{$php} {$cron} 2>&1", $out, $code); $check($code === 0 && str_contains(implode("\n", $out), '1 Ziel(e) geprüft'), 'Cronjob prüft das fällige Ziel: ' . implode(' | ', $out)); $m = $pdo->query('SELECT * FROM plugin_ueberwachung_monitors')->fetch(); $check($m['last_check_at'] !== null && (int) $m['fails'] === 1 && str_contains((string) $m['last_error'], 'Nicht erreichbar'), 'Ergebnis wurde gespeichert (Fehlschlag Nr. 1)'); $tick = (int) $pdo->query("SELECT setting_value FROM settings WHERE setting_key = 'plugin.ueberwachung.last_tick'")->fetchColumn(); $check($tick > time() - 60, 'Zeitpunkt des Laufs ist vermerkt (für die Anzeige auf der Seite)'); unset($out); exec("{$php} {$cron} 2>&1", $out, $code); $check($code === 0 && str_contains(implode("\n", $out), '0 Ziel(e) geprüft'), 'ein zweiter Aufruf direkt danach prüft nichts (noch nicht fällig)'); // Deaktiviert: klare Meldung statt Fehler im Hintergrund plugin_set_active($pdo, 'ueberwachung', false); unset($out); exec("{$php} {$cron} 2>&1", $out, $code); $check($code === 1 && str_contains(implode("\n", $out), 'nicht aktiv'), 'deaktiviertes Plugin: Hinweis und Exit-Code 1'); foreach (scandir($pluginDir) ?: [] as $entry) { if ($entry === '.' || $entry === '..') continue; is_dir($pluginDir . '/' . $entry) ? plugin_rmdir($pluginDir . '/' . $entry) : @unlink($pluginDir . '/' . $entry); } @rmdir($pluginDir); @unlink($zipPath); @unlink($db); if ($failures) { fwrite(STDERR, "Fehlgeschlagen:\n - " . implode("\n - ", $failures) . "\n"); exit(1); } echo 'Überwachung cron checks passed.' . "\n";