summaryrefslogtreecommitdiff
path: root/src/contrib/SDL-3.2.20/test/emscripten/driver.py
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
committer3gg <3gg@shellblade.net>2025-08-30 16:53:58 -0700
commit6aaedb813fa11ba0679c3051bc2eb28646b9506c (patch)
tree34acbfc9840e02cb4753e6306ea7ce978bf8b58e /src/contrib/SDL-3.2.20/test/emscripten/driver.py
parent8f228ade99dd3d4c8da9b78ade1815c9adf85c8f (diff)
Update to SDL3
Diffstat (limited to 'src/contrib/SDL-3.2.20/test/emscripten/driver.py')
-rwxr-xr-xsrc/contrib/SDL-3.2.20/test/emscripten/driver.py184
1 files changed, 184 insertions, 0 deletions
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 @@
1#!/usr/bin/env python
2
3import argparse
4import contextlib
5import logging
6import os
7import pathlib
8import shlex
9import sys
10import time
11from typing import Optional
12import urllib.parse
13
14from selenium import webdriver
15import selenium.common.exceptions
16from selenium.webdriver.common.by import By
17from selenium.webdriver.support.ui import WebDriverWait
18
19
20logger = logging.getLogger(__name__)
21
22
23class SDLSeleniumTestDriver:
24 def __init__(self, server: str, test: str, arguments: list[str], browser: str, firefox_binary: Optional[str]=None, chrome_binary: Optional[str]=None):
25 self. server = server
26 self.test = test
27 self.arguments = arguments
28 self.chrome_binary = chrome_binary
29 self.firefox_binary = firefox_binary
30 self.driver = None
31 self.stdout_printed = False
32 self.failed_messages: list[str] = []
33 self.return_code = None
34
35 options = [
36 "--headless",
37 ]
38
39 driver_contructor = None
40 match browser:
41 case "firefox":
42 driver_contructor = webdriver.Firefox
43 driver_options = webdriver.FirefoxOptions()
44 if self.firefox_binary:
45 driver_options.binary_location = self.firefox_binary
46 case "chrome":
47 driver_contructor = webdriver.Chrome
48 driver_options = webdriver.ChromeOptions()
49 if self.chrome_binary:
50 driver_options.binary_location = self.chrome_binary
51 options.append("--no-sandbox")
52 if driver_contructor is None:
53 raise ValueError(f"Invalid {browser=}")
54 for o in options:
55 driver_options.add_argument(o)
56 logger.debug("About to create driver")
57 self.driver = driver_contructor(options=driver_options)
58
59 @property
60 def finished(self):
61 return len(self.failed_messages) > 0 or self.return_code is not None
62
63 def __del__(self):
64 if self.driver:
65 self.driver.quit()
66
67 @property
68 def url(self):
69 req = {
70 "loghtml": "1",
71 "SDL_ASSERT": "abort",
72 }
73 for key, value in os.environ.items():
74 if key.startswith("SDL_"):
75 req[key] = value
76 req.update({f"arg_{i}": a for i, a in enumerate(self.arguments, 1) })
77 req_str = urllib.parse.urlencode(req)
78 return f"{self.server}/{self.test}.html?{req_str}"
79
80 @contextlib.contextmanager
81 def _selenium_catcher(self):
82 try:
83 yield
84 success = True
85 except selenium.common.exceptions.UnexpectedAlertPresentException as e:
86 # FIXME: switch context, verify text of dialog and answer "a" for abort
87 wait = WebDriverWait(self.driver, timeout=2)
88 try:
89 alert = wait.until(lambda d: d.switch_to.alert)
90 except selenium.common.exceptions.NoAlertPresentException:
91 self.failed_messages.append(e.msg)
92 return False
93 self.failed_messages.append(alert)
94 if "Assertion failure" in e.msg and "[ariA]" in e.msg:
95 alert.send_keys("a")
96 alert.accept()
97 else:
98 self.failed_messages.append(e.msg)
99 success = False
100 return success
101
102 def get_stdout_and_print(self):
103 if self.stdout_printed:
104 return
105 with self._selenium_catcher():
106 div_terminal = self.driver.find_element(by=By.ID, value="terminal")
107 assert div_terminal
108 text = div_terminal.text
109 print(text)
110 self.stdout_printed = True
111
112 def update_return_code(self):
113 with self._selenium_catcher():
114 div_process_quit = self.driver.find_element(by=By.ID, value="process-quit")
115 if not div_process_quit:
116 return
117 if div_process_quit.text != "":
118 try:
119 self.return_code = int(div_process_quit.text)
120 except ValueError:
121 raise ValueError(f"process-quit element contains invalid data: {div_process_quit.text:r}")
122
123 def loop(self):
124 print(f"Connecting to \"{self.url}\"", file=sys.stderr)
125 self.driver.get(url=self.url)
126 self.driver.implicitly_wait(0.2)
127
128 while True:
129 self.update_return_code()
130 if self.finished:
131 break
132 time.sleep(0.1)
133
134 self.get_stdout_and_print()
135 if not self.stdout_printed:
136 self.failed_messages.append("Failed to get stdout/stderr")
137
138
139
140def main() -> int:
141 parser = argparse.ArgumentParser(allow_abbrev=False, description="Selenium SDL test driver")
142 parser.add_argument("--browser", default="firefox", choices=["firefox", "chrome"], help="browser")
143 parser.add_argument("--server", default="http://localhost:8080", help="Server where SDL tests live")
144 parser.add_argument("--verbose", action="store_true", help="Verbose logging")
145 parser.add_argument("--chrome-binary", help="Chrome binary")
146 parser.add_argument("--firefox-binary", help="Firefox binary")
147
148 index_double_dash = sys.argv.index("--")
149 if index_double_dash < 0:
150 parser.error("Missing test arguments. Need -- <FILENAME> <ARGUMENTS>")
151 driver_arguments = sys.argv[1:index_double_dash]
152 test = pathlib.Path(sys.argv[index_double_dash+1]).name
153 test_arguments = sys.argv[index_double_dash+2:]
154
155 args = parser.parse_args(args=driver_arguments)
156
157 logging.basicConfig(level=logging.DEBUG if args.verbose else logging.INFO)
158
159 logger.debug("driver_arguments=%r test=%r test_arguments=%r", driver_arguments, test, test_arguments)
160
161 sdl_test_driver = SDLSeleniumTestDriver(
162 server=args.server,
163 test=test,
164 arguments=test_arguments,
165 browser=args.browser,
166 chrome_binary=args.chrome_binary,
167 firefox_binary=args.firefox_binary,
168 )
169 sdl_test_driver.loop()
170
171 rc = sdl_test_driver.return_code
172 if sdl_test_driver.failed_messages:
173 for msg in sdl_test_driver.failed_messages:
174 print(f"FAILURE MESSAGE: {msg}", file=sys.stderr)
175 if rc == 0:
176 print(f"Test signaled success (rc=0) but a failure happened", file=sys.stderr)
177 rc = 1
178 sys.stdout.flush()
179 logger.info("Exit code = %d", rc)
180 return rc
181
182
183if __name__ == "__main__":
184 raise SystemExit(main())