Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/_shared-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
description: "Run shader unit tests"
type: boolean
default: true
run-cpp-tests:
description: "Run C++ unit tests (tests/cpp)"
type: boolean
default: true
hlsl-should-build:
description: "Passed to check-hlsl-changes; 'true' forces shader steps to run"
type: string
Expand All @@ -31,6 +35,10 @@
description: "Passed to check-hlsl-changes for unit tests"
type: string
default: "true"
cpp-tests-should-build:
description: "Forces cpp_tests build+run when 'true'; lets PR-checks skip it otherwise"
type: string
default: "true"
cache-key-suffix:
description: "Optional suffix to invalidate the build cache"
type: string
Expand Down Expand Up @@ -259,3 +267,67 @@
build/ALL/Testing/**
retention-days: 7
if-no-files-found: ignore

cpp-unit-tests:
name: Run C++ Unit Tests
if: inputs.run-cpp-tests
runs-on: windows-2025
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ inputs.ref }}
repository: ${{ inputs.repository }}
submodules: recursive

# Inline gate (no composite action — the logic is one branch).
# PR events skip when no relevant files changed; push / dispatch /
# release always run.
- name: Check if cpp_tests should run
id: check-cpp
shell: bash
run: |
if [ "${{ github.event_name }}" != "pull_request_target" ]; then
echo "Non-PR event, proceeding."
echo "skip=false" >> $GITHUB_OUTPUT
elif [ "${{ inputs.cpp-tests-should-build }}" != "true" ]; then
echo "No cpp_tests-related changes detected, skipping."
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "cpp_tests-related changes detected, proceeding."
echo "skip=false" >> $GITHUB_OUTPUT
fi

- name: Setup Build Environment
id: setup
if: steps.check-cpp.outputs.skip != 'true'
uses: ./.github/actions/setup-build-environment
with:
cache-key-suffix: "cpp-tests${{ inputs.cache-key-suffix }}"
cmake-preset: "ALL"
build-dir: "build/ALL"

- name: Build cpp_tests

Check failure

Code scanning / CodeQL

Cache Poisoning via execution of untrusted code High

Potential cache poisoning in the context of the default branch due to privilege checkout of untrusted code. (
pull_request_target
).
Comment thread
alandtse marked this conversation as resolved.
Dismissed
if: steps.check-cpp.outputs.skip != 'true'
uses: lukka/run-cmake@v10
with:
configurePreset: ALL
buildPreset: ALL
buildPresetAdditionalArgs: "['--target cpp_tests']"

- name: Run C++ unit tests
if: steps.check-cpp.outputs.skip != 'true'
run: |
ctest --test-dir build/ALL -C Release --output-on-failure -R CppUtilTests --timeout 60

- name: Upload test results on failure
if: failure() && steps.check-cpp.outputs.skip != 'true'
uses: actions/upload-artifact@v7
with:
name: cpp-test-results
path: |
build/ALL/Testing/**
retention-days: 7
if-no-files-found: ignore
8 changes: 8 additions & 0 deletions .github/workflows/pr-checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ jobs:
should-build: ${{ steps.changed-files.outputs.build_any_changed == 'true' || steps.changed-files.outputs.cpp_any_changed == 'true' || steps.changed-files.outputs.build_ci_any_changed == 'true' || steps.changed-files.outcome == 'failure' }}
hlsl-should-build: ${{ steps.changed-files.outputs.hlsl_any_changed == 'true' || steps.changed-files.outputs.cmake_any_changed == 'true' || steps.changed-files.outputs.build_ci_any_changed == 'true' || steps.changed-files.outcome == 'failure' }}
shader-tests-should-build: ${{ steps.changed-files.outputs.shader_tests_any_changed == 'true' || steps.changed-files.outputs.hlsl_any_changed == 'true' || steps.changed-files.outputs.cmake_any_changed == 'true' || steps.changed-files.outputs.build_ci_any_changed == 'true' || steps.changed-files.outcome == 'failure' }}
# cpp_tests target compiles src/Utils/Subrect.cpp directly (see tests/cpp/CMakeLists.txt),
# so any cpp_any change is conservative-but-correct. cpp_tests_any catches changes to
# the test sources themselves. cmake/build_ci cover CMake + CI plumbing.
cpp-tests-should-build: ${{ steps.changed-files.outputs.cpp_tests_any_changed == 'true' || steps.changed-files.outputs.cpp_any_changed == 'true' || steps.changed-files.outputs.cmake_any_changed == 'true' || steps.changed-files.outputs.build_ci_any_changed == 'true' || steps.changed-files.outcome == 'failure' }}
steps:
- uses: actions/checkout@v6
with:
Expand Down Expand Up @@ -104,6 +108,8 @@ jobs:
- 'features/**/Shaders/**'
shader_tests:
- 'tests/shaders/**'
cpp_tests:
- 'tests/cpp/**'
base_sha: ${{ github.event.pull_request.base.sha }}
sha: ${{ github.event.pull_request.head.sha }}

Expand All @@ -125,8 +131,10 @@ jobs:
run-cpp: ${{ needs.check-changes.outputs.should-build != 'false' }}
run-shader-validation: ${{ needs.check-changes.outputs.hlsl-should-build != 'false' }}
run-shader-tests: ${{ needs.check-changes.outputs.shader-tests-should-build != 'false' }}
run-cpp-tests: ${{ needs.check-changes.outputs.cpp-tests-should-build != 'false' }}
hlsl-should-build: ${{ needs.check-changes.outputs.hlsl-should-build || 'true' }}
shader-tests-should-build: ${{ needs.check-changes.outputs.shader-tests-should-build || 'true' }}
cpp-tests-should-build: ${{ needs.check-changes.outputs.cpp-tests-should-build || 'true' }}

# Security: this job uses GITHUB_TOKEN with write permissions but does NOT execute
# fork code — it only downloads pre-built artifacts from the build job above.
Expand Down
32 changes: 22 additions & 10 deletions tests/cpp/test_subrect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,18 @@ TEST_CASE("Stereo SaveSettings emits right_uv for every preset", "[subrect][ster
// preserved" from "default fallback mirrored it back".
const UVRegion leftUV{ 0.10f, 0.0f, 0.40f, 1.0f };
const UVRegion rightUV{ 0.55f, 0.0f, 0.35f, 1.0f };

// Build the preset object via direct mutation rather than a single nested
// initializer list. MSVC's C++23 module-aware parse cannot disambiguate
// `json::array({ json{ {k,v}, {k,v} } })` from the
// `initializer_list<initializer_list<json>>` overload of `json`'s
// constructor, producing a misleading C3329 at the inner closing `)`.
// Building element-by-element sidesteps the ambiguity entirely.
json preset = json::object();
preset["name"] = "Asymmetric";
preset["uv"] = json::array({ leftUV.x, leftUV.y, leftUV.w, leftUV.h });
preset["right_uv"] = json::array({ rightUV.x, rightUV.y, rightUV.w, rightUV.h });

json staged = {
{ "CropX", leftUV.x },
{ "CropY", leftUV.y },
Expand All @@ -224,11 +236,7 @@ TEST_CASE("Stereo SaveSettings emits right_uv for every preset", "[subrect][ster
{ "CropRightY", rightUV.y },
{ "CropRightW", rightUV.w },
{ "CropRightH", rightUV.h },
{ "CropPresets", json::array({ json{
{ "name", "Asymmetric" },
{ "uv", json::array({ leftUV.x, leftUV.y, leftUV.w, leftUV.h }) },
{ "right_uv", json::array({ rightUV.x, rightUV.y, rightUV.w, rightUV.h }) } }) }
},
{ "CropPresets", json::array({ preset }) },
{ "SelectedPresetIndex", 0 }
};
src.LoadSettings(staged);
Expand Down Expand Up @@ -392,12 +400,16 @@ TEST_CASE("Malformed preset right_uv falls back to auto-mirror", "[subrect][ster
// With validation, malformed input is ignored and the mirror takes over.
Controller c;
c.SetStereoEnabled(true);

// Same C++23-modules-friendly construction as above (see the regression
// test for the rationale).
json badPreset = json::object();
badPreset["name"] = "Bad";
badPreset["uv"] = json::array({ 0.10f, 0.0f, 0.40f, 1.0f });
badPreset["right_uv"] = "not an array"; // malformed

json bad = {
{ "CropPresets", json::array({ json{
{ "name", "Bad" },
{ "uv", { 0.10f, 0.0f, 0.40f, 1.0f } },
{ "right_uv", "not an array" } // malformed
} }) },
{ "CropPresets", json::array({ badPreset }) },
{ "SelectedPresetIndex", 0 }
};
c.LoadSettings(bad);
Expand Down
Loading