FrameBridge 0.3.1 community source release
This commit is contained in:
commit
b23819fff1
1354 files changed
+343716
No files matched your search
@@ -0,0 +1,76 @@
|
||||
"""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()
|
||||
Reference in new issue
Block a user