mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-14 23:28:05 +00:00
test(sync): probe broadcast by sending, not by listening
The broadcast check added in the previous commit bound INADDR_ANY to receive its own probe datagram, and the free-port probe did the same to pick a port. CodeQL flagged both, correctly: a test suite has no reason to open a socket the whole network can reach. Sending is enough for what the probe is actually for. An environment that refuses broadcast raises on sendto, which is the case that occurs in sandboxes and is the one worth skipping over; confirming delivery would have required the listening socket. A network that accepts the send and silently drops it still reaches the assertion, exactly as it did before either commit. The port probe binds loopback -- it only needs a number, and the manager's own bind is the one that has to succeed, with the retry loop already covering a port taken elsewhere. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NohXi78cwsAKtN1sCfxjUh
This commit is contained in:
+25
-20
@@ -853,29 +853,30 @@ class TestStop:
|
|||||||
make_manager(role=SyncRole.STANDALONE).stop() # all sockets None
|
make_manager(role=SyncRole.STANDALONE).stop() # all sockets None
|
||||||
|
|
||||||
|
|
||||||
def _broadcast_works(port):
|
def _broadcast_available(port):
|
||||||
"""True when this environment can actually deliver a UDP broadcast.
|
"""True when a UDP broadcast can be sent at all in this environment.
|
||||||
|
|
||||||
The handshake below depends on it: the follower announces itself to
|
The handshake below depends on broadcast: the follower announces
|
||||||
("<broadcast>", port). Sandboxes and some CI networks drop or refuse
|
itself to ("<broadcast>", port), and sync_manager swallows any sendto
|
||||||
broadcast, and sync_manager swallows the sendto error, so without
|
error. Without this probe, a sandbox or CI network that refuses
|
||||||
this probe the test would just wait out its deadline and fail for a
|
broadcast would make the test wait out its whole deadline and then
|
||||||
reason that has nothing to do with the code.
|
fail for a reason that has nothing to do with the code.
|
||||||
|
|
||||||
|
Sending is enough to detect the case that actually occurs — a
|
||||||
|
refusing environment raises here. Confirming *delivery* would mean
|
||||||
|
binding INADDR_ANY to receive, which is a listening socket this suite
|
||||||
|
has no reason to open; a network that accepts the send and silently
|
||||||
|
drops it still reaches the assertion, exactly as before.
|
||||||
"""
|
"""
|
||||||
recv = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
||||||
try:
|
try:
|
||||||
recv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||||
recv.bind(("", port))
|
sock.sendto(b"probe", ("<broadcast>", port))
|
||||||
recv.settimeout(0.5)
|
return True
|
||||||
send.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
|
||||||
send.sendto(b"probe", ("<broadcast>", port))
|
|
||||||
return recv.recvfrom(64)[0] == b"probe"
|
|
||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
finally:
|
finally:
|
||||||
recv.close()
|
sock.close()
|
||||||
send.close()
|
|
||||||
|
|
||||||
|
|
||||||
class TestRealSocketHandshake:
|
class TestRealSocketHandshake:
|
||||||
@@ -895,13 +896,17 @@ class TestRealSocketHandshake:
|
|||||||
# The free-port probe is inherently racy — the port can be taken
|
# The free-port probe is inherently racy — the port can be taken
|
||||||
# between release and rebind — so retry rather than fail on it.
|
# between release and rebind — so retry rather than fail on it.
|
||||||
for attempt in range(5):
|
for attempt in range(5):
|
||||||
|
# Probed on loopback: this only needs a port number, and the
|
||||||
|
# manager's own bind is what has to succeed. If the port turns
|
||||||
|
# out to be taken on another interface, the retry below covers
|
||||||
|
# it — same as for the race.
|
||||||
probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
probe = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
probe.bind(("", 0))
|
probe.bind(("127.0.0.1", 0))
|
||||||
port = probe.getsockname()[1]
|
port = probe.getsockname()[1]
|
||||||
probe.close()
|
probe.close()
|
||||||
|
|
||||||
if not _broadcast_works(port):
|
if not _broadcast_available(port):
|
||||||
pytest.skip("environment cannot deliver UDP broadcast")
|
pytest.skip("environment refuses UDP broadcast")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
leader = DisplaySyncManager("leader", {"port": port}, hw, MagicMock())
|
leader = DisplaySyncManager("leader", {"port": port}, hw, MagicMock())
|
||||||
|
|||||||
Reference in New Issue
Block a user