test: add client timeouts and de-flake default-port test
This commit is contained in:
@@ -1,23 +1,57 @@
|
||||
"""CLI validation and preflight checks."""
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
from common import BUILD_DIR, CLIENT_CMD, SERVER_CMD, TEST_DATA_DIR, run_client, verify_transfer
|
||||
from common import (
|
||||
BUILD_DIR,
|
||||
CLIENT_CMD,
|
||||
CLIENT_TIMEOUT,
|
||||
SERVER_CMD,
|
||||
TEST_DATA_DIR,
|
||||
get_dest_received_dir,
|
||||
run_client,
|
||||
verify_transfer,
|
||||
)
|
||||
|
||||
DEFAULT_PORT = 8080
|
||||
|
||||
|
||||
def _port_is_listening(host, port, timeout=0.3):
|
||||
"""True if something accepts a TCP connection on host:port right now."""
|
||||
try:
|
||||
with socket.create_connection((host, port), timeout=timeout):
|
||||
return True
|
||||
except OSError:
|
||||
return False
|
||||
|
||||
|
||||
def _wait_for_listener(host, port, timeout=5.0):
|
||||
"""Poll host:port until a listener accepts, or the deadline passes."""
|
||||
deadline = time.monotonic() + timeout
|
||||
while time.monotonic() < deadline:
|
||||
if _port_is_listening(host, port):
|
||||
return True
|
||||
time.sleep(0.05)
|
||||
return False
|
||||
|
||||
|
||||
class TestHelp:
|
||||
def test_client_help(self):
|
||||
r = subprocess.run(CLIENT_CMD + ["--help"], capture_output=True, text=True)
|
||||
r = subprocess.run(CLIENT_CMD + ["--help"], capture_output=True,
|
||||
text=True, timeout=CLIENT_TIMEOUT)
|
||||
assert r.returncode == 0
|
||||
assert "Usage:" in r.stdout
|
||||
assert "SSH transport" in r.stdout
|
||||
|
||||
def test_server_help(self):
|
||||
r = subprocess.run(SERVER_CMD + ["--help"], capture_output=True, text=True)
|
||||
r = subprocess.run(SERVER_CMD + ["--help"], capture_output=True,
|
||||
text=True, timeout=CLIENT_TIMEOUT)
|
||||
assert r.returncode == 0
|
||||
assert "Usage:" in r.stdout
|
||||
|
||||
@@ -67,19 +101,24 @@ class TestServerPort:
|
||||
|
||||
def test_default_port(self):
|
||||
"""Server should start on default port 8080."""
|
||||
if _port_is_listening("127.0.0.1", DEFAULT_PORT):
|
||||
pytest.skip(f"port {DEFAULT_PORT} already in use by another process")
|
||||
|
||||
proc = subprocess.Popen(
|
||||
SERVER_CMD, stdout=subprocess.DEVNULL, stderr=None,
|
||||
)
|
||||
try:
|
||||
import socket, time
|
||||
time.sleep(0.5)
|
||||
with socket.create_connection(("127.0.0.1", 8080), timeout=2):
|
||||
pass # Port is listening
|
||||
except (ConnectionRefusedError, OSError):
|
||||
pytest.fail("Server not listening on default port 8080")
|
||||
if not _wait_for_listener("127.0.0.1", DEFAULT_PORT, timeout=5.0):
|
||||
if proc.poll() is not None and _port_is_listening("127.0.0.1", DEFAULT_PORT):
|
||||
pytest.skip(f"port {DEFAULT_PORT} was taken by another process")
|
||||
pytest.fail(f"Server not listening on default port {DEFAULT_PORT}")
|
||||
finally:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=5)
|
||||
try:
|
||||
proc.wait(timeout=5)
|
||||
except subprocess.TimeoutExpired:
|
||||
proc.kill()
|
||||
proc.wait()
|
||||
|
||||
|
||||
def _seed_protocol_source(source):
|
||||
@@ -105,7 +144,7 @@ class TestProtocol:
|
||||
port=shared_server.port)
|
||||
assert result.returncode == 0, \
|
||||
f"--protocol current run failed: {(result.stderr or result.stdout)[:400]}"
|
||||
received = os.path.join(dest, os.path.abspath(source).lstrip(os.sep))
|
||||
received = get_dest_received_dir(dest, source)
|
||||
mismatches, missing = verify_transfer(source, received)
|
||||
assert not mismatches and not missing, \
|
||||
f"transfer mismatch: missing={missing} mismatches={mismatches}"
|
||||
|
||||
Reference in New Issue
Block a user