Files
PS5_RetroArch/tests/test_webui_transfer_browser.py
Mihawk f25de5852e Tests: a WebUI server whose port was taken starts again on another
The host tests found a free port by binding port 0 and closing it, then started the
WebUI's server on it. In between, any connection on the machine can take that port as
its own (the same ephemeral range): the server then exits at once, "Failed to bind to
port N: Address already in use", and the test waited out its window and failed with
"the server did not start" (test_scraper, test_scraper_launchbox) or "HTTP server
exited" (test_webui). It happened in about one gate run in three, under JOBS=4 or not.

tests/webui_build.py start() starts the server, waits for its status and returns the
process, port and session token; a server that exits before answering is started again
on another port (five tries). Every harness that started the server itself uses it:
test_scraper, test_scraper_launchbox, test_scraper_screenscraper, test_webui (its start
and two restarts), test_webui_language, test_webui_transfer_browser. test_scraper's
free_port() had no other user and is gone.

Evidence:
- the cause: 40 sequential starts with each server's stderr kept: 1 failed, "Failed to
  bind to port 44505: Address already in use" (exit 1, after 0.02 s); through start(),
  40 of 40 started.
- python3 -m unittest tests.test_scraper tests.test_scraper_launchbox
  tests.test_scraper_screenscraper: OK; tests.test_webui tests.test_webui_language
  tests.test_webui_transfer_browser: 21 tests OK.
- gates on the tree with the next commit: format, unit (210 tests), build, integration
  (210 tests), evidence - PASS.
2026-10-18 07:39:56 -04:00

63 lines
3.1 KiB
Python

"""The page's transfer engine in Chromium (tests/webui_transfer_browser.cjs) against
the native server, then the files on disk compared with what the page made."""
from pathlib import Path
import os
import shutil
import subprocess
import tempfile
import unittest
import sys
sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent))
import webui_build # noqa: E402
ROOT = Path(__file__).resolve().parent.parent
PLAYWRIGHT = os.environ.get('PLAYWRIGHT_PATH') or next(
(str(p) for p in (Path.home() / '.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright-core',
Path('/usr/lib/chatgpt/resources/cua_node/lib/node_modules/playwright-core')) if p.exists()), '')
def pattern(size, seed):
data = bytearray(size)
for i in range(0, size, 4096):
data[i] = (seed + i) & 255
return bytes(data)
@unittest.skipUnless(PLAYWRIGHT and shutil.which('node') and Path('/usr/bin/chromium').exists(), 'needs node, Playwright and Chromium')
class TransferBrowser(unittest.TestCase):
def test_page_engine(self):
http = subprocess.check_output(['bash', 'tools/build-webui-http.sh', 'host'], cwd=ROOT, text=True).strip()
update = subprocess.check_output(['bash', 'tools/build-webui-update.sh', 'host'], cwd=ROOT, text=True).strip()
with tempfile.TemporaryDirectory() as temp:
root = Path(temp) / 'title'
for name in ('config', 'content', 'webui'):
(root / name).mkdir(parents=True)
shutil.copytree(ROOT / 'webui', root / 'webui', dirs_exist_ok=True)
binary = Path(temp) / 'server'
webui_build.build(binary, 'tests/webui_server_main.cpp', flags=('-O1',))
server, port, _ = webui_build.start(binary, root)
try:
try:
run = subprocess.run(['node', 'tests/webui_transfer_browser.cjs'], cwd=ROOT, capture_output=True, text=True, timeout=600,
env={**os.environ, 'PLAYWRIGHT_PATH': PLAYWRIGHT, 'WEBUI_TEST_URL': f'http://127.0.0.1:{port}'})
except subprocess.TimeoutExpired as expired: # what it printed says where it stopped
self.fail(f'the page engine test hung: {expired.stdout!r} {expired.stderr!r}')
self.assertEqual(run.returncode, 0, run.stdout + run.stderr)
print(run.stdout.strip())
finally:
server.terminate(); server.wait(timeout=5)
folder = root / 'content/engine'
for i in range(600):
self.assertEqual((folder / f'shot-{i:04}.png').read_bytes(), pattern(1000 + (i * 997) % 60000, i))
for i in range(3):
self.assertEqual((folder / f'medium-{i}.bin').read_bytes(), pattern(9 * 1024 * 1024 + i, 7 + i))
for i in range(2):
self.assertEqual((folder / f'large-{i}.iso').read_bytes(), pattern(150 * 1024 * 1024 + 4097 * i, 31 + i))
self.assertFalse((folder / 'cancel.iso').exists())
self.assertEqual(list(folder.glob('.upload-*')), [])
if __name__ == '__main__':
unittest.main()