Files

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