mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-12 19:22:30 +00:00
chore(build): use SDL3
This commit is contained in:
parent
9d04a35d87
commit
b3c0734a9e
3286 changed files with 866354 additions and 554996 deletions
184
vendor/sdl-3.2.10/test/emscripten/driver.py
vendored
Executable file
184
vendor/sdl-3.2.10/test/emscripten/driver.py
vendored
Executable file
|
|
@ -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 -- <FILENAME> <ARGUMENTS>")
|
||||
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())
|
||||
25
vendor/sdl-3.2.10/test/emscripten/joystick-pre.js
vendored
Normal file
25
vendor/sdl-3.2.10/test/emscripten/joystick-pre.js
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Module['arguments'] = ['0'];
|
||||
//Gamepads don't appear until a button is pressed and the joystick/gamepad tests expect one to be connected
|
||||
Module['preRun'].push(function()
|
||||
{
|
||||
Module['print']("Waiting for gamepad...");
|
||||
Module['addRunDependency']("gamepad");
|
||||
window.addEventListener('gamepadconnected', function()
|
||||
{
|
||||
//OK, got one
|
||||
Module['removeRunDependency']("gamepad");
|
||||
}, false);
|
||||
|
||||
//chrome
|
||||
if(!!navigator.webkitGetGamepads)
|
||||
{
|
||||
var timeout = function()
|
||||
{
|
||||
if(navigator.webkitGetGamepads()[0] !== undefined)
|
||||
Module['removeRunDependency']("gamepad");
|
||||
else
|
||||
setTimeout(timeout, 100);
|
||||
}
|
||||
setTimeout(timeout, 100);
|
||||
}
|
||||
});
|
||||
54
vendor/sdl-3.2.10/test/emscripten/pre.js
vendored
Normal file
54
vendor/sdl-3.2.10/test/emscripten/pre.js
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
const searchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
Module.preRun = () => {
|
||||
};
|
||||
|
||||
const arguments = [];
|
||||
for (let i = 1; true; i++) {
|
||||
const arg_i = searchParams.get(`arg_${i}`);
|
||||
if (arg_i == null) {
|
||||
break;
|
||||
}
|
||||
arguments.push(arg_i);
|
||||
}
|
||||
|
||||
Module.arguments = arguments;
|
||||
|
||||
if (searchParams.get("loghtml") === "1") {
|
||||
const divTerm = document.createElement("div");
|
||||
divTerm.id = "terminal";
|
||||
document.body.append(divTerm);
|
||||
|
||||
function printToStdOut(msg, id) {
|
||||
const divMsg = document.createElement("div", {class: "stdout"});
|
||||
divMsg.id = id;
|
||||
divMsg.append(document.createTextNode(msg));
|
||||
divTerm.append(divMsg);
|
||||
return divMsg;
|
||||
}
|
||||
|
||||
Module.print = (msg) => {
|
||||
console.log(msg);
|
||||
printToStdOut(msg, "stdout");
|
||||
}
|
||||
|
||||
Module.printErr = (msg) => {
|
||||
console.error(msg);
|
||||
const e = printToStdOut(msg, "stderr");
|
||||
e.style = "color:red";
|
||||
}
|
||||
|
||||
const divQuit = document.createElement("div");
|
||||
divQuit.id = "process-quit";
|
||||
document.body.append(divQuit);
|
||||
|
||||
Module.quit = (msg) => {
|
||||
divQuit.innerText = msg;
|
||||
console.log(`QUIT: ${msg}`)
|
||||
}
|
||||
|
||||
Module.onabort = (msg) => {
|
||||
printToStdOut(`ABORT: ${msg}`, "stderr");
|
||||
console.log(`ABORT: ${msg}`);
|
||||
}
|
||||
}
|
||||
102
vendor/sdl-3.2.10/test/emscripten/server.py
vendored
Executable file
102
vendor/sdl-3.2.10/test/emscripten/server.py
vendored
Executable file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Based on http/server.py from Python
|
||||
|
||||
from argparse import ArgumentParser
|
||||
import contextlib
|
||||
from http.server import SimpleHTTPRequestHandler
|
||||
from http.server import ThreadingHTTPServer
|
||||
import os
|
||||
import socket
|
||||
|
||||
|
||||
class MyHTTPRequestHandler(SimpleHTTPRequestHandler):
|
||||
extensions_map = {
|
||||
".manifest": "text/cache-manifest",
|
||||
".html": "text/html",
|
||||
".png": "image/png",
|
||||
".jpg": "image/jpg",
|
||||
".svg": "image/svg+xml",
|
||||
".css": "text/css",
|
||||
".js": "application/x-javascript",
|
||||
".wasm": "application/wasm",
|
||||
"": "application/octet-stream",
|
||||
}
|
||||
|
||||
def __init__(self, *args, maps=None, **kwargs):
|
||||
self.maps = maps or []
|
||||
SimpleHTTPRequestHandler.__init__(self, *args, **kwargs)
|
||||
|
||||
def end_headers(self):
|
||||
self.send_my_headers()
|
||||
SimpleHTTPRequestHandler.end_headers(self)
|
||||
|
||||
def send_my_headers(self):
|
||||
self.send_header("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||
self.send_header("Pragma", "no-cache")
|
||||
self.send_header("Expires", "0")
|
||||
|
||||
def translate_path(self, path):
|
||||
for map_path, map_prefix in self.maps:
|
||||
if path.startswith(map_prefix):
|
||||
res = os.path.join(map_path, path.removeprefix(map_prefix).lstrip("/"))
|
||||
break
|
||||
else:
|
||||
res = super().translate_path(path)
|
||||
return res
|
||||
|
||||
|
||||
def serve_forever(port: int, ServerClass):
|
||||
handler = MyHTTPRequestHandler
|
||||
|
||||
addr = ("0.0.0.0", port)
|
||||
with ServerClass(addr, handler) as httpd:
|
||||
host, port = httpd.socket.getsockname()[:2]
|
||||
url_host = f"[{host}]" if ":" in host else host
|
||||
print(f"Serving HTTP on {host} port {port} (http://{url_host}:{port}/) ...")
|
||||
try:
|
||||
httpd.serve_forever()
|
||||
except KeyboardInterrupt:
|
||||
print("\nKeyboard interrupt received, exiting.")
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
parser = ArgumentParser(allow_abbrev=False)
|
||||
parser.add_argument("port", nargs="?", type=int, default=8080)
|
||||
parser.add_argument("-d", dest="directory", type=str, default=None)
|
||||
parser.add_argument("--map", dest="maps", nargs="+", type=str, help="Mappings, used as e.g. \"$HOME/projects/SDL:/sdl\"")
|
||||
args = parser.parse_args()
|
||||
|
||||
maps = []
|
||||
for m in args.maps:
|
||||
try:
|
||||
path, uri = m.split(":", 1)
|
||||
except ValueError:
|
||||
parser.error(f"Invalid mapping: \"{m}\"")
|
||||
maps.append((path, uri))
|
||||
|
||||
class DualStackServer(ThreadingHTTPServer):
|
||||
def server_bind(self):
|
||||
# suppress exception when protocol is IPv4
|
||||
with contextlib.suppress(Exception):
|
||||
self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
|
||||
return super().server_bind()
|
||||
|
||||
def finish_request(self, request, client_address):
|
||||
self.RequestHandlerClass(
|
||||
request,
|
||||
client_address,
|
||||
self,
|
||||
directory=args.directory,
|
||||
maps=maps,
|
||||
)
|
||||
|
||||
return serve_forever(
|
||||
port=args.port,
|
||||
ServerClass=DualStackServer,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue