From 6aaedb813fa11ba0679c3051bc2eb28646b9506c Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 30 Aug 2025 16:53:58 -0700 Subject: Update to SDL3 --- src/contrib/SDL-3.2.20/test/emscripten/driver.py | 184 +++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100755 src/contrib/SDL-3.2.20/test/emscripten/driver.py (limited to 'src/contrib/SDL-3.2.20/test/emscripten/driver.py') diff --git a/src/contrib/SDL-3.2.20/test/emscripten/driver.py b/src/contrib/SDL-3.2.20/test/emscripten/driver.py new file mode 100755 index 0000000..ee91610 --- /dev/null +++ b/src/contrib/SDL-3.2.20/test/emscripten/driver.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python + +import argparse +import contextlib +import logging +import os +import pathlib +import shlex +import sys +import time +from typing import Optional +import urllib.parse + +from selenium import webdriver +import selenium.common.exceptions +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait + + +logger = logging.getLogger(__name__) + + +class SDLSeleniumTestDriver: + def __init__(self, server: str, test: str, arguments: list[str], browser: str, firefox_binary: Optional[str]=None, chrome_binary: Optional[str]=None): + self. server = server + self.test = test + self.arguments = arguments + self.chrome_binary = chrome_binary + self.firefox_binary = firefox_binary + self.driver = None + self.stdout_printed = False + self.failed_messages: list[str] = [] + self.return_code = None + + options = [ + "--headless", + ] + + driver_contructor = None + match browser: + case "firefox": + driver_contructor = webdriver.Firefox + driver_options = webdriver.FirefoxOptions() + if self.firefox_binary: + driver_options.binary_location = self.firefox_binary + case "chrome": + driver_contructor = webdriver.Chrome + driver_options = webdriver.ChromeOptions() + if self.chrome_binary: + driver_options.binary_location = self.chrome_binary + options.append("--no-sandbox") + if driver_contructor is None: + raise ValueError(f"Invalid {browser=}") + for o in options: + driver_options.add_argument(o) + logger.debug("About to create driver") + self.driver = driver_contructor(options=driver_options) + + @property + def finished(self): + return len(self.failed_messages) > 0 or self.return_code is not None + + def __del__(self): + if self.driver: + self.driver.quit() + + @property + def url(self): + req = { + "loghtml": "1", + "SDL_ASSERT": "abort", + } + for key, value in os.environ.items(): + if key.startswith("SDL_"): + req[key] = value + req.update({f"arg_{i}": a for i, a in enumerate(self.arguments, 1) }) + req_str = urllib.parse.urlencode(req) + return f"{self.server}/{self.test}.html?{req_str}" + + @contextlib.contextmanager + def _selenium_catcher(self): + try: + yield + success = True + except selenium.common.exceptions.UnexpectedAlertPresentException as e: + # FIXME: switch context, verify text of dialog and answer "a" for abort + wait = WebDriverWait(self.driver, timeout=2) + try: + alert = wait.until(lambda d: d.switch_to.alert) + except selenium.common.exceptions.NoAlertPresentException: + self.failed_messages.append(e.msg) + return False + self.failed_messages.append(alert) + if "Assertion failure" in e.msg and "[ariA]" in e.msg: + alert.send_keys("a") + alert.accept() + else: + self.failed_messages.append(e.msg) + success = False + return success + + def get_stdout_and_print(self): + if self.stdout_printed: + return + with self._selenium_catcher(): + div_terminal = self.driver.find_element(by=By.ID, value="terminal") + assert div_terminal + text = div_terminal.text + print(text) + self.stdout_printed = True + + def update_return_code(self): + with self._selenium_catcher(): + div_process_quit = self.driver.find_element(by=By.ID, value="process-quit") + if not div_process_quit: + return + if div_process_quit.text != "": + try: + self.return_code = int(div_process_quit.text) + except ValueError: + raise ValueError(f"process-quit element contains invalid data: {div_process_quit.text:r}") + + def loop(self): + print(f"Connecting to \"{self.url}\"", file=sys.stderr) + self.driver.get(url=self.url) + self.driver.implicitly_wait(0.2) + + while True: + self.update_return_code() + if self.finished: + break + time.sleep(0.1) + + self.get_stdout_and_print() + if not self.stdout_printed: + self.failed_messages.append("Failed to get stdout/stderr") + + + +def main() -> int: + parser = argparse.ArgumentParser(allow_abbrev=False, description="Selenium SDL test driver") + parser.add_argument("--browser", default="firefox", choices=["firefox", "chrome"], help="browser") + parser.add_argument("--server", default="http://localhost:8080", help="Server where SDL tests live") + parser.add_argument("--verbose", action="store_true", help="Verbose logging") + parser.add_argument("--chrome-binary", help="Chrome binary") + parser.add_argument("--firefox-binary", help="Firefox binary") + + index_double_dash = sys.argv.index("--") + if index_double_dash < 0: + parser.error("Missing test arguments. Need -- ") + driver_arguments = sys.argv[1:index_double_dash] + test = pathlib.Path(sys.argv[index_double_dash+1]).name + test_arguments = sys.argv[index_double_dash+2:] + + args = parser.parse_args(args=driver_arguments) + + logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO) + + logger.debug("driver_arguments=%r test=%r test_arguments=%r", driver_arguments, test, test_arguments) + + sdl_test_driver = SDLSeleniumTestDriver( + server=args.server, + test=test, + arguments=test_arguments, + browser=args.browser, + chrome_binary=args.chrome_binary, + firefox_binary=args.firefox_binary, + ) + sdl_test_driver.loop() + + rc = sdl_test_driver.return_code + if sdl_test_driver.failed_messages: + for msg in sdl_test_driver.failed_messages: + print(f"FAILURE MESSAGE: {msg}", file=sys.stderr) + if rc == 0: + print(f"Test signaled success (rc=0) but a failure happened", file=sys.stderr) + rc = 1 + sys.stdout.flush() + logger.info("Exit code = %d", rc) + return rc + + +if __name__ == "__main__": + raise SystemExit(main()) -- cgit v1.2.3