Files
framebridge/source/tests/test_runtime_ports.py
T

77 lines
3.4 KiB
Python

"""Exercise the real start preflight with disposable TCP sockets, without spawning services."""
import errno
from pathlib import Path
import socket
import sys
import tempfile
import unittest
from unittest.mock import patch
from framebridge_expanded import runtime
class SpawnBoundaryReached(Exception):
pass
@unittest.skipUnless(sys.platform.startswith("linux"), "Linux TCP restart regression")
class RuntimePortPreflightTests(unittest.TestCase):
def start_until_spawn(self, state, ports):
settings = {"role": "central", "ports": ports}
with patch.object(runtime, "state_path", return_value=state), \
patch.object(runtime, "load_config", return_value=settings), \
patch.object(runtime, "status", return_value={"running": False}), \
patch.object(runtime, "doctor", return_value={"ok": True}), \
patch.object(runtime, "environment", return_value={}), \
patch.object(runtime, "_spawn", side_effect=SpawnBoundaryReached) as spawn:
with self.assertRaises(SpawnBoundaryReached):
runtime.start(state)
spawn.assert_called_once()
def close_server_first(self):
with socket.socket() as listener, socket.socket() as client:
listener.settimeout(2)
client.settimeout(2)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind(("127.0.0.1", 0))
port = listener.getsockname()[1]
listener.listen(1)
client.connect(("127.0.0.1", port))
with listener.accept()[0] as accepted:
accepted.settimeout(2)
accepted.shutdown(socket.SHUT_WR)
self.assertEqual(client.recv(1), b"")
client.close()
self.assertEqual(accepted.recv(1), b"")
return port
def test_closed_connections_do_not_block_central_restart(self):
ports = {name: self.close_server_first() for name in ("mcp", "hub", "broker")}
self.assertEqual(len(set(ports.values())), 3)
# Establish that each port has the regression condition, not an active listener.
for port in ports.values():
with socket.socket() as original_probe:
with self.assertRaises(OSError) as blocked:
original_probe.bind(("127.0.0.1", port))
self.assertEqual(blocked.exception.errno, errno.EADDRINUSE)
with tempfile.TemporaryDirectory() as directory:
self.start_until_spawn(Path(directory), ports)
def test_active_loopback_and_wildcard_listeners_still_block_start(self):
for address in ("127.0.0.1", "0.0.0.0"):
with self.subTest(address=address), socket.socket() as listener, \
tempfile.TemporaryDirectory() as directory:
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listener.bind((address, 0))
listener.listen(1)
port = listener.getsockname()[1]
# The first preflight port is occupied, so no process may be spawned.
ports = {name: port for name in ("mcp", "hub", "broker")}
with self.assertRaises(OSError) as blocked:
self.start_until_spawn(Path(directory), ports)
self.assertEqual(blocked.exception.errno, errno.EADDRINUSE)
if __name__ == "__main__":
unittest.main()