import importlib import sys import types import unittest from pathlib import Path from unittest.mock import Mock, patch from librenet_scanner.fastscan import parse_naabu_host_json_line from librenet_scanner.models import Host from librenet_scanner.privileged_helper import command_for ROOT = Path(__file__).resolve().parents[1] if "PySide6.QtCore" not in sys.modules: qtcore = types.ModuleType("PySide6.QtCore") pyside = types.ModuleType("PySide6") class DummySignal: def __init__(self, *args, **kwargs): self.calls = [] def emit(self, *args): self.calls.append(args) class DummyQThread: def __init__(self, parent=None): self._interrupted = False def requestInterruption(self): self._interrupted = True def isInterruptionRequested(self): return self._interrupted qtcore.Signal = DummySignal qtcore.QThread = DummyQThread pyside.QtCore = qtcore sys.modules["PySide6"] = pyside sys.modules["PySide6.QtCore"] = qtcore scanner = importlib.import_module("librenet_scanner.scanner") class NaabuDiscovery0421Tests(unittest.TestCase): def test_host_discovery_json_without_port_becomes_live_host(self): host = parse_naabu_host_json_line('{"ip":"192.168.50.20"}') self.assertIsNotNone(host) self.assertEqual(host.ip, "192.168.50.20") self.assertEqual(host.status, "up") self.assertEqual(host.ports, []) def test_legacy_admin_host_discovery_helper_remains_hardened(self): with patch("librenet_scanner.privileged_helper._trusted_binary", return_value="/usr/local/bin/naabu"): cmd = command_for("naabu-discover", ["192.168.50.10", "192.168.50.11"]) self.assertIn("-sn", cmd) self.assertEqual(cmd[cmd.index("-config") + 1], "/dev/null") self.assertIn("-auth=false", cmd) class StandardBehavior0421Tests(unittest.TestCase): def _worker(self, *, privileged=False): req = scanner.ScanRequest( target="192.168.50.0/30", profile="Standard", interface=None, privileged=privileged ) return scanner.ScanWorker(req) def test_standard_scan_uses_adaptive_baseline(self): worker = self._worker() worker._standard_baseline = Mock(return_value=({"192.168.50.1"}, "nmap")) worker._set_progress = Mock() worker._standard_scan() worker._standard_baseline.assert_called_once() self.assertIn("Nmap TCP (adaptatif)", worker._set_progress.call_args.args[1]) def test_small_active_set_uses_nmap_and_never_starts_naabu(self): worker = self._worker() worker._standard_discovery = Mock(return_value={"192.168.50.1"}) worker._naabu_ports = Mock(side_effect=AssertionError("Naabu ne doit pas démarrer pour un petit LAN")) worker._nmap_standard_ports = Mock(return_value=[]) worker._neighbor_hosts = Mock(return_value=[]) worker._set_progress = Mock() result, engine = worker._standard_baseline(start_percent=4, end_percent=96) self.assertEqual(result, {"192.168.50.1"}) self.assertEqual(engine, "nmap") worker._naabu_ports.assert_not_called() self.assertFalse(worker._nmap_standard_ports.call_args.kwargs["fallback"]) def test_naabu_failure_falls_back_only_on_large_discovered_set(self): worker = self._worker() live = {f"192.168.50.{i}" for i in range(1, scanner.NAABU_ACTIVE_HOST_THRESHOLD + 1)} worker._standard_discovery = Mock(return_value=live) worker._naabu_ports = Mock(return_value=None) worker._nmap_standard_ports = Mock(return_value=[]) worker._neighbor_hosts = Mock(return_value=[]) worker._set_progress = Mock() result, engine = worker._standard_baseline(start_percent=4, end_percent=96) self.assertEqual(engine, "nmap-fallback") self.assertEqual(result, live) fallback_ips = worker._nmap_standard_ports.call_args.args[0] self.assertEqual(fallback_ips, sorted(live, key=scanner.ipaddress.ip_address)) self.assertTrue(worker._nmap_standard_ports.call_args.kwargs["fallback"]) def test_deep_reuses_adaptive_baseline_before_enrichment(self): req = scanner.ScanRequest( target="192.168.50.0/30", profile="Approfondi", interface=None, privileged=False ) worker = scanner.ScanWorker(req) worker._set_progress = Mock() worker._standard_baseline = Mock(return_value=({"192.168.50.1"}, "nmap")) worker._nmap = Mock(return_value=[]) worker._neighbor_hosts = Mock(return_value=[]) worker.run() worker._standard_baseline.assert_called_once() worker._nmap.assert_called_once() args = worker._nmap.call_args.args[0] self.assertIn("-sV", args) self.assertIn("1000", args) class Diagnostics0421Tests(unittest.TestCase): def test_ui_distinguishes_user_and_admin_naabu(self): source = (ROOT / "src/librenet_scanner/ui.py").read_text(encoding="utf-8") self.assertIn("Naabu utilisateur", source) self.assertIn("Naabu Admin SYN", source) self.assertIn("naabu_diagnostic()", source) def test_profile_signatures_identify_current_pipeline(self): source = (ROOT / "src/librenet_scanner/scanner.py").read_text(encoding="utf-8") self.assertIn("standard-v9:adaptive-nmap-small-naabu-large", source) self.assertIn("deep-v10:adaptive-standard-baseline-nmap-enrichment", source) if __name__ == "__main__": unittest.main()