Files
singbox_glue/tests/test_guard.py
T

57 lines
2.2 KiB
Python

from __future__ import annotations
import subprocess
import tempfile
import unittest
from pathlib import Path
from vpn_egressctl.errors import CommandError
from vpn_egressctl.guard import apply_guard
from tests.helpers import make_policy
class GuardRunner:
def __init__(self, *, missing_interface: bool = False, batch_result: int = 0) -> None:
self.missing_interface = missing_interface
self.batch_result = batch_result
self.calls: list[tuple[list[str], str | None]] = []
def __call__(self, args: list[str], **kwargs: object) -> subprocess.CompletedProcess[str]:
input_text = kwargs.get("input")
self.calls.append((list(args), input_text if isinstance(input_text, str) else None))
if "link" in args and self.missing_interface:
return subprocess.CompletedProcess(args, 1, "", "")
if args[-2:] == ["-f", "-"]:
return subprocess.CompletedProcess(args, self.batch_result, "", "")
return subprocess.CompletedProcess(args, 0, "", "")
class GuardTests(unittest.TestCase):
def test_atomic_ruleset_uses_policy_interfaces(self) -> None:
with tempfile.TemporaryDirectory() as directory:
policy = make_policy(Path(directory))
runner = GuardRunner()
apply_guard(policy, runner)
batch = [item for args, item in runner.calls if args[-2:] == ["-f", "-"]][0]
self.assertIsNotNone(batch)
self.assertIn("delete table inet vpn_egress_guard", batch)
self.assertIn('iifname "eth1" oifname "eth0"', batch)
self.assertIn("counter reject", batch)
def test_missing_interface_is_non_mutating(self) -> None:
with tempfile.TemporaryDirectory() as directory:
runner = GuardRunner(missing_interface=True)
with self.assertRaises(CommandError):
apply_guard(make_policy(Path(directory)), runner)
self.assertFalse(any(args[-2:] == ["-f", "-"] for args, _ in runner.calls))
def test_batch_failure_is_reported(self) -> None:
with tempfile.TemporaryDirectory() as directory:
with self.assertRaises(CommandError):
apply_guard(make_policy(Path(directory)), GuardRunner(batch_result=1))
if __name__ == "__main__":
unittest.main()