SDL: emscripten: pass --no-sandbox to the chrome web driver

From cb3cc28809c08d7af4d1c7fe7bbcdd552918e75c Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Wed, 22 Jan 2025 01:07:52 +0100
Subject: [PATCH] emscripten: pass --no-sandbox to the chrome web driver

This fixes running the Emscripten tests on Ubuntu 24.04.
---
 .github/workflows/create-test-plan.py | 10 ++++++++--
 .github/workflows/generic.yml         | 14 +++++++++-----
 test/emscripten/driver.py             |  9 +++++----
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/.github/workflows/create-test-plan.py b/.github/workflows/create-test-plan.py
index 2ac30fbabaee9..925b994957ebb 100755
--- a/.github/workflows/create-test-plan.py
+++ b/.github/workflows/create-test-plan.py
@@ -129,7 +129,7 @@ class JobSpec:
     "android-cmake-lean": JobSpec(name="Android (CMake, lean)",             os=JobOs.UbuntuLatest,      platform=SdlPlatform.Android,     artifact="SDL-lean-android-arm64", android_abi="arm64-v8a", android_arch="aarch64", android_platform=23, lean=True, ),
     "android-mk": JobSpec(name="Android (Android.mk)",                      os=JobOs.UbuntuLatest,      platform=SdlPlatform.Android,     artifact=None,                     no_cmake=True, android_mk=True, ),
     "android-gradle": JobSpec(name="Android (Gradle)",                      os=JobOs.UbuntuLatest,      platform=SdlPlatform.Android,     artifact=None,                     no_cmake=True, android_gradle=True, ),
-    "emscripten": JobSpec(name="Emscripten",                                os=JobOs.Ubuntu22_04,       platform=SdlPlatform.Emscripten,  artifact="SDL-emscripten", ),
+    "emscripten": JobSpec(name="Emscripten",                                os=JobOs.UbuntuLatest,      platform=SdlPlatform.Emscripten,  artifact="SDL-emscripten", ),
     "haiku": JobSpec(name="Haiku",                                          os=JobOs.UbuntuLatest,      platform=SdlPlatform.Haiku,       artifact="SDL-haiku-x64",          container="ghcr.io/haiku/cross-compiler:x86_64-r1beta5", ),
     "loongarch64": JobSpec(name="LoongArch64",                              os=JobOs.UbuntuLatest,      platform=SdlPlatform.LoongArch64, artifact="SDL-loongarch64", ),
     "n3ds": JobSpec(name="Nintendo 3DS",                                    os=JobOs.UbuntuLatest,      platform=SdlPlatform.N3ds,        artifact="SDL-n3ds",               container="devkitpro/devkitarm:latest", ),
@@ -223,6 +223,8 @@ class JobDetails:
     cpactions_install_cmd: str = ""
     setup_vita_gles_type: str = ""
     check_sources: bool = False
+    setup_python: bool = False
+    pypi_packages: list[str] = dataclasses.field(default_factory=list)
 
     def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
         data = {
@@ -287,6 +289,8 @@ def to_workflow(self, enable_artifacts: bool) -> dict[str, str|bool]:
             "setup-vita-gles-type": self.setup_vita_gles_type,
             "setup-gdk-folder": self.setup_gdk_folder,
             "check-sources": self.check_sources,
+            "setup-python": self.setup_python,
+            "pypi-packages": my_shlex_join(self.pypi_packages),
         }
         return {k: v for k, v in data.items() if v != ""}
 
@@ -541,7 +545,6 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
             job.cmake_config_emulator = "emcmake"
             job.cmake_build_type = "Debug"
             job.test_pkg_config = False
-            job.apt_packages.append("python3-selenium")
             job.cmake_arguments.extend((
                 "-DSDLTEST_BROWSER=chrome",
                 "-DSDLTEST_TIMEOUT_MULTIPLIER=4",
@@ -561,6 +564,8 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
                 "chromedriver --version",
             ))
             job.static_lib = StaticLibType.A
+            job.setup_python = True
+            job.pypi_packages.append("selenium")
         case SdlPlatform.Ps2:
             build_parallel = False
             job.shared = False
@@ -713,6 +718,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool) -> JobDeta
 
     if "ubuntu" in spec.name.lower():
         job.check_sources = True
+        job.setup_python = True
 
     if not build_parallel:
         job.cmake_build_arguments.append("-j1")
diff --git a/.github/workflows/generic.yml b/.github/workflows/generic.yml
index d7bdb88291be9..0e42831759fbf 100644
--- a/.github/workflows/generic.yml
+++ b/.github/workflows/generic.yml
@@ -133,6 +133,15 @@ jobs:
           export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
           brew update
           brew install ${{ matrix.platform.brew-packages }}
+      - name: 'Setup Python'
+        uses: 'actions/setup-python@main'
+        if: ${{ matrix.platform.setup-python }}
+        with:
+          python-version: '3.x'
+      - name: 'Install PyPI packages'
+        if: ${{ matrix.platform.pypi-packages != '' }}
+        run: |
+          python -m pip install --user ${{ matrix.platform.pypi-packages }}
       - name: 'Set up GLES for VITA'  # Must be after apk
         if: ${{ matrix.platform.setup-vita-gles-type != '' }}
         uses: ./.github/actions/setup-vita-gles
@@ -348,11 +357,6 @@ jobs:
         if: ${{ matrix.platform.xcode-sdk != '' }}
         run: |
           xcodebuild -project Xcode/SDL/SDL.xcodeproj -target SDL3 -configuration Release -sdk ${{ matrix.platform.xcode-sdk }} clean build
-      - name: 'Setup Python'
-        uses: 'actions/setup-python@main'
-        if: ${{ matrix.platform.check-sources }}
-        with:
-          python-version: '3.x'
       - name: 'Check Sources'
         if: ${{ matrix.platform.check-sources }}
         run: |
diff --git a/test/emscripten/driver.py b/test/emscripten/driver.py
index 9735e95b9255a..ee91610dfc01c 100755
--- a/test/emscripten/driver.py
+++ b/test/emscripten/driver.py
@@ -32,6 +32,10 @@ def __init__(self, server: str, test: str, arguments: list[str], browser: str, f
         self.failed_messages: list[str] = []
         self.return_code = None
 
+        options = [
+            "--headless",
+        ]
+
         driver_contructor = None
         match browser:
             case "firefox":
@@ -44,12 +48,9 @@ def __init__(self, server: str, test: str, arguments: list[str], browser: str, f
                 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=}")
-
-        options = [
-            "--headless",
-        ]
         for o in options:
             driver_options.add_argument(o)
         logger.debug("About to create driver")