# Stress test umbrella workflow. # # Each job is one stress scenario, filtered by NUnit Category. Add new # scenarios by adding a sibling job below with the same seed-generation # pattern and the same 'if' gate. # # Opt-in: nightly, manual, and pull requests labelled 'stress'. It is not a # required check. Adding the label starts a run; every later push to the # labelled pull request starts a new one and cancels the run in progress. name: Stress Tests on: schedule: # Run nightly at 3:00 AM UTC. - cron: '0 3 * * *' workflow_dispatch: inputs: seed: description: 'Optional ChaosTCP seed. Leave empty to generate a random seed.' required: false default: '' type: string pull_request: types: [labeled, synchronize, opened, reopened] permissions: contents: read # A pull request run is superseded by the next push. A 'labeled' event for any # other label gets a group of its own so it cannot cancel a run in progress. concurrency: group: ${{ github.workflow }}-${{ github.event.action == 'labeled' && github.event.label.name != 'stress' && github.run_id || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: chaos-tcp: name: Chaos TCP # On a pull request only when it carries the 'stress' label, and not again # when some other label is added to it. if: >- github.event_name != 'pull_request' || (contains(github.event.pull_request.labels.*.name, 'stress') && (github.event.action != 'labeled' || github.event.label.name == 'stress')) runs-on: ubuntu-latest timeout-minutes: 120 env: DOTNET_VERSION: '10.0.401' TARGET_FRAMEWORK: 'net10.0' CONFIGURATION: 'Release' CUSTOM_TEST_TARGET: 'net10.0' STRESS_PROJECT: './tests/Opc.Ua.Stress.Tests/Opc.Ua.Stress.Tests.csproj' TESTRESULTS: './TestResults/chaos-tcp' steps: - name: Checkout code uses: actions/checkout@v7 with: fetch-depth: 0 - name: Setup .NET ${{ env.DOTNET_VERSION }} uses: actions/setup-dotnet@v6 with: dotnet-version: ${{ env.DOTNET_VERSION }} - name: Set Cloud Version shell: pwsh run: ./.azurepipelines/set-version.ps1 - name: Restore dependencies run: dotnet restore 'UA.slnx' - name: Build Stress Tests run: > dotnet build ${{ env.STRESS_PROJECT }} --framework ${{ env.TARGET_FRAMEWORK }} --configuration ${{ env.CONFIGURATION }} --no-restore /p:CustomTestTarget=${{ env.CUSTOM_TEST_TARGET }} - name: Generate ChaosTCP seed id: seed shell: pwsh env: INPUT_SEED: ${{ github.event.inputs.seed }} run: | $configuredSeed = $env:INPUT_SEED if ([string]::IsNullOrWhiteSpace($configuredSeed)) { $seed = [System.Security.Cryptography.RandomNumberGenerator]::GetInt32([int]::MaxValue) } else { $seed = [int]::Parse($configuredSeed, [System.Globalization.CultureInfo]::InvariantCulture) } New-Item -ItemType Directory -Force -Path $env:TESTRESULTS | Out-Null "OPCUA_CHAOS_SEED=$seed" | Out-File -FilePath $env:GITHUB_ENV -Append "OPCUA_TEST_SEED=$seed" | Out-File -FilePath $env:GITHUB_ENV -Append "seed=$seed" | Out-File -FilePath $env:GITHUB_OUTPUT -Append $repro = @( "ChaosTCP seed: $seed", '', 'Reproduce locally from the repository root:', 'PowerShell:', " `$env:OPCUA_CHAOS_SEED = '$seed'", " `$env:OPCUA_TEST_SEED = '$seed'", ' dotnet test .\tests\Opc.Ua.Stress.Tests\Opc.Ua.Stress.Tests.csproj --framework net10.0 --configuration Release --filter "Category=ChaosTCP"', '', 'Bash:', " OPCUA_CHAOS_SEED=$seed OPCUA_TEST_SEED=$seed dotnet test ./tests/Opc.Ua.Stress.Tests/Opc.Ua.Stress.Tests.csproj --framework net10.0 --configuration Release --filter 'Category=ChaosTCP'") $repro | Set-Content -Path (Join-Path $env:TESTRESULTS 'chaos-seed.txt') Write-Host "ChaosTCP seed: $seed" - name: Run ChaosTCP tests shell: pwsh run: | dotnet test $env:STRESS_PROJECT ` --configuration $env:CONFIGURATION ` --no-build ` --framework $env:TARGET_FRAMEWORK ` --filter "Category=ChaosTCP" ` --logger "trx;LogFileName=chaos-tcp.trx" ` --logger "console;verbosity=detailed" ` --results-directory $env:TESTRESULTS ` /p:CustomTestTarget=$env:CUSTOM_TEST_TARGET - name: Check that the ChaosTCP tests ran shell: pwsh run: ./.github/scripts/assert-tests-ran.ps1 -ResultsDirectory $env:TESTRESULTS - name: Upload ChaosTCP results uses: actions/upload-artifact@v7 with: name: chaos-tcp-${{ steps.seed.outputs.seed }} path: ${{ env.TESTRESULTS }} if: always()