1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#!/usr/bin/env python3
"""TCP auth smoke test for max25d M25/1."""
import socket
import subprocess
import sys
import tempfile
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
DAEMON = ROOT / "stacks/daemon/max25d"
BASE_INI = ROOT / "share/max25/max25d.ini.example"
class LineReader:
def __init__(self, sock: socket.socket) -> None:
self.sock = sock
self.buf = b""
def read(self, timeout: float = 5.0) -> str:
self.sock.settimeout(timeout)
while b"\n" not in self.buf:
chunk = self.sock.recv(4096)
if not chunk:
raise RuntimeError("connection closed")
self.buf += chunk
line, self.buf = self.buf.split(b"\n", 1)
return line.decode("utf-8")
def free_port() -> int:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("127.0.0.1", 0))
port = sock.getsockname()[1]
sock.close()
return port
def main() -> int:
port = free_port()
password = "preview-secret"
with tempfile.NamedTemporaryFile("w", suffix=".ini", delete=False) as tmp:
tmp.write(BASE_INI.read_text())
tmp.write(f"\n[network]\ntcp_password = {password}\n")
ini_path = Path(tmp.name)
proc = subprocess.Popen(
[str(DAEMON), "--no-stack", "-c", str(ini_path), "--tcp-port", str(port)],
stdout=subprocess.DEVNULL,
stderr=subprocess.PIPE,
text=True,
)
time.sleep(0.6)
try:
sock = socket.create_connection(("127.0.0.1", port), timeout=3)
except OSError as exc:
proc.terminate()
proc.wait(timeout=3)
print(f"FAIL: connect: {exc}", file=sys.stderr)
return 1
reader = LineReader(sock)
try:
assert reader.read() == "AUTH required"
sock.sendall(b"AUTH wrong\n")
assert reader.read() == "ERR auth failed"
sock.close()
sock = socket.create_connection(("127.0.0.1", port), timeout=3)
reader = LineReader(sock)
assert reader.read() == "AUTH required"
sock.sendall(f"AUTH {password}\n".encode())
assert reader.read() == "OK"
status = reader.read()
assert status.startswith("STATUS ")
sock.sendall(b"PING\n")
assert reader.read() == "OK"
print("OK: max25d TCP auth smoke")
return 0
finally:
try:
sock.close()
except OSError:
pass
proc.terminate()
proc.wait(timeout=5)
ini_path.unlink(missing_ok=True)
if __name__ == "__main__":
sys.exit(main())
|