216 lines
9.5 KiB
YAML
216 lines
9.5 KiB
YAML
# Tests that need no game files, keys or GPU. GitHub's macOS runners are virtual Macs without Metal 4 (issue #112), so the tests that go through mtl_init
|
|
# (t_nvn, t_mip_extent, t_rt_range and the rest of dm/gfx/tests' run list) stay local: run `make -C dm/gfx/tests GAME=<id> run` on an Apple-silicon Mac.
|
|
# `profile_guess.py --check` stays local too: it compares the guesses with the extractions of the games (it needs their files).
|
|
name: tests
|
|
|
|
on:
|
|
pull_request:
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
concurrency:
|
|
group: tests-${{ github.event.pull_request.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
env:
|
|
GAME: 010015100B514000 # Super Mario Bros. Wonder: the profile the host and gfx tests are built for (any profile does; the tests are about code, not the game)
|
|
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
|
|
# Actions are pinned to commit SHAs (the tag in the comment): a tag can be moved, a SHA cannot. Dependabot (github-actions) can raise them.
|
|
jobs:
|
|
host-tests:
|
|
name: Host unit tests and CPU-only gfx tests
|
|
runs-on: macos-26
|
|
timeout-minutes: 20
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Complete game catalog and bilingual galleries
|
|
run: python3 scripts/sync_game_catalog.py --check
|
|
- name: Personal unsigned-build automation tests
|
|
run: |
|
|
python3 -m unittest discover -s scripts/tests
|
|
python3 -m unittest dm.tools.tests.test_nsp_space
|
|
python3 -m unittest discover -s dm/ios/tests -p test_pad_geometry.py
|
|
- name: Host unit tests (dm/host/tests)
|
|
run: |
|
|
mkdir -p logs
|
|
make -C dm/host/tests GAME="$GAME" -j3 run 2>&1 | tee logs/host-tests.log
|
|
- name: ThreadSanitizer (audio, HID and guest memory)
|
|
run: |
|
|
make -C dm/host/tests GAME="$GAME" -j3 tsan memory-tsan 2>&1 | tee logs/tsan.log
|
|
- name: Thermal cap and ThreadSanitizer (concurrent frame-cap readers)
|
|
run: |
|
|
make -C dm/gfx/tests GAME="$GAME" -j3 check_t_thermal thermal-tsan 2>&1 | tee logs/thermal.log
|
|
- name: CPU texture layout and deswizzle tests
|
|
run: |
|
|
make -C dm/gfx/tex/tests t_tex 2>&1 | tee logs/texture-build.log
|
|
dm/gfx/tex/tests/t_tex 2>&1 | tee logs/texture-tests.log
|
|
- name: CPU-only gfx tests (dm/gfx/tests)
|
|
run: |
|
|
mkdir -p logs
|
|
cd dm/gfx/tests
|
|
make GAME="$GAME" -j3 t_perf_order
|
|
./t_perf_order --cpu 2>&1 | tee ../../../logs/t_perf_order.log
|
|
make GAME="$GAME" -j3 perf-order-tsan 2>&1 | tee ../../../logs/t_perf_order-tsan.log
|
|
tests="t_dirty_slots t_dirty_race t_tex_layout t_pace t_fstep t_link_ticks t_hmap t_cover t_pso_skey t_refl t_rt_range_ro t_present_rescue t_gpuprof"
|
|
make GAME="$GAME" -j3 $tests 2>&1 | tee ../../../logs/gfx-build.log
|
|
failed=0
|
|
for t in $tests; do
|
|
echo "::group::$t"
|
|
./$t 2>&1 | tee "../../../logs/$t.log" && rc=0 || rc=1 # pipefail: the test's status
|
|
echo "::endgroup::"
|
|
if [ "$rc" != 0 ]; then echo "::error::$t failed"; failed=1; fi
|
|
done
|
|
exit $failed
|
|
- name: Direct OpenGL imports and EGL lookup (no GPU)
|
|
run: make -C dm/gfx/tests GAME="$GAME" gl-imports 2>&1 | tee logs/gl-imports.log
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
if: failure()
|
|
with:
|
|
name: logs-host-tests
|
|
path: logs
|
|
retention-days: 7
|
|
|
|
tool-tests:
|
|
name: Tool tests
|
|
runs-on: macos-26
|
|
timeout-minutes: 15
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
|
|
with:
|
|
python-version: '3.14'
|
|
cache: pip
|
|
cache-dependency-path: .github/workflows/tests.yml # no requirements file: the packages are listed in the step below
|
|
- name: Install the Python packages the tools import
|
|
run: python -m pip install lz4 capstone fonttools # backports.zstd is for Python before 3.14 only
|
|
# The shader translator's tests (test_image_atomic_bounds, test_dmsh_geometry) run the committed translator on synthetic Maxwell shaders, then spirv-val and spirv-cross:
|
|
# one translation chain serves every game, so these are what checks a translator change on games its author does not own (GitHub issue #272). Compiling their MSL with
|
|
# Metal (DMSH_TEST_METAL=1) and running it on the GPU (DMSH_TEST_GPU=1) stay local.
|
|
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
|
|
with:
|
|
dotnet-version: '10.0.x' # dm/gfx/tools/dmsh_xlate_bin targets net10.0
|
|
- name: Install spirv-cross and spirv-val
|
|
env:
|
|
HOMEBREW_NO_AUTO_UPDATE: 1
|
|
run: brew install spirv-cross spirv-tools
|
|
- name: Run the test files
|
|
env:
|
|
DM_GAME: ${{ env.GAME }} # test_tbdr_budget runs a tool that needs a profile
|
|
DMSH_TEST_XLATE: ${{ github.workspace }}/dm/gfx/tools/dmsh_xlate_bin/dmsh_xlate
|
|
run: |
|
|
mkdir -p logs
|
|
failed=0
|
|
for f in dm/tools/tests/test_*.py dm/ios/tests/test_*.py dm/gfx/tests/test_*.py; do
|
|
echo "::group::$f"
|
|
python -m unittest -v "$f" 2>&1 | tee "logs/$(basename "$f").log" || { echo "::error::$f failed"; failed=1; }
|
|
echo "::endgroup::"
|
|
done
|
|
exit $failed
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
if: failure()
|
|
with:
|
|
name: logs-tool-tests
|
|
path: logs
|
|
retention-days: 7
|
|
|
|
build:
|
|
name: Build check (Mac host, gfx tests, iOS sources)
|
|
runs-on: macos-26
|
|
timeout-minutes: 40
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Mac host for three profiles (Vulkan, NVN, OpenGL)
|
|
run: |
|
|
mkdir -p logs
|
|
# Wonder: NVN; Hades: Vulkan; Digimon Story Cyber Sleuth: OpenGL. The second and third reuse the libvpx build in dm/host/gen/vpx.
|
|
for g in 010015100B514000 0100535012974000 010014E00DB56000; do
|
|
echo "::group::dmhost $g"
|
|
make -C dm/host GAME=$g -j3 dmhost 2>&1 | tee "logs/dmhost-$g.log"
|
|
test -x dm/host/dmhost
|
|
echo "::endgroup::"
|
|
done
|
|
- name: Every gfx test compiled, not run
|
|
run: |
|
|
mkdir -p logs
|
|
cd dm/gfx/tests
|
|
tests=$(sed -n 's/^\(t_[a-z0-9_]*\):.*/\1/p' Makefile | sort -u)
|
|
echo "$tests" | tr '\n' ' '; echo
|
|
make GAME="$GAME" -j3 $tests 2>&1 | tee ../../../logs/gfx-tests-build.log
|
|
- name: iOS host sources compiled for the iPhone SDK (no signing, no Xcode project)
|
|
run: python3 dm/ios/tools/compile_check.py 2>&1 | tee logs/ios-compile.log
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
if: failure()
|
|
with:
|
|
name: logs-build
|
|
path: logs
|
|
retention-days: 7
|
|
|
|
ios-build:
|
|
name: Unsigned iOS app (synthetic modules, Swift and link)
|
|
runs-on: macos-26
|
|
timeout-minutes: 40
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Install XcodeGen
|
|
run: command -v xcodegen || brew install xcodegen
|
|
- name: Build the production iOS project with synthetic inputs
|
|
run: |
|
|
mkdir -p logs
|
|
python3 dm/ios/tools/build_smoke.py --output "$RUNNER_TEMP/ios-smoke" 2>&1 | tee logs/ios-build.log
|
|
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
if: failure()
|
|
with:
|
|
name: logs-ios-build
|
|
path: logs
|
|
retention-days: 7
|
|
|
|
save-api:
|
|
name: Save API authentication, conflicts and immutable sharing
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0
|
|
with:
|
|
python-version: '3.13'
|
|
- run: python -m pip install -r dm/cloud/requirements.txt
|
|
- run: python -m unittest scripts.tests.test_save_api
|
|
|
|
native-sideload:
|
|
name: ARM64 sideload helper and redacted IPC (no account or device)
|
|
runs-on: macos-26
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
|
|
with:
|
|
persist-credentials: false
|
|
- name: Install checksum-pinned isolated Rust toolchain
|
|
run: python3 scripts/build_sideload_helper.py --cache "$RUNNER_TEMP/native-tools" --toolchain-only
|
|
- name: Test helper policies, recovery and archive boundaries
|
|
run: |
|
|
export PATH="$RUNNER_TEMP/native-tools/rust-1.99.1/bin:$PATH"
|
|
export CARGO_HOME="$RUNNER_TEMP/native-tools/cargo"
|
|
export CARGO_TARGET_DIR="$RUNNER_TEMP/native-tools/target"
|
|
export CARGO_BUILD_JOBS=2
|
|
cargo test --locked --manifest-path native/sideload-helper/Cargo.toml
|
|
cargo build --locked --manifest-path native/sideload-helper/Cargo.toml
|
|
NXE_SIDELOAD_TEST_HELPER="$CARGO_TARGET_DIR/debug/nxnative-sideload" python3 -m unittest scripts.tests.test_sideload_protocol
|