From 7184cc4e7b495554f598329d55c273fcacc2bda6 Mon Sep 17 00:00:00 2001 From: xbsheng Date: Mon, 26 Oct 2026 15:47:57 +0800 Subject: [PATCH] tools: bench.py leaves the TV's address and port to tools/tv.py --port is passed on as text, so TV_PORT=abc or an empty TV_PORT gets tv.py's own 'not a port number' instead of a ValueError traceback from argparse, and TV._connect keeps the HOST/PORT tv.py made of the environment bench.py set for it - the split of a host:port and the 1..65535 check live there, and already reached the arguments. --- tests/test_bench_connection.py | 23 ++++++++++++++++++++--- tools/bench.py | 16 ++++++++++++---- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tests/test_bench_connection.py b/tests/test_bench_connection.py index f99623d3..8021ffda 100644 --- a/tests/test_bench_connection.py +++ b/tests/test_bench_connection.py @@ -5,12 +5,13 @@ ADB handshake, several times per key, plus the whole main log pulled back for ev 100 MB on a TCL C755, 41 s a read). Through a relay one full run took over 45 minutes. Now the TV class connects once with tools/tv.py's client and reuses it, reopening it once if it drops; only the log's newest lines are read, filtered on the -TV, and not at all once the first keys show the TV doesn't log them; and the key loop looks up Home once. --host also has to reach the client: the old subprocesses only read TV_HOST. +TV, and not at all once the first keys show the TV doesn't log them; and the key loop looks up Home once. --host also has to reach the client: the old subprocesses only read TV_HOST. It reaches it as TV_HOST/TV_PORT, and the target the run keeps is the one tools/tv.py made of those two (it splits `host:port` and checks the range), not the arguments again. The TV and tools/tv.py are faked, so these run without either. Run from the repository root: python3 -m unittest discover -s tests -v """ +import os import sys import types import unittest @@ -38,7 +39,11 @@ class FakeDevice: def fake_client(devices): - """A stand-in for tools/tv.py: connect() hands out the given devices in turn.""" + """A stand-in for tools/tv.py: connect() hands out the given devices in turn. + + HOST and PORT stand for the target the real client resolves from TV_HOST/TV_PORT when bench.py + imports it; this one has no parser, so the environment bench.py sets for it is what a test reads. + """ module = types.ModuleType("tv") module.HOST, module.PORT = None, None module.connects = 0 @@ -67,7 +72,19 @@ class OneConnectionTest(unittest.TestCase): def test_host_and_port_from_the_command_line_reach_the_client(self): tv, client = self.tv_with(FakeDevice()) tv.shell("true") - self.assertEqual((client.HOST, client.PORT), ("192.0.2.7", 15555)) + # bench.py hands the command line to the client through TV_HOST/TV_PORT, the two the real + # tools/tv.py reads when it is imported. The fake client resolves neither, so the pair is + # what this can check; the read-back is the test below. + self.assertEqual((os.environ["TV_HOST"], os.environ["TV_PORT"]), ("192.0.2.7", "15555")) + + def test_the_target_the_client_resolved_is_the_one_the_run_keeps(self): + # tools/tv.py splits `host:port` out of the address and refuses a port outside 1..65535. + # bench.py used to put the arguments back over that (tv_client.HOST, PORT = self.host, + # int(self.port)), so `--host :` reached the client as a machine of that name. + tv, client = self.tv_with(FakeDevice()) + client.HOST, client.PORT = "192.0.2.20", 5877 + tv.shell("true") + self.assertEqual((tv.host, tv.port, tv.serial), ("192.0.2.20", 5877, "192.0.2.20:5877")) def test_a_dropped_connection_is_reopened_once(self): first, second = FakeDevice(fail_first=True), FakeDevice({"echo": b"ok"}) diff --git a/tools/bench.py b/tools/bench.py index fccf63b5..8a33e07a 100644 --- a/tools/bench.py +++ b/tools/bench.py @@ -74,13 +74,17 @@ class TV: if here not in sys.path: sys.path.insert(0, here) # tv.py reads its target from the environment when imported, including CLI overrides here. - os.environ["TV_HOST"], os.environ["TV_PORT"] = self.host, str(self.port) + os.environ["TV_HOST"], os.environ["TV_PORT"] = str(self.host), str(self.port) try: import tv as tv_client # noqa: E402 except ModuleNotFoundError as e: raise SystemExit(f"bench.py needs {e.name}: python3 -m venv tools/venv && " "tools/venv/bin/pip install -r tools/requirements.txt") from e - tv_client.HOST, tv_client.PORT = self.host, int(self.port) + # Read back the target tv.py made of that environment: it splits `host:port` and refuses a + # port outside 1..65535 there. Overriding these from the arguments (as this did) put the + # `:port` back into the host, so `--host 192.0.2.20:5877` asked for a machine of that name. + self.host, self.port = tv_client.HOST, tv_client.PORT + self.serial = f"{self.host}:{self.port}" self.client = tv_client.connect() return self.client @@ -505,8 +509,12 @@ def main(): parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument("--host", default=os.environ.get("TV_HOST"), - help="TV address (or set TV_HOST)") - parser.add_argument("--port", type=int, default=int(os.environ.get("TV_PORT", "5555"))) + help="TV address, IP or IP:port (or set TV_HOST)") + # Left as typed: tools/tv.py parses TV_HOST/TV_PORT when TV._connect imports it, refuses a port that + # is not 1..65535 there, and splits the port out of the address. int() here ran before any of that, + # so TV_PORT=abc (or an empty TV_PORT, which tools/tv.py reads as 5555) was a ValueError traceback. + parser.add_argument("--port", default=os.environ.get("TV_PORT") or "5555", + help="the TV's ADB port (or set TV_PORT); default 5555") parser.add_argument("--keys", type=int, default=36, help="keys per series") parser.add_argument("--series", type=int, default=3, help="how many series") parser.add_argument("--cold", type=int, default=5, help="cold starts")