diff --git a/tests/test_firewall_sync.py b/tests/test_firewall_sync.py new file mode 100644 index 0000000..998d15c --- /dev/null +++ b/tests/test_firewall_sync.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +"""Tests for evidence-first firewall sync behavior.""" + +from __future__ import annotations + +import unittest +from unittest.mock import patch + +from app.firewall import MikrotikFirewall + + +class _FakeFirewall(MikrotikFirewall): + def __init__(self): + super().__init__(router_ip="0.0.0.0", username="x", password="x") + self.calls: list[str] = [] + + def get_address_list_ipv4(self, name: str) -> set[str]: + self.calls.append(f"v4:{name}") + if name == "Blocked": + return {"9.9.9.9/32"} + if name == "Init7": + return {"77.74.80.0/21"} + return set() + + def get_address_list_ipv6(self, name: str) -> set[str]: + self.calls.append(f"v6:{name}") + if name == "Blocked": + return set() + if name == "Init7": + return {"2001:1620::/30"} + return set() + + +class FirewallSyncEvidenceTest(unittest.TestCase): + def test_sync_loads_router_status_before_computing_changes(self): + fw = _FakeFirewall() + # type: ignore[assignment] + fw.save_state_report = lambda *args, **kwargs: "noop" + + with patch("app.firewall.cumulative_blocklist", + return_value=({"8.8.8.8/32"}, set())): + changes = fw.sync_blocklist(["8.8.8.8/32"], [], dry_run=True) + + self.assertIn("v4:Blocked", fw.calls) + self.assertIn("v6:Blocked", fw.calls) + self.assertIn("v4:Init7", fw.calls) + self.assertIn("v6:Init7", fw.calls) + self.assertEqual(changes["added_ipv4"], ["8.8.8.8/32"]) + self.assertEqual(changes["removed_ipv4"], ["9.9.9.9/32"]) + + def test_sync_evaluates_against_loaded_current_status(self): + fw = _FakeFirewall() + # type: ignore[assignment] + fw.save_state_report = lambda *args, **kwargs: "noop" + + with patch("app.firewall.cumulative_blocklist", + return_value=({"9.9.9.9/32"}, set())): + changes = fw.sync_blocklist(["9.9.9.9/32"], [], dry_run=True) + + self.assertEqual(changes["added_ipv4"], []) + self.assertEqual(changes["removed_ipv4"], []) + + +if __name__ == "__main__": + unittest.main()