Skip to content

Fixes #4408. Phase 2: Migrate Toplevel, Dialog, MessageBox, and Wizard to IRunnable pattern #2305

Fixes #4408. Phase 2: Migrate Toplevel, Dialog, MessageBox, and Wizard to IRunnable pattern

Fixes #4408. Phase 2: Migrate Toplevel, Dialog, MessageBox, and Wizard to IRunnable pattern #2305

Workflow file for this run

name: Build & Run Unit Tests
on:
push:
branches: [ v2_release, v2_develop ]
paths-ignore:
- '**.md'
pull_request:
branches: [ v2_release, v2_develop ]
paths-ignore:
- '**.md'
jobs:
# Call the quick-build workflow to build Debug configuration only
build:
uses: ./.github/workflows/quick-build.yml
non_parallel_unittests:
name: Non-Parallel Unit Tests
runs-on: ${{ matrix.os }}
needs: build
strategy:
# Turn off fail-fast to let all runners run even if there are errors
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
timeout-minutes: 15 # Increased from 10 for Windows
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x
dotnet-quality: 'ga'
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: test-build-artifacts
path: .
# KEEP THIS - It's needed for --no-build to work
- name: Restore NuGet packages
run: dotnet restore
# Optimize Windows performance
- name: Disable Windows Defender (Windows only)
if: runner.os == 'Windows'
shell: powershell
run: |
Add-MpPreference -ExclusionPath "${{ github.workspace }}"
Add-MpPreference -ExclusionProcess "dotnet.exe"
Add-MpPreference -ExclusionProcess "testhost.exe"
Add-MpPreference -ExclusionProcess "VSTest.Console.exe"
- name: Set VSTEST_DUMP_PATH
shell: bash
run: echo "VSTEST_DUMP_PATH=logs/UnitTests/${{ runner.os }}/" >> $GITHUB_ENV
- name: Run UnitTests
shell: bash
run: |
if [ "${{ runner.os }}" == "Linux" ]; then
# Run with coverage on Linux only
dotnet test Tests/UnitTests \
--no-build \
--verbosity normal \
--collect:"XPlat Code Coverage" \
--settings Tests/UnitTests/runsettings.xml \
--diag:logs/UnitTests/${{ runner.os }}/logs.txt \
--blame \
--blame-crash \
--blame-hang \
--blame-hang-timeout 60s \
--blame-crash-collect-always
else
# Run without coverage on Windows/macOS for speed
dotnet test Tests/UnitTests \
--no-build \
--verbosity normal \
--settings Tests/UnitTests/runsettings.xml \
--diag:logs/UnitTests/${{ runner.os }}/logs.txt \
--blame \
--blame-crash \
--blame-hang \
--blame-hang-timeout 120s \
--blame-crash-collect-always
fi
- name: Upload Test Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: non_parallel_unittests-logs-${{ runner.os }}
path: |
logs/UnitTests
TestResults/
- name: Upload Non-Parallel UnitTests Coverage to Codecov
if: matrix.os == 'ubuntu-latest' && always()
uses: codecov/codecov-action@v4
with:
files: TestResults/**/coverage.cobertura.xml
flags: unittests-nonparallel
name: UnitTests-${{ runner.os }}
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false
parallel_unittests:
name: Parallel Unit Tests
runs-on: ${{ matrix.os }}
needs: build
strategy:
# Turn off fail-fast to let all runners run even if there are errors
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
timeout-minutes: 60
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.x
dotnet-quality: 'ga'
- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: test-build-artifacts
path: .
- name: Restore NuGet packages
run: dotnet restore
- name: Disable Windows Defender (Windows only)
if: runner.os == 'Windows'
shell: powershell
run: |
Add-MpPreference -ExclusionPath "${{ github.workspace }}"
Add-MpPreference -ExclusionProcess "dotnet.exe"
Add-MpPreference -ExclusionProcess "testhost.exe"
Add-MpPreference -ExclusionProcess "VSTest.Console.exe"
- name: Set VSTEST_DUMP_PATH
shell: bash
run: echo "VSTEST_DUMP_PATH=logs/UnitTestsParallelizable/${{ runner.os }}/" >> $GITHUB_ENV
- name: Run UnitTestsParallelizable (10 iterations with varying parallelization)
shell: bash
run: |
# Run tests 10 times with different parallelization settings to expose concurrency issues
for RUN in {1..10}; do
echo "============================================"
echo "Starting test run $RUN of 10"
echo "============================================"
# Use a combination of run number and timestamp to create different execution patterns
SEED=$((1000 + $RUN + $(date +%s) % 1000))
echo "Using randomization seed: $SEED"
# Vary the xUnit parallelization based on run number to expose race conditions
# Runs 1-3: Default parallelization (2x CPU cores)
# Runs 4-6: Max parallelization (unlimited)
# Runs 7-9: Single threaded (1)
# Run 10: Random (1-4 threads)
if [ $RUN -le 3 ]; then
XUNIT_MAX_PARALLEL_THREADS="2x"
echo "Run $RUN: Using default parallelization (2x)"
elif [ $RUN -le 6 ]; then
XUNIT_MAX_PARALLEL_THREADS="unlimited"
echo "Run $RUN: Using maximum parallelization (unlimited)"
elif [ $RUN -le 9 ]; then
XUNIT_MAX_PARALLEL_THREADS="1"
echo "Run $RUN: Using single-threaded execution"
else
# Random parallelization based on seed
PROC_COUNT=$(( ($SEED % 4) + 1 ))
XUNIT_MAX_PARALLEL_THREADS="$PROC_COUNT"
echo "Run $RUN: Using random parallelization with $PROC_COUNT threads"
fi
# Run tests with or without coverage based on OS and run number
if [ "${{ runner.os }}" == "Linux" ] && [ $RUN -eq 1 ]; then
echo "Run $RUN: Running with coverage collection"
dotnet test Tests/UnitTestsParallelizable \
--no-build \
--verbosity normal \
--collect:"XPlat Code Coverage" \
--settings Tests/UnitTests/runsettings.coverage.xml \
--diag:logs/UnitTestsParallelizable/${{ runner.os }}/run${RUN}-logs.txt \
--blame \
--blame-crash \
--blame-hang \
--blame-hang-timeout 60s \
--blame-crash-collect-always \
-- xUnit.MaxParallelThreads=${XUNIT_MAX_PARALLEL_THREADS}
else
dotnet test Tests/UnitTestsParallelizable \
--no-build \
--verbosity normal \
--settings Tests/UnitTestsParallelizable/runsettings.xml \
--diag:logs/UnitTestsParallelizable/${{ runner.os }}/run${RUN}-logs.txt \
--blame \
--blame-crash \
--blame-hang \
--blame-hang-timeout 60s \
--blame-crash-collect-always \
-- xUnit.MaxParallelThreads=${XUNIT_MAX_PARALLEL_THREADS}
fi
if [ $? -ne 0 ]; then
echo "ERROR: Test run $RUN failed!"
exit 1
fi
echo "Test run $RUN completed successfully"
echo ""
done
echo "============================================"
echo "All 10 test runs completed successfully!"
echo "============================================"
- name: Upload UnitTestsParallelizable Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: parallel_unittests-logs-${{ runner.os }}
path: |
logs/UnitTestsParallelizable/
TestResults/
- name: Upload Parallelizable UnitTests Coverage to Codecov
if: matrix.os == 'ubuntu-latest' && always()
uses: codecov/codecov-action@v4
with:
files: TestResults/**/coverage.cobertura.xml
flags: unittests-parallel
name: UnitTestsParallelizable-${{ runner.os }}
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: false