diff --git a/.gitea/workflows/advisory-ai-release.yml b/.gitea/workflows/advisory-ai-release.yml index c077577dd..7044882b3 100644 --- a/.gitea/workflows/advisory-ai-release.yml +++ b/.gitea/workflows/advisory-ai-release.yml @@ -15,7 +15,7 @@ on: jobs: package-feeds: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: COSIGN_PRIVATE_KEY_B64: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} @@ -68,3 +68,4 @@ jobs: out/advisory-ai/feeds/provenance.json if-no-files-found: warn retention-days: 30 + diff --git a/.gitea/workflows/airgap-sealed-ci.yml b/.gitea/workflows/airgap-sealed-ci.yml index 2c5ab8504..0c62298dd 100644 --- a/.gitea/workflows/airgap-sealed-ci.yml +++ b/.gitea/workflows/airgap-sealed-ci.yml @@ -14,7 +14,7 @@ on: jobs: sealed-smoke: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read steps: @@ -26,3 +26,4 @@ jobs: run: pip install dnslib - name: Run sealed-mode smoke run: sudo devops/airgap/sealed-ci-smoke.sh + diff --git a/.gitea/workflows/aoc-backfill-release.yml b/.gitea/workflows/aoc-backfill-release.yml index 060011985..0359c4a30 100644 --- a/.gitea/workflows/aoc-backfill-release.yml +++ b/.gitea/workflows/aoc-backfill-release.yml @@ -14,7 +14,7 @@ on: jobs: package-backfill: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: COSIGN_PRIVATE_KEY_B64: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} @@ -81,3 +81,4 @@ jobs: out/aoc/SHA256SUMS if-no-files-found: warn retention-days: 30 + diff --git a/.gitea/workflows/aoc-guard.yml b/.gitea/workflows/aoc-guard.yml index 87d7f0de6..2fa68e4e4 100644 --- a/.gitea/workflows/aoc-guard.yml +++ b/.gitea/workflows/aoc-guard.yml @@ -22,7 +22,7 @@ on: jobs: aoc-guard: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' ARTIFACT_DIR: ${{ github.workspace }}/.artifacts @@ -100,7 +100,7 @@ jobs: aoc-verify: needs: aoc-guard - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event_name != 'schedule' env: DOTNET_VERSION: '10.0.100' @@ -168,3 +168,4 @@ jobs: with: name: aoc-verify-artifacts path: ${{ env.ARTIFACT_DIR }} + diff --git a/.gitea/workflows/authority-key-rotation.yml b/.gitea/workflows/authority-key-rotation.yml index 46ec6b15f..2fe189ca3 100644 --- a/.gitea/workflows/authority-key-rotation.yml +++ b/.gitea/workflows/authority-key-rotation.yml @@ -50,7 +50,7 @@ on: jobs: rotate: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: ${{ inputs.environment }} steps: - name: Checkout repository @@ -164,3 +164,4 @@ jobs: echo "Key Path: ${{ inputs.key_path }}" echo "Source: ${{ inputs.source }}" echo "Algorithm: ${{ inputs.algorithm }}" + diff --git a/.gitea/workflows/build-test-deploy.yml b/.gitea/workflows/build-test-deploy.yml index 26e75d05a..bbdf1dd87 100644 --- a/.gitea/workflows/build-test-deploy.yml +++ b/.gitea/workflows/build-test-deploy.yml @@ -55,7 +55,7 @@ env: jobs: profile-validation: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout repository uses: actions/checkout@v4 @@ -82,7 +82,7 @@ jobs: run: ./devops/tools/validate-profiles.sh build-test: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: ${{ github.event_name == 'pull_request' && 'preview' || 'staging' }} env: PUBLISH_DIR: ${{ github.workspace }}/artifacts/publish/webservice @@ -590,7 +590,7 @@ PY # Quality Gates Foundation (Sprint 0350) # ============================================================================ quality-gates: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test permissions: contents: read @@ -674,7 +674,7 @@ PY retention-days: 14 security-testing: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test if: github.event_name == 'pull_request' || github.event_name == 'schedule' permissions: @@ -717,7 +717,7 @@ PY retention-days: 30 mutation-testing: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test if: github.event_name == 'schedule' || (github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'mutation-test')) permissions: @@ -790,7 +790,7 @@ PY fi sealed-mode-ci: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test permissions: contents: read @@ -828,7 +828,7 @@ PY retention-days: 14 authority-container: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test steps: - name: Checkout repository @@ -843,7 +843,7 @@ PY excititor-batch-validation: needs: build-test if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.excititor_batch == 'true') - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: BATCH_RESULTS_DIR: ${{ github.workspace }}/artifacts/test-results/excititor-batch steps: @@ -876,7 +876,7 @@ PY path: ${{ env.BATCH_RESULTS_DIR }} docs: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOCS_OUTPUT_DIR: ${{ github.workspace }}/artifacts/docs-site steps: @@ -906,7 +906,7 @@ PY retention-days: 7 scanner-perf: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test env: BENCH_DIR: src/Bench/StellaOps.Bench/Scanner.Analyzers @@ -987,7 +987,7 @@ PY retention-days: 7 deploy: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [build-test, docs, scanner-perf] if: >- needs.build-test.result == 'success' && @@ -1160,7 +1160,7 @@ PY echo " Ref: ${{ github.ref }}" notify-smoke: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: deploy if: needs.deploy.result == 'success' env: @@ -1202,3 +1202,4 @@ PY - name: Run Notify smoke validation run: dotnet run --project tools/NotifySmokeCheck/NotifySmokeCheck.csproj --configuration Release + diff --git a/.gitea/workflows/concelier-store-aoc-19-005.yml b/.gitea/workflows/concelier-store-aoc-19-005.yml index e814600a7..99db0ccb0 100644 --- a/.gitea/workflows/concelier-store-aoc-19-005.yml +++ b/.gitea/workflows/concelier-store-aoc-19-005.yml @@ -5,7 +5,7 @@ on: jobs: build-dataset: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: ARTIFACT_DIR: ${{ github.workspace }}/out/linksets steps: @@ -30,3 +30,4 @@ jobs: path: | ${ARTIFACT_DIR}/linksets-stage-backfill.tar.zst ${ARTIFACT_DIR}/linksets-stage-backfill.tar.zst.sha256 + diff --git a/.gitea/workflows/connector-fixture-drift.yml b/.gitea/workflows/connector-fixture-drift.yml index 197da1c63..725077530 100644 --- a/.gitea/workflows/connector-fixture-drift.yml +++ b/.gitea/workflows/connector-fixture-drift.yml @@ -32,7 +32,7 @@ env: jobs: detect-drift: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: write pull-requests: write @@ -124,7 +124,7 @@ jobs: create-pr: needs: detect-drift if: needs.detect-drift.outputs.has_drift == 'true' && (github.event.inputs.create_pr == 'true' || github.event_name == 'schedule') - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: write pull-requests: write @@ -245,3 +245,4 @@ This commit was auto-generated by the connector-fixture-drift workflow. issue_number: pr.number, labels: ['automated', 'fixtures', 'schema-drift'] }); + diff --git a/.gitea/workflows/crypto-compliance.yml b/.gitea/workflows/crypto-compliance.yml index 7b5ac05b4..706712d2d 100644 --- a/.gitea/workflows/crypto-compliance.yml +++ b/.gitea/workflows/crypto-compliance.yml @@ -17,7 +17,7 @@ on: jobs: crypto-audit: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -42,3 +42,4 @@ jobs: path: | scripts/audit-crypto-usage.ps1 retention-days: 30 + diff --git a/.gitea/workflows/dead-path-detection.yml b/.gitea/workflows/dead-path-detection.yml index 1448c3532..3d6d12000 100644 --- a/.gitea/workflows/dead-path-detection.yml +++ b/.gitea/workflows/dead-path-detection.yml @@ -49,7 +49,7 @@ jobs: detect: name: Detect Dead Paths - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: has-new-dead-paths: ${{ steps.check.outputs.has_new_dead_paths }} new-dead-path-count: ${{ steps.check.outputs.new_count }} @@ -354,7 +354,7 @@ jobs: name: Post Report needs: detect if: github.event_name == 'pull_request' && always() - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: pull-requests: write steps: @@ -436,3 +436,4 @@ jobs: body: body }); } + diff --git a/.gitea/workflows/deploy-keyless-verify.yml b/.gitea/workflows/deploy-keyless-verify.yml index cbbe9d1c3..6f1ba77a8 100644 --- a/.gitea/workflows/deploy-keyless-verify.yml +++ b/.gitea/workflows/deploy-keyless-verify.yml @@ -38,7 +38,7 @@ env: jobs: pre-flight: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: identity-pattern: ${{ steps.config.outputs.identity-pattern }} @@ -61,7 +61,7 @@ jobs: verify-attestations: needs: pre-flight - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read @@ -123,7 +123,7 @@ jobs: verify-provenance: needs: pre-flight - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read @@ -160,7 +160,7 @@ jobs: create-audit-entry: needs: [verify-attestations, verify-provenance] - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Install StellaOps CLI @@ -183,7 +183,7 @@ jobs: approve-deployment: needs: [verify-attestations, verify-provenance, create-audit-entry] - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: ${{ github.event.inputs.environment }} steps: @@ -202,3 +202,4 @@ jobs: Deployment can now proceed. EOF + diff --git a/.gitea/workflows/determinism-gate.yml b/.gitea/workflows/determinism-gate.yml index 1b26e64af..de33aef20 100644 --- a/.gitea/workflows/determinism-gate.yml +++ b/.gitea/workflows/determinism-gate.yml @@ -48,7 +48,7 @@ jobs: # =========================================================================== schema-validation: name: Schema Validation - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event.inputs.skip_schema_validation != 'true' timeout-minutes: 10 @@ -128,7 +128,7 @@ jobs: needs: [schema-validation] if: always() && (needs.schema-validation.result == 'success' || needs.schema-validation.result == 'skipped') name: Determinism Validation - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 outputs: @@ -243,7 +243,7 @@ jobs: # =========================================================================== update-baselines: name: Update Baselines - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [schema-validation, determinism-gate] if: github.event_name == 'workflow_dispatch' && github.event.inputs.update_baselines == 'true' @@ -293,7 +293,7 @@ jobs: # =========================================================================== drift-check: name: Drift Detection Gate - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [schema-validation, determinism-gate] if: always() @@ -328,3 +328,4 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "Schema Validation: ${{ needs.schema-validation.result || 'skipped' }}" >> $GITHUB_STEP_SUMMARY echo "Determinism Status: ${{ needs.determinism-gate.outputs.status || 'pass' }}" >> $GITHUB_STEP_SUMMARY + diff --git a/.gitea/workflows/docs.yml b/.gitea/workflows/docs.yml index 22c47e94d..674c72769 100755 --- a/.gitea/workflows/docs.yml +++ b/.gitea/workflows/docs.yml @@ -22,7 +22,7 @@ env: jobs: lint-and-preview: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOCS_OUTPUT_DIR: ${{ github.workspace }}/artifacts/docs-preview steps: @@ -99,3 +99,4 @@ jobs: name: feedser-docs-preview path: ${{ env.DOCS_OUTPUT_DIR }} retention-days: 7 + diff --git a/.gitea/workflows/epss-ingest-perf.yml b/.gitea/workflows/epss-ingest-perf.yml index c03655957..7d77fec2f 100644 --- a/.gitea/workflows/epss-ingest-perf.yml +++ b/.gitea/workflows/epss-ingest-perf.yml @@ -40,7 +40,7 @@ on: jobs: perf: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -96,3 +96,4 @@ jobs: path: | bench/results/epss-ingest-perf-${{ github.sha }}.json retention-days: 90 + diff --git a/.gitea/workflows/export-ci.yml b/.gitea/workflows/export-ci.yml index 64fa806d5..d858eb73b 100644 --- a/.gitea/workflows/export-ci.yml +++ b/.gitea/workflows/export-ci.yml @@ -18,7 +18,7 @@ on: jobs: export-ci: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' MINIO_ACCESS_KEY: exportci @@ -83,3 +83,4 @@ jobs: - name: Teardown MinIO if: always() run: docker compose -f devops/export/minio-compose.yml down -v + diff --git a/.gitea/workflows/findings-ledger-ci.yml b/.gitea/workflows/findings-ledger-ci.yml index 8b8940846..109b5d849 100644 --- a/.gitea/workflows/findings-ledger-ci.yml +++ b/.gitea/workflows/findings-ledger-ci.yml @@ -26,7 +26,7 @@ env: jobs: build-test: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: TEST_RESULTS_DIR: ${{ github.workspace }}/artifacts/test-results steps: @@ -68,7 +68,7 @@ jobs: path: ${{ env.TEST_RESULTS_DIR }} migration-validation: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} services: postgres: image: postgres:16-alpine @@ -228,7 +228,7 @@ jobs: echo "✓ Migration is idempotent" generate-manifest: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [build-test, migration-validation] steps: - name: Checkout repository @@ -323,3 +323,4 @@ jobs: name: findings-ledger-migrations path: out/findings-ledger/ if-no-files-found: error + diff --git a/.gitea/workflows/icscisa-kisa-refresh.yml b/.gitea/workflows/icscisa-kisa-refresh.yml index a5a2a8f25..0c5cab9ae 100644 --- a/.gitea/workflows/icscisa-kisa-refresh.yml +++ b/.gitea/workflows/icscisa-kisa-refresh.yml @@ -18,7 +18,7 @@ on: jobs: refresh: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read env: @@ -66,3 +66,4 @@ jobs: path: out/feeds/icscisa-kisa/${{ steps.meta.outputs.run_date }} if-no-files-found: error retention-days: 21 + diff --git a/.gitea/workflows/interop-e2e.yml b/.gitea/workflows/interop-e2e.yml index e81d9906e..c2aa3fb91 100644 --- a/.gitea/workflows/interop-e2e.yml +++ b/.gitea/workflows/interop-e2e.yml @@ -15,7 +15,7 @@ env: jobs: interop-tests: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} strategy: fail-fast: false matrix: @@ -96,7 +96,7 @@ jobs: fi summary: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: interop-tests if: always() @@ -126,3 +126,4 @@ jobs: fi echo "| ${format} | ${STATUS} |" >> $GITHUB_STEP_SUMMARY done + diff --git a/.gitea/workflows/ledger-oas-ci.yml b/.gitea/workflows/ledger-oas-ci.yml index 6cef5c7fa..9daefb7cf 100644 --- a/.gitea/workflows/ledger-oas-ci.yml +++ b/.gitea/workflows/ledger-oas-ci.yml @@ -13,7 +13,7 @@ on: jobs: validate-oas: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -44,7 +44,7 @@ jobs: if-no-files-found: warn check-wellknown: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: validate-oas steps: - name: Checkout @@ -64,7 +64,7 @@ jobs: fi deprecation-check: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: validate-oas steps: - name: Checkout @@ -79,3 +79,4 @@ jobs: else echo "[info] No deprecation policy yet (OK for initial setup)" fi + diff --git a/.gitea/workflows/ledger-packs-ci.yml b/.gitea/workflows/ledger-packs-ci.yml index ee83fc19b..ee47eff53 100644 --- a/.gitea/workflows/ledger-packs-ci.yml +++ b/.gitea/workflows/ledger-packs-ci.yml @@ -18,7 +18,7 @@ on: jobs: build-pack: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: COSIGN_PRIVATE_KEY_B64: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }} steps: @@ -71,7 +71,7 @@ jobs: retention-days: 30 verify-pack: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-pack steps: - name: Checkout @@ -99,3 +99,4 @@ jobs: fi fi done + diff --git a/.gitea/workflows/license-audit.yml b/.gitea/workflows/license-audit.yml index d4e5f1e49..295944ab2 100644 --- a/.gitea/workflows/license-audit.yml +++ b/.gitea/workflows/license-audit.yml @@ -35,7 +35,7 @@ on: jobs: nuget-license-audit: name: NuGet License Audit - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -94,7 +94,7 @@ jobs: npm-license-audit: name: npm License Audit - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -142,7 +142,7 @@ jobs: vendored-license-check: name: Vendored Components Check - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -207,7 +207,7 @@ jobs: license-compatibility-check: name: License Compatibility Check - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [nuget-license-audit, npm-license-audit] steps: - name: Checkout @@ -297,3 +297,4 @@ jobs: name: license-audit-summary path: out/combined retention-days: 90 + diff --git a/.gitea/workflows/lighthouse-ci.yml b/.gitea/workflows/lighthouse-ci.yml index 223528d4c..4eeb57ea1 100644 --- a/.gitea/workflows/lighthouse-ci.yml +++ b/.gitea/workflows/lighthouse-ci.yml @@ -26,7 +26,7 @@ env: jobs: lighthouse: name: Lighthouse Audit - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} defaults: run: working-directory: src/Web/StellaOps.Web @@ -145,7 +145,7 @@ jobs: axe-accessibility: name: Axe Accessibility Audit - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} defaults: run: working-directory: src/Web/StellaOps.Web @@ -186,3 +186,4 @@ jobs: name: axe-accessibility-results path: src/Web/StellaOps.Web/test-results/ retention-days: 30 + diff --git a/.gitea/workflows/lnm-backfill.yml b/.gitea/workflows/lnm-backfill.yml index fdc507dde..4da80f423 100644 --- a/.gitea/workflows/lnm-backfill.yml +++ b/.gitea/workflows/lnm-backfill.yml @@ -19,7 +19,7 @@ on: jobs: lnm-backfill: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' ARTIFACT_DIR: ${{ github.workspace }}/.artifacts @@ -62,3 +62,4 @@ jobs: with: name: lnm-backfill-artifacts path: ${{ env.ARTIFACT_DIR }} + diff --git a/.gitea/workflows/lnm-migration-ci.yml b/.gitea/workflows/lnm-migration-ci.yml index 43878735e..cd21a2568 100644 --- a/.gitea/workflows/lnm-migration-ci.yml +++ b/.gitea/workflows/lnm-migration-ci.yml @@ -15,7 +15,7 @@ on: jobs: build-runner: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -60,7 +60,7 @@ jobs: if-no-files-found: warn validate-metrics: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-runner steps: - name: Checkout @@ -81,3 +81,4 @@ jobs: fi echo "Monitoring config validation complete" + diff --git a/.gitea/workflows/lnm-vex-backfill.yml b/.gitea/workflows/lnm-vex-backfill.yml index fb0b0af8d..ac6cf0011 100644 --- a/.gitea/workflows/lnm-vex-backfill.yml +++ b/.gitea/workflows/lnm-vex-backfill.yml @@ -23,7 +23,7 @@ on: jobs: vex-backfill: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' ARTIFACT_DIR: ${{ github.workspace }}/.artifacts @@ -61,3 +61,4 @@ jobs: with: name: lnm-vex-backfill-artifacts path: ${{ env.ARTIFACT_DIR }} + diff --git a/.gitea/workflows/migration-test.yml b/.gitea/workflows/migration-test.yml index e9a68070a..a6aa10f07 100644 --- a/.gitea/workflows/migration-test.yml +++ b/.gitea/workflows/migration-test.yml @@ -69,7 +69,7 @@ jobs: discover: name: Discover Migrations - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: modules: ${{ steps.find.outputs.modules }} module_count: ${{ steps.find.outputs.count }} @@ -119,7 +119,7 @@ jobs: forward-migrations: name: Forward Migration - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 needs: discover if: needs.discover.outputs.module_count != '0' @@ -246,7 +246,7 @@ jobs: rollback-migrations: name: Rollback Migration - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 needs: [discover, forward-migrations] if: | @@ -371,7 +371,7 @@ jobs: idempotency: name: Idempotency Test - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 20 needs: [discover, forward-migrations] if: | @@ -490,7 +490,7 @@ jobs: summary: name: Migration Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [discover, forward-migrations, rollback-migrations, idempotency] if: always() steps: @@ -510,3 +510,4 @@ jobs: - name: Check for failures if: contains(needs.*.result, 'failure') run: exit 1 + diff --git a/.gitea/workflows/mirror-sign.yml b/.gitea/workflows/mirror-sign.yml index bae11f92f..fb408af4c 100644 --- a/.gitea/workflows/mirror-sign.yml +++ b/.gitea/workflows/mirror-sign.yml @@ -7,7 +7,7 @@ on: jobs: mirror-sign: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: MIRROR_SIGN_KEY_B64: ${{ secrets.MIRROR_SIGN_KEY_B64 }} REQUIRE_PROD_SIGNING: 1 @@ -72,3 +72,4 @@ jobs: out/mirror/thin/export-center/schedule-response.json if-no-files-found: error retention-days: 14 + diff --git a/.gitea/workflows/module-publish.yml b/.gitea/workflows/module-publish.yml index 80d759350..8b6cfc3e2 100644 --- a/.gitea/workflows/module-publish.yml +++ b/.gitea/workflows/module-publish.yml @@ -59,7 +59,7 @@ jobs: parse-tag: name: Parse Tag - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event_name == 'push' outputs: module: ${{ steps.parse.outputs.module }} @@ -90,7 +90,7 @@ jobs: validate: name: Validate Inputs - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [parse-tag] if: always() && (needs.parse-tag.result == 'success' || needs.parse-tag.result == 'skipped') outputs: @@ -139,7 +139,7 @@ jobs: publish-nuget: name: Publish NuGet - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] if: needs.validate.outputs.publish_nuget == 'true' steps: @@ -251,7 +251,7 @@ jobs: publish-container: name: Publish Container - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] if: needs.validate.outputs.publish_container == 'true' && needs.validate.outputs.module != 'CLI' steps: @@ -310,7 +310,7 @@ jobs: publish-cli: name: Publish CLI (${{ matrix.runtime }}) - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] if: needs.validate.outputs.module == 'CLI' strategy: @@ -378,7 +378,7 @@ jobs: summary: name: Publish Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, publish-nuget, publish-container, publish-cli] if: always() steps: @@ -403,3 +403,4 @@ jobs: run: | echo "::error::One or more publish jobs failed" exit 1 + diff --git a/.gitea/workflows/nightly-regression.yml b/.gitea/workflows/nightly-regression.yml index 7c4603c16..8456c3120 100644 --- a/.gitea/workflows/nightly-regression.yml +++ b/.gitea/workflows/nightly-regression.yml @@ -47,7 +47,7 @@ jobs: prepare: name: Prepare Nightly Run - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: run_id: ${{ steps.metadata.outputs.run_id }} run_date: ${{ steps.metadata.outputs.run_date }} @@ -88,7 +88,7 @@ jobs: build: name: Full Build - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 needs: prepare steps: @@ -126,7 +126,7 @@ jobs: test-pr-gating: name: PR-Gating Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 45 needs: build services: @@ -184,7 +184,7 @@ jobs: test-extended: name: Extended Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 60 needs: build if: github.event.inputs.skip_performance != 'true' @@ -227,7 +227,7 @@ jobs: determinism: name: Determinism Verification - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 45 needs: build if: github.event.inputs.skip_determinism != 'true' @@ -289,7 +289,7 @@ jobs: cross-module: name: Cross-Module Validation - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 needs: build steps: @@ -341,7 +341,7 @@ jobs: coverage: name: Code Coverage - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 45 needs: build services: @@ -415,7 +415,7 @@ jobs: summary: name: Nightly Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: - prepare - build @@ -483,3 +483,4 @@ jobs: - name: Exit with appropriate code if: steps.status.outputs.status == 'failure' run: exit 1 + diff --git a/.gitea/workflows/offline-e2e.yml b/.gitea/workflows/offline-e2e.yml index 003c890fe..301f1ca04 100644 --- a/.gitea/workflows/offline-e2e.yml +++ b/.gitea/workflows/offline-e2e.yml @@ -16,7 +16,7 @@ env: jobs: offline-e2e: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout @@ -82,7 +82,7 @@ jobs: path: ./results/ verify-isolation: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: offline-e2e if: always() @@ -119,3 +119,4 @@ jobs: else echo "⚠️ No test results found" >> $GITHUB_STEP_SUMMARY fi + diff --git a/.gitea/workflows/policy-lint.yml b/.gitea/workflows/policy-lint.yml index 531cc36c0..34715d383 100644 --- a/.gitea/workflows/policy-lint.yml +++ b/.gitea/workflows/policy-lint.yml @@ -17,7 +17,7 @@ on: jobs: policy-lint: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -68,3 +68,4 @@ jobs: name: policy-lint path: out/policy-lint retention-days: 7 + diff --git a/.gitea/workflows/policy-simulate.yml b/.gitea/workflows/policy-simulate.yml index 624f70a96..cd9fd1b21 100644 --- a/.gitea/workflows/policy-simulate.yml +++ b/.gitea/workflows/policy-simulate.yml @@ -17,7 +17,7 @@ on: jobs: policy-simulate: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -87,3 +87,4 @@ jobs: name: policy-signing path: out/policy-sign retention-days: 7 + diff --git a/.gitea/workflows/promote.yml b/.gitea/workflows/promote.yml index 8a1c327e6..96dd44482 100644 --- a/.gitea/workflows/promote.yml +++ b/.gitea/workflows/promote.yml @@ -19,7 +19,7 @@ on: jobs: promote: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: production steps: - name: Checkout repository @@ -207,3 +207,4 @@ jobs: else echo " Docs: skipped" fi + diff --git a/.gitea/workflows/reachability-bench.yaml b/.gitea/workflows/reachability-bench.yaml index 84b65d56b..161f7a086 100644 --- a/.gitea/workflows/reachability-bench.yaml +++ b/.gitea/workflows/reachability-bench.yaml @@ -34,7 +34,7 @@ on: jobs: benchmark: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -242,7 +242,7 @@ jobs: update-baseline: needs: benchmark if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.benchmark.outputs.regression != 'true' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Checkout uses: actions/checkout@v4 @@ -263,7 +263,7 @@ jobs: notify-pr: needs: benchmark if: github.event_name == 'pull_request' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: pull-requests: write steps: @@ -304,3 +304,4 @@ jobs: repo: context.repo.repo, body: body }); + diff --git a/.gitea/workflows/reachability-corpus-ci.yml b/.gitea/workflows/reachability-corpus-ci.yml index d10ea232e..58bcb4de4 100644 --- a/.gitea/workflows/reachability-corpus-ci.yml +++ b/.gitea/workflows/reachability-corpus-ci.yml @@ -20,7 +20,7 @@ on: jobs: validate-corpus: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -136,7 +136,7 @@ jobs: retention-days: 14 validate-ground-truths: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: TZ: UTC steps: @@ -205,7 +205,7 @@ jobs: EOF determinism-check: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: TZ: UTC needs: validate-corpus @@ -265,3 +265,4 @@ jobs: print(f"Checked {len(json_files)} JSON files") EOF + diff --git a/.gitea/workflows/release-keyless-sign.yml b/.gitea/workflows/release-keyless-sign.yml index 1892b1a3b..71c302b76 100644 --- a/.gitea/workflows/release-keyless-sign.yml +++ b/.gitea/workflows/release-keyless-sign.yml @@ -37,7 +37,7 @@ env: jobs: sign-images: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: id-token: write contents: read @@ -170,7 +170,7 @@ jobs: --registry "stellaops/gateway" sign-binaries: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: id-token: write contents: read @@ -329,7 +329,7 @@ jobs: verify-signatures: needs: [sign-images, sign-binaries] - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read packages: read @@ -397,3 +397,4 @@ jobs: --certificate-oidc-issuer "https://git.stella-ops.org" \`\`\` EOF + diff --git a/.gitea/workflows/release-suite.yml b/.gitea/workflows/release-suite.yml index c25897b77..faf4fe2e5 100644 --- a/.gitea/workflows/release-suite.yml +++ b/.gitea/workflows/release-suite.yml @@ -50,7 +50,7 @@ jobs: parse-tag: name: Parse Tag - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event_name == 'push' outputs: version: ${{ steps.parse.outputs.version }} @@ -89,7 +89,7 @@ jobs: validate: name: Validate Release - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [parse-tag] if: always() && (needs.parse-tag.result == 'success' || needs.parse-tag.result == 'skipped') outputs: @@ -150,7 +150,7 @@ jobs: test-gate: name: Test Gate - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] if: github.event.inputs.skip_tests != 'true' steps: @@ -192,7 +192,7 @@ jobs: build-modules: name: Build ${{ matrix.module }} - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, test-gate] if: always() && needs.validate.result == 'success' && (needs.test-gate.result == 'success' || needs.test-gate.result == 'skipped') strategy: @@ -293,7 +293,7 @@ jobs: build-containers: name: Container ${{ matrix.module }} - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-modules] if: needs.validate.outputs.dry_run != 'true' strategy: @@ -351,7 +351,7 @@ jobs: build-cli: name: CLI (${{ matrix.runtime }}) - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, test-gate] if: always() && needs.validate.result == 'success' && (needs.test-gate.result == 'success' || needs.test-gate.result == 'skipped') strategy: @@ -421,7 +421,7 @@ jobs: build-helm: name: Helm Chart - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] steps: - name: Checkout @@ -459,7 +459,7 @@ jobs: release-manifest: name: Release Manifest - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-modules, build-cli, build-helm] if: always() && needs.validate.result == 'success' steps: @@ -538,7 +538,7 @@ jobs: generate-changelog: name: Generate Changelog - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-modules] if: always() && needs.validate.result == 'success' steps: @@ -595,7 +595,7 @@ jobs: generate-suite-docs: name: Generate Suite Docs - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, generate-changelog, release-manifest] if: always() && needs.validate.result == 'success' steps: @@ -658,7 +658,7 @@ jobs: generate-compose: name: Generate Docker Compose - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, release-manifest] if: always() && needs.validate.result == 'success' steps: @@ -704,7 +704,7 @@ jobs: commit-docs: name: Commit Documentation - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, generate-suite-docs, generate-compose, create-release] if: needs.validate.outputs.dry_run != 'true' && needs.create-release.result == 'success' steps: @@ -765,7 +765,7 @@ jobs: create-release: name: Create Gitea Release - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-modules, build-containers, build-cli, build-helm, release-manifest] if: needs.validate.outputs.dry_run != 'true' steps: @@ -877,7 +877,7 @@ jobs: summary: name: Release Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-modules, build-containers, build-cli, build-helm, release-manifest, generate-changelog, generate-suite-docs, generate-compose, create-release, commit-docs] if: always() steps: @@ -912,3 +912,4 @@ jobs: run: | echo "::error::One or more release jobs failed" exit 1 + diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index bcd46d666..d1af176f0 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -34,7 +34,7 @@ on: jobs: build-release: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' REGISTRY: registry.stella-ops.org @@ -249,3 +249,4 @@ jobs: name: stellaops-debug-${{ steps.meta.outputs.version }} path: out/release/debug if-no-files-found: error + diff --git a/.gitea/workflows/replay-verification.yml b/.gitea/workflows/replay-verification.yml index 60fcecfd2..f0e59627b 100644 --- a/.gitea/workflows/replay-verification.yml +++ b/.gitea/workflows/replay-verification.yml @@ -1,4 +1,4 @@ -name: Replay Verification +name: Replay Verification on: pull_request: @@ -11,7 +11,7 @@ on: jobs: replay-verification: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - uses: actions/checkout@v4 @@ -37,3 +37,4 @@ jobs: with: name: replay-diff-report path: results/diff-report.json + diff --git a/.gitea/workflows/risk-bundle-ci.yml b/.gitea/workflows/risk-bundle-ci.yml index 97ca9802d..1a75e7b21 100644 --- a/.gitea/workflows/risk-bundle-ci.yml +++ b/.gitea/workflows/risk-bundle-ci.yml @@ -30,7 +30,7 @@ on: jobs: risk-bundle-build: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_VERSION: '10.0.100' ARTIFACT_DIR: ${{ github.workspace }}/.artifacts @@ -101,7 +101,7 @@ jobs: path: ${{ env.ARTIFACT_DIR }}/*.trx risk-bundle-offline-kit: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: risk-bundle-build env: ARTIFACT_DIR: ${{ github.workspace }}/.artifacts @@ -156,7 +156,7 @@ jobs: path: ${{ env.OFFLINE_KIT_DIR }} publish-checksums: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: risk-bundle-build if: github.ref == 'refs/heads/main' && (github.event_name == 'push' || github.event.inputs.publish_checksums == 'true') env: @@ -196,3 +196,4 @@ jobs: with: name: risk-bundle-published-checksums path: out/checksums/risk-bundle/ + diff --git a/.gitea/workflows/rollback-lag.yml b/.gitea/workflows/rollback-lag.yml index 862941cf6..05debb184 100644 --- a/.gitea/workflows/rollback-lag.yml +++ b/.gitea/workflows/rollback-lag.yml @@ -60,7 +60,7 @@ jobs: preflight: name: Pre-Flight Checks - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: ${{ inputs.environment || 'staging' }} outputs: current-version: ${{ steps.current.outputs.version }} @@ -173,7 +173,7 @@ jobs: name: Measure Rollback Lag needs: preflight if: needs.preflight.outputs.can-rollback == 'true' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} environment: ${{ inputs.environment || 'staging' }} outputs: rollback-time: ${{ steps.timing.outputs.rollback_time }} @@ -328,7 +328,7 @@ jobs: name: Generate Report needs: [preflight, measure] if: always() && needs.preflight.result == 'success' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Generate Report run: | @@ -401,3 +401,4 @@ jobs: SLO_SECONDS="${{ inputs.rollback_slo_seconds || 300 }}" echo "::error::Rollback took ${TOTAL_LAG}s, exceeds SLO of ${SLO_SECONDS}s" exit 1 + diff --git a/.gitea/workflows/router-chaos.yml b/.gitea/workflows/router-chaos.yml index 6c7af0ed5..69e9d5ea3 100644 --- a/.gitea/workflows/router-chaos.yml +++ b/.gitea/workflows/router-chaos.yml @@ -33,7 +33,7 @@ env: jobs: load-tests: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 services: @@ -139,7 +139,7 @@ jobs: fi chaos-unit-tests: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 20 needs: load-tests if: always() @@ -198,7 +198,7 @@ jobs: retention-days: 30 valkey-failure-tests: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 20 needs: load-tests if: ${{ github.event.inputs.run_valkey_tests != 'false' }} @@ -235,7 +235,7 @@ jobs: path: results/ analyze-results: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [load-tests, chaos-unit-tests] if: always() @@ -304,3 +304,4 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "### Thresholds" >> $GITHUB_STEP_SUMMARY echo "- Status: ${{ steps.analysis.outputs.thresholds_passed == 'true' && 'PASSED' || 'FAILED' }}" >> $GITHUB_STEP_SUMMARY + diff --git a/.gitea/workflows/sast-scan.yml b/.gitea/workflows/sast-scan.yml index 7f44b8cd4..f7a707f86 100644 --- a/.gitea/workflows/sast-scan.yml +++ b/.gitea/workflows/sast-scan.yml @@ -74,7 +74,7 @@ jobs: sast-scan: name: SAST Analysis - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 permissions: security-events: write @@ -197,7 +197,7 @@ jobs: dotnet-security: name: .NET Security Analysis - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 20 steps: - name: Checkout @@ -257,7 +257,7 @@ jobs: dependency-check: name: Dependency Vulnerabilities - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 15 steps: - name: Checkout @@ -308,7 +308,7 @@ jobs: dockerfile-lint: name: Dockerfile Security - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 10 steps: - name: Checkout @@ -362,7 +362,7 @@ jobs: summary: name: SAST Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [sast-scan, dotnet-security, dependency-check, dockerfile-lint] if: always() steps: @@ -384,3 +384,4 @@ jobs: needs.dotnet-security.result == 'failure' || needs.dependency-check.result == 'failure') run: exit 1 + diff --git a/.gitea/workflows/schema-evolution.yml b/.gitea/workflows/schema-evolution.yml index 4098430f7..6cbdab5b1 100644 --- a/.gitea/workflows/schema-evolution.yml +++ b/.gitea/workflows/schema-evolution.yml @@ -53,7 +53,7 @@ jobs: discover: name: Discover Changed Modules - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: modules: ${{ steps.detect.outputs.modules }} has-schema-changes: ${{ steps.detect.outputs.has_changes }} @@ -126,7 +126,7 @@ jobs: name: Test ${{ matrix.module }} (Schema ${{ matrix.schema-version }}) needs: discover if: needs.discover.outputs.has-schema-changes == 'true' || github.event_name == 'workflow_dispatch' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} strategy: fail-fast: false matrix: @@ -275,7 +275,7 @@ jobs: name: Generate Compatibility Report needs: [discover, test] if: always() && needs.discover.outputs.has-schema-changes == 'true' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Download All Results uses: actions/download-artifact@v4 @@ -337,7 +337,7 @@ jobs: name: Post Report to PR needs: [discover, test, report] if: github.event_name == 'pull_request' && always() - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: pull-requests: write steps: @@ -416,3 +416,4 @@ jobs: body: body }); } + diff --git a/.gitea/workflows/sdk-publish.yml b/.gitea/workflows/sdk-publish.yml index 62bbf0079..13e67eb7c 100644 --- a/.gitea/workflows/sdk-publish.yml +++ b/.gitea/workflows/sdk-publish.yml @@ -17,7 +17,7 @@ on: jobs: sdk-publish: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -89,3 +89,4 @@ jobs: .nuget/packages/*.nupkg if-no-files-found: warn retention-days: 7 + diff --git a/.gitea/workflows/secrets-bundle-release.yml b/.gitea/workflows/secrets-bundle-release.yml index 1517699f4..5093b071b 100644 --- a/.gitea/workflows/secrets-bundle-release.yml +++ b/.gitea/workflows/secrets-bundle-release.yml @@ -47,7 +47,7 @@ jobs: validate: name: Validate Inputs - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: version: ${{ steps.resolve.outputs.version }} sign_bundle: ${{ steps.resolve.outputs.sign_bundle }} @@ -95,7 +95,7 @@ jobs: build-bundle: name: Build Secrets Bundle - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate] steps: - name: Checkout @@ -201,7 +201,7 @@ jobs: sign-bundle: name: Sign Secrets Bundle - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-bundle] if: needs.validate.outputs.sign_bundle == 'true' steps: @@ -305,7 +305,7 @@ jobs: package-offline-kit: name: Package for Offline Kit - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-bundle, sign-bundle] if: always() && needs.build-bundle.result == 'success' && needs.validate.outputs.include_in_kit == 'true' steps: @@ -357,7 +357,7 @@ jobs: publish: name: Publish Bundle - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, sign-bundle, package-offline-kit] if: needs.validate.outputs.dry_run != 'true' && needs.sign-bundle.result == 'success' steps: @@ -478,7 +478,7 @@ jobs: summary: name: Build Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [validate, build-bundle, sign-bundle, package-offline-kit, publish] if: always() steps: @@ -501,3 +501,4 @@ jobs: echo "| Sign Bundle | ${{ needs.sign-bundle.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY echo "| Package Offline Kit | ${{ needs.package-offline-kit.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY echo "| Publish | ${{ needs.publish.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY + diff --git a/.gitea/workflows/signals-ci.yml b/.gitea/workflows/signals-ci.yml index c9a546389..7a99448fe 100644 --- a/.gitea/workflows/signals-ci.yml +++ b/.gitea/workflows/signals-ci.yml @@ -19,7 +19,7 @@ on: jobs: signals-ci: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -73,3 +73,4 @@ jobs: out/signals out/signals/signals-image.tar retention-days: 7 + diff --git a/.gitea/workflows/signals-dsse-sign.yml b/.gitea/workflows/signals-dsse-sign.yml index 58bf99be4..0a250f940 100644 --- a/.gitea/workflows/signals-dsse-sign.yml +++ b/.gitea/workflows/signals-dsse-sign.yml @@ -22,7 +22,7 @@ on: jobs: sign-signals-artifacts: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: COSIGN_PRIVATE_KEY_B64: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }} COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }} @@ -120,7 +120,7 @@ jobs: echo "Artifacts available as workflow artifact for manual ingestion" verify-signatures: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: sign-signals-artifacts steps: - name: Checkout @@ -181,3 +181,4 @@ jobs: done echo "" >> "$GITHUB_STEP_SUMMARY" echo "Run ID: ${{ github.run_number }}" >> "$GITHUB_STEP_SUMMARY" + diff --git a/.gitea/workflows/signals-reachability.yml b/.gitea/workflows/signals-reachability.yml index d33aa6567..02aaedea9 100644 --- a/.gitea/workflows/signals-reachability.yml +++ b/.gitea/workflows/signals-reachability.yml @@ -21,7 +21,7 @@ on: jobs: reachability-smoke: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: DOTNET_NOLOGO: 1 DOTNET_CLI_TELEMETRY_OPTOUT: 1 @@ -54,7 +54,7 @@ jobs: scripts/signals/reachability-smoke.sh sign-and-upload: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: reachability-smoke env: COSIGN_PRIVATE_KEY_B64: ${{ secrets.COSIGN_PRIVATE_KEY_B64 }} @@ -125,3 +125,4 @@ jobs: if: ${{ env.CI_EVIDENCE_LOCKER_TOKEN == '' || env.EVIDENCE_LOCKER_URL == '' }} run: | echo "::notice::Evidence Locker upload skipped (CI_EVIDENCE_LOCKER_TOKEN or EVIDENCE_LOCKER_URL not set)" + diff --git a/.gitea/workflows/symbols-ci.yml b/.gitea/workflows/symbols-ci.yml index 6a3505369..49bfcc0a0 100644 --- a/.gitea/workflows/symbols-ci.yml +++ b/.gitea/workflows/symbols-ci.yml @@ -17,7 +17,7 @@ on: jobs: symbols-smoke: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: ARTIFACT_DIR: ${{ github.workspace }}/artifacts/symbols-ci steps: @@ -45,3 +45,4 @@ jobs: name: symbols-ci path: ${{ env.ARTIFACT_DIR }} retention-days: 7 + diff --git a/.gitea/workflows/symbols-release.yml b/.gitea/workflows/symbols-release.yml index e5b7e497f..686da2bee 100644 --- a/.gitea/workflows/symbols-release.yml +++ b/.gitea/workflows/symbols-release.yml @@ -8,7 +8,7 @@ on: jobs: symbols-release-smoke: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} env: ARTIFACT_DIR: ${{ github.workspace }}/artifacts/symbols-release steps: @@ -39,3 +39,4 @@ jobs: name: symbols-release path: ${{ env.ARTIFACT_DIR }} retention-days: 14 + diff --git a/.gitea/workflows/test-blast-radius.yml b/.gitea/workflows/test-blast-radius.yml index 33613fd60..d2eb56edf 100644 --- a/.gitea/workflows/test-blast-radius.yml +++ b/.gitea/workflows/test-blast-radius.yml @@ -39,7 +39,7 @@ jobs: validate: name: Validate Annotations - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: has-violations: ${{ steps.validate.outputs.has_violations }} violation-count: ${{ steps.validate.outputs.violation_count }} @@ -205,7 +205,7 @@ jobs: name: Post Report needs: validate if: github.event_name == 'pull_request' && needs.validate.outputs.has-violations == 'true' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: pull-requests: write steps: @@ -253,3 +253,4 @@ jobs: issue_number: context.issue.number, body: body }); + diff --git a/.gitea/workflows/test-infrastructure.yml b/.gitea/workflows/test-infrastructure.yml index 069044bd5..f2b2e34ba 100644 --- a/.gitea/workflows/test-infrastructure.yml +++ b/.gitea/workflows/test-infrastructure.yml @@ -45,7 +45,7 @@ jobs: detect-changes: name: Detect Changes - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: has-test-changes: ${{ steps.changes.outputs.tests }} has-schema-changes: ${{ steps.changes.outputs.schema }} @@ -109,7 +109,7 @@ jobs: name: Blast-Radius Validation needs: detect-changes if: needs.detect-changes.outputs.has-test-changes == 'true' || inputs.run_all == true || github.event_name == 'schedule' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: status: ${{ steps.validate.outputs.status }} violations: ${{ steps.validate.outputs.violation_count }} @@ -156,7 +156,7 @@ jobs: name: Dead-Path Detection needs: detect-changes if: needs.detect-changes.outputs.has-code-changes == 'true' || inputs.run_all == true || github.event_name == 'schedule' - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: status: ${{ steps.detect.outputs.status }} new-paths: ${{ steps.detect.outputs.new_paths }} @@ -213,7 +213,7 @@ jobs: name: Schema Evolution Check needs: detect-changes if: needs.detect-changes.outputs.has-schema-changes == 'true' || inputs.run_all == true - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} services: postgres: image: postgres:16-alpine @@ -274,7 +274,7 @@ jobs: name: Config-Diff Check needs: detect-changes if: needs.detect-changes.outputs.has-config-changes == 'true' || inputs.run_all == true - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: status: ${{ steps.test.outputs.status }} tested-configs: ${{ steps.test.outputs.tested }} @@ -319,7 +319,7 @@ jobs: name: Generate Report needs: [detect-changes, blast-radius, dead-paths, schema-evolution, config-diff] if: always() - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} steps: - name: Generate Infrastructure Report run: | @@ -417,7 +417,7 @@ jobs: name: Post PR Comment needs: [report, blast-radius, dead-paths, schema-evolution, config-diff] if: github.event_name == 'pull_request' && always() - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: pull-requests: write steps: @@ -504,3 +504,4 @@ jobs: body: body }); } + diff --git a/.gitea/workflows/test-lanes.yml b/.gitea/workflows/test-lanes.yml index b7e78dd66..aece5f987 100644 --- a/.gitea/workflows/test-lanes.yml +++ b/.gitea/workflows/test-lanes.yml @@ -38,7 +38,7 @@ jobs: # =========================================================================== unit-tests: name: Unit Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 15 steps: - name: Checkout repository @@ -79,7 +79,7 @@ jobs: # =========================================================================== architecture-tests: name: Architecture Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 10 steps: - name: Checkout repository @@ -121,7 +121,7 @@ jobs: # =========================================================================== contract-tests: name: Contract Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 10 steps: - name: Checkout repository @@ -162,7 +162,7 @@ jobs: # =========================================================================== integration-tests: name: Integration Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 30 steps: - name: Checkout repository @@ -205,7 +205,7 @@ jobs: # =========================================================================== security-tests: name: Security Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 20 steps: - name: Checkout repository @@ -246,7 +246,7 @@ jobs: # =========================================================================== performance-tests: name: Performance Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.run_performance == 'true') timeout-minutes: 30 steps: @@ -288,7 +288,7 @@ jobs: # =========================================================================== live-tests: name: Live Tests (External Dependencies) - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} if: github.event_name == 'workflow_dispatch' && github.event.inputs.run_live == 'true' timeout-minutes: 20 steps: @@ -331,7 +331,7 @@ jobs: # =========================================================================== test-summary: name: Test Results Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [unit-tests, architecture-tests, contract-tests, integration-tests, security-tests] if: always() steps: @@ -356,3 +356,4 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY echo "See individual job logs for detailed test output." >> $GITHUB_STEP_SUMMARY + diff --git a/.gitea/workflows/test-matrix.yml b/.gitea/workflows/test-matrix.yml index d79e87dde..7fac02975 100644 --- a/.gitea/workflows/test-matrix.yml +++ b/.gitea/workflows/test-matrix.yml @@ -73,7 +73,7 @@ jobs: discover: name: Discover Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} outputs: test-projects: ${{ steps.find.outputs.projects }} test-count: ${{ steps.find.outputs.count }} @@ -120,7 +120,7 @@ jobs: pr-gating-tests: name: ${{ matrix.category }} Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: ${{ matrix.timeout }} needs: discover strategy: @@ -178,7 +178,7 @@ jobs: integration: name: Integration Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: 45 needs: discover services: @@ -229,7 +229,7 @@ jobs: extended-tests: name: ${{ matrix.category }} Tests - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} timeout-minutes: ${{ matrix.timeout }} needs: discover if: >- @@ -321,7 +321,7 @@ jobs: summary: name: Test Summary - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: [discover, pr-gating-tests, integration] if: always() steps: @@ -372,3 +372,4 @@ jobs: - name: Check for failures if: contains(needs.*.result, 'failure') run: exit 1 + diff --git a/.gitea/workflows/unknowns-budget-gate.yml b/.gitea/workflows/unknowns-budget-gate.yml index cb09f1033..a19806308 100644 --- a/.gitea/workflows/unknowns-budget-gate.yml +++ b/.gitea/workflows/unknowns-budget-gate.yml @@ -29,7 +29,7 @@ env: jobs: scan-and-check-budget: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} permissions: contents: read pull-requests: write @@ -197,3 +197,4 @@ jobs: if: steps.env.outputs.environment != 'prod' && steps.budget.outputs.exit_code == '2' run: | echo "::warning::Unknowns budget exceeded for ${{ steps.env.outputs.environment }}" + diff --git a/docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md b/docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md index 61e1b19f9..02609caf6 100644 --- a/docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md +++ b/docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md @@ -151,21 +151,9 @@ CREATE INDEX idx_hlc_state_updated ON scheduler.hlc_state(updated_at DESC); | 7 | HLC-007 | DONE | HLC-003 | Guild | Add `HlcTimestampTypeHandler` for Npgsql/Dapper | | 8 | HLC-008 | DONE | HLC-005 | Guild | Write unit tests: tick monotonicity, receive merge, clock skew handling | | 9 | HLC-009 | DONE | HLC-008 | Guild | Write integration tests: concurrent ticks, node restart recovery | -<<<<<<< HEAD | 10 | HLC-010 | DONE | HLC-009 | Guild | Write benchmarks: tick throughput, memory allocation | | 11 | HLC-011 | DONE | HLC-010 | Guild | Create `HlcServiceCollectionExtensions` for DI registration | | 12 | HLC-012 | DONE | HLC-011 | Guild | Documentation: README.md, API docs, usage examples | -======= -<<<<<<<< HEAD:docs/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md -| 10 | HLC-010 | TODO | HLC-009 | Guild | Write benchmarks: tick throughput, memory allocation | -| 11 | HLC-011 | DONE | HLC-010 | Guild | Create `HlcServiceCollectionExtensions` for DI registration | -| 12 | HLC-012 | TODO | HLC-011 | Guild | Documentation: README.md, API docs, usage examples | -======== -| 10 | HLC-010 | DONE | HLC-009 | Guild | Write benchmarks: tick throughput, memory allocation | -| 11 | HLC-011 | DONE | HLC-010 | Guild | Create `HlcServiceCollectionExtensions` for DI registration | -| 12 | HLC-012 | DONE | HLC-011 | Guild | Documentation: README.md, API docs, usage examples | ->>>>>>>> 47890273170663b2236a1eb995d218fe5de6b11a:docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md ->>>>>>> 47890273170663b2236a1eb995d218fe5de6b11a ## Implementation Details @@ -347,23 +335,12 @@ hlc_physical_time_offset_seconds{node_id} // Drift from wall clock | Date (UTC) | Update | Owner | |------------|--------|-------| | 2026-01-05 | Sprint created from product advisory gap analysis | Planning | -<<<<<<< HEAD -| 2026-01-05 | HLC-001 to HLC-011 implemented: core library, state stores, JSON/Dapper serializers, DI extensions, 56 unit tests all passing | Agent | -| 2026-01-06 | HLC-010: Created StellaOps.HybridLogicalClock.Benchmarks project with tick throughput, memory allocation, and concurrency benchmarks | Agent | -| 2026-01-06 | HLC-012: Created comprehensive README.md with API reference, usage examples, configuration guide, and algorithm documentation | Agent | -| 2026-01-06 | Sprint COMPLETE: All 12 tasks done, 56 tests passing, benchmarks verified | Agent | -======= -<<<<<<<< HEAD:docs/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md -| 2026-01-05 | HLC-001 to HLC-011 implemented: core library, state stores, JSON/Dapper serializers, DI extensions, 56 unit tests all passing | Agent | -======== | 2026-01-06 | HLC-001 to HLC-006 and HLC-011 DONE: Created StellaOps.HybridLogicalClock project with HlcTimestamp record (comparison, parsing, serialization), HybridLogicalClock class (Tick/Receive/Current), IHybridLogicalClock and IHlcStateStore interfaces, InMemoryHlcStateStore, PostgresHlcStateStore (atomic upsert with conditional update for monotonicity), HlcClockSkewException, HlcTimestampJsonConverter (string and object format), NullableHlcTimestampJsonConverter, and HlcServiceCollectionExtensions. All builds verified. | Agent | | 2026-01-06 | HLC-007 DONE: Created HlcTimestampTypeHandler.cs with HlcTimestampNpgsqlExtensions (AddHlcTimestamp, GetHlcTimestamp, GetHlcTimestampOrNull methods for NpgsqlCommand and NpgsqlDataReader), HlcTimestampDapperHandler, NullableHlcTimestampDapperHandler, and HlcTypeHandlerRegistration for DI. Added Dapper package reference. Build verified. | Agent | | 2026-01-06 | HLC-008 DONE: Created StellaOps.HybridLogicalClock.Tests project with comprehensive unit tests: HlcTimestampTests (20+ tests for parsing, comparison, operators, lexicographic ordering), HybridLogicalClockTests (25+ tests for tick monotonicity, receive merge, clock skew handling, state initialization/persistence, causal ordering), InMemoryHlcStateStoreTests (15+ tests for load/save/monotonicity), HlcTimestampJsonConverterTests (25+ tests for string and object JSON converters). Build verified. | Agent | | 2026-01-06 | HLC-009 DONE: Added HybridLogicalClockIntegrationTests with 10+ integration tests covering: concurrent ticks (all unique, within-thread monotonicity), node restart recovery (resume from persisted, same physical time counter increment), multi-node causal ordering (request-response, broadcast-gather, clock skew detection, concurrent events total ordering), state store concurrency (no loss, maintains monotonicity). Build verified. | Agent | | 2026-01-06 | HLC-010 DONE: Created HybridLogicalClockBenchmarks.cs with 12+ performance benchmarks: tick throughput (single-thread 100K/sec target, multi-thread 50K/sec, with time advance), receive throughput (50K/sec), parse/serialize throughput (500K/sec), comparison throughput (10M/sec), memory allocation tests (value type verification, reasonable struct size), InMemoryStateStore throughput (save 100K/sec, load 500K/sec). Uses xUnit Facts with TestCategories.Performance trait. Build verified. | Agent | | 2026-01-06 | HLC-012 DONE: Created comprehensive README.md with: overview and problem statement, installation and quick start, DI registration (3 patterns), core types reference (HlcTimestamp, IHybridLogicalClock, IHlcStateStore), PostgreSQL persistence schema, JSON serialization (string and object formats), Npgsql/Dapper type handlers, clock skew handling, recovery from restart, testing patterns, HLC algorithm pseudocode, performance benchmarks table, and academic references. Sprint complete. | Agent | ->>>>>>>> 47890273170663b2236a1eb995d218fe5de6b11a:docs-archived/implplan/SPRINT_20260105_002_001_LB_hlc_core_library.md ->>>>>>> 47890273170663b2236a1eb995d218fe5de6b11a ## Next Checkpoints diff --git a/docs-archived/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md b/docs-archived/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md index a7714fe8b..bf2da3d45 100644 --- a/docs-archived/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md +++ b/docs-archived/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md @@ -419,22 +419,6 @@ public sealed class SchedulerOptions | Date (UTC) | Update | Owner | |------------|--------|-------| | 2026-01-05 | Sprint created from product advisory gap analysis | Planning | -<<<<<<< HEAD:docs/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md -| 2026-01-06 | SQC-001: Added HLC and CanonicalJson references to Scheduler.Persistence and Scheduler.Queue projects | Agent | -| 2026-01-06 | SQC-002-004: Created migration 002_hlc_queue_chain.sql with scheduler_log, batch_snapshot, chain_heads tables | Agent | -| 2026-01-06 | SQC-005-008: Implemented SchedulerChainLinking, ISchedulerLogRepository, PostgresSchedulerLogRepository, IChainHeadRepository, PostgresChainHeadRepository | Agent | -| 2026-01-06 | SQC-009: Implemented HlcSchedulerEnqueueService with chain linking and idempotency | Agent | -| 2026-01-06 | SQC-010: Implemented HlcSchedulerDequeueService with HLC-ordered retrieval and cursor pagination | Agent | -| 2026-01-06 | SQC-013: Implemented BatchSnapshotService with audit anchoring and optional DSSE signing | Agent | -| 2026-01-06 | SQC-015: Implemented SchedulerChainVerifier for chain integrity verification | Agent | -| 2026-01-06 | SQC-020: Added SchedulerHlcOptions with EnableHlcOrdering, DualWriteMode, VerifyOnDequeue flags | Agent | -| 2026-01-06 | SQC-022: Implemented HlcSchedulerMetrics with enqueue, dequeue, verification, and snapshot metrics | Agent | -| 2026-01-06 | Added HlcSchedulerServiceCollectionExtensions for DI registration | Agent | -| 2026-01-06 | SQC-011-012: Verified Redis and NATS adapters already have HLC support (IHybridLogicalClock injection, Tick(), header storage) | Agent | -| 2026-01-06 | SQC-021: Created HLC migration guide at docs/modules/scheduler/hlc-migration-guide.md | Agent | -| 2026-01-06 | SQC-014: Implemented BatchSnapshotDsseSigner with HMAC-SHA256 signing, PAE encoding, and verification | Agent | -| 2026-01-06 | SQC-019: Updated JobRepository with optional HLC ordering via JobRepositoryOptions; GetScheduledJobsAsync and GetByStatusAsync now join with scheduler_log when enabled | Agent | -======= | 2026-01-06 | SQC-001 DONE: Added HybridLogicalClock project reference to StellaOps.Scheduler.Persistence and StellaOps.Scheduler.Queue. Build verified. | Agent | | 2026-01-06 | SQC-002-004 DONE: Created 002_hlc_queue_chain.sql migration with: scheduler_log (HLC-ordered queue with chain linking), batch_snapshot (audit anchors with optional DSSE), chain_heads (per-partition head tracking), and upsert_chain_head function for atomic monotonic updates. | Agent | | 2026-01-06 | SQC-005-007 DONE: Created entity models (SchedulerLogEntity, BatchSnapshotEntity, ChainHeadEntity), ISchedulerLogRepository interface (insert, HLC-ordered query, range query, job/link lookup), SchedulerLogRepository (transactional insert with chain head update), IChainHeadRepository (get, upsert with monotonicity), ChainHeadRepository. Build verified. | Agent | @@ -457,7 +441,6 @@ public sealed class SchedulerOptions | 2026-01-06 | SQC-014 DONE: Created ISchedulerSnapshotSigner interface with SignAsync() method and SnapshotSignResult record. Updated BatchSnapshotService to optionally sign snapshots when SignBatchSnapshots=true and signer is available. Added ComputeSnapshotDigest() for deterministic SHA-256 digest. Build verified. | Agent | | 2026-01-06 | SQC-019 DONE: Created HlcJobRepositoryDecorator implementing decorator pattern for IJobRepository. Supports dual-write mode (writes to both scheduler.jobs AND scheduler.scheduler_log) and HLC ordering for dequeue. Uses ISchedulerLogRepository.InsertWithChainUpdateAsync for atomic chain updates. Build verified. | Agent | | 2026-01-06 | SQC-017 DONE: Created HlcSchedulerPostgresFixture.cs (PostgreSQL test fixture with Testcontainers, scheduler schema migrations, table truncation) and HlcSchedulerIntegrationTests.cs with 13 integration tests: EnqueueAsync_SingleJob_CreatesLogEntryWithChainLink, EnqueueAsync_MultipleJobs_FormsChain, EnqueueAsync_UpdatesChainHead, DequeueAsync_ReturnsJobsInHlcOrder, DequeueAsync_EmptyQueue_ReturnsEmptyList, DequeueAsync_RespectsLimit, VerifyAsync_ValidChain_ReturnsTrue, VerifyAsync_EmptyChain_ReturnsTrue, GetByHlcRangeAsync_ReturnsJobsInRange, Enqueue_DifferentTenants_MaintainsSeparateChains, EnqueueAsync_DuplicateIdempotencyKey_ReturnsExistingJob, VerifySingleAsync_ValidEntry_ReturnsTrue, VerifySingleAsync_NonExistentJob_ReturnsFalse. Properly aligned API with SchedulerJobPayload, SchedulerEnqueueResult, SchedulerDequeueResult, ChainVerificationResult, and correct service constructors. Build verified. | Agent | ->>>>>>> 47890273170663b2236a1eb995d218fe5de6b11a:docs-archived/implplan/SPRINT_20260105_002_002_SCHEDULER_hlc_queue_chain.md ## Next Checkpoints diff --git a/docs/implplan/permament/SPRINT_20251229_006_CICD_full_pipeline_validation.md b/docs/implplan/permament/SPRINT_20251229_006_CICD_full_pipeline_validation.md index 71ae9618a..f682502c3 100644 --- a/docs/implplan/permament/SPRINT_20251229_006_CICD_full_pipeline_validation.md +++ b/docs/implplan/permament/SPRINT_20251229_006_CICD_full_pipeline_validation.md @@ -48,15 +48,16 @@ | 14 | CICD-VAL-021 | TODO | CICD-VAL-020 | DevOps | Run test-matrix.yml with act (PR trigger). | | 15 | CICD-VAL-022 | TODO | CICD-VAL-021 | DevOps | Run build-test-deploy.yml with act (PR trigger). | | 16 | CICD-VAL-023 | TODO | CICD-VAL-022 | DevOps | Document act simulation results and gaps. | +| 17 | CICD-VAL-024 | DONE | Runner labels available | DevOps | Align workflow runner labels with available Gitea runner pool (configurable Linux label). | ### Phase 4: Test Failure Remediation | # | Task ID | Status | Key dependency / next step | Owners | Task Definition | | --- | --- | --- | --- | --- | --- | -| 17 | CICD-VAL-030 | TODO | CICD-VAL-016 | DevOps | Fix test categorization (move integration tests from Unit). | -| 18 | CICD-VAL-031 | TODO | CICD-VAL-030 | DevOps | Fix PostgreSQL connection/fixture issues in tests. | -| 19 | CICD-VAL-032 | TODO | CICD-VAL-031 | DevOps | Fix golden fixture mismatches. | -| 20 | CICD-VAL-033 | TODO | CICD-VAL-032 | DevOps | Fix remaining test failures (actual bugs). | -| 21 | CICD-VAL-034 | TODO | CICD-VAL-033 | DevOps | Re-run full test suite to verify all green. | +| 18 | CICD-VAL-030 | TODO | CICD-VAL-016 | DevOps | Fix test categorization (move integration tests from Unit). | +| 19 | CICD-VAL-031 | TODO | CICD-VAL-030 | DevOps | Fix PostgreSQL connection/fixture issues in tests. | +| 20 | CICD-VAL-032 | TODO | CICD-VAL-031 | DevOps | Fix golden fixture mismatches. | +| 21 | CICD-VAL-033 | TODO | CICD-VAL-032 | DevOps | Fix remaining test failures (actual bugs). | +| 22 | CICD-VAL-034 | TODO | CICD-VAL-033 | DevOps | Re-run full test suite to verify all green. | ## Execution Log | Date (UTC) | Update | Owner | @@ -72,6 +73,10 @@ | 2026-01-06 | BLOCKED: Act workflow simulation not yet run. Requires CI image build and further investigation of test categorization issues. | DevOps | | 2026-01-06 | SCOPE EXPANDED: Sprint amended to include Phase 2 (local test execution), Phase 3 (act simulation), Phase 4 (test remediation). | Planning | | 2026-01-06 | CICD-VAL-010 analysis: 137 passed, 85 failed, 10 aborted. Root cause: 133 PostgreSQL connection exhaustion errors. Many tests tagged "Unit" require DB. | DevOps | +| 2026-01-07 | Updated workflows to use a configurable Linux runner label defaulting to ubuntu-latest to avoid runner label mismatches. | DevOps | +| 2026-01-07 | Act dry-run for test-matrix (pr-gating-tests job only) progresses through discover and matrix setup; integration job still pending due to act service container handling. | DevOps | +| 2026-01-07 | Local smoke build step exceeded 10 minutes and was stopped; unit-split 1-5 failed in AdvisoryAI due to stale build outputs, re-run `dotnet test` for AdvisoryAI passed (207 tests). | DevOps | +| 2026-01-07 | Unit-split runs (projects 1-20) completed after AdvisoryAI rebuild; all 20 projects passed. | DevOps | ## Decisions & Risks - Risk: local CI steps drift from pipeline definitions; mitigate with scheduled doc sync. diff --git a/docs/technical/testing/ci-quality-gates.md b/docs/technical/testing/ci-quality-gates.md index bb9612466..0763a6248 100644 --- a/docs/technical/testing/ci-quality-gates.md +++ b/docs/technical/testing/ci-quality-gates.md @@ -93,7 +93,7 @@ Quality gates are integrated into the main CI workflow: # .gitea/workflows/build-test-deploy.yml quality-gates: - runs-on: ubuntu-22.04 + runs-on: ${{ vars.LINUX_RUNNER_LABEL || 'ubuntu-latest' }} needs: build-test steps: - name: Reachability quality gate diff --git a/src/Attestor/StellaOps.Attestor.Verify/AttestorVerificationEngine.cs b/src/Attestor/StellaOps.Attestor.Verify/AttestorVerificationEngine.cs index 1a5353359..74e46ddb8 100644 --- a/src/Attestor/StellaOps.Attestor.Verify/AttestorVerificationEngine.cs +++ b/src/Attestor/StellaOps.Attestor.Verify/AttestorVerificationEngine.cs @@ -44,7 +44,7 @@ public sealed class AttestorVerificationEngine : IAttestorVerificationEngine { ArgumentNullException.ThrowIfNull(entry); - var signatureIssuer = await EvaluateSignatureAndIssuerAsync(entry, bundle, cancellationToken).ConfigureAwait(false); + var signatureIssuer = await EvaluateSignatureAndIssuerAsync(entry, bundle, evaluationTime, cancellationToken).ConfigureAwait(false); var freshness = EvaluateFreshness(entry, evaluationTime); var transparency = EvaluateTransparency(entry); var policy = EvaluatePolicy(entry, signatureIssuer.Signatures, signatureIssuer.Issuer, freshness, transparency, bundle is not null); @@ -55,6 +55,7 @@ public sealed class AttestorVerificationEngine : IAttestorVerificationEngine private async Task<(SignatureEvaluationResult Signatures, IssuerEvaluationResult Issuer)> EvaluateSignatureAndIssuerAsync( AttestorEntry entry, AttestorSubmissionRequest.SubmissionBundle? bundle, + DateTimeOffset evaluationTime, CancellationToken cancellationToken) { var signatureIssues = new List(); @@ -178,7 +179,7 @@ public sealed class AttestorVerificationEngine : IAttestorVerificationEngine break; case "keyless": - var keylessResult = EvaluateKeylessSignature(entry, bundle, preAuth, signatureIssues, issuerIssues); + var keylessResult = EvaluateKeylessSignature(entry, bundle, preAuth, signatureIssues, issuerIssues, evaluationTime); verifiedSignatures = keylessResult.VerifiedSignatures; subjectAlternativeName = keylessResult.SubjectAlternativeName; break; @@ -270,7 +271,8 @@ public sealed class AttestorVerificationEngine : IAttestorVerificationEngine AttestorSubmissionRequest.SubmissionBundle bundle, byte[] preAuthEncoding, List signatureIssues, - List issuerIssues) + List issuerIssues, + DateTimeOffset evaluationTime) { if (bundle.CertificateChain.Count == 0) { @@ -296,46 +298,47 @@ public sealed class AttestorVerificationEngine : IAttestorVerificationEngine var leafCertificate = certificates[0]; var subjectAltName = GetSubjectAlternativeNames(leafCertificate).FirstOrDefault(); - if (_options.Security.SignerIdentity.FulcioRoots.Count > 0) + if (_options.Security.SignerIdentity.FulcioRoots.Count > 0) + { + using var chain = new X509Chain { - using var chain = new X509Chain - { - ChainPolicy = + ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck, VerificationFlags = X509VerificationFlags.NoFlag, - TrustMode = X509ChainTrustMode.CustomRootTrust + TrustMode = X509ChainTrustMode.CustomRootTrust, + VerificationTime = evaluationTime.UtcDateTime } }; - foreach (var rootPath in _options.Security.SignerIdentity.FulcioRoots) + foreach (var rootPath in _options.Security.SignerIdentity.FulcioRoots) + { + try { - try + if (File.Exists(rootPath)) { - if (File.Exists(rootPath)) - { - var rootCertificate = X509CertificateLoader.LoadCertificateFromFile(rootPath); - chain.ChainPolicy.CustomTrustStore.Add(rootCertificate); - } - } - catch (Exception ex) - { - _logger.LogWarning(ex, "Failed to load Fulcio root {Root}", rootPath); + var rootCertificate = X509CertificateLoader.LoadCertificateFromFile(rootPath); + chain.ChainPolicy.CustomTrustStore.Add(rootCertificate); } } - - for (var i = 1; i < certificates.Count; i++) + catch (Exception ex) { - chain.ChainPolicy.ExtraStore.Add(certificates[i]); - } - - if (!chain.Build(leafCertificate)) - { - var status = string.Join(";", chain.ChainStatus.Select(s => s.StatusInformation.Trim())).Trim(';'); - issuerIssues.Add(string.IsNullOrEmpty(status) ? "certificate_chain_untrusted" : $"certificate_chain_untrusted:{status}"); + _logger.LogWarning(ex, "Failed to load Fulcio root {Root}", rootPath); } } + for (var i = 1; i < certificates.Count; i++) + { + chain.ChainPolicy.ExtraStore.Add(certificates[i]); + } + + if (!chain.Build(leafCertificate)) + { + var status = string.Join(";", chain.ChainStatus.Select(s => s.StatusInformation.Trim())).Trim(';'); + issuerIssues.Add(string.IsNullOrEmpty(status) ? "certificate_chain_untrusted" : $"certificate_chain_untrusted:{status}"); + } + } + if (_options.Security.SignerIdentity.AllowedSans.Count > 0) { var sans = GetSubjectAlternativeNames(leafCertificate); diff --git a/src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core.Tests/Chain/AttestationChainBuilderTests.cs b/src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core.Tests/Chain/AttestationChainBuilderTests.cs index ed322e09e..12f562590 100644 --- a/src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core.Tests/Chain/AttestationChainBuilderTests.cs +++ b/src/Attestor/StellaOps.Attestor/StellaOps.Attestor.Core.Tests/Chain/AttestationChainBuilderTests.cs @@ -223,9 +223,12 @@ public class AttestationChainBuilderTests result.IsSuccess.Should().BeTrue(); result.LinksCreated.Should().HaveCount(3); // Links should be created in layer order - result.LinksCreated[0].Metadata!.Annotations["layerIndex"].Should().Be("0"); - result.LinksCreated[1].Metadata!.Annotations["layerIndex"].Should().Be("1"); - result.LinksCreated[2].Metadata!.Annotations["layerIndex"].Should().Be("2"); + Assert.NotNull(result.LinksCreated[0].Metadata?.Annotations); + Assert.NotNull(result.LinksCreated[1].Metadata?.Annotations); + Assert.NotNull(result.LinksCreated[2].Metadata?.Annotations); + result.LinksCreated[0].Metadata!.Annotations!["layerIndex"].Should().Be("0"); + result.LinksCreated[1].Metadata!.Annotations!["layerIndex"].Should().Be("1"); + result.LinksCreated[2].Metadata!.Annotations!["layerIndex"].Should().Be("2"); } [Fact] diff --git a/src/Attestor/__Tests/StellaOps.Attestor.Verify.Tests/AttestorVerificationEngineTests.cs b/src/Attestor/__Tests/StellaOps.Attestor.Verify.Tests/AttestorVerificationEngineTests.cs index 778a2970f..db0d1cc3f 100644 --- a/src/Attestor/__Tests/StellaOps.Attestor.Verify.Tests/AttestorVerificationEngineTests.cs +++ b/src/Attestor/__Tests/StellaOps.Attestor.Verify.Tests/AttestorVerificationEngineTests.cs @@ -319,7 +319,21 @@ public sealed class AttestorVerificationEngineTests } private static X509Certificate2 EnsurePrivateKey(X509Certificate2 certificate, ECDsa key) - => certificate.HasPrivateKey ? certificate : certificate.CopyWithPrivateKey(key); + { + if (certificate.HasPrivateKey) + { + return certificate; + } + + try + { + return certificate.CopyWithPrivateKey(key); + } + catch (InvalidOperationException) + { + return certificate; + } + } private static string ToPem(X509Certificate2 certificate) { diff --git a/src/Authority/StellaOps.Authority/StellaOps.Auth.Abstractions.Tests/AuthAbstractionsConstantsTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Auth.Abstractions.Tests/AuthAbstractionsConstantsTests.cs index b6dd9da23..674fbfacf 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Auth.Abstractions.Tests/AuthAbstractionsConstantsTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Auth.Abstractions.Tests/AuthAbstractionsConstantsTests.cs @@ -65,35 +65,35 @@ public class AuthAbstractionsConstantsTests [nameof(StellaOpsClaimTypes.SessionId)] = "sid" }; - Assert.Equal(expected[nameof(StellaOpsClaimTypes.Subject)], StellaOpsClaimTypes.Subject); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.Tenant)], StellaOpsClaimTypes.Tenant); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.Project)], StellaOpsClaimTypes.Project); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.ClientId)], StellaOpsClaimTypes.ClientId); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.ServiceAccount)], StellaOpsClaimTypes.ServiceAccount); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.TokenId)], StellaOpsClaimTypes.TokenId); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.AuthenticationMethod)], StellaOpsClaimTypes.AuthenticationMethod); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.Scope)], StellaOpsClaimTypes.Scope); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.ScopeItem)], StellaOpsClaimTypes.ScopeItem); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.Audience)], StellaOpsClaimTypes.Audience); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.IdentityProvider)], StellaOpsClaimTypes.IdentityProvider); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.OperatorReason)], StellaOpsClaimTypes.OperatorReason); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.OperatorTicket)], StellaOpsClaimTypes.OperatorTicket); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.QuotaReason)], StellaOpsClaimTypes.QuotaReason); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.QuotaTicket)], StellaOpsClaimTypes.QuotaTicket); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.BackfillReason)], StellaOpsClaimTypes.BackfillReason); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.BackfillTicket)], StellaOpsClaimTypes.BackfillTicket); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PolicyDigest)], StellaOpsClaimTypes.PolicyDigest); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PolicyTicket)], StellaOpsClaimTypes.PolicyTicket); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PolicyReason)], StellaOpsClaimTypes.PolicyReason); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PackRunId)], StellaOpsClaimTypes.PackRunId); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PackGateId)], StellaOpsClaimTypes.PackGateId); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PackPlanHash)], StellaOpsClaimTypes.PackPlanHash); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.PolicyOperation)], StellaOpsClaimTypes.PolicyOperation); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.IncidentReason)], StellaOpsClaimTypes.IncidentReason); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.VulnerabilityEnvironment)], StellaOpsClaimTypes.VulnerabilityEnvironment); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.VulnerabilityOwner)], StellaOpsClaimTypes.VulnerabilityOwner); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.VulnerabilityBusinessTier)], StellaOpsClaimTypes.VulnerabilityBusinessTier); - Assert.Equal(expected[nameof(StellaOpsClaimTypes.SessionId)], StellaOpsClaimTypes.SessionId); + Assert.Equal(StellaOpsClaimTypes.Subject, expected[nameof(StellaOpsClaimTypes.Subject)]); + Assert.Equal(StellaOpsClaimTypes.Tenant, expected[nameof(StellaOpsClaimTypes.Tenant)]); + Assert.Equal(StellaOpsClaimTypes.Project, expected[nameof(StellaOpsClaimTypes.Project)]); + Assert.Equal(StellaOpsClaimTypes.ClientId, expected[nameof(StellaOpsClaimTypes.ClientId)]); + Assert.Equal(StellaOpsClaimTypes.ServiceAccount, expected[nameof(StellaOpsClaimTypes.ServiceAccount)]); + Assert.Equal(StellaOpsClaimTypes.TokenId, expected[nameof(StellaOpsClaimTypes.TokenId)]); + Assert.Equal(StellaOpsClaimTypes.AuthenticationMethod, expected[nameof(StellaOpsClaimTypes.AuthenticationMethod)]); + Assert.Equal(StellaOpsClaimTypes.Scope, expected[nameof(StellaOpsClaimTypes.Scope)]); + Assert.Equal(StellaOpsClaimTypes.ScopeItem, expected[nameof(StellaOpsClaimTypes.ScopeItem)]); + Assert.Equal(StellaOpsClaimTypes.Audience, expected[nameof(StellaOpsClaimTypes.Audience)]); + Assert.Equal(StellaOpsClaimTypes.IdentityProvider, expected[nameof(StellaOpsClaimTypes.IdentityProvider)]); + Assert.Equal(StellaOpsClaimTypes.OperatorReason, expected[nameof(StellaOpsClaimTypes.OperatorReason)]); + Assert.Equal(StellaOpsClaimTypes.OperatorTicket, expected[nameof(StellaOpsClaimTypes.OperatorTicket)]); + Assert.Equal(StellaOpsClaimTypes.QuotaReason, expected[nameof(StellaOpsClaimTypes.QuotaReason)]); + Assert.Equal(StellaOpsClaimTypes.QuotaTicket, expected[nameof(StellaOpsClaimTypes.QuotaTicket)]); + Assert.Equal(StellaOpsClaimTypes.BackfillReason, expected[nameof(StellaOpsClaimTypes.BackfillReason)]); + Assert.Equal(StellaOpsClaimTypes.BackfillTicket, expected[nameof(StellaOpsClaimTypes.BackfillTicket)]); + Assert.Equal(StellaOpsClaimTypes.PolicyDigest, expected[nameof(StellaOpsClaimTypes.PolicyDigest)]); + Assert.Equal(StellaOpsClaimTypes.PolicyTicket, expected[nameof(StellaOpsClaimTypes.PolicyTicket)]); + Assert.Equal(StellaOpsClaimTypes.PolicyReason, expected[nameof(StellaOpsClaimTypes.PolicyReason)]); + Assert.Equal(StellaOpsClaimTypes.PackRunId, expected[nameof(StellaOpsClaimTypes.PackRunId)]); + Assert.Equal(StellaOpsClaimTypes.PackGateId, expected[nameof(StellaOpsClaimTypes.PackGateId)]); + Assert.Equal(StellaOpsClaimTypes.PackPlanHash, expected[nameof(StellaOpsClaimTypes.PackPlanHash)]); + Assert.Equal(StellaOpsClaimTypes.PolicyOperation, expected[nameof(StellaOpsClaimTypes.PolicyOperation)]); + Assert.Equal(StellaOpsClaimTypes.IncidentReason, expected[nameof(StellaOpsClaimTypes.IncidentReason)]); + Assert.Equal(StellaOpsClaimTypes.VulnerabilityEnvironment, expected[nameof(StellaOpsClaimTypes.VulnerabilityEnvironment)]); + Assert.Equal(StellaOpsClaimTypes.VulnerabilityOwner, expected[nameof(StellaOpsClaimTypes.VulnerabilityOwner)]); + Assert.Equal(StellaOpsClaimTypes.VulnerabilityBusinessTier, expected[nameof(StellaOpsClaimTypes.VulnerabilityBusinessTier)]); + Assert.Equal(StellaOpsClaimTypes.SessionId, expected[nameof(StellaOpsClaimTypes.SessionId)]); } [Trait("Category", TestCategories.Unit)] diff --git a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/ServiceCollectionExtensionsTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/ServiceCollectionExtensionsTests.cs index 281f65f88..a857d5741 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/ServiceCollectionExtensionsTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/ServiceCollectionExtensionsTests.cs @@ -72,7 +72,7 @@ public class ServiceCollectionExtensionsTests using var provider = services.BuildServiceProvider(); var cache = provider.GetRequiredService(); - var configuration = await cache.GetAsync(CancellationToken.None); + var configuration = await cache.GetAsync(TestContext.Current.CancellationToken); Assert.Equal(new Uri("https://authority.test/connect/token"), configuration.TokenEndpoint); Assert.Equal(2, attemptCount); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsDiscoveryCacheTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsDiscoveryCacheTests.cs index 9c5591c62..56aab4c2e 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsDiscoveryCacheTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsDiscoveryCacheTests.cs @@ -47,12 +47,12 @@ public class StellaOpsDiscoveryCacheTests var monitor = new TestOptionsMonitor(options); var cache = new StellaOpsDiscoveryCache(httpClient, monitor, timeProvider, NullLogger.Instance); - var configuration = await cache.GetAsync(CancellationToken.None); + var configuration = await cache.GetAsync(TestContext.Current.CancellationToken); Assert.Equal(new Uri("https://authority.test/connect/token"), configuration.TokenEndpoint); timeProvider.Advance(TimeSpan.FromMinutes(1) + TimeSpan.FromSeconds(5)); - configuration = await cache.GetAsync(CancellationToken.None); + configuration = await cache.GetAsync(TestContext.Current.CancellationToken); Assert.Equal(new Uri("https://authority.test/connect/token"), configuration.TokenEndpoint); Assert.Equal(2, callCount); @@ -66,7 +66,7 @@ public class StellaOpsDiscoveryCacheTests HttpRequestException? exception = null; try { - await cache.GetAsync(CancellationToken.None); + await cache.GetAsync(TestContext.Current.CancellationToken); } catch (HttpRequestException ex) { diff --git a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsJwksCacheTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsJwksCacheTests.cs index d073e33c0..4021982fe 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsJwksCacheTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Auth.Client.Tests/StellaOpsJwksCacheTests.cs @@ -52,12 +52,12 @@ public class StellaOpsJwksCacheTests var discoveryCache = new StellaOpsDiscoveryCache(discoveryClient, monitor, timeProvider, NullLogger.Instance); var jwksCache = new StellaOpsJwksCache(jwksClient, discoveryCache, monitor, timeProvider, NullLogger.Instance); - var keys = await jwksCache.GetAsync(CancellationToken.None); + var keys = await jwksCache.GetAsync(TestContext.Current.CancellationToken); Assert.NotNull(keys); timeProvider.Advance(TimeSpan.FromMinutes(1) + TimeSpan.FromSeconds(5)); - keys = await jwksCache.GetAsync(CancellationToken.None); + keys = await jwksCache.GetAsync(TestContext.Current.CancellationToken); Assert.NotNull(keys); Assert.Equal(2, jwksCallCount); @@ -68,7 +68,7 @@ public class StellaOpsJwksCacheTests Assert.True(offlineExpiry < timeProvider.GetUtcNow()); - await Assert.ThrowsAsync(() => jwksCache.GetAsync(CancellationToken.None)); + await Assert.ThrowsAsync(() => jwksCache.GetAsync(TestContext.Current.CancellationToken)); } private static HttpResponseMessage CreateJsonResponse(string json) diff --git a/src/Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration.Tests/StellaOpsAuthorityConfigurationManagerTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration.Tests/StellaOpsAuthorityConfigurationManagerTests.cs index d0f1d39b5..d1469727a 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration.Tests/StellaOpsAuthorityConfigurationManagerTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration.Tests/StellaOpsAuthorityConfigurationManagerTests.cs @@ -38,7 +38,7 @@ public class StellaOpsAuthorityConfigurationManagerTests var initialMetadataRequests = handler.MetadataRequests; var initialJwksRequests = handler.JwksRequests; - var second = await manager.GetConfigurationAsync(CancellationToken.None); + var second = await manager.GetConfigurationAsync(TestContext.Current.CancellationToken); // Cache must return same instance Assert.Same(first, second); @@ -70,11 +70,11 @@ public class StellaOpsAuthorityConfigurationManagerTests timeProvider, NullLogger.Instance); - var first = await manager.GetConfigurationAsync(CancellationToken.None); + var first = await manager.GetConfigurationAsync(TestContext.Current.CancellationToken); timeProvider.Advance(TimeSpan.FromMinutes(2)); - var second = await manager.GetConfigurationAsync(CancellationToken.None); + var second = await manager.GetConfigurationAsync(TestContext.Current.CancellationToken); Assert.Same(first, second); Assert.Equal(2, handler.MetadataRequests); @@ -100,12 +100,12 @@ public class StellaOpsAuthorityConfigurationManagerTests timeProvider, NullLogger.Instance); - await manager.GetConfigurationAsync(CancellationToken.None); + await manager.GetConfigurationAsync(TestContext.Current.CancellationToken); var updated = CreateOptions("https://authority2.test"); optionsMonitor.Set(updated); - await manager.GetConfigurationAsync(CancellationToken.None); + await manager.GetConfigurationAsync(TestContext.Current.CancellationToken); Assert.Equal(2, handler.MetadataRequests); } diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsCacheTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsCacheTests.cs index 00f90a217..cfe2b773e 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsCacheTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsCacheTests.cs @@ -21,8 +21,8 @@ public sealed class InMemoryLdapClaimsCacheTests ["displayName"] = "Alice Example" }); - await cache.SetAsync("uid=alice,ou=people,dc=example,dc=internal", claims, CancellationToken.None); - var fetched = await cache.GetAsync("uid=alice,ou=people,dc=example,dc=internal", CancellationToken.None); + await cache.SetAsync("uid=alice,ou=people,dc=example,dc=internal", claims, TestContext.Current.CancellationToken); + var fetched = await cache.GetAsync("uid=alice,ou=people,dc=example,dc=internal", TestContext.Current.CancellationToken); Assert.NotNull(fetched); Assert.Contains("operators", fetched!.Roles); @@ -35,10 +35,10 @@ public sealed class InMemoryLdapClaimsCacheTests var timeProvider = new TestTimeProvider(new DateTimeOffset(2025, 11, 9, 6, 0, 0, TimeSpan.Zero)); var cache = CreateCache(enabled: true, ttlSeconds: 60, timeProvider: timeProvider); - await cache.SetAsync("uid=expired,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), CancellationToken.None); + await cache.SetAsync("uid=expired,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), TestContext.Current.CancellationToken); timeProvider.Advance(TimeSpan.FromMinutes(5)); - var fetched = await cache.GetAsync("uid=expired,ou=people,dc=example,dc=internal", CancellationToken.None); + var fetched = await cache.GetAsync("uid=expired,ou=people,dc=example,dc=internal", TestContext.Current.CancellationToken); Assert.Null(fetched); } @@ -48,11 +48,11 @@ public sealed class InMemoryLdapClaimsCacheTests { var cache = CreateCache(enabled: true, ttlSeconds: 600, maxEntries: 1); - await cache.SetAsync("uid=first,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), CancellationToken.None); - await cache.SetAsync("uid=second,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), CancellationToken.None); + await cache.SetAsync("uid=first,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), TestContext.Current.CancellationToken); + await cache.SetAsync("uid=second,ou=people,dc=example,dc=internal", new LdapCachedClaims(Array.Empty(), new Dictionary()), TestContext.Current.CancellationToken); - var first = await cache.GetAsync("uid=first,ou=people,dc=example,dc=internal", CancellationToken.None); - var second = await cache.GetAsync("uid=second,ou=people,dc=example,dc=internal", CancellationToken.None); + var first = await cache.GetAsync("uid=first,ou=people,dc=example,dc=internal", TestContext.Current.CancellationToken); + var second = await cache.GetAsync("uid=second,ou=people,dc=example,dc=internal", TestContext.Current.CancellationToken); Assert.Null(first); Assert.NotNull(second); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsEnricherTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsEnricherTests.cs index 170c3edf6..d61a98695 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsEnricherTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Claims/LdapClaimsEnricherTests.cs @@ -41,7 +41,7 @@ public class LdapClaimsEnricherTests var identity = new ClaimsIdentity(); var context = CreateContext("uid=j.doe,ou=people,dc=example,dc=internal"); - await enricher.EnrichAsync(identity, context, CancellationToken.None); + await enricher.EnrichAsync(identity, context, TestContext.Current.CancellationToken); Assert.Contains(identity.Claims, claim => claim.Type == ClaimTypes.Role && claim.Value == "operators"); } @@ -74,7 +74,7 @@ public class LdapClaimsEnricherTests var identity = new ClaimsIdentity(); var context = CreateContext("uid=ops,ou=people,dc=example,dc=internal"); - await enricher.EnrichAsync(identity, context, CancellationToken.None); + await enricher.EnrichAsync(identity, context, TestContext.Current.CancellationToken); Assert.Contains(identity.Claims, claim => claim.Type == ClaimTypes.Role && claim.Value == "incident"); } @@ -107,7 +107,7 @@ public class LdapClaimsEnricherTests var identity = new ClaimsIdentity(); var context = CreateContext("uid=alice,ou=people,dc=example,dc=internal"); - await enricher.EnrichAsync(identity, context, CancellationToken.None); + await enricher.EnrichAsync(identity, context, TestContext.Current.CancellationToken); Assert.Contains(identity.Claims, claim => claim.Type == "displayName" && claim.Value == "Alice Example"); Assert.Contains(identity.Claims, claim => claim.Type == "email" && claim.Value == "alice@example.test"); @@ -134,11 +134,11 @@ public class LdapClaimsEnricherTests var identity = new ClaimsIdentity(); var context = CreateContext("uid=cached,ou=people,dc=example,dc=internal"); - await enricher.EnrichAsync(identity, context, CancellationToken.None); + await enricher.EnrichAsync(identity, context, TestContext.Current.CancellationToken); Assert.Contains(identity.Claims, claim => claim.Type == ClaimTypes.Role && claim.Value == "operators"); Assert.Contains(identity.Claims, claim => claim.Type == "displayName" && claim.Value == "Cached User"); - Assert.Equal(0, connection.Operations.Count); + Assert.Empty(connection.Operations); Assert.Equal(0, cache.SetCount); } diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapCapabilityProbeTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapCapabilityProbeTests.cs index d4261c718..a2bf99d3b 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapCapabilityProbeTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapCapabilityProbeTests.cs @@ -25,7 +25,7 @@ public class LdapCapabilityProbeTests checkClientProvisioning: true, checkBootstrap: true, options.CapabilityProbe.Timeout, - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.True(snapshot.ClientProvisioningWritable); Assert.True(snapshot.BootstrapWritable); @@ -47,7 +47,7 @@ public class LdapCapabilityProbeTests checkClientProvisioning: true, checkBootstrap: true, options.CapabilityProbe.Timeout, - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.False(snapshot.ClientProvisioningWritable); Assert.False(snapshot.BootstrapWritable); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapClientProvisioningStoreTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapClientProvisioningStoreTests.cs index 9445bad19..f61fdd2c5 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapClientProvisioningStoreTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/ClientProvisioning/LdapClientProvisioningStoreTests.cs @@ -49,7 +49,7 @@ public sealed class LdapClientProvisioningStoreTests allowedScopes: new[] { "signer.sign" }, allowedAudiences: new[] { "signer" }); - var result = await store.CreateOrUpdateAsync(registration, CancellationToken.None); + var result = await store.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.True(clientStore.Documents.ContainsKey("svc-bootstrap")); @@ -88,7 +88,7 @@ public sealed class LdapClientProvisioningStoreTests SecretHash = "hash" }; - var result = await store.DeleteAsync("svc-bootstrap", CancellationToken.None); + var result = await store.DeleteAsync("svc-bootstrap", TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.DoesNotContain("svc-bootstrap", clientStore.Documents.Keys); @@ -124,7 +124,7 @@ public sealed class LdapClientProvisioningStoreTests allowedGrantTypes: new[] { "client_credentials" }, allowedScopes: new[] { "signer.sign" }); - var result = await store.CreateOrUpdateAsync(registration, CancellationToken.None); + var result = await store.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.False(result.Succeeded); Assert.Equal("disabled", result.ErrorCode); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Credentials/LdapCredentialStoreTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Credentials/LdapCredentialStoreTests.cs index 0d63f816c..969274429 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Credentials/LdapCredentialStoreTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Credentials/LdapCredentialStoreTests.cs @@ -44,7 +44,7 @@ public class LdapCredentialStoreTests monitor, new FakeLdapConnectionFactory(connection)); - var result = await store.VerifyPasswordAsync("J.Doe", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("J.Doe", "Password1!", TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.Equal(2, bindCalls.Count); @@ -86,7 +86,7 @@ public class LdapCredentialStoreTests monitor, new FakeLdapConnectionFactory(connection)); - var result = await store.VerifyPasswordAsync("J.Doe", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("J.Doe", "Password1!", TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.NotNull(result.User); @@ -119,7 +119,7 @@ public class LdapCredentialStoreTests new FakeLdapConnectionFactory(connection), delayAsync: (_, _) => Task.CompletedTask); - var result = await store.VerifyPasswordAsync("jdoe", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("jdoe", "Password1!", TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.Equal(2, attempts); @@ -142,7 +142,7 @@ public class LdapCredentialStoreTests new FakeLdapConnectionFactory(connection), delayAsync: (_, _) => Task.CompletedTask); - var result = await store.VerifyPasswordAsync("jdoe", "bad", CancellationToken.None); + var result = await store.VerifyPasswordAsync("jdoe", "bad", TestContext.Current.CancellationToken); Assert.False(result.Succeeded); Assert.Equal(AuthorityCredentialFailureCode.InvalidCredentials, result.FailureCode); @@ -176,7 +176,7 @@ public class LdapCredentialStoreTests monitor, new FakeLdapConnectionFactory(connection)); - var result = await store.FindBySubjectAsync("uid=j.doe,ou=people,dc=example,dc=internal", CancellationToken.None); + var result = await store.FindBySubjectAsync("uid=j.doe,ou=people,dc=example,dc=internal", TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("uid=j.doe,ou=people,dc=example,dc=internal", result!.SubjectId); @@ -201,7 +201,7 @@ public class LdapCredentialStoreTests email: "bootstrap@example.internal", requirePasswordReset: true); - var result = await store.UpsertUserAsync(registration, CancellationToken.None); + var result = await store.UpsertUserAsync(registration, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.Contains(connection.Operations, op => op.StartsWith("add:uid=bootstrap.user", StringComparison.OrdinalIgnoreCase)); @@ -234,7 +234,7 @@ public class LdapCredentialStoreTests email: "bootstrap@example.internal", requirePasswordReset: false); - var result = await store.UpsertUserAsync(registration, CancellationToken.None); + var result = await store.UpsertUserAsync(registration, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.Contains(connection.Operations, op => op.StartsWith("modify:uid=bootstrap.user", StringComparison.OrdinalIgnoreCase)); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Resilience/LdapConnectorResilienceTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Resilience/LdapConnectorResilienceTests.cs index bab31bc0f..9f3c8bc5f 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Resilience/LdapConnectorResilienceTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Resilience/LdapConnectorResilienceTests.cs @@ -61,7 +61,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("noname", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("noname", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeTrue("Missing displayName should not prevent authentication"); @@ -88,7 +88,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("nomail", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("nomail", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeTrue("Missing mail should not prevent authentication"); @@ -113,7 +113,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("nogroups", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("nogroups", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeTrue("Empty memberOf should not prevent authentication"); @@ -135,7 +135,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("nonexistent", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("nonexistent", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Nonexistent user should fail authentication"); @@ -177,7 +177,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync("user", "WrongPassword!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("user", "WrongPassword!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Wrong password should fail authentication"); @@ -200,7 +200,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("malformed", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("malformed", "Password1!", TestContext.Current.CancellationToken); // Assert - should handle gracefully (either succeed with warning or fail cleanly) // The exact behavior depends on implementation @@ -225,7 +225,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", CancellationToken.None); + Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", TestContext.Current.CancellationToken); // Assert await act.Should().ThrowAsync(); @@ -247,7 +247,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", CancellationToken.None); + Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", TestContext.Current.CancellationToken); // Assert await act.Should().ThrowAsync(); @@ -303,7 +303,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("münchen-user", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("münchen-user", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeTrue("Unicode username should be handled"); @@ -329,7 +329,7 @@ public sealed class LdapConnectorResilienceTests var store = CreateStore(options, connection); // Act - var result = await store.VerifyPasswordAsync("user+test", "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync("user+test", "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeTrue("Special characters in DN should be handled"); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Security/LdapConnectorSecurityTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Security/LdapConnectorSecurityTests.cs index 73c54cffd..89cd563a9 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Security/LdapConnectorSecurityTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Security/LdapConnectorSecurityTests.cs @@ -69,7 +69,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync(maliciousUsername, "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync(maliciousUsername, "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Injection attempt should fail"); @@ -103,7 +103,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync(emptyUsername, "Password1!", CancellationToken.None); + var result = await store.VerifyPasswordAsync(emptyUsername, "Password1!", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Empty username should be rejected"); @@ -120,7 +120,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync("user", null!, CancellationToken.None); + var result = await store.VerifyPasswordAsync("user", null!, TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Null password should be rejected"); @@ -137,7 +137,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync("user", "", CancellationToken.None); + var result = await store.VerifyPasswordAsync("user", "", TestContext.Current.CancellationToken); // Assert result.Succeeded.Should().BeFalse("Empty password should be rejected"); @@ -169,7 +169,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", CancellationToken.None); + Func act = async () => await store.VerifyPasswordAsync("user", "Password1!", TestContext.Current.CancellationToken); // Assert await act.Should().ThrowAsync(); @@ -201,7 +201,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - await store.VerifyPasswordAsync("targetuser", "Password1!", CancellationToken.None); + await store.VerifyPasswordAsync("targetuser", "Password1!", TestContext.Current.CancellationToken); // Assert bindDns.Should().HaveCountGreaterThanOrEqualTo(2, "Should bind as service then as user"); @@ -289,7 +289,7 @@ public sealed class LdapConnectorSecurityTests // Act try { - await store.VerifyPasswordAsync("user", "SuperSecret123!", CancellationToken.None); + await store.VerifyPasswordAsync("user", "SuperSecret123!", TestContext.Current.CancellationToken); } catch { @@ -308,7 +308,7 @@ public sealed class LdapConnectorSecurityTests var store = CreateStore(options, new FakeLdapConnectionFactory(connection)); // Act - var result = await store.VerifyPasswordAsync("user", "MyPassword123", CancellationToken.None); + var result = await store.VerifyPasswordAsync("user", "MyPassword123", TestContext.Current.CancellationToken); // Assert var resultString = result.ToString(); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Snapshots/LdapConnectorSnapshotTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Snapshots/LdapConnectorSnapshotTests.cs index efb6a795a..84dd7972d 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Snapshots/LdapConnectorSnapshotTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Ldap.Tests/Snapshots/LdapConnectorSnapshotTests.cs @@ -112,13 +112,13 @@ public sealed class LdapConnectorSnapshotTests { // Arrange var fixtureFiles = Directory.Exists(FixturesPath) - ? Directory.EnumerateFiles(FixturesPath, "*.json").Select(Path.GetFileNameWithoutExtension).ToList() + ? Directory.EnumerateFiles(FixturesPath, "*.json").Select(Path.GetFileNameWithoutExtension).Where(n => n is not null).Cast().ToList() : new List(); var expectedFiles = Directory.Exists(ExpectedPath) ? Directory.EnumerateFiles(ExpectedPath, "*.canonical.json") - .Select(f => Path.GetFileNameWithoutExtension(f).Replace(".canonical", "")) - .ToList() + .Select(f => Path.GetFileNameWithoutExtension(f)?.Replace(".canonical", "")) + .Where(n => n is not null).Cast().ToList() : new List(); // Assert diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Credentials/OidcCredentialStoreTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Credentials/OidcCredentialStoreTests.cs index ed05ce4d0..ab7200a35 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Credentials/OidcCredentialStoreTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Credentials/OidcCredentialStoreTests.cs @@ -52,7 +52,7 @@ public sealed class OidcCredentialStoreTests username: "user@example.com", signingCredentials: new SigningCredentials(symmetricKey, SecurityAlgorithms.HmacSha256)); - var result = await store.VerifyPasswordAsync("user@example.com", token, CancellationToken.None); + var result = await store.VerifyPasswordAsync("user@example.com", token, TestContext.Current.CancellationToken); Assert.False(result.Succeeded); Assert.Equal(AuthorityCredentialFailureCode.InvalidCredentials, result.FailureCode); @@ -102,10 +102,10 @@ public sealed class OidcCredentialStoreTests username: "user2@example.com", signingCredentials: new SigningCredentials(rsaKey, SecurityAlgorithms.RsaSha256)); - var result = await storeA.VerifyPasswordAsync("user2@example.com", token, CancellationToken.None); + var result = await storeA.VerifyPasswordAsync("user2@example.com", token, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); - var cached = await storeB.FindBySubjectAsync("user-2", CancellationToken.None); + var cached = await storeB.FindBySubjectAsync("user-2", TestContext.Current.CancellationToken); Assert.Null(cached); } @@ -220,8 +220,8 @@ public sealed class OidcCredentialStoreTests public OidcPluginOptions CurrentValue => options.Values.First(); - public OidcPluginOptions Get(string name) - => options.TryGetValue(name, out var value) ? value : options.Values.First(); + public OidcPluginOptions Get(string? name) + => name is not null && options.TryGetValue(name, out var value) ? value : options.Values.First(); public IDisposable OnChange(Action listener) => new NoopDisposable(); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/OidcIdentityProviderPluginTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/OidcIdentityProviderPluginTests.cs index 091a2e3d8..be5cb563e 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/OidcIdentityProviderPluginTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/OidcIdentityProviderPluginTests.cs @@ -23,7 +23,7 @@ public sealed class OidcIdentityProviderPluginTests { var (plugin, _) = CreatePlugin(HttpStatusCode.OK); - var result = await plugin.CheckHealthAsync(CancellationToken.None); + var result = await plugin.CheckHealthAsync(TestContext.Current.CancellationToken); Assert.Equal(AuthorityPluginHealthStatus.Healthy, result.Status); } @@ -33,7 +33,7 @@ public sealed class OidcIdentityProviderPluginTests { var (plugin, _) = CreatePlugin(HttpStatusCode.ServiceUnavailable); - var result = await plugin.CheckHealthAsync(CancellationToken.None); + var result = await plugin.CheckHealthAsync(TestContext.Current.CancellationToken); Assert.Equal(AuthorityPluginHealthStatus.Degraded, result.Status); } @@ -132,7 +132,7 @@ public sealed class OidcIdentityProviderPluginTests public OidcPluginOptions CurrentValue => options; - public OidcPluginOptions Get(string name) + public OidcPluginOptions Get(string? name) => string.Equals(name, pluginName, StringComparison.Ordinal) ? options : options; public IDisposable OnChange(Action listener) diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Snapshots/OidcConnectorSnapshotTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Snapshots/OidcConnectorSnapshotTests.cs index 8c4d71475..03193726c 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Snapshots/OidcConnectorSnapshotTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Oidc.Tests/Snapshots/OidcConnectorSnapshotTests.cs @@ -129,13 +129,13 @@ public sealed class OidcConnectorSnapshotTests { // Arrange var fixtureFiles = Directory.Exists(FixturesPath) - ? Directory.EnumerateFiles(FixturesPath, "*.json").Select(Path.GetFileNameWithoutExtension).ToList() + ? Directory.EnumerateFiles(FixturesPath, "*.json").Select(Path.GetFileNameWithoutExtension).Where(n => n is not null).Cast().ToList() : new List(); var expectedFiles = Directory.Exists(ExpectedPath) ? Directory.EnumerateFiles(ExpectedPath, "*.canonical.json") .Select(f => Path.GetFileNameWithoutExtension(f)?.Replace(".canonical", "")) - .ToList() + .Where(n => n is not null).Cast().ToList() : new List(); // Assert diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/SamlIdentityProviderPluginTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/SamlIdentityProviderPluginTests.cs index d44597573..90783be48 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/SamlIdentityProviderPluginTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/SamlIdentityProviderPluginTests.cs @@ -23,7 +23,7 @@ public sealed class SamlIdentityProviderPluginTests { var plugin = CreatePlugin(HttpStatusCode.OK); - var result = await plugin.CheckHealthAsync(CancellationToken.None); + var result = await plugin.CheckHealthAsync(TestContext.Current.CancellationToken); Assert.Equal(AuthorityPluginHealthStatus.Healthy, result.Status); } @@ -33,7 +33,7 @@ public sealed class SamlIdentityProviderPluginTests { var plugin = CreatePlugin(HttpStatusCode.ServiceUnavailable); - var result = await plugin.CheckHealthAsync(CancellationToken.None); + var result = await plugin.CheckHealthAsync(TestContext.Current.CancellationToken); Assert.Equal(AuthorityPluginHealthStatus.Degraded, result.Status); } @@ -130,7 +130,7 @@ public sealed class SamlIdentityProviderPluginTests public SamlPluginOptions CurrentValue => options; - public SamlPluginOptions Get(string name) + public SamlPluginOptions Get(string? name) => string.Equals(name, pluginName, StringComparison.Ordinal) ? options : options; public IDisposable OnChange(Action listener) diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/Snapshots/SamlConnectorSnapshotTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/Snapshots/SamlConnectorSnapshotTests.cs index 98d85d983..1516672e8 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/Snapshots/SamlConnectorSnapshotTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Saml.Tests/Snapshots/SamlConnectorSnapshotTests.cs @@ -122,13 +122,13 @@ public sealed class SamlConnectorSnapshotTests { // Arrange var fixtureFiles = Directory.Exists(FixturesPath) - ? Directory.EnumerateFiles(FixturesPath, "*.xml").Select(Path.GetFileNameWithoutExtension).ToList() + ? Directory.EnumerateFiles(FixturesPath, "*.xml").Select(Path.GetFileNameWithoutExtension).Where(n => n is not null).Cast().ToList() : new List(); var expectedFiles = Directory.Exists(ExpectedPath) ? Directory.EnumerateFiles(ExpectedPath, "*.canonical.json") .Select(f => Path.GetFileNameWithoutExtension(f)?.Replace(".canonical", "")) - .ToList() + .Where(n => n is not null).Cast().ToList() : new List(); // Assert diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/Security/StandardCredentialAuditLoggerTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/Security/StandardCredentialAuditLoggerTests.cs index 817d39832..496719f57 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/Security/StandardCredentialAuditLoggerTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/Security/StandardCredentialAuditLoggerTests.cs @@ -39,7 +39,7 @@ public class StandardCredentialAuditLoggerTests failureCode: null, reason: null, properties: Array.Empty(), - CancellationToken.None); + TestContext.Current.CancellationToken); var record = Assert.Single(sink.Records); Assert.Equal("authority.plugin.standard.password_verification", record.EventType); @@ -92,7 +92,7 @@ public class StandardCredentialAuditLoggerTests failureCode: AuthorityCredentialFailureCode.InvalidCredentials, reason: "Invalid credentials.", properties, - CancellationToken.None); + TestContext.Current.CancellationToken); var record = Assert.Single(sink.Records); Assert.Equal(AuthEventOutcome.Failure, record.Outcome); @@ -147,7 +147,7 @@ public class StandardCredentialAuditLoggerTests failureCode: AuthorityCredentialFailureCode.LockedOut, reason: "Account locked.", properties, - CancellationToken.None); + TestContext.Current.CancellationToken); var record = Assert.Single(sink.Records); Assert.Equal(AuthEventOutcome.LockedOut, record.Outcome); @@ -189,7 +189,7 @@ public class StandardCredentialAuditLoggerTests failureCode: AuthorityCredentialFailureCode.RequiresMfa, reason: "MFA required.", properties: null, - CancellationToken.None); + TestContext.Current.CancellationToken); var record = Assert.Single(sink.Records); var property = Assert.Single(record.Properties); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClaimsEnricherTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClaimsEnricherTests.cs index 88f1e450c..d476f1312 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClaimsEnricherTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClaimsEnricherTests.cs @@ -43,7 +43,7 @@ public class StandardClaimsEnricherTests var identity = new ClaimsIdentity(); var enricher = new StandardClaimsEnricher(); - await enricher.EnrichAsync(identity, context, CancellationToken.None); + await enricher.EnrichAsync(identity, context, TestContext.Current.CancellationToken); Assert.Contains(identity.Claims, claim => claim.Type == ClaimTypes.Role && claim.Value == "admin"); Assert.Contains(identity.Claims, claim => claim.Type == ClaimTypes.Role && claim.Value == "ops"); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClientProvisioningStoreTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClientProvisioningStoreTests.cs index 103e89379..98743eee3 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClientProvisioningStoreTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardClientProvisioningStoreTests.cs @@ -32,7 +32,7 @@ public class StandardClientProvisioningStoreTests allowedGrantTypes: new[] { "client_credentials" }, allowedScopes: new[] { "scopeA" }); - var result = await provisioning.CreateOrUpdateAsync(registration, CancellationToken.None); + var result = await provisioning.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.True(store.Documents.TryGetValue("bootstrap-client", out var document)); @@ -40,7 +40,7 @@ public class StandardClientProvisioningStoreTests Assert.Equal(AuthoritySecretHasher.ComputeHash("SuperSecret1!"), document!.SecretHash); Assert.Equal("standard", document.Plugin); - var descriptor = await provisioning.FindByClientIdAsync("bootstrap-client", CancellationToken.None); + var descriptor = await provisioning.FindByClientIdAsync("bootstrap-client", TestContext.Current.CancellationToken); Assert.NotNull(descriptor); Assert.Equal("bootstrap-client", descriptor!.ClientId); Assert.True(descriptor.Confidential); @@ -65,13 +65,13 @@ public class StandardClientProvisioningStoreTests allowedScopes: new[] { "scopeA" }, tenant: " Tenant-Alpha " ); - await provisioning.CreateOrUpdateAsync(registration, CancellationToken.None); + await provisioning.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.True(store.Documents.TryGetValue("tenant-client", out var document)); Assert.NotNull(document); Assert.Equal("tenant-alpha", document!.Properties[AuthorityClientMetadataKeys.Tenant]); - var descriptor = await provisioning.FindByClientIdAsync("tenant-client", CancellationToken.None); + var descriptor = await provisioning.FindByClientIdAsync("tenant-client", TestContext.Current.CancellationToken); Assert.NotNull(descriptor); Assert.Equal("tenant-alpha", descriptor!.Tenant); } @@ -92,14 +92,14 @@ public class StandardClientProvisioningStoreTests allowedScopes: new[] { "signer.sign" }, allowedAudiences: new[] { "attestor", "signer" }); - var result = await provisioning.CreateOrUpdateAsync(registration, CancellationToken.None); + var result = await provisioning.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.True(store.Documents.TryGetValue("signer", out var document)); Assert.NotNull(document); Assert.Equal("attestor signer", document!.Properties[AuthorityClientMetadataKeys.Audiences]); - var descriptor = await provisioning.FindByClientIdAsync("signer", CancellationToken.None); + var descriptor = await provisioning.FindByClientIdAsync("signer", TestContext.Current.CancellationToken); Assert.NotNull(descriptor); Assert.Equal(new[] { "attestor", "signer" }, descriptor!.AllowedAudiences.OrderBy(value => value, StringComparer.Ordinal)); } @@ -132,7 +132,7 @@ public class StandardClientProvisioningStoreTests allowedAudiences: new[] { "signer" }, certificateBindings: new[] { bindingRegistration }); - await provisioning.CreateOrUpdateAsync(registration, CancellationToken.None); + await provisioning.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); Assert.True(store.Documents.TryGetValue("mtls-client", out var document)); Assert.NotNull(document); @@ -164,9 +164,9 @@ public class StandardClientProvisioningStoreTests allowedGrantTypes: new[] { "client_credentials" }, allowedScopes: new[] { "scopeA" }); - await provisioning.CreateOrUpdateAsync(registration, CancellationToken.None); + await provisioning.CreateOrUpdateAsync(registration, TestContext.Current.CancellationToken); - var result = await provisioning.DeleteAsync("delete-me", CancellationToken.None); + var result = await provisioning.DeleteAsync("delete-me", TestContext.Current.CancellationToken); Assert.True(result.Succeeded); Assert.False(store.Documents.ContainsKey("delete-me")); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardIdentityProviderPluginTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardIdentityProviderPluginTests.cs index 952512032..74fa99c98 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardIdentityProviderPluginTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardIdentityProviderPluginTests.cs @@ -58,7 +58,7 @@ public class StandardIdentityProviderPluginTests new StandardClaimsEnricher(), NullLogger.Instance); - var health = await plugin.CheckHealthAsync(CancellationToken.None); + var health = await plugin.CheckHealthAsync(TestContext.Current.CancellationToken); Assert.Equal(AuthorityPluginHealthStatus.Healthy, health.Status); } diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardPluginBootstrapperTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardPluginBootstrapperTests.cs index c38f75ae9..6ef98ba5e 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardPluginBootstrapperTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardPluginBootstrapperTests.cs @@ -67,7 +67,7 @@ public class StandardPluginBootstrapperTests using var provider = services.BuildServiceProvider(); var bootstrapper = provider.GetRequiredService(); - var exception = await Record.ExceptionAsync(() => bootstrapper.StartAsync(CancellationToken.None)); + var exception = await Record.ExceptionAsync(() => bootstrapper.StartAsync(TestContext.Current.CancellationToken)); Assert.Null(exception); } diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardUserCredentialStoreTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardUserCredentialStoreTests.cs index a09d53116..2365fdc86 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardUserCredentialStoreTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Plugin.Standard.Tests/StandardUserCredentialStoreTests.cs @@ -228,6 +228,7 @@ public class StandardUserCredentialStoreTests : IAsyncLifetime var updated = await store.UpsertUserAsync(update, CancellationToken.None); Assert.True(updated.Succeeded); + Assert.NotNull(updated.Value); Assert.Contains("editor", updated.Value.Roles); Assert.Contains("admin", updated.Value.Roles); Assert.Equal("us", updated.Value.Attributes["region"]); @@ -250,6 +251,7 @@ public class StandardUserCredentialStoreTests : IAsyncLifetime var created = await store.UpsertUserAsync(registration, CancellationToken.None); Assert.True(created.Succeeded); + Assert.NotNull(created.Value); var found = await store.FindBySubjectAsync(created.Value.SubjectId, CancellationToken.None); Assert.NotNull(found); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/AdvisoryAi/AdvisoryAiRemoteInferenceEndpointTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/AdvisoryAi/AdvisoryAiRemoteInferenceEndpointTests.cs index 559b294be..341d937d6 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/AdvisoryAi/AdvisoryAiRemoteInferenceEndpointTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/AdvisoryAi/AdvisoryAiRemoteInferenceEndpointTests.cs @@ -115,7 +115,7 @@ public sealed class AdvisoryAiRemoteInferenceEndpointTests : IClassFixture record.EventType == "authority.advisory_ai.remote_inference")); + var doc = Assert.Single(lastLoginAttemptStore!.Records, record => record.EventType == "authority.advisory_ai.remote_inference"); Assert.Equal("authority.advisory_ai.remote_inference", doc.EventType); var properties = doc.Properties.ToDictionary(p => p.Name, p => p.Value); Assert.Equal(expectedHash, properties["advisory_ai.prompt.hash"]); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/Audit/AuthorityAuditSinkTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/Audit/AuthorityAuditSinkTests.cs index 9ad42f5e3..fe5f5a191 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/Audit/AuthorityAuditSinkTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/Audit/AuthorityAuditSinkTests.cs @@ -77,7 +77,7 @@ public class AuthorityAuditSinkTests Assert.Equal(record.OccurredAt, document.OccurredAt); Assert.Equal(new[] { "openid", "profile" }, document.Scopes); - var pluginProperty = Assert.Single(document.Properties.Where(property => property.Name == "plugin.failed_attempts")); + var pluginProperty = Assert.Single(document.Properties, property => property.Name == "plugin.failed_attempts"); Assert.Equal("0", pluginProperty.Value); Assert.Equal("none", pluginProperty.Classification); diff --git a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/OpenIddict/ClientCredentialsAndTokenHandlersTests.cs b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/OpenIddict/ClientCredentialsAndTokenHandlersTests.cs index 81456003c..c911d3672 100644 --- a/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/OpenIddict/ClientCredentialsAndTokenHandlersTests.cs +++ b/src/Authority/StellaOps.Authority/StellaOps.Authority.Tests/OpenIddict/ClientCredentialsAndTokenHandlersTests.cs @@ -2926,9 +2926,9 @@ public class ClientCredentialsHandlersTests Assert.False(validateContext.IsRejected); Assert.False(validateContext.Transaction.Properties.ContainsKey(AuthorityOpenIddictConstants.SenderConstraintProperty)); - var bypassEvent = Assert.Single(auditSink.Events.Where(record => record.EventType == "authority.dpop.proof.bypass")); + var bypassEvent = Assert.Single(auditSink.Events, record => record.EventType == "authority.dpop.proof.bypass"); Assert.Equal(AuthEventOutcome.Success, bypassEvent.Outcome); - var reasonProperty = Assert.Single(bypassEvent.Properties.Where(property => property.Name == "dpop.reason_code")); + var reasonProperty = Assert.Single(bypassEvent.Properties, property => property.Name == "dpop.reason_code"); Assert.Equal("bypass", reasonProperty.Value.Value); } @@ -3387,7 +3387,7 @@ public class ClientCredentialsHandlersTests var grantEvent = authSink.Events.LastOrDefault(evt => evt.EventType == "authority.client_credentials.grant"); Assert.NotNull(grantEvent); - var serviceProperty = Assert.Single(grantEvent!.Properties.Where(prop => prop.Name == "delegation.service_account")); + var serviceProperty = Assert.Single(grantEvent!.Properties, prop => prop.Name == "delegation.service_account"); Assert.Equal(serviceAccount.AccountId, serviceProperty.Value.Value); var actorPropertyValues = grantEvent.Properties diff --git a/src/Authority/__Tests/StellaOps.Authority.ConfigDiff.Tests/AuthorityConfigDiffTests.cs b/src/Authority/__Tests/StellaOps.Authority.ConfigDiff.Tests/AuthorityConfigDiffTests.cs index 04afcc96d..baeb7bad0 100644 --- a/src/Authority/__Tests/StellaOps.Authority.ConfigDiff.Tests/AuthorityConfigDiffTests.cs +++ b/src/Authority/__Tests/StellaOps.Authority.ConfigDiff.Tests/AuthorityConfigDiffTests.cs @@ -22,6 +22,9 @@ namespace StellaOps.Authority.ConfigDiff.Tests; [Trait("BlastRadius", TestCategories.BlastRadius.Auth)] public class AuthorityConfigDiffTests : ConfigDiffTestBase { + private static readonly DateTimeOffset SnapshotTimestamp = + new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero); + /// /// Initializes a new instance of the class. /// @@ -61,7 +64,8 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase async config => await GetSessionBehaviorAsync(config), async config => await GetRefreshBehaviorAsync(config), async config => await GetAuthenticationBehaviorAsync(config) - ]); + ], + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -93,7 +97,8 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase changedConfig, getBehavior: async config => await CaptureSessionBehaviorAsync(config), computeDelta: ComputeBehaviorSnapshotDelta, - expectedDelta: expectedDelta); + expectedDelta: expectedDelta, + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -119,7 +124,8 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase [ async config => await GetSessionBehaviorAsync(config), async config => await GetPasswordPolicyBehaviorAsync(config) - ]); + ], + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -151,7 +157,8 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase changedConfig, getBehavior: async config => await CapturePasswordPolicyBehaviorAsync(config), computeDelta: ComputeBehaviorSnapshotDelta, - expectedDelta: expectedDelta); + expectedDelta: expectedDelta, + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue(); @@ -176,7 +183,8 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase [ async config => await GetTokenBehaviorAsync(config), async config => await GetSessionBehaviorAsync(config) - ]); + ], + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -216,11 +224,11 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase ConfigurationId: $"sessions-{config.MaxConcurrentSessions}", Behaviors: [ - new CapturedBehavior("SessionLimit", config.MaxConcurrentSessions.ToString(), DateTimeOffset.UtcNow), + new CapturedBehavior("SessionLimit", config.MaxConcurrentSessions.ToString(), SnapshotTimestamp), new CapturedBehavior("ConcurrencyPolicy", - config.MaxConcurrentSessions > 5 ? "permissive" : "restrictive", DateTimeOffset.UtcNow) + config.MaxConcurrentSessions > 5 ? "permissive" : "restrictive", SnapshotTimestamp) ], - CapturedAt: DateTimeOffset.UtcNow); + CapturedAt: SnapshotTimestamp); return Task.FromResult(snapshot); } @@ -232,11 +240,11 @@ public class AuthorityConfigDiffTests : ConfigDiffTestBase Behaviors: [ new CapturedBehavior("PasswordComplexity", - config.MinPasswordLength >= 12 ? "enhanced" : "standard", DateTimeOffset.UtcNow), + config.MinPasswordLength >= 12 ? "enhanced" : "standard", SnapshotTimestamp), new CapturedBehavior("ValidationRejectionRate", - config.MinPasswordLength >= 12 ? "increase" : "standard", DateTimeOffset.UtcNow) + config.MinPasswordLength >= 12 ? "increase" : "standard", SnapshotTimestamp) ], - CapturedAt: DateTimeOffset.UtcNow); + CapturedAt: SnapshotTimestamp); return Task.FromResult(snapshot); } diff --git a/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/AuthorityPostgresFixture.cs b/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/AuthorityPostgresFixture.cs index b79c34ac5..e16fc75dd 100644 --- a/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/AuthorityPostgresFixture.cs +++ b/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/AuthorityPostgresFixture.cs @@ -33,7 +33,7 @@ public sealed class AuthorityPostgresFixture : PostgresIntegrationFixture, IColl public PostgresOptions CreateOptions() { var options = Fixture.CreateOptions(); - options.SchemaName = SchemaName; + options.SchemaName = AuthorityDataSource.DefaultSchemaName; options.MaxPoolSize = 10; options.MinPoolSize = 0; return options; diff --git a/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/VerdictManifestStoreTests.cs b/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/VerdictManifestStoreTests.cs index bb56882dc..1f900af42 100644 --- a/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/VerdictManifestStoreTests.cs +++ b/src/Authority/__Tests/StellaOps.Authority.Persistence.Tests/VerdictManifestStoreTests.cs @@ -1,5 +1,4 @@ using System.Collections.Immutable; -using System.Threading; using FluentAssertions; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; @@ -7,6 +6,7 @@ using Npgsql; using StellaOps.Authority.Core.Verdicts; using StellaOps.Authority.Persistence.Postgres; using StellaOps.TestKit; +using System.Text.Json; using Xunit; namespace StellaOps.Authority.Persistence.Tests; @@ -37,7 +37,7 @@ public sealed class VerdictManifestStoreTests : IAsyncLifetime [Fact] public async Task StoreAndGetById_RoundTripsManifest() { - var evaluatedAt = DateTimeOffset.Parse("2025-01-15T10:00:00Z"); + var evaluatedAt = new DateTimeOffset(2025, 1, 15, 10, 0, 0, TimeSpan.Zero); var manifest = CreateManifest("tenant-1", "manifest-001", evaluatedAt, VexStatus.NotAffected); await _store.StoreAsync(manifest); @@ -58,12 +58,15 @@ public sealed class VerdictManifestStoreTests : IAsyncLifetime [Fact] public async Task StoreAsync_WritesStringEnumJson() { - var evaluatedAt = DateTimeOffset.Parse("2025-01-15T11:00:00Z"); + var evaluatedAt = new DateTimeOffset(2025, 1, 15, 11, 0, 0, TimeSpan.Zero); var manifest = CreateManifest("tenant-2", "manifest-002", evaluatedAt, VexStatus.UnderInvestigation); await _store.StoreAsync(manifest); - await using var conn = await _dataSource.OpenConnectionAsync(manifest.Tenant, "reader", CancellationToken.None); + await using var conn = await _dataSource.OpenConnectionAsync( + manifest.Tenant, + "reader", + TestContext.Current.CancellationToken); await using var cmd = new NpgsqlCommand(""" SELECT result_json::text FROM verdict_manifests @@ -77,7 +80,8 @@ public sealed class VerdictManifestStoreTests : IAsyncLifetime var json = (string?)await cmd.ExecuteScalarAsync(); json.Should().NotBeNull(); - json.Should().Contain("\"status\":\"under_investigation\""); + using var document = JsonDocument.Parse(json!); + document.RootElement.GetProperty("status").GetString().Should().Be("under_investigation"); } private static VerdictManifest CreateManifest(string tenant, string manifestId, DateTimeOffset evaluatedAt, VexStatus status) diff --git a/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs b/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs index 18516c098..741b01dec 100644 --- a/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs +++ b/src/Cli/__Tests/StellaOps.Cli.Tests/Commands/CommandHandlersTests.cs @@ -223,7 +223,7 @@ public sealed class CommandHandlersTests Assert.Equal("scan-missing", backend.LastEntryTraceScanId); Assert.Contains("No EntryTrace data", output.Combined, StringComparison.OrdinalIgnoreCase); - var warning = Assert.Single(loggerProvider.Entries.Where(entry => entry.Level == LogLevel.Warning)); + var warning = Assert.Single(loggerProvider.Entries, entry => entry.Level == LogLevel.Warning); Assert.Contains("No EntryTrace data", warning.Message, StringComparison.OrdinalIgnoreCase); } finally diff --git a/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/AnalyzerReleases.Unshipped.md b/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/AnalyzerReleases.Unshipped.md index 63415e80e..c4ce85da1 100644 --- a/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/AnalyzerReleases.Unshipped.md @@ -1,5 +1,7 @@ -## Release History +; Unshipped analyzer releases -### Unreleased +### New Rules -- CONCELIER0004: Flag direct `new HttpClient()` usage inside `StellaOps.Concelier.Connector*` namespaces; require sandboxed `IHttpClientFactory` to enforce allow/deny lists. Exempts test assemblies and uses symbol-based namespace matching. +Rule ID | Category | Severity | Notes +--------|----------|----------|------ +CONCELIER0004 | Sandbox | Warning | Flag direct `new HttpClient()` usage inside `StellaOps.Concelier.Connector*` namespaces diff --git a/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/ConnectorHttpClientSandboxAnalyzer.cs b/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/ConnectorHttpClientSandboxAnalyzer.cs index 200bd90cf..8e3a0e177 100644 --- a/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/ConnectorHttpClientSandboxAnalyzer.cs +++ b/src/Concelier/__Analyzers/StellaOps.Concelier.Analyzers/ConnectorHttpClientSandboxAnalyzer.cs @@ -15,7 +15,7 @@ public sealed class ConnectorHttpClientSandboxAnalyzer : DiagnosticAnalyzer private static readonly DiagnosticDescriptor Rule = new( id: DiagnosticId, title: "Connector HTTP clients must use sandboxed factory", - messageFormat: "Use IHttpClientFactory or connector sandbox helpers instead of 'new HttpClient()' inside Concelier connectors.", + messageFormat: "Use IHttpClientFactory or connector sandbox helpers instead of 'new HttpClient()' inside Concelier connectors", category: "Sandbox", defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, @@ -73,7 +73,7 @@ public sealed class ConnectorHttpClientSandboxAnalyzer : DiagnosticAnalyzer return false; } - return assemblyName.EndsWith(".Tests", StringComparison.OrdinalIgnoreCase) + return assemblyName!.EndsWith(".Tests", StringComparison.OrdinalIgnoreCase) || assemblyName.EndsWith(".Test", StringComparison.OrdinalIgnoreCase) || assemblyName.EndsWith(".Testing", StringComparison.OrdinalIgnoreCase); } diff --git a/src/Concelier/__Analyzers/StellaOps.Concelier.Merge.Analyzers/AnalyzerReleases.Unshipped.md b/src/Concelier/__Analyzers/StellaOps.Concelier.Merge.Analyzers/AnalyzerReleases.Unshipped.md index 4dad2afeb..dab24d1ca 100644 --- a/src/Concelier/__Analyzers/StellaOps.Concelier.Merge.Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Concelier/__Analyzers/StellaOps.Concelier.Merge.Analyzers/AnalyzerReleases.Unshipped.md @@ -1,9 +1,7 @@ -## Release History +; Unshipped analyzer releases -### Unreleased +### New Rules -#### New Rules - -Rule ID | Title | Notes ---------|-------|------ -CONCELIER0002 | Legacy merge service usage detected | Flags references to `AdvisoryMergeService` and `AddMergeModule`. +Rule ID | Category | Severity | Notes +--------|----------|----------|------ +CONCELIER0002 | Usage | Warning | Legacy merge service usage detected - flags references to `AdvisoryMergeService` and `AddMergeModule` diff --git a/src/Concelier/__Connectors/StellaOps.Concelier.Connector.Astra/AstraConnector.cs b/src/Concelier/__Connectors/StellaOps.Concelier.Connector.Astra/AstraConnector.cs index 26fce2244..28dd20abc 100644 --- a/src/Concelier/__Connectors/StellaOps.Concelier.Connector.Astra/AstraConnector.cs +++ b/src/Concelier/__Connectors/StellaOps.Concelier.Connector.Astra/AstraConnector.cs @@ -185,6 +185,11 @@ public sealed class AstraConnector : IFeedConnector /// private async Task FetchOvalDatabaseAsync(string version, CancellationToken cancellationToken) { + if (_fetchService is null || _rawDocumentStorage is null) + { + throw new InvalidOperationException("Fetch and raw document storage services are required for OVAL database fetch"); + } + var uri = _options.BuildOvalDatabaseUri(version); _logger.LogDebug("Fetching OVAL database for Astra Linux {Version} from {Uri}", version, uri); @@ -197,18 +202,24 @@ public sealed class AstraConnector : IFeedConnector var result = await _fetchService.FetchAsync(request, cancellationToken).ConfigureAwait(false); - if (!result.IsSuccess || result.Document is null) + if (result is null || !result.IsSuccess || result.Document is null) { throw new InvalidOperationException($"Failed to fetch OVAL database for version {version}"); } - if (!result.Document.PayloadId.HasValue) + var document = result.Document; + + if (!document.PayloadId.HasValue) { throw new InvalidOperationException($"OVAL database document for version {version} has no payload"); } // Download the raw XML content - var payloadBytes = await _rawDocumentStorage.DownloadAsync(result.Document.PayloadId.Value, cancellationToken).ConfigureAwait(false); + var payloadBytes = await _rawDocumentStorage.DownloadAsync(document.PayloadId.Value, cancellationToken).ConfigureAwait(false); + if (payloadBytes is null) + { + throw new InvalidOperationException($"OVAL database payload for version {version} not found"); + } return System.Text.Encoding.UTF8.GetString(payloadBytes); } diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/Internal/CccsHtmlParser.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/Internal/CccsHtmlParser.cs index 6e52e9be1..67414867d 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/Internal/CccsHtmlParser.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/Internal/CccsHtmlParser.cs @@ -359,7 +359,7 @@ public sealed class CccsHtmlParser var candidate = href.Trim(); var hasAbsolute = Uri.TryCreate(candidate, UriKind.Absolute, out var absolute); - if (!hasAbsolute || string.Equals(absolute.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) + if (!hasAbsolute || absolute is null || string.Equals(absolute.Scheme, Uri.UriSchemeFile, StringComparison.OrdinalIgnoreCase)) { if (baseUri is null || !Uri.TryCreate(baseUri, candidate, out absolute)) { diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/CertCcConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/CertCcConnector.cs index e0ba1204d..a77c775df 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/CertCcConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/CertCcConnector.cs @@ -177,7 +177,7 @@ public sealed class CertCcConnector : IFeedConnector await _documentStore.UpdateStatusAsync(result.Document.Id, DocumentStatuses.Mapped, cancellationToken).ConfigureAwait(false); } - if (!shouldProcessNotes) + if (!shouldProcessNotes || result.Document is null) { continue; } diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/Internal/CertCcCursor.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/Internal/CertCcCursor.cs index 2f95ba550..c8f72a27f 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/Internal/CertCcCursor.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/Internal/CertCcCursor.cs @@ -168,7 +168,7 @@ internal sealed record CertCcCursor( } var bytes = binary.AsByteArray; - if (bytes.Length == 16) + if (bytes is not null && bytes.Length == 16) { guid = new Guid(bytes); return true; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.Debian/DebianConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.Debian/DebianConnector.cs index 19bf147de..74e956194 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.Debian/DebianConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.Debian/DebianConnector.cs @@ -605,7 +605,7 @@ public sealed class DebianConnector : IFeedConnector { ["advisoryId"] = dto.AdvisoryId, ["sourcePackage"] = dto.SourcePackage, - ["title"] = dto.Title, + ["title"] = dto.Title ?? string.Empty, ["description"] = dto.Description ?? string.Empty, ["cves"] = new DocumentArray(dto.CveIds), ["packages"] = packages, diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/Internal/RedHatMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/Internal/RedHatMapper.cs index 660528dbf..c0e0a5178 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/Internal/RedHatMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Distro.RedHat/Internal/RedHatMapper.cs @@ -29,7 +29,12 @@ internal static class RedHatMapper ArgumentNullException.ThrowIfNull(payload); var csaf = JsonSerializer.Deserialize(payload.RootElement.GetRawText(), SerializerOptions); - var documentSection = csaf?.Document; + if (csaf is null) + { + return null; + } + + var documentSection = csaf.Document; if (documentSection is null) { return null; @@ -722,7 +727,7 @@ internal sealed class RedHatProductIndex return new RedHatProductIndex(products); } - public bool TryGetValue(string productId, out RedHatProductNode node) + public bool TryGetValue(string productId, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out RedHatProductNode? node) => _products.TryGetValue(productId, out node); private static void Traverse(RedHatProductBranch? branch, IDictionary products) diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Epss/Internal/EpssConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Epss/Internal/EpssConnector.cs index 2a8a2d6e5..f4dd375c5 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Epss/Internal/EpssConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Epss/Internal/EpssConnector.cs @@ -464,7 +464,7 @@ public sealed class EpssConnector : IFeedConnector ["epss.file"] = GetSnapshotFileName(fetchResult.SnapshotDate) }; - if (_options.AirgapMode) + if (_options.AirgapMode && fetchResult.Content is not null) { TryApplyBundleManifest(fetchResult.SnapshotDate, fetchResult.Content, metadata); } @@ -473,6 +473,11 @@ public sealed class EpssConnector : IFeedConnector // Use existing ID or derive deterministic ID from source + uri var recordId = existing?.Id ?? ComputeDeterministicId(SourceName, fetchResult.SourceUri); + if (fetchResult.Content is null) + { + throw new InvalidOperationException($"EPSS fetch returned null content for {fetchResult.SourceUri}"); + } + await _rawDocumentStorage.UploadAsync( SourceName, fetchResult.SourceUri, diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/IcsCisaConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/IcsCisaConnector.cs index bfc8b581f..f1d868f8d 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/IcsCisaConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/IcsCisaConnector.cs @@ -25,8 +25,6 @@ using StellaOps.Concelier.Connector.Ics.Cisa.Configuration; using StellaOps.Concelier.Connector.Ics.Cisa.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Normalization.SemVer; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/Internal/JvnAdvisoryMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/Internal/JvnAdvisoryMapper.cs index 3837c737c..69c58e6d2 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/Internal/JvnAdvisoryMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/Internal/JvnAdvisoryMapper.cs @@ -7,7 +7,6 @@ using StellaOps.Concelier.Normalization.Cvss; using StellaOps.Concelier.Normalization.Identifiers; using StellaOps.Concelier.Normalization.Text; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.JpFlags; namespace StellaOps.Concelier.Connector.Jvn.Internal; @@ -68,7 +67,7 @@ internal static class JvnAdvisoryMapper var flag = new JpFlagRecord( detail.VulnerabilityId, JvnConnectorPlugin.SourceName, - detail.JvnCategory, + detail.JvnCategory ?? string.Empty, vendorStatus, timeProvider.GetUtcNow()); diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/JvnConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/JvnConnector.cs index 1ac1dae7d..ade8996f7 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/JvnConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Jvn/JvnConnector.cs @@ -13,8 +13,6 @@ using StellaOps.Concelier.Connector.Jvn.Configuration; using StellaOps.Concelier.Connector.Jvn.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.JpFlags; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/KevConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/KevConnector.cs index d3fe0ca85..b739ded53 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/KevConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/KevConnector.cs @@ -18,8 +18,6 @@ using StellaOps.Concelier.Connector.Kev.Configuration; using StellaOps.Concelier.Connector.Kev.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/KisaConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/KisaConnector.cs index 79b1a8753..bba21f557 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/KisaConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kisa/KisaConnector.cs @@ -14,8 +14,6 @@ using StellaOps.Concelier.Connector.Kisa.Configuration; using StellaOps.Concelier.Connector.Kisa.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/Internal/OsvMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/Internal/OsvMapper.cs index 2c85db11e..a1db88674 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/Internal/OsvMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/Internal/OsvMapper.cs @@ -10,7 +10,6 @@ using StellaOps.Concelier.Normalization.Identifiers; using StellaOps.Concelier.Normalization.Text; using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; namespace StellaOps.Concelier.Connector.Osv.Internal; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Bdu/RuBduConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Bdu/RuBduConnector.cs index a01d3f78a..548fb3990 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Bdu/RuBduConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Bdu/RuBduConnector.cs @@ -17,8 +17,6 @@ using StellaOps.Concelier.Connector.Ru.Bdu.Configuration; using StellaOps.Concelier.Connector.Ru.Bdu.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Plugin; using StellaOps.Cryptography; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/RuNkckiConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/RuNkckiConnector.cs index 330713629..f69178413 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/RuNkckiConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/RuNkckiConnector.cs @@ -18,8 +18,6 @@ using StellaOps.Concelier.Connector.Ru.Nkcki.Configuration; using StellaOps.Concelier.Connector.Ru.Nkcki.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Plugin; using StellaOps.Cryptography; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.StellaOpsMirror/StellaOpsMirrorConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.StellaOpsMirror/StellaOpsMirrorConnector.cs index 92e11e131..8b7f35a6b 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.StellaOpsMirror/StellaOpsMirrorConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.StellaOpsMirror/StellaOpsMirrorConnector.cs @@ -14,8 +14,6 @@ using StellaOps.Concelier.Connector.StellaOpsMirror.Settings; using StellaOps.Concelier.Models; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Plugin; using StellaOps.Cryptography; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Adobe/AdobeConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Adobe/AdobeConnector.cs index 557811ef0..f9290e056 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Adobe/AdobeConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Adobe/AdobeConnector.cs @@ -18,8 +18,6 @@ using StellaOps.Concelier.Connector.Vndr.Adobe.Configuration; using StellaOps.Concelier.Connector.Vndr.Adobe.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Concelier.Models; using StellaOps.Cryptography; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/AppleConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/AppleConnector.cs index 888ab6670..350db5231 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/AppleConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/AppleConnector.cs @@ -16,8 +16,6 @@ using StellaOps.Concelier.Connector.Common.Fetch; using StellaOps.Concelier.Connector.Vndr.Apple.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleIndexEntry.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleIndexEntry.cs index 01f0d32ca..0dc0cbd93 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleIndexEntry.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleIndexEntry.cs @@ -118,23 +118,24 @@ internal static class AppleIndexParser return entries.Count == 0 ? Array.Empty() : entries; } - private static bool TryResolveDetailUri(AppleIndexEntryDto dto, Uri baseUri, out Uri uri) + private static bool TryResolveDetailUri(AppleIndexEntryDto dto, Uri baseUri, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out Uri? uri) { - if (!string.IsNullOrWhiteSpace(dto.DetailUrl) && Uri.TryCreate(dto.DetailUrl, UriKind.Absolute, out uri)) + if (!string.IsNullOrWhiteSpace(dto.DetailUrl) && Uri.TryCreate(dto.DetailUrl, UriKind.Absolute, out var parsedUri)) { + uri = parsedUri; return true; } if (string.IsNullOrWhiteSpace(dto.ArticleId)) { - uri = default!; + uri = null; return false; } var article = dto.ArticleId.Trim(); if (article.Length == 0) { - uri = default!; + uri = null; return false; } diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleMapper.cs index c3909a99a..bd46d04d3 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/Internal/AppleMapper.cs @@ -5,7 +5,6 @@ using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Common.Packages; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; namespace StellaOps.Concelier.Connector.Vndr.Apple.Internal; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/ChromiumConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/ChromiumConnector.cs index d61bdaddb..63911600e 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/ChromiumConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/ChromiumConnector.cs @@ -14,8 +14,6 @@ using StellaOps.Concelier.Connector.Vndr.Chromium.Configuration; using StellaOps.Concelier.Connector.Vndr.Chromium.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/Internal/ChromiumCursor.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/Internal/ChromiumCursor.cs index 5df34ac79..55641bbce 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/Internal/ChromiumCursor.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Chromium/Internal/ChromiumCursor.cs @@ -69,7 +69,7 @@ internal sealed record ChromiumCursor( public ChromiumCursor WithFetchCache(IDictionary cache) => this with { FetchCache = cache is null ? new Dictionary(StringComparer.Ordinal) : new Dictionary(cache, StringComparer.Ordinal) }; - public bool TryGetFetchCache(string key, out ChromiumFetchCacheEntry entry) + public bool TryGetFetchCache(string key, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out ChromiumFetchCacheEntry? entry) => FetchCache.TryGetValue(key, out entry); private static DateTimeOffset? ReadDateTime(DocumentValue value) diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/CiscoConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/CiscoConnector.cs index 4a9c00c88..5db8305f4 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/CiscoConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/CiscoConnector.cs @@ -12,8 +12,6 @@ using StellaOps.Concelier.Connector.Vndr.Cisco.Configuration; using StellaOps.Concelier.Connector.Vndr.Cisco.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/Internal/CiscoMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/Internal/CiscoMapper.cs index 879cf8303..4a258c79f 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/Internal/CiscoMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/Internal/CiscoMapper.cs @@ -4,7 +4,6 @@ using System.Linq; using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Common.Packages; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Normalization.SemVer; namespace StellaOps.Concelier.Connector.Vndr.Cisco.Internal; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/MsrcConnector.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/MsrcConnector.cs index 2b73ef105..b2e039837 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/MsrcConnector.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/MsrcConnector.cs @@ -17,8 +17,6 @@ using StellaOps.Concelier.Connector.Vndr.Msrc.Configuration; using StellaOps.Concelier.Connector.Vndr.Msrc.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; using StellaOps.Plugin; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Oracle/Internal/OracleMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Oracle/Internal/OracleMapper.cs index 96182a365..196c1c0d0 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Oracle/Internal/OracleMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Oracle/Internal/OracleMapper.cs @@ -5,7 +5,6 @@ using System.Text.RegularExpressions; using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Common.Packages; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; namespace StellaOps.Concelier.Connector.Vndr.Oracle.Internal; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Vmware/Internal/VmwareMapper.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Vmware/Internal/VmwareMapper.cs index 4ec10ae5f..9d7336103 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Vmware/Internal/VmwareMapper.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Vmware/Internal/VmwareMapper.cs @@ -5,7 +5,6 @@ using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Common.Packages; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; namespace StellaOps.Concelier.Connector.Vndr.Vmware.Internal; diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryLinksetCacheRepository.cs b/src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryLinksetCacheRepository.cs index be3217559..a4bc4597b 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryLinksetCacheRepository.cs +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/Repositories/AdvisoryLinksetCacheRepository.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.Extensions.Logging; using Npgsql; +using NpgsqlTypes; using StellaOps.Concelier.Core.Linksets; using StellaOps.Concelier.Persistence.Postgres.Models; using StellaOps.Infrastructure.Postgres.Repositories; @@ -127,8 +128,14 @@ public sealed class AdvisoryLinksetCacheRepository if (cursor is null) { - AddParameter(cmd, "cursor_created_at", DBNull.Value); - AddParameter(cmd, "cursor_advisory_id", DBNull.Value); + cmd.Parameters.Add(new NpgsqlParameter("cursor_created_at", NpgsqlDbType.TimestampTz) + { + Value = DBNull.Value + }); + cmd.Parameters.Add(new NpgsqlParameter("cursor_advisory_id", NpgsqlDbType.Text) + { + Value = DBNull.Value + }); } else { diff --git a/src/Concelier/__Tests/StellaOps.Concelier.ConfigDiff.Tests/ConcelierConfigDiffTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.ConfigDiff.Tests/ConcelierConfigDiffTests.cs index 32c70430d..43e1652fa 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.ConfigDiff.Tests/ConcelierConfigDiffTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.ConfigDiff.Tests/ConcelierConfigDiffTests.cs @@ -22,6 +22,9 @@ namespace StellaOps.Concelier.ConfigDiff.Tests; [Trait("BlastRadius", TestCategories.BlastRadius.Advisories)] public class ConcelierConfigDiffTests : ConfigDiffTestBase { + private static readonly DateTimeOffset SnapshotTimestamp = + new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero); + /// /// Initializes a new instance of the class. /// @@ -61,7 +64,8 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase async config => await GetDownloadBehaviorAsync(config), async config => await GetRetryBehaviorAsync(config), async config => await GetParseBehaviorAsync(config) - ]); + ], + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -93,7 +97,8 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase changedConfig, getBehavior: async config => await CaptureRetryBehaviorAsync(config), computeDelta: ComputeBehaviorSnapshotDelta, - expectedDelta: expectedDelta); + expectedDelta: expectedDelta, + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -120,7 +125,8 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase async config => await GetCacheBehaviorAsync(config), async config => await GetRetryBehaviorAsync(config), async config => await GetParseBehaviorAsync(config) - ]); + ], + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue( @@ -152,7 +158,8 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase changedConfig, getBehavior: async config => await CaptureValidationBehaviorAsync(config), computeDelta: ComputeBehaviorSnapshotDelta, - expectedDelta: expectedDelta); + expectedDelta: expectedDelta, + ct: TestContext.Current.CancellationToken); // Assert result.IsSuccess.Should().BeTrue(); @@ -186,11 +193,11 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase ConfigurationId: $"retry-{config.RetryCount}", Behaviors: [ - new CapturedBehavior("MaxRetryAttempts", config.RetryCount.ToString(), DateTimeOffset.UtcNow), + new CapturedBehavior("MaxRetryAttempts", config.RetryCount.ToString(), SnapshotTimestamp), new CapturedBehavior("FailureRecoveryWindow", - config.RetryCount > 3 ? "increase" : "standard", DateTimeOffset.UtcNow) + config.RetryCount > 3 ? "increase" : "standard", SnapshotTimestamp) ], - CapturedAt: DateTimeOffset.UtcNow); + CapturedAt: SnapshotTimestamp); return Task.FromResult(snapshot); } @@ -202,11 +209,11 @@ public class ConcelierConfigDiffTests : ConfigDiffTestBase Behaviors: [ new CapturedBehavior("ValidationStrictness", - config.StrictValidation ? "strict" : "relaxed", DateTimeOffset.UtcNow), + config.StrictValidation ? "strict" : "relaxed", SnapshotTimestamp), new CapturedBehavior("RejectionRate", - config.StrictValidation ? "increase" : "standard", DateTimeOffset.UtcNow) + config.StrictValidation ? "increase" : "standard", SnapshotTimestamp) ], - CapturedAt: DateTimeOffset.UtcNow); + CapturedAt: SnapshotTimestamp); return Task.FromResult(snapshot); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorFetchTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorFetchTests.cs index 22ced8603..9dc22a9b8 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorFetchTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorFetchTests.cs @@ -51,9 +51,10 @@ public sealed class AcscConnectorFetchTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal("Direct", state!.Cursor.GetValue("preferredEndpoint").AsString); + var stateValue = state!; + Assert.Equal("Direct", stateValue.Cursor.GetValue("preferredEndpoint").AsString); - var feeds = state.Cursor.GetValue("feeds").AsDocumentObject; + var feeds = stateValue.Cursor.GetValue("feeds").AsDocumentObject; Assert.True(feeds.TryGetValue("alerts", out var published)); Assert.Equal(DateTime.Parse("2025-10-11T05:30:00Z").ToUniversalTime(), published.ToUniversalTime()); @@ -90,9 +91,10 @@ public sealed class AcscConnectorFetchTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal("Relay", state!.Cursor.GetValue("preferredEndpoint").AsString); + var stateValue = state!; + Assert.Equal("Relay", stateValue.Cursor.GetValue("preferredEndpoint").AsString); - var feeds = state.Cursor.GetValue("feeds").AsDocumentObject; + var feeds = stateValue.Cursor.GetValue("feeds").AsDocumentObject; Assert.True(feeds.TryGetValue("alerts", out var published)); Assert.Equal(DateTime.Parse("2025-10-11T00:00:00Z").ToUniversalTime(), published.ToUniversalTime()); @@ -142,7 +144,8 @@ public sealed class AcscConnectorFetchTests var state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal("Direct", state!.Cursor.GetValue("preferredEndpoint").AsString); + var stateValue = state!; + Assert.Equal("Direct", stateValue.Cursor.GetValue("preferredEndpoint").AsString); Assert.Collection(harness.Handler.Requests, request => @@ -175,7 +178,8 @@ public sealed class AcscConnectorFetchTests var state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal("Direct", state!.Cursor.GetValue("preferredEndpoint").AsString); + var stateValue = state!; + Assert.Equal("Direct", stateValue.Cursor.GetValue("preferredEndpoint").AsString); Assert.Empty(harness.Handler.Requests); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorParseTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorParseTests.cs index 76fdd8714..8302792b7 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorParseTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Acsc.Tests/Acsc/AcscConnectorParseTests.cs @@ -80,8 +80,9 @@ public sealed class AcscConnectorParseTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.DoesNotContain(document.Id.ToString(), state!.Cursor.GetValue("pendingDocuments").AsDocumentArray.Select(v => v.AsString)); - Assert.Contains(document.Id.ToString(), state.Cursor.GetValue("pendingMappings").AsDocumentArray.Select(v => v.AsString)); + var stateValue = state!; + Assert.DoesNotContain(document.Id.ToString(), stateValue.Cursor.GetValue("pendingDocuments").AsDocumentArray.Select(v => v.AsString)); + Assert.Contains(document.Id.ToString(), stateValue.Cursor.GetValue("pendingMappings").AsDocumentArray.Select(v => v.AsString)); await connector.MapAsync(harness.ServiceProvider, CancellationToken.None); @@ -103,7 +104,8 @@ public sealed class AcscConnectorParseTests state = await stateRepository.TryGetAsync(AcscConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.GetValue("pendingMappings").AsDocumentArray.Count == 0); + stateValue = state!; + Assert.True(stateValue.Cursor.GetValue("pendingMappings").AsDocumentArray.Count == 0); } [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorFetchTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorFetchTests.cs index e56ecdc5e..ae8ed4bef 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorFetchTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorFetchTests.cs @@ -18,7 +18,6 @@ using StellaOps.Concelier.Connector.Common.Http; using StellaOps.Concelier.Connector.Common.Cursors; using StellaOps.Concelier.Connector.Common.Testing; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; using Xunit; @@ -110,9 +109,10 @@ public sealed class CertCcConnectorFetchTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertCcConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); + var stateValue = state!; DocumentValue summaryValue; - Assert.True(state!.Cursor.TryGetValue("summary", out summaryValue)); + Assert.True(stateValue.Cursor.TryGetValue("summary", out summaryValue)); var summaryDocument = Assert.IsType(summaryValue); Assert.True(summaryDocument.TryGetValue("start", out _)); Assert.True(summaryDocument.TryGetValue("end", out _)); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorSnapshotTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorSnapshotTests.cs index 0839522c7..7c0d7c80a 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorSnapshotTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorSnapshotTests.cs @@ -23,7 +23,6 @@ using StellaOps.Concelier.Connector.Common.Cursors; using StellaOps.Concelier.Connector.Common.Http; using StellaOps.Concelier.Connector.Common.Testing; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; using StellaOps.Concelier.Testing; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorTests.cs index c6a0d82ab..3107aa95a 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/CertCc/CertCcConnectorTests.cs @@ -22,7 +22,6 @@ using StellaOps.Concelier.Connector.Common.Cursors; using StellaOps.Concelier.Connector.Common.Http; using StellaOps.Concelier.Connector.Common.Testing; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; using StellaOps.Concelier.Testing; using Xunit; @@ -135,8 +134,9 @@ public sealed class CertCcConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertCcConnectorPlugin.SourceName, CancellationToken.None); state.Should().NotBeNull(); - state!.Cursor.Should().NotBeNull(); - var pendingNotesCount = state.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue) + var stateValue = state!; + stateValue.Cursor.Should().NotBeNull(); + var pendingNotesCount = stateValue.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue) ? pendingNotesValue!.AsDocumentArray.Count : 0; pendingNotesCount.Should().Be(0); @@ -216,10 +216,11 @@ public sealed class CertCcConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertCcConnectorPlugin.SourceName, CancellationToken.None); state.Should().NotBeNull(); - state!.FailCount.Should().BeGreaterThan(0); - state.BackoffUntil.Should().NotBeNull(); - state.BackoffUntil.Should().BeAfter(_timeProvider.GetUtcNow()); - state.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue).Should().BeTrue(); + var stateValue = state!; + stateValue.FailCount.Should().BeGreaterThan(0); + stateValue.BackoffUntil.Should().NotBeNull(); + stateValue.BackoffUntil.Should().BeAfter(_timeProvider.GetUtcNow()); + stateValue.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue).Should().BeTrue(); pendingNotesValue!.AsDocumentArray.Should().Contain(value => value.AsString == "294418"); var pendingSummaries = state.Cursor.TryGetValue("pendingSummaries", out var pendingSummariesValue) ? pendingSummariesValue!.AsDocumentArray.Count @@ -259,11 +260,12 @@ public sealed class CertCcConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertCcConnectorPlugin.SourceName, CancellationToken.None); state.Should().NotBeNull(); - state!.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue).Should().BeTrue(); + var stateValue = state!; + stateValue.Cursor.TryGetValue("pendingNotes", out var pendingNotesValue).Should().BeTrue(); pendingNotesValue!.AsDocumentArray.Should().BeEmpty(); - state.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue).Should().BeTrue(); + stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue).Should().BeTrue(); pendingDocsValue!.AsDocumentArray.Should().BeEmpty(); - state.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue).Should().BeTrue(); + stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue).Should().BeTrue(); pendingMappingsValue!.AsDocumentArray.Should().BeEmpty(); } @@ -298,11 +300,12 @@ public sealed class CertCcConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertCcConnectorPlugin.SourceName, CancellationToken.None); state.Should().NotBeNull(); - var pendingDocuments = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) + var stateValue = state!; + var pendingDocuments = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue!.AsDocumentArray.Count : 0; pendingDocuments.Should().BeGreaterThan(0); - var pendingMappings = state.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue) + var pendingMappings = stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue) ? pendingMappingsValue!.AsDocumentArray.Count : 0; pendingMappings.Should().Be(0); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/Internal/CertCcMapperTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/Internal/CertCcMapperTests.cs index 7d536e83e..20610b240 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/Internal/CertCcMapperTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertCc.Tests/Internal/CertCcMapperTests.cs @@ -4,7 +4,6 @@ using StellaOps.Concelier.Documents; using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.CertCc.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using Xunit; namespace StellaOps.Concelier.Connector.CertCc.Tests.Internal; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertFr.Tests/CertFr/CertFrConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertFr.Tests/CertFr/CertFrConnectorTests.cs index 949a54f76..fb8bb07e9 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertFr.Tests/CertFr/CertFrConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertFr.Tests/CertFr/CertFrConnectorTests.cs @@ -95,11 +95,12 @@ public sealed class CertFrConnectorTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertFrConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal(1, state!.FailCount); - Assert.NotNull(state.LastFailureReason); - Assert.Contains("500", state.LastFailureReason, StringComparison.Ordinal); - Assert.NotNull(state.BackoffUntil); - Assert.True(state.BackoffUntil > harness.TimeProvider.GetUtcNow()); + var stateValue = state!; + Assert.Equal(1, stateValue.FailCount); + Assert.NotNull(stateValue.LastFailureReason); + Assert.Contains("500", stateValue.LastFailureReason, StringComparison.Ordinal); + Assert.NotNull(stateValue.BackoffUntil); + Assert.True(stateValue.BackoffUntil > harness.TimeProvider.GetUtcNow()); } [Fact] @@ -139,8 +140,9 @@ public sealed class CertFrConnectorTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertFrConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMaps) && pendingMaps.AsDocumentArray.Count == 0); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMaps) && pendingMaps.AsDocumentArray.Count == 0); } [Fact] @@ -182,8 +184,9 @@ public sealed class CertFrConnectorTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertFrConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMaps) && pendingMaps.AsDocumentArray.Count == 0); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMaps) && pendingMaps.AsDocumentArray.Count == 0); } private async Task BuildHarnessAsync() diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertIn.Tests/CertIn/CertInConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertIn.Tests/CertIn/CertInConnectorTests.cs index b6080adaf..761bc2063 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertIn.Tests/CertIn/CertInConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.CertIn.Tests/CertIn/CertInConnectorTests.cs @@ -25,8 +25,6 @@ using StellaOps.Concelier.Connector.Common.Testing; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; using StellaOps.Concelier.Persistence.Postgres; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Testing; namespace StellaOps.Concelier.Connector.CertIn.Tests; @@ -100,7 +98,8 @@ public sealed class CertInConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertInConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pending)); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pending)); Assert.Empty(pending.AsDocumentArray); } @@ -131,11 +130,12 @@ public sealed class CertInConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertInConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal(1, state!.FailCount); - Assert.NotNull(state.LastFailureReason); - Assert.Contains("500", state.LastFailureReason, StringComparison.Ordinal); - Assert.True(state.BackoffUntil.HasValue); - Assert.True(state.BackoffUntil!.Value > _timeProvider.GetUtcNow()); + var stateValue = state!; + Assert.Equal(1, stateValue.FailCount); + Assert.NotNull(stateValue.LastFailureReason); + Assert.Contains("500", stateValue.LastFailureReason, StringComparison.Ordinal); + Assert.True(stateValue.BackoffUntil.HasValue); + Assert.True(stateValue.BackoffUntil!.Value > _timeProvider.GetUtcNow()); } [Fact] @@ -209,9 +209,9 @@ public sealed class CertInConnectorTests : IAsyncLifetime var state = await stateRepository.TryGetAsync(CertInConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); - Assert.Equal(0, pendingDocs.AsDocumentArray.Count); + Assert.Empty(pendingDocs.AsDocumentArray); Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings)); - Assert.Equal(0, pendingMappings.AsDocumentArray.Count); + Assert.Empty(pendingMappings.AsDocumentArray); } [Fact] @@ -263,10 +263,11 @@ public sealed class CertInConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(CertInConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); - Assert.Equal(0, pendingDocs.AsDocumentArray.Count); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings)); - Assert.Equal(0, pendingMappings.AsDocumentArray.Count); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); + Assert.Empty(pendingDocs.AsDocumentArray); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings)); + Assert.Empty(pendingMappings.AsDocumentArray); } private async Task EnsureServiceProviderAsync(CertInOptions template) diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceFetchServiceGuardTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceFetchServiceGuardTests.cs index 46b970279..b5ecd4200 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceFetchServiceGuardTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceFetchServiceGuardTests.cs @@ -14,7 +14,6 @@ using StellaOps.Concelier.Core.Aoc; using StellaOps.Concelier.Core.Linksets; using StellaOps.Concelier.RawModels; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; namespace StellaOps.Concelier.Connector.Common.Tests; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceStateSeedProcessorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceStateSeedProcessorTests.cs index 6d7dbb809..e876f615e 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceStateSeedProcessorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/Common/SourceStateSeedProcessorTests.cs @@ -10,7 +10,6 @@ using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Common.Fetch; using StellaOps.Concelier.Connector.Common.State; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; namespace StellaOps.Concelier.Connector.Common.Tests; @@ -105,9 +104,10 @@ public sealed class SourceStateSeedProcessorTests : IAsyncLifetime var state = await _stateRepository.TryGetAsync("vndr.test", CancellationToken.None); Assert.NotNull(state); - Assert.Equal(_timeProvider.GetUtcNow().UtcDateTime, state!.LastSuccess); + var stateValue = state!; + Assert.Equal(_timeProvider.GetUtcNow().UtcDateTime, stateValue.LastSuccess); - var cursor = state.Cursor; + var cursor = stateValue.Cursor; var pendingDocs = cursor["pendingDocuments"].AsDocumentArray.Select(v => Guid.Parse(v.AsString)).ToList(); Assert.Contains(documentId, pendingDocs); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/StellaOps.Concelier.Connector.Common.Tests.csproj b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/StellaOps.Concelier.Connector.Common.Tests.csproj index fcf7ac8e7..519e1d58e 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/StellaOps.Concelier.Connector.Common.Tests.csproj +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Common.Tests/StellaOps.Concelier.Connector.Common.Tests.csproj @@ -6,6 +6,8 @@ enable false true + + false diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Cve.Tests/Cve/CveConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Cve.Tests/Cve/CveConnectorTests.cs index 345a0721e..15fb6ec50 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Cve.Tests/Cve/CveConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Cve.Tests/Cve/CveConnectorTests.cs @@ -17,8 +17,6 @@ using StellaOps.Concelier.Connector.Cve.Internal; using StellaOps.Concelier.Testing; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; namespace StellaOps.Concelier.Connector.Cve.Tests; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Alpine.Tests/AlpineConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Alpine.Tests/AlpineConnectorTests.cs index e1094883a..fd2cacd9a 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Alpine.Tests/AlpineConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Alpine.Tests/AlpineConnectorTests.cs @@ -56,9 +56,10 @@ public sealed class AlpineConnectorTests var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(AlpineConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings) + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings) && pendingMappings.AsDocumentArray.Count == 0); harness.Handler.AssertNoPendingResponses(); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Debian.Tests/DebianConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Debian.Tests/DebianConnectorTests.cs index 8ed200d4c..cb4b1e534 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Debian.Tests/DebianConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.Debian.Tests/DebianConnectorTests.cs @@ -22,8 +22,6 @@ using StellaOps.Concelier.Connector.Common.Testing; using StellaOps.Concelier.Connector.Distro.Debian.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Testing; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorHarnessTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorHarnessTests.cs index 4aa4915a6..77f0de1c5 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorHarnessTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorHarnessTests.cs @@ -107,8 +107,9 @@ public sealed class RedHatConnectorHarnessTests : IAsyncLifetime var state = await stateRepository.TryGetAsync(RedHatConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings) && pendingMappings.AsDocumentArray.Count == 0); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings) && pendingMappings.AsDocumentArray.Count == 0); } public ValueTask InitializeAsync() => ValueTask.CompletedTask; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorTests.cs index 4f0e31026..542bb6541 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Distro.RedHat.Tests/RedHat/RedHatConnectorTests.cs @@ -25,8 +25,6 @@ using StellaOps.Concelier.Connector.Distro.RedHat.Internal; using StellaOps.Concelier.Models; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; using StellaOps.Plugin; @@ -170,8 +168,9 @@ public sealed class RedHatConnectorTests : IAsyncLifetime var state = await stateRepository.TryGetAsync(RedHatConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs2) && pendingDocs2.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings2) && pendingMappings2.AsDocumentArray.Count == 0); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs2) && pendingDocs2.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings2) && pendingMappings2.AsDocumentArray.Count == 0); const string fetchKind = "source:redhat:fetch"; const string parseKind = "source:redhat:parse"; @@ -241,8 +240,9 @@ public sealed class RedHatConnectorTests : IAsyncLifetime state = await stateRepository.TryGetAsync(RedHatConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs3) && pendingDocs3.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings3) && pendingMappings3.AsDocumentArray.Count == 0); + stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs3) && pendingDocs3.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings3) && pendingMappings3.AsDocumentArray.Count == 0); } [Fact] @@ -338,7 +338,8 @@ public sealed class RedHatConnectorTests : IAsyncLifetime var state = await stateRepository.TryGetAsync(RedHatConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocs = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) + var stateValue = state!; + var pendingDocs = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); Assert.NotEmpty(pendingDocs); @@ -368,9 +369,10 @@ public sealed class RedHatConnectorTests : IAsyncLifetime var stateRepository = resumeProvider.GetRequiredService(); var finalState = await stateRepository.TryGetAsync(RedHatConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(finalState); - var finalPendingDocs = finalState!.Cursor.TryGetValue("pendingDocuments", out var docsValue) ? docsValue.AsDocumentArray : new DocumentArray(); + var finalStateValue = finalState!; + var finalPendingDocs = finalStateValue.Cursor.TryGetValue("pendingDocuments", out var docsValue) ? docsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(finalPendingDocs); - var finalPendingMappings = finalState.Cursor.TryGetValue("pendingMappings", out var mappingsValue) ? mappingsValue.AsDocumentArray : new DocumentArray(); + var finalPendingMappings = finalStateValue.Cursor.TryGetValue("pendingMappings", out var mappingsValue) ? mappingsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(finalPendingMappings); } } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ghsa.Tests/Ghsa/GhsaConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ghsa.Tests/Ghsa/GhsaConnectorTests.cs index bda02dbc1..1610f155e 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ghsa.Tests/Ghsa/GhsaConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ghsa.Tests/Ghsa/GhsaConnectorTests.cs @@ -142,10 +142,11 @@ public sealed class GhsaConnectorTests : IAsyncLifetime var stateRepository = harness.ServiceProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(GhsaConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); + var stateValue = state!; - Assert.True(state!.Cursor.TryGetValue("currentWindowStart", out var startValue)); - Assert.True(state.Cursor.TryGetValue("currentWindowEnd", out var endValue)); - Assert.True(state.Cursor.TryGetValue("nextPage", out var nextPageValue)); + Assert.True(stateValue.Cursor.TryGetValue("currentWindowStart", out var startValue)); + Assert.True(stateValue.Cursor.TryGetValue("currentWindowEnd", out var endValue)); + Assert.True(stateValue.Cursor.TryGetValue("nextPage", out var nextPageValue)); Assert.Equal(since.UtcDateTime, startValue.ToUniversalTime()); Assert.Equal(until.UtcDateTime, endValue.ToUniversalTime()); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Cisa.Tests/IcsCisaConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Cisa.Tests/IcsCisaConnectorTests.cs index 8f3c74f0e..a4ce3192c 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Cisa.Tests/IcsCisaConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Cisa.Tests/IcsCisaConnectorTests.cs @@ -70,7 +70,7 @@ public sealed class IcsCisaConnectorTests var icsma = Assert.Single(advisories, advisory => advisory.AdvisoryKey == "ICSMA-25-045-01"); Assert.Contains("CVE-2025-11111", icsma.Aliases); - var icsmaMitigation = Assert.Single(icsma.References.Where(reference => reference.Kind == "mitigation")); + var icsmaMitigation = Assert.Single(icsma.References, reference => reference.Kind == "mitigation"); Assert.Contains("Contact HealthTech support", icsmaMitigation.Summary, StringComparison.Ordinal); Assert.Contains(icsma.References, reference => reference.Url == "https://www.cisa.gov/sites/default/files/2025-10/ICSMA-25-045-01_Supplement.pdf"); var infusionPackage = Assert.Single(icsma.AffectedPackages, package => string.Equals(package.Identifier, "InfusionManager", StringComparison.OrdinalIgnoreCase)); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Kaspersky.Tests/Kaspersky/KasperskyConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Kaspersky.Tests/Kaspersky/KasperskyConnectorTests.cs index 58fa31c29..a1ec1d071 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Kaspersky.Tests/Kaspersky/KasperskyConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ics.Kaspersky.Tests/Kaspersky/KasperskyConnectorTests.cs @@ -21,8 +21,6 @@ using StellaOps.Concelier.Connector.Ics.Kaspersky; using StellaOps.Concelier.Connector.Ics.Kaspersky.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; @@ -97,7 +95,8 @@ public sealed class KasperskyConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(KasperskyConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocuments = state!.Cursor.TryGetValue("pendingDocuments", out var pending) + var stateValue = state!; + var pendingDocuments = stateValue.Cursor.TryGetValue("pendingDocuments", out var pending) ? pending.AsDocumentArray : new DocumentArray(); Assert.Empty(pendingDocuments); @@ -130,11 +129,12 @@ public sealed class KasperskyConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(KasperskyConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal(1, state!.FailCount); - Assert.NotNull(state.LastFailureReason); - Assert.Contains("500", state.LastFailureReason, StringComparison.Ordinal); - Assert.True(state.BackoffUntil.HasValue); - Assert.True(state.BackoffUntil!.Value > _timeProvider.GetUtcNow()); + var stateValue = state!; + Assert.Equal(1, stateValue.FailCount); + Assert.NotNull(stateValue.LastFailureReason); + Assert.Contains("500", stateValue.LastFailureReason, StringComparison.Ordinal); + Assert.True(stateValue.BackoffUntil.HasValue); + Assert.True(stateValue.BackoffUntil!.Value > _timeProvider.GetUtcNow()); } [Fact] @@ -202,10 +202,11 @@ public sealed class KasperskyConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(KasperskyConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); - Assert.Equal(0, pendingDocs.AsDocumentArray.Count); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMappings)); - Assert.Equal(0, pendingMappings.AsDocumentArray.Count); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); + Assert.Empty(pendingDocs.AsDocumentArray); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappings)); + Assert.Empty(pendingMappings.AsDocumentArray); } [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Jvn.Tests/Jvn/JvnConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Jvn.Tests/Jvn/JvnConnectorTests.cs index 4170dad77..1788de1be 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Jvn.Tests/Jvn/JvnConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Jvn.Tests/Jvn/JvnConnectorTests.cs @@ -20,8 +20,6 @@ using StellaOps.Concelier.Connector.Jvn; using StellaOps.Concelier.Connector.Jvn.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.JpFlags; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; @@ -123,7 +121,8 @@ public sealed class JvnConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(JvnConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs)); Assert.Empty(pendingDocs.AsDocumentArray); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kev.Tests/Kev/KevConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kev.Tests/Kev/KevConnectorTests.cs index a655eb159..12eb8d088 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kev.Tests/Kev/KevConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kev.Tests/Kev/KevConnectorTests.cs @@ -71,10 +71,11 @@ public sealed class KevConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(KevConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Equal("2025.10.09", state!.Cursor.TryGetValue("catalogVersion", out var versionValue) ? versionValue.AsString : null); - Assert.True(state.Cursor.TryGetValue("catalogReleased", out var releasedValue) && releasedValue.DocumentType is DocumentType.DateTime); - Assert.True(IsEmptyArray(state.Cursor, "pendingDocuments")); - Assert.True(IsEmptyArray(state.Cursor, "pendingMappings")); + var stateValue = state!; + Assert.Equal("2025.10.09", stateValue.Cursor.TryGetValue("catalogVersion", out var versionValue) ? versionValue.AsString : null); + Assert.True(stateValue.Cursor.TryGetValue("catalogReleased", out var releasedValue) && releasedValue.DocumentType is DocumentType.DateTime); + Assert.True(IsEmptyArray(stateValue.Cursor, "pendingDocuments")); + Assert.True(IsEmptyArray(stateValue.Cursor, "pendingMappings")); } private async Task BuildServiceProviderAsync() diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/KisaConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/KisaConnectorTests.cs index 859984ee6..713f8c5d3 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/KisaConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Kisa.Tests/KisaConnectorTests.cs @@ -23,8 +23,6 @@ using StellaOps.Concelier.Connector.Kisa.Internal; using StellaOps.Concelier.Models; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorHarnessTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorHarnessTests.cs index d45982136..c3bb4dfd3 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorHarnessTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorHarnessTests.cs @@ -10,7 +10,6 @@ using StellaOps.Concelier.Connector.Nvd; using StellaOps.Concelier.Connector.Nvd.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Testing; using StellaOps.Concelier.Testing; using System.Net; @@ -74,15 +73,18 @@ public sealed class NvdConnectorHarnessTests : IAsyncLifetime var firstDocument = await documentStore.FindBySourceAndUriAsync(NvdConnectorPlugin.SourceName, firstUri.ToString(), CancellationToken.None); Assert.NotNull(firstDocument); - Assert.Equal("0", firstDocument!.Metadata["startIndex"]); + Assert.NotNull(firstDocument!.Metadata); + Assert.Equal("0", firstDocument.Metadata["startIndex"]); var secondDocument = await documentStore.FindBySourceAndUriAsync(NvdConnectorPlugin.SourceName, secondUri.ToString(), CancellationToken.None); Assert.NotNull(secondDocument); - Assert.Equal("2", secondDocument!.Metadata["startIndex"]); + Assert.NotNull(secondDocument!.Metadata); + Assert.Equal("2", secondDocument.Metadata["startIndex"]); var thirdDocument = await documentStore.FindBySourceAndUriAsync(NvdConnectorPlugin.SourceName, thirdUri.ToString(), CancellationToken.None); Assert.NotNull(thirdDocument); - Assert.Equal("4", thirdDocument!.Metadata["startIndex"]); + Assert.NotNull(thirdDocument!.Metadata); + Assert.Equal("4", thirdDocument.Metadata["startIndex"]); var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorTests.cs index bb53f38f4..8ef969d19 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Nvd.Tests/Nvd/NvdConnectorTests.cs @@ -22,8 +22,6 @@ using StellaOps.Concelier.Connector.Nvd.Configuration; using StellaOps.Concelier.Connector.Nvd.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.ChangeHistory; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; @@ -146,7 +144,8 @@ public sealed class NvdConnectorTests : IAsyncLifetime var documentStore = provider.GetRequiredService(); var finalState = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(finalState); - var pendingDocuments = finalState!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) + var finalStateValue = finalState!; + var pendingDocuments = finalStateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray(); Assert.Empty(pendingDocuments); @@ -188,7 +187,8 @@ public sealed class NvdConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocuments = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) + var stateValue = state!; + var pendingDocuments = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray.Select(v => Guid.Parse(v.AsString)).ToArray() : Array.Empty(); Assert.Equal(3, pendingDocuments.Length); @@ -280,8 +280,9 @@ public sealed class NvdConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); + var stateValue = state!; - var cursorDocument = state!.Cursor; + var cursorDocument = stateValue.Cursor; var lastWindowEnd = cursorDocument.TryGetValue("windowEnd", out var endValue) ? ReadDateTime(endValue) : (DateTimeOffset?)null; var startCandidate = (lastWindowEnd ?? windowEnd) - options.WindowOverlap; var backfillLimit = now - options.InitialBackfill; @@ -350,9 +351,10 @@ public sealed class NvdConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocs = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); + var stateValue = state!; + var pendingDocs = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(pendingDocs); - var pendingMappings = state.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue) ? pendingMappingsValue.AsDocumentArray : new DocumentArray(); + var pendingMappings = stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMappingsValue) ? pendingMappingsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(pendingMappings); Assert.Equal(1, collector.GetValue("nvd.fetch.documents")); @@ -462,7 +464,8 @@ public sealed class NvdConnectorTests : IAsyncLifetime var stateRepository = fetchProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pending = state!.Cursor.TryGetValue("pendingDocuments", out var value) + var stateValue = state!; + var pending = stateValue.Cursor.TryGetValue("pendingDocuments", out var value) ? value.AsDocumentArray : new DocumentArray(); Assert.NotEmpty(pending); @@ -492,7 +495,8 @@ public sealed class NvdConnectorTests : IAsyncLifetime var stateRepository = resumeProvider.GetRequiredService(); var finalState = await stateRepository.TryGetAsync(NvdConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(finalState); - var cursor = finalState!.Cursor; + var finalStateValue = finalState!; + var cursor = finalStateValue.Cursor; var finalPendingDocs = cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray(); Assert.Empty(finalPendingDocs); var finalPendingMappings = cursor.TryGetValue("pendingMappings", out var pendingMappings) ? pendingMappings.AsDocumentArray : new DocumentArray(); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvConflictFixtureTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvConflictFixtureTests.cs index 7b4fd5a2a..8b4eedc56 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvConflictFixtureTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvConflictFixtureTests.cs @@ -3,7 +3,6 @@ using StellaOps.Concelier.Documents; using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Osv.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; namespace StellaOps.Concelier.Connector.Osv.Tests; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvGhsaParityRegressionTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvGhsaParityRegressionTests.cs index 499eb8c71..53b6a5d8a 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvGhsaParityRegressionTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvGhsaParityRegressionTests.cs @@ -14,7 +14,6 @@ using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Osv; using StellaOps.Concelier.Connector.Osv.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Cryptography; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvMapperTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvMapperTests.cs index e975e76ef..49c6e7d0d 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvMapperTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvMapperTests.cs @@ -10,7 +10,6 @@ using StellaOps.Concelier.Connector.Osv; using StellaOps.Concelier.Connector.Osv.Internal; using StellaOps.Concelier.Normalization.Identifiers; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using Xunit; namespace StellaOps.Concelier.Connector.Osv.Tests; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvSnapshotTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvSnapshotTests.cs index 0a451d40c..54150ce1e 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvSnapshotTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Osv.Tests/Osv/OsvSnapshotTests.cs @@ -7,7 +7,6 @@ using StellaOps.Concelier.Models; using StellaOps.Concelier.Connector.Osv; using StellaOps.Concelier.Connector.Osv.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Connector.Common; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Bdu.Tests/RuBduConnectorSnapshotTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Bdu.Tests/RuBduConnectorSnapshotTests.cs index e40f5c0d4..e0bf01c4f 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Bdu.Tests/RuBduConnectorSnapshotTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Bdu.Tests/RuBduConnectorSnapshotTests.cs @@ -21,8 +21,6 @@ using StellaOps.Concelier.Connector.Ru.Bdu.Configuration; using StellaOps.Concelier.Connector.Ru.Bdu.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Testing; using StellaOps.Cryptography; using Xunit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Nkcki.Tests/RuNkckiConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Nkcki.Tests/RuNkckiConnectorTests.cs index cf9e2ded4..5f29158a1 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Nkcki.Tests/RuNkckiConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Ru.Nkcki.Tests/RuNkckiConnectorTests.cs @@ -21,7 +21,6 @@ using StellaOps.Concelier.Connector.Ru.Nkcki; using StellaOps.Concelier.Connector.Ru.Nkcki.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Testing; using StellaOps.Concelier.Models; using StellaOps.Concelier.Persistence.Postgres; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.StellaOpsMirror.Tests/StellaOpsMirrorConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.StellaOpsMirror.Tests/StellaOpsMirrorConnectorTests.cs index 8d7476c5b..356364535 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.StellaOpsMirror.Tests/StellaOpsMirrorConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.StellaOpsMirror.Tests/StellaOpsMirrorConnectorTests.cs @@ -20,8 +20,6 @@ using StellaOps.Concelier.Connector.StellaOpsMirror.Internal; using StellaOps.Concelier.Connector.StellaOpsMirror.Settings; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; using StellaOps.Cryptography; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Adobe.Tests/Adobe/AdobeConnectorFetchTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Adobe.Tests/Adobe/AdobeConnectorFetchTests.cs index d37199dac..cafedef15 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Adobe.Tests/Adobe/AdobeConnectorFetchTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Adobe.Tests/Adobe/AdobeConnectorFetchTests.cs @@ -23,8 +23,6 @@ using StellaOps.Concelier.Connector.Vndr.Adobe; using StellaOps.Concelier.Connector.Vndr.Adobe.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; @@ -132,7 +130,8 @@ public sealed class AdobeConnectorFetchTests : IAsyncLifetime var state = await stateRepository.TryGetAsync(VndrAdobeConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var cursor = state!.Cursor; + var stateValue = state!; + var cursor = stateValue.Cursor; Assert.True(!cursor.TryGetValue("pendingDocuments", out _) || cursor.GetValue("pendingDocuments").AsDocumentArray.Count == 0); Assert.True(!cursor.TryGetValue("pendingMappings", out _) @@ -314,8 +313,9 @@ public sealed class AdobeConnectorFetchTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(VndrAdobeConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.True(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); - Assert.True(state.Cursor.TryGetValue("pendingMappings", out var pendingMap) && pendingMap.AsDocumentArray.Count == 0); + var stateValue = state!; + Assert.True(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) && pendingDocs.AsDocumentArray.Count == 0); + Assert.True(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMap) && pendingMap.AsDocumentArray.Count == 0); } private async Task BuildServiceProviderAsync(CannedHttpMessageHandler handler) diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Chromium.Tests/Chromium/ChromiumConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Chromium.Tests/Chromium/ChromiumConnectorTests.cs index fd6673fa0..cdf458e63 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Chromium.Tests/Chromium/ChromiumConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Chromium.Tests/Chromium/ChromiumConnectorTests.cs @@ -19,7 +19,6 @@ using StellaOps.Concelier.Connector.Vndr.Chromium; using StellaOps.Concelier.Connector.Vndr.Chromium.Configuration; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Concelier.Testing; @@ -137,7 +136,8 @@ public sealed class ChromiumConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(VndrChromiumConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocuments = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) + var stateValue = state!; + var pendingDocuments = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(pendingDocuments); @@ -167,7 +167,8 @@ public sealed class ChromiumConnectorTests : IAsyncLifetime var stateRepository = fetchProvider.GetRequiredService(); var state = await stateRepository.TryGetAsync(VndrChromiumConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var pendingDocuments = state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) + var stateValue = state!; + var pendingDocuments = stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); Assert.NotEmpty(pendingDocuments); @@ -180,7 +181,8 @@ public sealed class ChromiumConnectorTests : IAsyncLifetime var stateRepositoryBefore = resumeProvider.GetRequiredService(); var resumeState = await stateRepositoryBefore.TryGetAsync(VndrChromiumConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(resumeState); - var resumePendingDocs = resumeState!.Cursor.TryGetValue("pendingDocuments", out var resumePendingValue) + var resumeStateValue = resumeState!; + var resumePendingDocs = resumeStateValue.Cursor.TryGetValue("pendingDocuments", out var resumePendingValue) ? resumePendingValue.AsDocumentArray : new DocumentArray(); Assert.Equal(pendingDocumentIds.Length, resumePendingDocs.Count); @@ -202,12 +204,13 @@ public sealed class ChromiumConnectorTests : IAsyncLifetime var stateRepositoryAfter = resumeProvider.GetRequiredService(); var finalState = await stateRepositoryAfter.TryGetAsync(VndrChromiumConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(finalState); - var finalPending = finalState!.Cursor.TryGetValue("pendingDocuments", out var finalPendingDocs) + var finalStateValue = finalState!; + var finalPending = finalStateValue.Cursor.TryGetValue("pendingDocuments", out var finalPendingDocs) ? finalPendingDocs.AsDocumentArray : new DocumentArray(); Assert.Empty(finalPending); - var finalPendingMappings = finalState.Cursor.TryGetValue("pendingMappings", out var finalPendingMappingsValue) + var finalPendingMappings = finalStateValue.Cursor.TryGetValue("pendingMappings", out var finalPendingMappingsValue) ? finalPendingMappingsValue.AsDocumentArray : new DocumentArray(); Assert.Empty(finalPendingMappings); @@ -246,7 +249,8 @@ public sealed class ChromiumConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(VndrChromiumConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - var cursor = state!.Cursor; + var stateValue = state!; + var cursor = stateValue.Cursor; var pendingDocuments = cursor.TryGetValue("pendingDocuments", out var pendingDocsValue) ? pendingDocsValue.AsDocumentArray : new DocumentArray(); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Cisco.Tests/CiscoMapperTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Cisco.Tests/CiscoMapperTests.cs index 3e37bb3c5..72f0969b0 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Cisco.Tests/CiscoMapperTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Cisco.Tests/CiscoMapperTests.cs @@ -8,7 +8,6 @@ using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Vndr.Cisco; using StellaOps.Concelier.Connector.Vndr.Cisco.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using Xunit; using StellaOps.TestKit; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Msrc.Tests/MsrcConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Msrc.Tests/MsrcConnectorTests.cs index aa50007db..82aacab37 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Msrc.Tests/MsrcConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Msrc.Tests/MsrcConnectorTests.cs @@ -18,8 +18,6 @@ using StellaOps.Concelier.Connector.Vndr.Msrc.Configuration; using StellaOps.Concelier.Connector.Vndr.Msrc.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Testing; using Xunit; @@ -74,7 +72,8 @@ public sealed class MsrcConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(MsrcConnectorPlugin.SourceName, CancellationToken.None); state.Should().NotBeNull(); - state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs).Should().BeTrue(); + var stateValue = state!; + stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs).Should().BeTrue(); pendingDocs!.AsDocumentArray.Should().BeEmpty(); var documentStore = provider.GetRequiredService(); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Oracle.Tests/Oracle/OracleConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Oracle.Tests/Oracle/OracleConnectorTests.cs index ea0414b13..f76c1f79f 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Oracle.Tests/Oracle/OracleConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Oracle.Tests/Oracle/OracleConnectorTests.cs @@ -24,8 +24,6 @@ using StellaOps.Concelier.Connector.Vndr.Oracle.Configuration; using StellaOps.Concelier.Connector.Vndr.Oracle.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Concelier.Testing; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareConnectorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareConnectorTests.cs index 9947e51f3..0f7d52dd0 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareConnectorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareConnectorTests.cs @@ -23,8 +23,6 @@ using StellaOps.Concelier.Connector.Vndr.Vmware.Configuration; using StellaOps.Concelier.Connector.Vndr.Vmware.Internal; using StellaOps.Concelier.Storage; using StellaOps.Concelier.Storage.Advisories; -using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Storage.PsirtFlags; using StellaOps.Concelier.Testing; @@ -98,9 +96,10 @@ public sealed class VmwareConnectorTests : IAsyncLifetime var stateRepository = provider.GetRequiredService(); var state = await stateRepository.TryGetAsync(VmwareConnectorPlugin.SourceName, CancellationToken.None); Assert.NotNull(state); - Assert.Empty(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray()); - Assert.Empty(state.Cursor.TryGetValue("pendingMappings", out var pendingMaps) ? pendingMaps.AsDocumentArray : new DocumentArray()); - var cursorSnapshot = VmwareCursor.FromDocument(state.Cursor); + var stateValue = state!; + Assert.Empty(stateValue.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray()); + Assert.Empty(stateValue.Cursor.TryGetValue("pendingMappings", out var pendingMaps) ? pendingMaps.AsDocumentArray : new DocumentArray()); + var cursorSnapshot = VmwareCursor.FromDocument(stateValue.Cursor); _output.WriteLine($"Initial fetch cache entries: {cursorSnapshot.FetchCache.Count}"); foreach (var entry in cursorSnapshot.FetchCache) { diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareMapperTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareMapperTests.cs index 66c40f405..22aea028e 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareMapperTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Connector.Vndr.Vmware.Tests/Vmware/VmwareMapperTests.cs @@ -7,7 +7,6 @@ using StellaOps.Concelier.Connector.Common; using StellaOps.Concelier.Connector.Vndr.Vmware; using StellaOps.Concelier.Connector.Vndr.Vmware.Internal; using StellaOps.Concelier.Storage; -using StellaOps.Concelier.Storage; using Xunit; namespace StellaOps.Concelier.Connector.Vndr.Vmware.Tests; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Attestation/EvidenceBundleAttestationBuilderTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Attestation/EvidenceBundleAttestationBuilderTests.cs index ecb000126..3baaf7326 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Attestation/EvidenceBundleAttestationBuilderTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Attestation/EvidenceBundleAttestationBuilderTests.cs @@ -24,7 +24,7 @@ public sealed class EvidenceBundleAttestationBuilderTests manifestPath, transparencyPath, "git:test-sha"), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Equal("evidence-bundle-m0", claims.SubjectName); Assert.StartsWith("sha256:", claims.SubjectDigest); @@ -62,7 +62,7 @@ public sealed class EvidenceBundleAttestationBuilderTests var builder = new EvidenceBundleAttestationBuilder(); var ex = await Assert.ThrowsAsync(() => - builder.BuildAsync(new EvidenceBundleAttestationRequest(tempTar, tempManifest, null, "git:test"), CancellationToken.None)); + builder.BuildAsync(new EvidenceBundleAttestationRequest(tempTar, tempManifest, null, "git:test"), TestContext.Current.CancellationToken)); Assert.Contains("Tenant must be lowercase", ex.Message); } @@ -88,7 +88,7 @@ public sealed class EvidenceBundleAttestationBuilderTests var builder = new EvidenceBundleAttestationBuilder(); var ex = await Assert.ThrowsAsync(() => - builder.BuildAsync(new EvidenceBundleAttestationRequest(tempTar, tempManifest, null, "git:test"), CancellationToken.None)); + builder.BuildAsync(new EvidenceBundleAttestationRequest(tempTar, tempManifest, null, "git:test"), TestContext.Current.CancellationToken)); Assert.Contains("Tenant must be present", ex.Message); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/CanonicalMergerTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/CanonicalMergerTests.cs index 444e7b2af..b6ab73c66 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/CanonicalMergerTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/CanonicalMergerTests.cs @@ -230,11 +230,11 @@ public sealed class CanonicalMergerTests var reference = Assert.Single(result.Advisory.References); Assert.Equal("https://example.com/path/resource?a=1&b=2", reference.Url); - var unionDecision = Assert.Single(result.Decisions.Where(decision => decision.Field == "references")); + var unionDecision = Assert.Single(result.Decisions, decision => decision.Field == "references"); Assert.Null(unionDecision.SelectedSource); Assert.Equal("union", unionDecision.DecisionReason); - var itemDecision = Assert.Single(result.Decisions.Where(decision => decision.Field.StartsWith("references[", StringComparison.OrdinalIgnoreCase))); + var itemDecision = Assert.Single(result.Decisions, decision => decision.Field.StartsWith("references[", StringComparison.OrdinalIgnoreCase)); Assert.Equal("osv", itemDecision.SelectedSource); Assert.Equal("freshness_override", itemDecision.DecisionReason); Assert.Contains("https://example.com/path/resource?a=1&b=2", itemDecision.Field, StringComparison.OrdinalIgnoreCase); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Diagnostics/VulnExplorerTelemetryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Diagnostics/VulnExplorerTelemetryTests.cs index f93a6a85f..2f8dc20c6 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Diagnostics/VulnExplorerTelemetryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Diagnostics/VulnExplorerTelemetryTests.cs @@ -40,7 +40,7 @@ public sealed class VulnExplorerTelemetryTests var service = new AdvisoryObservationQueryService(new TestObservationLookup(observations)); - await service.QueryAsync(new AdvisoryObservationQueryOptions("tenant-a"), CancellationToken.None); + await service.QueryAsync(new AdvisoryObservationQueryOptions("tenant-a"), TestContext.Current.CancellationToken); listener.Dispose(); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Events/AdvisoryEventLogTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Events/AdvisoryEventLogTests.cs index 705ddda2b..816a9f7b2 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Events/AdvisoryEventLogTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Events/AdvisoryEventLogTests.cs @@ -42,7 +42,7 @@ public sealed class AdvisoryEventLogTests AsOf: DateTimeOffset.Parse("2025-10-03T00:00:00Z"), InputDocumentIds: new[] { Guid.Parse("11111111-1111-1111-1111-111111111111") }); - await log.AppendAsync(new AdvisoryEventAppendRequest(new[] { statementInput }), CancellationToken.None); + await log.AppendAsync(new AdvisoryEventAppendRequest(new[] { statementInput }), TestContext.Current.CancellationToken); Assert.Single(repository.InsertedStatements); var entry = repository.InsertedStatements.Single(); @@ -87,7 +87,7 @@ public sealed class AdvisoryEventLogTests AsOf: DateTimeOffset.Parse("2025-11-10T12:00:00Z"), InputDocumentIds: Array.Empty()); - await log.AppendAsync(new AdvisoryEventAppendRequest(new[] { statementInput }), CancellationToken.None); + await log.AppendAsync(new AdvisoryEventAppendRequest(new[] { statementInput }), TestContext.Current.CancellationToken); var entry = Assert.Single(repository.InsertedStatements); Assert.NotNull(entry.Provenance); @@ -112,7 +112,7 @@ public sealed class AdvisoryEventLogTests AsOf: DateTimeOffset.Parse("2025-10-04T00:00:00Z"), StatementIds: new[] { Guid.Parse("22222222-2222-2222-2222-222222222222") }); - await log.AppendAsync(new AdvisoryEventAppendRequest(Array.Empty(), new[] { conflictInput }), CancellationToken.None); + await log.AppendAsync(new AdvisoryEventAppendRequest(Array.Empty(), new[] { conflictInput }), TestContext.Current.CancellationToken); Assert.Single(repository.InsertedConflicts); var entry = repository.InsertedConflicts.Single(); @@ -147,7 +147,7 @@ public sealed class AdvisoryEventLogTests await log.AppendAsync( new AdvisoryEventAppendRequest(Array.Empty(), new[] { conflictInput }), - CancellationToken.None); + TestContext.Current.CancellationToken); var entry = Assert.Single(repository.InsertedConflicts); Assert.Equal( @@ -225,7 +225,7 @@ public sealed class AdvisoryEventLogTests RecordedAt: DateTimeOffset.Parse("2025-10-04T03:00:00Z"), StatementIds: ImmutableArray.Empty)); - var replay = await log.ReplayAsync("CVE-2025-0001", asOf: null, CancellationToken.None); + var replay = await log.ReplayAsync("CVE-2025-0001", asOf: null, TestContext.Current.CancellationToken); Assert.Equal("cve-2025-0001", replay.VulnerabilityKey); Assert.Collection( diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/JobCoordinatorTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/JobCoordinatorTests.cs index 6cb32d519..f112d258f 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/JobCoordinatorTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/JobCoordinatorTests.cs @@ -49,7 +49,7 @@ public sealed class JobCoordinatorTests new TestTimeProvider(), diagnostics); - var result = await coordinator.TriggerAsync(definition.Kind, new Dictionary { ["foo"] = "bar" }, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, new Dictionary { ["foo"] = "bar" }, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.Accepted, result.Outcome); var completed = await jobStore.Completion.Task.WaitAsync(TimeSpan.FromSeconds(2)); @@ -100,7 +100,7 @@ public sealed class JobCoordinatorTests new TestTimeProvider(), diagnostics); - var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.Accepted, result.Outcome); var completed = await jobStore.Completion.Task.WaitAsync(TimeSpan.FromSeconds(2)); @@ -151,7 +151,7 @@ public sealed class JobCoordinatorTests new TestTimeProvider(), diagnostics); - var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.Accepted, result.Outcome); var completed = await jobStore.Completion.Task.WaitAsync(TimeSpan.FromSeconds(6)); @@ -195,7 +195,7 @@ public sealed class JobCoordinatorTests new TestTimeProvider(), diagnostics); - var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.AlreadyRunning, result.Outcome); Assert.False(jobStore.CreatedRuns.Any()); @@ -237,7 +237,7 @@ public sealed class JobCoordinatorTests ["bad"] = new object(), }; - var result = await coordinator.TriggerAsync(definition.Kind, parameters, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, parameters, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.InvalidParameters, result.Outcome); Assert.Contains("unsupported", result.ErrorMessage, StringComparison.OrdinalIgnoreCase); @@ -280,7 +280,7 @@ public sealed class JobCoordinatorTests new TestTimeProvider(), diagnostics); - var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", CancellationToken.None); + var result = await coordinator.TriggerAsync(definition.Kind, null, "unit-test", TestContext.Current.CancellationToken); Assert.Equal(JobTriggerOutcome.Accepted, result.Outcome); var completed = await jobStore.Completion.Task.WaitAsync(TimeSpan.FromSeconds(2)); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Linksets/AdvisoryLinksetQueryServiceTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Linksets/AdvisoryLinksetQueryServiceTests.cs index 4b56924f7..f66d39997 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Linksets/AdvisoryLinksetQueryServiceTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Linksets/AdvisoryLinksetQueryServiceTests.cs @@ -32,7 +32,7 @@ public sealed class AdvisoryLinksetQueryServiceTests var lookup = new FakeLinksetLookup(linksets); var service = new AdvisoryLinksetQueryService(lookup); - var firstPage = await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 2), CancellationToken.None); + var firstPage = await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 2), TestContext.Current.CancellationToken); Assert.Equal(2, firstPage.Linksets.Length); Assert.True(firstPage.HasMore); @@ -40,7 +40,7 @@ public sealed class AdvisoryLinksetQueryServiceTests Assert.Equal("adv-003", firstPage.Linksets[0].AdvisoryId); Assert.Equal("pkg:npm/a", firstPage.Linksets[0].Normalized?.Purls?.First()); - var secondPage = await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 2, Cursor: firstPage.NextCursor), CancellationToken.None); + var secondPage = await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 2, Cursor: firstPage.NextCursor), TestContext.Current.CancellationToken); Assert.Single(secondPage.Linksets); Assert.False(secondPage.HasMore); @@ -56,7 +56,7 @@ public sealed class AdvisoryLinksetQueryServiceTests await Assert.ThrowsAsync(async () => { - await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 1, Cursor: "not-base64"), CancellationToken.None); + await service.QueryAsync(new AdvisoryLinksetQueryOptions("tenant", Limit: 1, Cursor: "not-base64"), TestContext.Current.CancellationToken); }); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Noise/NoisePriorServiceTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Noise/NoisePriorServiceTests.cs index 48ed05691..7dd5c5cb7 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Noise/NoisePriorServiceTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Noise/NoisePriorServiceTests.cs @@ -69,7 +69,7 @@ public sealed class NoisePriorServiceTests var result = await service.RecomputeAsync( new NoisePriorComputationRequest("CVE-9999-0001"), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Equal("cve-9999-0001", result.VulnerabilityKey); Assert.Single(result.Summaries); @@ -135,7 +135,7 @@ public sealed class NoisePriorServiceTests var result = await service.RecomputeAsync( new NoisePriorComputationRequest("cve-2025-1111"), - CancellationToken.None); + TestContext.Current.CancellationToken); var summary = Assert.Single(result.Summaries); Assert.Equal(1.0, summary.Probability); @@ -170,13 +170,13 @@ public sealed class NoisePriorServiceTests await service.RecomputeAsync( new NoisePriorComputationRequest("CVE-2025-2000"), - CancellationToken.None); + TestContext.Current.CancellationToken); var summaries = await service.GetByPackageAsync( " SemVer ", "pkg:npm/example", " linux ", - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Single(summaries); Assert.Equal("semver", summaries[0].PackageType); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Observations/AdvisoryObservationQueryServiceTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Observations/AdvisoryObservationQueryServiceTests.cs index 4cb18fd06..cd470c93c 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Observations/AdvisoryObservationQueryServiceTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Observations/AdvisoryObservationQueryServiceTests.cs @@ -57,7 +57,7 @@ public sealed class AdvisoryObservationQueryServiceTests var lookup = new InMemoryLookup(observations); var service = new AdvisoryObservationQueryService(lookup); - var result = await service.QueryAsync(new AdvisoryObservationQueryOptions("tenant-a"), CancellationToken.None); + var result = await service.QueryAsync(new AdvisoryObservationQueryOptions("tenant-a"), TestContext.Current.CancellationToken); Assert.Equal(2, result.Observations.Length); Assert.Equal("tenant-a:osv:beta:1", result.Observations[0].ObservationId); @@ -118,7 +118,7 @@ public sealed class AdvisoryObservationQueryServiceTests var result = await service.QueryAsync( new AdvisoryObservationQueryOptions("TEnant-A", aliases: new[] { " CVE-2025-0001 ", "CVE-2025-9999" }), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Equal(2, result.Observations.Length); Assert.All(result.Observations, observation => @@ -164,7 +164,7 @@ public sealed class AdvisoryObservationQueryServiceTests purls: new[] { "pkg:pypi/package-b@2.0.0" }, cpes: new[] { "cpe:/a:vendor:product:2.0" }); - var result = await service.QueryAsync(options, CancellationToken.None); + var result = await service.QueryAsync(options, TestContext.Current.CancellationToken); Assert.Single(result.Observations); Assert.Equal("tenant-a:ghsa:beta:1", result.Observations[0].ObservationId); @@ -212,7 +212,7 @@ public sealed class AdvisoryObservationQueryServiceTests var firstPage = await service.QueryAsync( new AdvisoryObservationQueryOptions("tenant-a", limit: 2), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Equal(2, firstPage.Observations.Length); Assert.True(firstPage.HasMore); @@ -220,7 +220,7 @@ public sealed class AdvisoryObservationQueryServiceTests var secondPage = await service.QueryAsync( new AdvisoryObservationQueryOptions("tenant-a", limit: 2, cursor: firstPage.NextCursor), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Single(secondPage.Observations); Assert.False(secondPage.HasMore); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Orchestration/OrchestratorRegistryStoreTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Orchestration/OrchestratorRegistryStoreTests.cs index 83db086b6..a44737fed 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Orchestration/OrchestratorRegistryStoreTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Orchestration/OrchestratorRegistryStoreTests.cs @@ -10,9 +10,9 @@ public sealed class OrchestratorRegistryStoreTests var store = new InMemoryOrchestratorRegistryStore(); var record = CreateRegistryRecord("tenant-1", "connector-1"); - await store.UpsertAsync(record, CancellationToken.None); + await store.UpsertAsync(record, TestContext.Current.CancellationToken); - var retrieved = await store.GetAsync("tenant-1", "connector-1", CancellationToken.None); + var retrieved = await store.GetAsync("tenant-1", "connector-1", TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.Equal("tenant-1", retrieved.Tenant); Assert.Equal("connector-1", retrieved.ConnectorId); @@ -25,10 +25,10 @@ public sealed class OrchestratorRegistryStoreTests var record1 = CreateRegistryRecord("tenant-1", "connector-1", source: "nvd"); var record2 = CreateRegistryRecord("tenant-1", "connector-1", source: "osv"); - await store.UpsertAsync(record1, CancellationToken.None); - await store.UpsertAsync(record2, CancellationToken.None); + await store.UpsertAsync(record1, TestContext.Current.CancellationToken); + await store.UpsertAsync(record2, TestContext.Current.CancellationToken); - var retrieved = await store.GetAsync("tenant-1", "connector-1", CancellationToken.None); + var retrieved = await store.GetAsync("tenant-1", "connector-1", TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.Equal("osv", retrieved.Source); } @@ -38,7 +38,7 @@ public sealed class OrchestratorRegistryStoreTests { var store = new InMemoryOrchestratorRegistryStore(); - var retrieved = await store.GetAsync("tenant-1", "nonexistent", CancellationToken.None); + var retrieved = await store.GetAsync("tenant-1", "nonexistent", TestContext.Current.CancellationToken); Assert.Null(retrieved); } @@ -47,11 +47,11 @@ public sealed class OrchestratorRegistryStoreTests public async Task ListAsync_ReturnsRecordsForTenant() { var store = new InMemoryOrchestratorRegistryStore(); - await store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-a"), CancellationToken.None); - await store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-b"), CancellationToken.None); - await store.UpsertAsync(CreateRegistryRecord("tenant-2", "connector-c"), CancellationToken.None); + await store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-a"), TestContext.Current.CancellationToken); + await store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-b"), TestContext.Current.CancellationToken); + await store.UpsertAsync(CreateRegistryRecord("tenant-2", "connector-c"), TestContext.Current.CancellationToken); - var records = await store.ListAsync("tenant-1", CancellationToken.None); + var records = await store.ListAsync("tenant-1", TestContext.Current.CancellationToken); Assert.Equal(2, records.Count); Assert.All(records, r => Assert.Equal("tenant-1", r.Tenant)); @@ -61,10 +61,10 @@ public sealed class OrchestratorRegistryStoreTests public async Task ListAsync_ReturnsOrderedByConnectorId() { var store = new InMemoryOrchestratorRegistryStore(); - await store.UpsertAsync(CreateRegistryRecord("tenant-1", "zzz-connector"), CancellationToken.None); - await store.UpsertAsync(CreateRegistryRecord("tenant-1", "aaa-connector"), CancellationToken.None); + await store.UpsertAsync(CreateRegistryRecord("tenant-1", "zzz-connector"), TestContext.Current.CancellationToken); + await store.UpsertAsync(CreateRegistryRecord("tenant-1", "aaa-connector"), TestContext.Current.CancellationToken); - var records = await store.ListAsync("tenant-1", CancellationToken.None); + var records = await store.ListAsync("tenant-1", TestContext.Current.CancellationToken); Assert.Equal("aaa-connector", records[0].ConnectorId); Assert.Equal("zzz-connector", records[1].ConnectorId); @@ -80,9 +80,9 @@ public sealed class OrchestratorRegistryStoreTests OrchestratorHeartbeatStatus.Running, 50, 10, null, null, null, null, DateTimeOffset.UtcNow); - await store.AppendHeartbeatAsync(heartbeat, CancellationToken.None); + await store.AppendHeartbeatAsync(heartbeat, TestContext.Current.CancellationToken); - var latest = await store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, CancellationToken.None); + var latest = await store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, TestContext.Current.CancellationToken); Assert.NotNull(latest); Assert.Equal(1, latest.Sequence); Assert.Equal(OrchestratorHeartbeatStatus.Running, latest.Status); @@ -95,11 +95,11 @@ public sealed class OrchestratorRegistryStoreTests var runId = Guid.NewGuid(); var now = DateTimeOffset.UtcNow; - await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 1, OrchestratorHeartbeatStatus.Starting, now), CancellationToken.None); - await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 3, OrchestratorHeartbeatStatus.Succeeded, now.AddMinutes(2)), CancellationToken.None); - await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 2, OrchestratorHeartbeatStatus.Running, now.AddMinutes(1)), CancellationToken.None); + await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 1, OrchestratorHeartbeatStatus.Starting, now), TestContext.Current.CancellationToken); + await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 3, OrchestratorHeartbeatStatus.Succeeded, now.AddMinutes(2)), TestContext.Current.CancellationToken); + await store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 2, OrchestratorHeartbeatStatus.Running, now.AddMinutes(1)), TestContext.Current.CancellationToken); - var latest = await store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, CancellationToken.None); + var latest = await store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, TestContext.Current.CancellationToken); Assert.NotNull(latest); Assert.Equal(3, latest.Sequence); @@ -116,9 +116,9 @@ public sealed class OrchestratorRegistryStoreTests OrchestratorCommandKind.Pause, null, null, DateTimeOffset.UtcNow, null); - await store.EnqueueCommandAsync(command, CancellationToken.None); + await store.EnqueueCommandAsync(command, TestContext.Current.CancellationToken); - var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, null, CancellationToken.None); + var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, null, TestContext.Current.CancellationToken); Assert.Single(commands); Assert.Equal(OrchestratorCommandKind.Pause, commands[0].Command); } @@ -130,11 +130,11 @@ public sealed class OrchestratorRegistryStoreTests var runId = Guid.NewGuid(); var now = DateTimeOffset.UtcNow; - await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 1, OrchestratorCommandKind.Pause, now), CancellationToken.None); - await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 2, OrchestratorCommandKind.Resume, now), CancellationToken.None); - await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 3, OrchestratorCommandKind.Throttle, now), CancellationToken.None); + await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 1, OrchestratorCommandKind.Pause, now), TestContext.Current.CancellationToken); + await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 2, OrchestratorCommandKind.Resume, now), TestContext.Current.CancellationToken); + await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 3, OrchestratorCommandKind.Throttle, now), TestContext.Current.CancellationToken); - var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, 1, CancellationToken.None); + var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, 1, TestContext.Current.CancellationToken); Assert.Equal(2, commands.Count); Assert.Equal(2, commands[0].Sequence); @@ -150,10 +150,10 @@ public sealed class OrchestratorRegistryStoreTests var expired = now.AddMinutes(-5); var future = now.AddMinutes(5); - await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 1, OrchestratorCommandKind.Pause, now, expired), CancellationToken.None); - await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 2, OrchestratorCommandKind.Resume, now, future), CancellationToken.None); + await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 1, OrchestratorCommandKind.Pause, now, expired), TestContext.Current.CancellationToken); + await store.EnqueueCommandAsync(CreateCommand("tenant-1", "connector-1", runId, 2, OrchestratorCommandKind.Resume, now, future), TestContext.Current.CancellationToken); - var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, null, CancellationToken.None); + var commands = await store.GetPendingCommandsAsync("tenant-1", "connector-1", runId, null, TestContext.Current.CancellationToken); Assert.Single(commands); Assert.Equal(2, commands[0].Sequence); @@ -171,9 +171,9 @@ public sealed class OrchestratorRegistryStoreTests "dsse-hash", DateTimeOffset.UtcNow); - await store.StoreManifestAsync(manifest, CancellationToken.None); + await store.StoreManifestAsync(manifest, TestContext.Current.CancellationToken); - var retrieved = await store.GetManifestAsync("tenant-1", "connector-1", runId, CancellationToken.None); + var retrieved = await store.GetManifestAsync("tenant-1", "connector-1", runId, TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.Equal(runId, retrieved.RunId); Assert.Equal(2, retrieved.ArtifactHashes.Count); @@ -185,7 +185,7 @@ public sealed class OrchestratorRegistryStoreTests { var store = new InMemoryOrchestratorRegistryStore(); - var manifest = await store.GetManifestAsync("tenant-1", "connector-1", Guid.NewGuid(), CancellationToken.None); + var manifest = await store.GetManifestAsync("tenant-1", "connector-1", Guid.NewGuid(), TestContext.Current.CancellationToken); Assert.Null(manifest); } @@ -196,13 +196,13 @@ public sealed class OrchestratorRegistryStoreTests var store = new InMemoryOrchestratorRegistryStore(); var runId = Guid.NewGuid(); - store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-1"), CancellationToken.None).Wait(); - store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 1, OrchestratorHeartbeatStatus.Running, DateTimeOffset.UtcNow), CancellationToken.None).Wait(); + store.UpsertAsync(CreateRegistryRecord("tenant-1", "connector-1"), TestContext.Current.CancellationToken).Wait(); + store.AppendHeartbeatAsync(CreateHeartbeat("tenant-1", "connector-1", runId, 1, OrchestratorHeartbeatStatus.Running, DateTimeOffset.UtcNow), TestContext.Current.CancellationToken).Wait(); store.Clear(); - Assert.Null(store.GetAsync("tenant-1", "connector-1", CancellationToken.None).Result); - Assert.Null(store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, CancellationToken.None).Result); + Assert.Null(store.GetAsync("tenant-1", "connector-1", TestContext.Current.CancellationToken).Result); + Assert.Null(store.GetLatestHeartbeatAsync("tenant-1", "connector-1", runId, TestContext.Current.CancellationToken).Result); } private static OrchestratorRegistryRecord CreateRegistryRecord(string tenant, string connectorId, string source = "nvd") diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Raw/AdvisoryRawServiceTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Raw/AdvisoryRawServiceTests.cs index 0f30735ff..6440252ef 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Raw/AdvisoryRawServiceTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Raw/AdvisoryRawServiceTests.cs @@ -33,7 +33,7 @@ public sealed class AdvisoryRawServiceTests var expectedResult = new AdvisoryRawUpsertResult(true, CreateRecord(storedDocument)); repository.NextResult = expectedResult; - var result = await service.IngestAsync(document, CancellationToken.None); + var result = await service.IngestAsync(document, TestContext.Current.CancellationToken); Assert.NotNull(repository.CapturedDocument); Assert.Null(repository.CapturedDocument!.Supersedes); @@ -55,7 +55,7 @@ public sealed class AdvisoryRawServiceTests var expectedResult = new AdvisoryRawUpsertResult(false, CreateRecord(existingDocument)); repository.NextResult = expectedResult; - var result = await service.IngestAsync(CreateDocument(), CancellationToken.None); + var result = await service.IngestAsync(CreateDocument(), TestContext.Current.CancellationToken); Assert.False(result.Inserted); Assert.Same(expectedResult.Record, result.Record); @@ -70,7 +70,7 @@ public sealed class AdvisoryRawServiceTests var measurements = await CollectCounterMeasurementsAsync( "ingestion_write_total", - () => service.IngestAsync(CreateDocument(), CancellationToken.None)); + () => service.IngestAsync(CreateDocument(), TestContext.Current.CancellationToken)); Assert.Contains( measurements, @@ -89,7 +89,7 @@ public sealed class AdvisoryRawServiceTests async () => { await Assert.ThrowsAsync( - () => service.IngestAsync(CreateDocument(), CancellationToken.None)); + () => service.IngestAsync(CreateDocument(), TestContext.Current.CancellationToken)); }); Assert.Contains( @@ -102,7 +102,7 @@ public sealed class AdvisoryRawServiceTests async () => { await Assert.ThrowsAsync( - () => service.IngestAsync(CreateDocument(), CancellationToken.None)); + () => service.IngestAsync(CreateDocument(), TestContext.Current.CancellationToken)); }); Assert.Contains( @@ -125,7 +125,7 @@ public sealed class AdvisoryRawServiceTests repository.NextResult = new AdvisoryRawUpsertResult(true, CreateRecord(document)); - await service.IngestAsync(document, CancellationToken.None); + await service.IngestAsync(document, TestContext.Current.CancellationToken); Assert.NotNull(repository.CapturedDocument); Assert.True(aliasSeries.SequenceEqual(repository.CapturedDocument!.Identifiers.Aliases)); @@ -148,7 +148,7 @@ public sealed class AdvisoryRawServiceTests "Tenant-Example", "ghsa-aaaa-bbbb-cccc", new[] { "Vendor-X", " " }, - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Single(results); Assert.Equal("tenant-example", repository.CapturedTenant); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Signals/AffectedSymbolProviderTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Signals/AffectedSymbolProviderTests.cs index aa0bb5ce1..481f3bb40 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Signals/AffectedSymbolProviderTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Signals/AffectedSymbolProviderTests.cs @@ -18,7 +18,7 @@ public sealed class AffectedSymbolProviderTests _timeProvider, NullLogger.Instance); - var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", CancellationToken.None); + var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", TestContext.Current.CancellationToken); Assert.Equal("tenant-1", result.TenantId); Assert.Equal("CVE-2024-0001", result.AdvisoryId); @@ -53,9 +53,9 @@ public sealed class AffectedSymbolProviderTests module: "lodash", versionRange: "<4.17.21"); - await store.StoreAsync([symbol], CancellationToken.None); + await store.StoreAsync([symbol], TestContext.Current.CancellationToken); - var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", CancellationToken.None); + var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", TestContext.Current.CancellationToken); Assert.Single(result.Symbols); Assert.Equal("lodash.template", result.Symbols[0].Symbol); @@ -84,9 +84,9 @@ public sealed class AffectedSymbolProviderTests AffectedSymbol.Method("tenant-1", "CVE-2024-0001", "obs-3", "method1", "ClassName", nvdProvenance, _timeProvider.GetUtcNow()) }; - await store.StoreAsync(symbols, CancellationToken.None); + await store.StoreAsync(symbols, TestContext.Current.CancellationToken); - var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", CancellationToken.None); + var result = await provider.GetByAdvisoryAsync("tenant-1", "CVE-2024-0001", TestContext.Current.CancellationToken); Assert.Equal(3, result.Symbols.Length); Assert.Equal(2, result.SourceSummaries.Length); @@ -121,9 +121,9 @@ public sealed class AffectedSymbolProviderTests extractedAt: _timeProvider.GetUtcNow(), purl: "pkg:npm/express@4.18.0"); - await store.StoreAsync([symbol], CancellationToken.None); + await store.StoreAsync([symbol], TestContext.Current.CancellationToken); - var result = await provider.GetByPackageAsync("tenant-1", "pkg:npm/express@4.18.0", CancellationToken.None); + var result = await provider.GetByPackageAsync("tenant-1", "pkg:npm/express@4.18.0", TestContext.Current.CancellationToken); Assert.Single(result.Symbols); Assert.Equal("express.render", result.Symbols[0].Symbol); @@ -146,10 +146,10 @@ public sealed class AffectedSymbolProviderTests AffectedSymbol.Function("tenant-1", "CVE-2024-0002", "obs-2", "func2", provenance, _timeProvider.GetUtcNow()) }; - await store.StoreAsync(symbols, CancellationToken.None); + await store.StoreAsync(symbols, TestContext.Current.CancellationToken); var options = AffectedSymbolQueryOptions.ForAdvisory("tenant-1", "CVE-2024-0001"); - var result = await provider.QueryAsync(options, CancellationToken.None); + var result = await provider.QueryAsync(options, TestContext.Current.CancellationToken); Assert.Equal(1, result.TotalCount); Assert.Single(result.Symbols); @@ -173,12 +173,12 @@ public sealed class AffectedSymbolProviderTests AffectedSymbol.Method("tenant-1", "CVE-2024-0001", "obs-2", "method1", "Class1", provenance, _timeProvider.GetUtcNow()) }; - await store.StoreAsync(symbols, CancellationToken.None); + await store.StoreAsync(symbols, TestContext.Current.CancellationToken); var options = new AffectedSymbolQueryOptions( TenantId: "tenant-1", SymbolTypes: [AffectedSymbolType.Method]); - var result = await provider.QueryAsync(options, CancellationToken.None); + var result = await provider.QueryAsync(options, TestContext.Current.CancellationToken); Assert.Equal(1, result.TotalCount); Assert.Equal(AffectedSymbolType.Method, result.Symbols[0].SymbolType); @@ -200,13 +200,13 @@ public sealed class AffectedSymbolProviderTests "tenant-1", "CVE-2024-0001", $"obs-{i}", $"func{i}", provenance, _timeProvider.GetUtcNow())) .ToList(); - await store.StoreAsync(symbols, CancellationToken.None); + await store.StoreAsync(symbols, TestContext.Current.CancellationToken); var options = new AffectedSymbolQueryOptions( TenantId: "tenant-1", Limit: 3, Offset: 2); - var result = await provider.QueryAsync(options, CancellationToken.None); + var result = await provider.QueryAsync(options, TestContext.Current.CancellationToken); Assert.Equal(10, result.TotalCount); Assert.Equal(3, result.Symbols.Length); @@ -230,12 +230,12 @@ public sealed class AffectedSymbolProviderTests AffectedSymbol.Function("tenant-1", "CVE-2024-0002", "obs-2", "func2", provenance, _timeProvider.GetUtcNow()) }; - await store.StoreAsync(symbols, CancellationToken.None); + await store.StoreAsync(symbols, TestContext.Current.CancellationToken); var result = await provider.GetByAdvisoriesBatchAsync( "tenant-1", ["CVE-2024-0001", "CVE-2024-0002", "CVE-2024-0003"], - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Equal(3, result.Count); Assert.Single(result["CVE-2024-0001"].Symbols); @@ -256,10 +256,10 @@ public sealed class AffectedSymbolProviderTests var symbol = AffectedSymbol.Function( "tenant-1", "CVE-2024-0001", "obs-1", "func1", provenance, _timeProvider.GetUtcNow()); - await store.StoreAsync([symbol], CancellationToken.None); + await store.StoreAsync([symbol], TestContext.Current.CancellationToken); - var exists = await provider.HasSymbolsAsync("tenant-1", "CVE-2024-0001", CancellationToken.None); - var notExists = await provider.HasSymbolsAsync("tenant-1", "CVE-2024-9999", CancellationToken.None); + var exists = await provider.HasSymbolsAsync("tenant-1", "CVE-2024-0001", TestContext.Current.CancellationToken); + var notExists = await provider.HasSymbolsAsync("tenant-1", "CVE-2024-9999", TestContext.Current.CancellationToken); Assert.True(exists); Assert.False(notExists); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Unknown/UnknownStateLedgerTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Unknown/UnknownStateLedgerTests.cs index e0c7a5368..2f2764213 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Unknown/UnknownStateLedgerTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Core.Tests/Unknown/UnknownStateLedgerTests.cs @@ -41,7 +41,7 @@ public sealed class UnknownStateLedgerTests }); var request = new UnknownStateLedgerRequest("CVE-2025-1111", advisory, observedAt); - var result = await ledger.RecordAsync(request, CancellationToken.None); + var result = await ledger.RecordAsync(request, TestContext.Current.CancellationToken); Assert.True(advisory.Provenance.IsDefaultOrEmpty); Assert.Equal("cve-2025-1111", result.VulnerabilityKey); @@ -62,7 +62,7 @@ public sealed class UnknownStateLedgerTests Assert.Equal("medium", fixMarker.ConfidenceBand); Assert.Contains("explicit fixed version", fixMarker.Evidence, StringComparison.OrdinalIgnoreCase); - var repositoryMarkers = await repository.GetByVulnerabilityAsync("cve-2025-1111", CancellationToken.None); + var repositoryMarkers = await repository.GetByVulnerabilityAsync("cve-2025-1111", TestContext.Current.CancellationToken); Assert.Equal(3, repositoryMarkers.Count); } @@ -89,7 +89,7 @@ public sealed class UnknownStateLedgerTests }), }); - var result = await ledger.RecordAsync(new UnknownStateLedgerRequest("GHSA-1234", advisory, observedAt), CancellationToken.None); + var result = await ledger.RecordAsync(new UnknownStateLedgerRequest("GHSA-1234", advisory, observedAt), TestContext.Current.CancellationToken); Assert.Equal("ghsa-1234", result.VulnerabilityKey); Assert.Empty(result.Markers); @@ -113,7 +113,7 @@ public sealed class UnknownStateLedgerTests repository.Stored["cve-2025-0001"] = new List { snapshot }; var ledger = new UnknownStateLedger(repository); - var markers = await ledger.GetByVulnerabilityAsync("CVE-2025-0001", CancellationToken.None); + var markers = await ledger.GetByVulnerabilityAsync("CVE-2025-0001", TestContext.Current.CancellationToken); Assert.Single(markers); Assert.Equal(snapshot, markers[0]); diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Merge.Tests/MergePropertyTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Merge.Tests/MergePropertyTests.cs index bbf1e379b..1a6297114 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Merge.Tests/MergePropertyTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Merge.Tests/MergePropertyTests.cs @@ -302,7 +302,8 @@ public sealed class MergePropertyTests // Assert - merge provenance trace should contain all original sources var mergeProvenance = result.Provenance.FirstOrDefault(p => p.Source == "merge"); mergeProvenance.Should().NotBeNull(); - mergeProvenance!.Value.ToLowerInvariant().Should().Contain("redhat"); + Assert.NotNull(mergeProvenance); + mergeProvenance.Value.ToLowerInvariant().Should().Contain("redhat"); mergeProvenance.Value.ToLowerInvariant().Should().Contain("ghsa"); mergeProvenance.Value.ToLowerInvariant().Should().Contain("osv"); } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryCanonicalRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryCanonicalRepositoryTests.cs index 83c5177da..f1c3ad4d8 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryCanonicalRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryCanonicalRepositoryTests.cs @@ -32,14 +32,14 @@ public sealed class AdvisoryCanonicalRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new AdvisoryCanonicalRepository(_dataSource, NullLogger.Instance); _sourceRepository = new SourceRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); #region GetByIdAsync Tests diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryIdempotencyTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryIdempotencyTests.cs index 7c046fda0..3211f578f 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryIdempotencyTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryIdempotencyTests.cs @@ -43,14 +43,14 @@ public sealed class AdvisoryIdempotencyTests : IAsyncLifetime { await _fixture.TruncateAllTablesAsync(); - var options = _fixture.Fixture.CreateOptions(); + var options = _fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _advisoryRepository = new AdvisoryRepository(_dataSource, NullLogger.Instance); _sourceRepository = new SourceRepository(_dataSource, NullLogger.Instance); _sourceStateRepository = new SourceStateRepository(_dataSource, NullLogger.Instance); } - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Fact] public async Task UpsertAsync_SameAdvisoryKey_Twice_NosDuplicates() diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryRepositoryTests.cs index 06592137f..a9e995e35 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/AdvisoryRepositoryTests.cs @@ -26,7 +26,7 @@ public sealed class AdvisoryRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new AdvisoryRepository(_dataSource, NullLogger.Instance); @@ -36,7 +36,7 @@ public sealed class AdvisoryRepositoryTests : IAsyncLifetime } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierMigrationTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierMigrationTests.cs index c1ee900f7..2a4e041a1 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierMigrationTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierMigrationTests.cs @@ -5,14 +5,16 @@ // Description: Model S1 migration tests for Concelier.Storage // ----------------------------------------------------------------------------- -using System.Reflection; using Dapper; using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; using StellaOps.Concelier.Persistence.Postgres; +using StellaOps.Infrastructure.Postgres.Migrations; using Npgsql; using StellaOps.TestKit; using Testcontainers.PostgreSql; using Xunit; +using Xunit.Sdk; namespace StellaOps.Concelier.Persistence.Tests; @@ -31,19 +33,34 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime public async ValueTask InitializeAsync() { - _container = new PostgreSqlBuilder() - .WithImage("postgres:16-alpine") - .WithDatabase("concelier_migration_test") - .WithUsername("postgres") - .WithPassword("postgres") - .Build(); + try + { + _container = new PostgreSqlBuilder() + .WithImage("postgres:16-alpine") + .WithDatabase("concelier_migration_test") + .WithUsername("postgres") + .WithPassword("postgres") + .Build(); - await _container.StartAsync(); + await _container.StartAsync(); + } + catch (ArgumentException ex) when (ShouldSkipForMissingDocker(ex)) + { + await SafeDisposeAsync(); + throw SkipException.ForSkip( + $"Postgres migration tests require Docker/Testcontainers. Skipping because the container failed to start: {ex.Message}"); + } + catch (TimeoutException ex) + { + await SafeDisposeAsync(); + throw SkipException.ForSkip( + $"Postgres migration tests require Docker/Testcontainers. Skipping because the container startup timed out: {ex.Message}"); + } } public async ValueTask DisposeAsync() { - await _container.DisposeAsync(); + await SafeDisposeAsync(); } [Fact] @@ -61,7 +78,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime var tables = await connection.QueryAsync( @"SELECT table_name FROM information_schema.tables - WHERE table_schema = 'public' + WHERE table_schema = 'vuln' ORDER BY table_name"); var tableList = tables.ToList(); @@ -69,7 +86,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime // Verify critical Concelier tables exist tableList.Should().Contain("advisories", "advisories table should exist"); tableList.Should().Contain("sources", "sources table should exist"); - tableList.Should().Contain("__migrations", "Migration tracking table should exist"); + tableList.Should().Contain("schema_migrations", "Migration tracking table should exist"); } [Fact] @@ -84,7 +101,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime await connection.OpenAsync(); var migrationsApplied = await connection.QueryAsync( - "SELECT migration_id FROM __migrations ORDER BY applied_at"); + "SELECT migration_name FROM vuln.schema_migrations ORDER BY applied_at"); var migrationList = migrationsApplied.ToList(); migrationList.Should().NotBeEmpty("migrations should be tracked"); @@ -109,11 +126,11 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime await connection.OpenAsync(); var migrationCount = await connection.ExecuteScalarAsync( - "SELECT COUNT(*) FROM __migrations"); + "SELECT COUNT(*) FROM vuln.schema_migrations"); // Count unique migrations var uniqueMigrations = await connection.ExecuteScalarAsync( - "SELECT COUNT(DISTINCT migration_id) FROM __migrations"); + "SELECT COUNT(DISTINCT migration_name) FROM vuln.schema_migrations"); migrationCount.Should().Be(uniqueMigrations, "each migration should only be recorded once"); @@ -132,7 +149,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime var indexes = await connection.QueryAsync( @"SELECT indexname FROM pg_indexes - WHERE schemaname = 'public' + WHERE schemaname = 'vuln' ORDER BY indexname"); var indexList = indexes.ToList(); @@ -152,7 +169,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime var advisoryColumns = await connection.QueryAsync( @"SELECT column_name FROM information_schema.columns - WHERE table_name = 'advisories' AND table_schema = 'public' + WHERE table_name = 'advisories' AND table_schema = 'vuln' ORDER BY ordinal_position"); var columnList = advisoryColumns.ToList(); @@ -177,7 +194,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime var sourceColumns = await connection.QueryAsync( @"SELECT column_name FROM information_schema.columns - WHERE table_name = 'sources' AND table_schema = 'public' + WHERE table_name = 'sources' AND table_schema = 'vuln' ORDER BY ordinal_position"); var columnList = sourceColumns.ToList(); @@ -195,49 +212,15 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime // Arrange var connectionString = _container.GetConnectionString(); - // Act - Apply migrations in sequence - var migrationFiles = GetMigrationFiles(); + // Act - Apply migrations from scratch + await ApplyAllMigrationsAsync(connectionString); + // Assert - at least some migrations should be applied (if any exist) await using var connection = new NpgsqlConnection(connectionString); await connection.OpenAsync(); - // Create migration tracking table first - await connection.ExecuteAsync(@" - CREATE TABLE IF NOT EXISTS __migrations ( - id SERIAL PRIMARY KEY, - migration_id TEXT NOT NULL UNIQUE, - applied_at TIMESTAMPTZ DEFAULT NOW() - )"); - - // Apply each migration in order - int appliedCount = 0; - foreach (var migrationFile in migrationFiles.OrderBy(f => f)) - { - var migrationId = Path.GetFileName(migrationFile); - - // Check if already applied - var alreadyApplied = await connection.ExecuteScalarAsync( - "SELECT COUNT(*) FROM __migrations WHERE migration_id = @Id", - new { Id = migrationId }); - - if (alreadyApplied > 0) - continue; - - // Apply migration - var sql = GetMigrationContent(migrationFile); - if (!string.IsNullOrWhiteSpace(sql)) - { - await connection.ExecuteAsync(sql); - await connection.ExecuteAsync( - "INSERT INTO __migrations (migration_id) VALUES (@Id)", - new { Id = migrationId }); - appliedCount++; - } - } - - // Assert - at least some migrations should be applied (if any exist) var totalMigrations = await connection.ExecuteScalarAsync( - "SELECT COUNT(*) FROM __migrations"); + "SELECT COUNT(*) FROM vuln.schema_migrations"); // This test passes even if no migrations exist yet totalMigrations.Should().BeGreaterThanOrEqualTo(0); @@ -258,7 +241,7 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime @"SELECT tc.constraint_name FROM information_schema.table_constraints tc WHERE tc.constraint_type = 'FOREIGN KEY' - AND tc.table_schema = 'public' + AND tc.table_schema = 'vuln' ORDER BY tc.constraint_name"); var fkList = foreignKeys.ToList(); @@ -268,63 +251,31 @@ public sealed class ConcelierMigrationTests : IAsyncLifetime private async Task ApplyAllMigrationsAsync(string connectionString) { - await using var connection = new NpgsqlConnection(connectionString); - await connection.OpenAsync(); + var runner = new MigrationRunner( + connectionString, + ConcelierDataSource.DefaultSchemaName, + "Concelier", + NullLogger.Instance); - // Create migration tracking table - await connection.ExecuteAsync(@" - CREATE TABLE IF NOT EXISTS __migrations ( - id SERIAL PRIMARY KEY, - migration_id TEXT NOT NULL UNIQUE, - applied_at TIMESTAMPTZ DEFAULT NOW() - )"); + await runner.RunFromAssemblyAsync( + typeof(ConcelierDataSource).Assembly, + resourcePrefix: null, + options: null, + cancellationToken: default); + } - // Get and apply all migrations - var migrationFiles = GetMigrationFiles(); - - foreach (var migrationFile in migrationFiles.OrderBy(f => f)) + private async ValueTask SafeDisposeAsync() + { + if (_container != null) { - var migrationId = Path.GetFileName(migrationFile); - - // Skip if already applied - var alreadyApplied = await connection.ExecuteScalarAsync( - "SELECT COUNT(*) FROM __migrations WHERE migration_id = @Id", - new { Id = migrationId }); - - if (alreadyApplied > 0) - continue; - - // Apply migration - var sql = GetMigrationContent(migrationFile); - if (!string.IsNullOrWhiteSpace(sql)) - { - await connection.ExecuteAsync(sql); - await connection.ExecuteAsync( - "INSERT INTO __migrations (migration_id) VALUES (@Id)", - new { Id = migrationId }); - } + await _container.DisposeAsync(); } } - private static IEnumerable GetMigrationFiles() + private static bool ShouldSkipForMissingDocker(ArgumentException exception) { - var assembly = typeof(ConcelierDataSource).Assembly; - var resourceNames = assembly.GetManifestResourceNames() - .Where(n => n.Contains("Migrations") && n.EndsWith(".sql")) - .OrderBy(n => n); - - return resourceNames; - } - - private static string GetMigrationContent(string resourceName) - { - var assembly = typeof(ConcelierDataSource).Assembly; - using var stream = assembly.GetManifestResourceStream(resourceName); - if (stream == null) - return string.Empty; - - using var reader = new StreamReader(stream); - return reader.ReadToEnd(); + return string.Equals(exception.ParamName, "DockerEndpointAuthConfig", StringComparison.Ordinal) + || exception.Message.Contains("Docker is either not running", StringComparison.OrdinalIgnoreCase); } } diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierPostgresFixture.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierPostgresFixture.cs index fd0ccf4be..0733738e9 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierPostgresFixture.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierPostgresFixture.cs @@ -1,6 +1,7 @@ using System.Reflection; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Infrastructure.Postgres.Testing; +using StellaOps.Infrastructure.Postgres.Options; using Xunit; namespace StellaOps.Concelier.Persistence.Tests; @@ -15,13 +16,21 @@ public sealed class ConcelierPostgresFixture : PostgresIntegrationFixture, IColl => typeof(ConcelierDataSource).Assembly; protected override string GetModuleName() => "Concelier"; + + public PostgresOptions CreateOptions() + { + var options = Fixture.CreateOptions(); + options.MaxPoolSize = 10; + options.MinPoolSize = 0; + return options; + } } /// /// Collection definition for Concelier PostgreSQL integration tests. /// Tests in this collection share a single PostgreSQL container instance. /// -[CollectionDefinition(Name)] +[CollectionDefinition(Name, DisableParallelization = true)] public sealed class ConcelierPostgresCollection : ICollectionFixture { public const string Name = "ConcelierPostgres"; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierQueryDeterminismTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierQueryDeterminismTests.cs index 1f1e0329b..e0bbd7b4f 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierQueryDeterminismTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ConcelierQueryDeterminismTests.cs @@ -44,7 +44,7 @@ public sealed class ConcelierQueryDeterminismTests : IAsyncLifetime { await _fixture.TruncateAllTablesAsync(); - var options = _fixture.Fixture.CreateOptions(); + var options = _fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _advisoryRepository = new AdvisoryRepository(_dataSource, NullLogger.Instance); _sourceRepository = new SourceRepository(_dataSource, NullLogger.Instance); @@ -52,7 +52,7 @@ public sealed class ConcelierQueryDeterminismTests : IAsyncLifetime _affectedRepository = new AdvisoryAffectedRepository(_dataSource, NullLogger.Instance); } - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Fact] public async Task GetModifiedSinceAsync_MultipleQueries_ReturnsDeterministicOrder() diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoreRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoreRepositoryTests.cs index a2d9b8a9b..6d5dc679d 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoreRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoreRepositoryTests.cs @@ -9,8 +9,10 @@ using FluentAssertions; using StellaOps.Concelier.Persistence.Postgres; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; +using StellaOps.Concelier.Core.Canonical; using StellaOps.Concelier.Interest; using StellaOps.Concelier.Interest.Models; +using StellaOps.Concelier.Persistence.Postgres.Models; using StellaOps.Concelier.Persistence.Postgres.Repositories; using Xunit; @@ -27,18 +29,20 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime private readonly ConcelierPostgresFixture _fixture; private readonly ConcelierDataSource _dataSource; private readonly InterestScoreRepository _repository; + private readonly AdvisoryCanonicalRepository _canonicalRepository; public InterestScoreRepositoryTests(ConcelierPostgresFixture fixture) { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new InterestScoreRepository(_dataSource, NullLogger.Instance); + _canonicalRepository = new AdvisoryCanonicalRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); #region GetByCanonicalIdAsync Tests @@ -48,7 +52,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime { // Arrange var score = CreateTestScore(); - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Act var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -84,9 +88,9 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score1 = CreateTestScore(); var score2 = CreateTestScore(); var score3 = CreateTestScore(); - await _repository.SaveAsync(score1); - await _repository.SaveAsync(score2); - await _repository.SaveAsync(score3); + await SaveScoreAsync(score1); + await SaveScoreAsync(score2); + await SaveScoreAsync(score3); // Act var result = await _repository.GetByCanonicalIdsAsync([score1.CanonicalId, score3.CanonicalId]); @@ -132,7 +136,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(score: 0.75, reasons: ["in_sbom", "reachable", "deployed"]); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -148,7 +152,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime // Arrange var canonicalId = Guid.NewGuid(); var original = CreateTestScore(canonicalId: canonicalId, score: 0.5, reasons: ["in_sbom"]); - await _repository.SaveAsync(original); + await SaveScoreAsync(original); var updated = CreateTestScore( canonicalId: canonicalId, @@ -156,7 +160,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime reasons: ["in_sbom", "reachable", "deployed", "no_vex_na"]); // Act - await _repository.SaveAsync(updated); + await SaveScoreAsync(updated); // Assert var result = await _repository.GetByCanonicalIdAsync(canonicalId); @@ -174,7 +178,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(lastSeenInBuild: buildId); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -190,7 +194,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(lastSeenInBuild: null); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -206,7 +210,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(reasons: []); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -231,7 +235,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime }; // Act - await _repository.SaveManyAsync(scores); + await SaveScoresAsync(scores); // Assert var count = await _repository.CountAsync(); @@ -245,7 +249,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime // Arrange var canonicalId = Guid.NewGuid(); var original = CreateTestScore(canonicalId: canonicalId, score: 0.3); - await _repository.SaveAsync(original); + await SaveScoreAsync(original); var scores = new[] { @@ -254,7 +258,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime }; // Act - await _repository.SaveManyAsync(scores); + await SaveScoresAsync(scores); // Assert var count = await _repository.CountAsync(); @@ -269,7 +273,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime public async Task SaveManyAsync_ShouldHandleEmptyInput() { // Act - should not throw - await _repository.SaveManyAsync([]); + await SaveScoresAsync([]); // Assert var count = await _repository.CountAsync(); @@ -286,7 +290,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime { // Arrange var score = CreateTestScore(); - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Verify exists var exists = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -324,9 +328,9 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var lowScore2 = CreateTestScore(score: 0.15, computedAt: oldDate); var highScore = CreateTestScore(score: 0.8, computedAt: oldDate); - await _repository.SaveAsync(lowScore1); - await _repository.SaveAsync(lowScore2); - await _repository.SaveAsync(highScore); + await SaveScoreAsync(lowScore1); + await SaveScoreAsync(lowScore2); + await SaveScoreAsync(highScore); // Act var result = await _repository.GetLowScoreCanonicalIdsAsync( @@ -349,8 +353,8 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var oldScore = CreateTestScore(score: 0.1, computedAt: DateTimeOffset.UtcNow.AddDays(-10)); var recentScore = CreateTestScore(score: 0.1, computedAt: DateTimeOffset.UtcNow); - await _repository.SaveAsync(oldScore); - await _repository.SaveAsync(recentScore); + await SaveScoreAsync(oldScore); + await SaveScoreAsync(recentScore); // Act var result = await _repository.GetLowScoreCanonicalIdsAsync( @@ -371,7 +375,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var oldDate = DateTimeOffset.UtcNow.AddDays(-10); for (int i = 0; i < 10; i++) { - await _repository.SaveAsync(CreateTestScore(score: 0.1, computedAt: oldDate)); + await SaveScoreAsync(CreateTestScore(score: 0.1, computedAt: oldDate)); } // Act @@ -397,9 +401,9 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var highScore2 = CreateTestScore(score: 0.75); var lowScore = CreateTestScore(score: 0.3); - await _repository.SaveAsync(highScore1); - await _repository.SaveAsync(highScore2); - await _repository.SaveAsync(lowScore); + await SaveScoreAsync(highScore1); + await SaveScoreAsync(highScore2); + await SaveScoreAsync(lowScore); // Act var result = await _repository.GetHighScoreCanonicalIdsAsync( @@ -420,7 +424,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime // Arrange for (int i = 0; i < 10; i++) { - await _repository.SaveAsync(CreateTestScore(score: 0.8)); + await SaveScoreAsync(CreateTestScore(score: 0.8)); } // Act @@ -445,9 +449,9 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var medium = CreateTestScore(score: 0.5); var high = CreateTestScore(score: 0.9); - await _repository.SaveAsync(low); - await _repository.SaveAsync(medium); - await _repository.SaveAsync(high); + await SaveScoreAsync(low); + await SaveScoreAsync(medium); + await SaveScoreAsync(high); // Act var result = await _repository.GetTopScoresAsync(limit: 10); @@ -466,7 +470,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime // Arrange for (int i = 0; i < 10; i++) { - await _repository.SaveAsync(CreateTestScore(score: 0.1 * (i + 1))); + await SaveScoreAsync(CreateTestScore(score: 0.1 * (i + 1))); } // Act @@ -487,7 +491,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime // Arrange for (int i = 0; i < 10; i++) { - await _repository.SaveAsync(CreateTestScore(score: 0.1 * (i + 1))); + await SaveScoreAsync(CreateTestScore(score: 0.1 * (i + 1))); } // Act @@ -516,8 +520,8 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var stale = CreateTestScore(computedAt: DateTimeOffset.UtcNow.AddDays(-30)); var fresh = CreateTestScore(computedAt: DateTimeOffset.UtcNow); - await _repository.SaveAsync(stale); - await _repository.SaveAsync(fresh); + await SaveScoreAsync(stale); + await SaveScoreAsync(fresh); // Act var result = await _repository.GetStaleCanonicalIdsAsync( @@ -537,7 +541,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var oldDate = DateTimeOffset.UtcNow.AddDays(-30); for (int i = 0; i < 10; i++) { - await _repository.SaveAsync(CreateTestScore(computedAt: oldDate)); + await SaveScoreAsync(CreateTestScore(computedAt: oldDate)); } // Act @@ -558,9 +562,9 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime public async Task CountAsync_ShouldReturnTotalCount() { // Arrange - await _repository.SaveAsync(CreateTestScore()); - await _repository.SaveAsync(CreateTestScore()); - await _repository.SaveAsync(CreateTestScore()); + await SaveScoreAsync(CreateTestScore()); + await SaveScoreAsync(CreateTestScore()); + await SaveScoreAsync(CreateTestScore()); // Act var count = await _repository.CountAsync(); @@ -590,15 +594,15 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime { // Arrange - create scores in different tiers // High tier (>= 0.7) - await _repository.SaveAsync(CreateTestScore(score: 0.9)); - await _repository.SaveAsync(CreateTestScore(score: 0.8)); + await SaveScoreAsync(CreateTestScore(score: 0.9)); + await SaveScoreAsync(CreateTestScore(score: 0.8)); // Medium tier (0.4 - 0.7) - await _repository.SaveAsync(CreateTestScore(score: 0.5)); + await SaveScoreAsync(CreateTestScore(score: 0.5)); // Low tier (0.2 - 0.4) - await _repository.SaveAsync(CreateTestScore(score: 0.3)); + await SaveScoreAsync(CreateTestScore(score: 0.3)); // None tier (< 0.2) - await _repository.SaveAsync(CreateTestScore(score: 0.1)); - await _repository.SaveAsync(CreateTestScore(score: 0.05)); + await SaveScoreAsync(CreateTestScore(score: 0.1)); + await SaveScoreAsync(CreateTestScore(score: 0.05)); // Act var distribution = await _repository.GetDistributionAsync(); @@ -635,8 +639,8 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime public async Task GetScoreDistributionAsync_ShouldBeAliasForGetDistributionAsync() { // Arrange - await _repository.SaveAsync(CreateTestScore(score: 0.9)); - await _repository.SaveAsync(CreateTestScore(score: 0.5)); + await SaveScoreAsync(CreateTestScore(score: 0.9)); + await SaveScoreAsync(CreateTestScore(score: 0.5)); // Act var distribution1 = await _repository.GetDistributionAsync(); @@ -660,7 +664,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(score: 1.0); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -675,7 +679,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(score: 0.0); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -691,7 +695,7 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var score = CreateTestScore(reasons: reasons); // Act - await _repository.SaveAsync(score); + await SaveScoreAsync(score); // Assert var result = await _repository.GetByCanonicalIdAsync(score.CanonicalId); @@ -706,8 +710,8 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime var older = CreateTestScore(score: 0.8, computedAt: DateTimeOffset.UtcNow.AddHours(-1)); var newer = CreateTestScore(score: 0.8, computedAt: DateTimeOffset.UtcNow); - await _repository.SaveAsync(older); - await _repository.SaveAsync(newer); + await SaveScoreAsync(older); + await SaveScoreAsync(newer); // Act var result = await _repository.GetTopScoresAsync(limit: 10); @@ -723,6 +727,49 @@ public sealed class InterestScoreRepositoryTests : IAsyncLifetime #region Test Helpers + private static readonly DateTimeOffset CanonicalSeedTimestamp = + new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero); + + private async Task SaveScoreAsync(InterestScore score) + { + await SeedCanonicalAsync(score.CanonicalId); + await _repository.SaveAsync(score); + } + + private async Task SaveScoresAsync(IReadOnlyCollection scores) + { + foreach (var score in scores) + { + await SeedCanonicalAsync(score.CanonicalId); + } + + await _repository.SaveManyAsync(scores); + } + + private async Task SeedCanonicalAsync(Guid canonicalId, CanonicalStatus status = CanonicalStatus.Active) + { + var entity = new AdvisoryCanonicalEntity + { + Id = canonicalId, + Cve = $"CVE-2024-{canonicalId.ToString("N")[..5]}", + AffectsKey = "pkg:npm/test@1.0.0", + MergeHash = $"sha256:{canonicalId:N}", + Status = CanonicalStatusToString(status), + CreatedAt = CanonicalSeedTimestamp, + UpdatedAt = CanonicalSeedTimestamp, + }; + + await _canonicalRepository.UpsertAsync(entity); + } + + private static string CanonicalStatusToString(CanonicalStatus status) => status switch + { + CanonicalStatus.Active => "active", + CanonicalStatus.Stub => "stub", + CanonicalStatus.Withdrawn => "withdrawn", + _ => "active" + }; + private static InterestScore CreateTestScore( Guid? canonicalId = null, double score = 0.5, diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoringServiceIntegrationTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoringServiceIntegrationTests.cs index 9b29e040f..bfa896104 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoringServiceIntegrationTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/InterestScoringServiceIntegrationTests.cs @@ -14,6 +14,7 @@ using StellaOps.Concelier.Cache.Valkey; using StellaOps.Concelier.Core.Canonical; using StellaOps.Concelier.Interest; using StellaOps.Concelier.Interest.Models; +using StellaOps.Concelier.Persistence.Postgres.Models; using StellaOps.Concelier.Persistence.Postgres.Repositories; using Xunit; @@ -30,6 +31,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime private readonly ConcelierPostgresFixture _fixture; private readonly ConcelierDataSource _dataSource; private readonly InterestScoreRepository _repository; + private readonly AdvisoryCanonicalRepository _canonicalRepository; private readonly Mock _cacheServiceMock; private readonly Mock _advisoryStoreMock; private readonly InterestScoreCalculator _calculator; @@ -40,9 +42,10 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new InterestScoreRepository(_dataSource, NullLogger.Instance); + _canonicalRepository = new AdvisoryCanonicalRepository(_dataSource, NullLogger.Instance); _cacheServiceMock = new Mock(); _advisoryStoreMock = new Mock(); @@ -83,7 +86,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime return new ValueTask(_fixture.TruncateAllTablesAsync()); } - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); #region ComputeScoreAsync Tests @@ -120,9 +123,10 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var score = await _service.ComputeScoreAsync(canonicalId); // Assert - score.Score.Should().Be(0.45); // in_sbom (0.30) + no_vex_na (0.15) + score.Score.Should().Be(0.55); // in_sbom (0.30) + no_vex_na (0.15) + recent (0.10) score.Reasons.Should().Contain("in_sbom"); score.Reasons.Should().Contain("no_vex_na"); + score.Reasons.Should().Contain("recent"); } [Trait("Category", TestCategories.Unit)] @@ -142,11 +146,12 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var score = await _service.ComputeScoreAsync(canonicalId); // Assert - score.Score.Should().Be(0.90); // in_sbom (0.30) + reachable (0.25) + deployed (0.20) + no_vex_na (0.15) + score.Score.Should().Be(1.00); // in_sbom + reachable + deployed + no_vex_na + recent score.Reasons.Should().Contain("in_sbom"); score.Reasons.Should().Contain("reachable"); score.Reasons.Should().Contain("deployed"); score.Reasons.Should().Contain("no_vex_na"); + score.Reasons.Should().Contain("recent"); } [Trait("Category", TestCategories.Unit)] @@ -173,9 +178,10 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var score = await _service.ComputeScoreAsync(canonicalId); // Assert - score.Score.Should().Be(0.30); // Only in_sbom, no no_vex_na + score.Score.Should().Be(0.40); // in_sbom + recent, no no_vex_na score.Reasons.Should().Contain("in_sbom"); score.Reasons.Should().NotContain("no_vex_na"); + score.Reasons.Should().Contain("recent"); } #endregion @@ -194,6 +200,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime Reasons = ["in_sbom", "reachable", "deployed"], ComputedAt = DateTimeOffset.UtcNow }; + await SeedCanonicalAsync(score.CanonicalId); // Act await _service.UpdateScoreAsync(score); @@ -217,6 +224,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime Reasons = ["in_sbom"], ComputedAt = DateTimeOffset.UtcNow }; + await SeedCanonicalAsync(score.CanonicalId); // Act await _service.UpdateScoreAsync(score); @@ -236,6 +244,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { // Arrange var canonicalId = Guid.NewGuid(); + await SeedCanonicalAsync(canonicalId); var initialScore = new InterestScore { CanonicalId = canonicalId, @@ -278,6 +287,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime Reasons = ["in_sbom", "deployed"], ComputedAt = DateTimeOffset.UtcNow }; + await SeedCanonicalAsync(score.CanonicalId); await _repository.SaveAsync(score); // Act @@ -311,6 +321,9 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); var id3 = Guid.NewGuid(); + await SeedCanonicalAsync(id1); + await SeedCanonicalAsync(id2); + await SeedCanonicalAsync(id3); // Setup signals for different scores await _service.RecordSbomMatchAsync(id1, "sha256:a", "pkg:npm/a@1.0.0"); @@ -327,8 +340,8 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var score2 = await _repository.GetByCanonicalIdAsync(id2); var score3 = await _repository.GetByCanonicalIdAsync(id3); - score1!.Score.Should().Be(0.45); // in_sbom + no_vex_na - score2!.Score.Should().Be(0.70); // in_sbom + reachable + no_vex_na + score1!.Score.Should().Be(0.55); // in_sbom + no_vex_na + recent + score2!.Score.Should().Be(0.80); // in_sbom + reachable + no_vex_na + recent score3!.Score.Should().Be(0.15); // only no_vex_na } @@ -339,6 +352,8 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime // Arrange var id1 = Guid.NewGuid(); var id2 = Guid.NewGuid(); + await SeedCanonicalAsync(id1); + await SeedCanonicalAsync(id2); await _service.RecordSbomMatchAsync(id1, "sha256:a", "pkg:npm/a@1.0.0"); await _service.RecordSbomMatchAsync(id2, "sha256:b", "pkg:npm/b@1.0.0"); @@ -374,6 +389,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime foreach (var score in scores) { + await SeedCanonicalAsync(score.CanonicalId); await _repository.SaveAsync(score); } @@ -398,14 +414,24 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { // Arrange // High tier - await _repository.SaveAsync(CreateScore(0.9)); - await _repository.SaveAsync(CreateScore(0.8)); + var highScore1 = CreateScore(0.9); + var highScore2 = CreateScore(0.8); + await SeedCanonicalAsync(highScore1.CanonicalId); + await SeedCanonicalAsync(highScore2.CanonicalId); + await _repository.SaveAsync(highScore1); + await _repository.SaveAsync(highScore2); // Medium tier - await _repository.SaveAsync(CreateScore(0.5)); + var mediumScore = CreateScore(0.5); + await SeedCanonicalAsync(mediumScore.CanonicalId); + await _repository.SaveAsync(mediumScore); // Low tier - await _repository.SaveAsync(CreateScore(0.3)); + var lowScore = CreateScore(0.3); + await SeedCanonicalAsync(lowScore.CanonicalId); + await _repository.SaveAsync(lowScore); // None tier - await _repository.SaveAsync(CreateScore(0.1)); + var noneScore = CreateScore(0.1); + await SeedCanonicalAsync(noneScore.CanonicalId); + await _repository.SaveAsync(noneScore); // Act var distribution = await _service.GetDistributionAsync(); @@ -431,6 +457,9 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var lowScore1 = CreateScore(0.1, oldDate); var lowScore2 = CreateScore(0.15, oldDate); var highScore = CreateScore(0.8, oldDate); + await SeedCanonicalAsync(lowScore1.CanonicalId); + await SeedCanonicalAsync(lowScore2.CanonicalId); + await SeedCanonicalAsync(highScore.CanonicalId); await _repository.SaveAsync(lowScore1); await _repository.SaveAsync(lowScore2); @@ -460,6 +489,8 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime // Arrange - one old, one recent var lowOld = CreateScore(0.1, DateTimeOffset.UtcNow.AddDays(-60)); var lowRecent = CreateScore(0.1, DateTimeOffset.UtcNow.AddDays(-5)); + await SeedCanonicalAsync(lowOld.CanonicalId); + await SeedCanonicalAsync(lowRecent.CanonicalId); await _repository.SaveAsync(lowOld); await _repository.SaveAsync(lowRecent); @@ -491,6 +522,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { // Arrange var highScore = CreateScore(0.8); + await SeedCanonicalAsync(highScore.CanonicalId); await _repository.SaveAsync(highScore); var stubAdvisory = CreateMockCanonicalAdvisory(highScore.CanonicalId, CanonicalStatus.Stub); @@ -517,6 +549,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { // Arrange var highScore = CreateScore(0.8); + await SeedCanonicalAsync(highScore.CanonicalId); await _repository.SaveAsync(highScore); var activeAdvisory = CreateMockCanonicalAdvisory(highScore.CanonicalId, CanonicalStatus.Active); @@ -544,6 +577,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime { // Arrange var canonicalId = Guid.NewGuid(); + await SeedCanonicalAsync(canonicalId); // Act 1: Record SBOM match await _service.RecordSbomMatchAsync( @@ -562,21 +596,22 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime // Assert: Verify in database var dbScore = await _repository.GetByCanonicalIdAsync(canonicalId); dbScore.Should().NotBeNull(); - dbScore!.Score.Should().Be(0.90); + dbScore!.Score.Should().Be(1.00); dbScore.Reasons.Should().Contain("in_sbom"); dbScore.Reasons.Should().Contain("reachable"); dbScore.Reasons.Should().Contain("deployed"); dbScore.Reasons.Should().Contain("no_vex_na"); + dbScore.Reasons.Should().Contain("recent"); // Assert: Verify cache was updated _cacheServiceMock.Verify( - x => x.UpdateScoreAsync(canonicalId.ToString(), 0.90, It.IsAny()), + x => x.UpdateScoreAsync(canonicalId.ToString(), 1.00, It.IsAny()), Times.Once); // Act 4: Retrieve via service var retrievedScore = await _service.GetScoreAsync(canonicalId); retrievedScore.Should().NotBeNull(); - retrievedScore!.Score.Should().Be(0.90); + retrievedScore!.Score.Should().Be(1.00); } [Trait("Category", TestCategories.Unit)] @@ -596,7 +631,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime // Compute initial score var initialScore = await _service.ComputeScoreAsync(canonicalId); - initialScore.Score.Should().Be(0.90); + initialScore.Score.Should().Be(1.00); // Act: Add VEX not_affected statement await _service.RecordVexStatementAsync( @@ -612,7 +647,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime var reducedScore = await _service.ComputeScoreAsync(canonicalId); // Assert: Score should be reduced (no no_vex_na factor) - reducedScore.Score.Should().Be(0.75); + reducedScore.Score.Should().Be(0.85); reducedScore.Reasons.Should().NotContain("no_vex_na"); } @@ -641,6 +676,7 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime Reasons = ["in_sbom"], ComputedAt = DateTimeOffset.UtcNow }; + await SeedCanonicalAsync(score.CanonicalId); // Act await serviceWithCacheDisabled.UpdateScoreAsync(score); @@ -659,6 +695,33 @@ public sealed class InterestScoringServiceIntegrationTests : IAsyncLifetime #region Test Helpers + private static readonly DateTimeOffset CanonicalSeedTimestamp = + new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero); + + private async Task SeedCanonicalAsync(Guid canonicalId, CanonicalStatus status = CanonicalStatus.Active) + { + var entity = new AdvisoryCanonicalEntity + { + Id = canonicalId, + Cve = $"CVE-2024-{canonicalId.ToString("N")[..5]}", + AffectsKey = "pkg:npm/test@1.0.0", + MergeHash = $"sha256:{canonicalId:N}", + Status = CanonicalStatusToString(status), + CreatedAt = CanonicalSeedTimestamp, + UpdatedAt = CanonicalSeedTimestamp, + }; + + await _canonicalRepository.UpsertAsync(entity); + } + + private static string CanonicalStatusToString(CanonicalStatus status) => status switch + { + CanonicalStatus.Active => "active", + CanonicalStatus.Stub => "stub", + CanonicalStatus.Withdrawn => "withdrawn", + _ => "active" + }; + private static InterestScore CreateScore(double score, DateTimeOffset? computedAt = null) { return new InterestScore diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/KevFlagRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/KevFlagRepositoryTests.cs index a46d66eef..da9f71359 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/KevFlagRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/KevFlagRepositoryTests.cs @@ -24,14 +24,14 @@ public sealed class KevFlagRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _advisoryRepository = new AdvisoryRepository(_dataSource, NullLogger.Instance); _repository = new KevFlagRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Linksets/AdvisoryLinksetCacheRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Linksets/AdvisoryLinksetCacheRepositoryTests.cs index 388c288bf..3ea8f1547 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Linksets/AdvisoryLinksetCacheRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Linksets/AdvisoryLinksetCacheRepositoryTests.cs @@ -14,20 +14,21 @@ namespace StellaOps.Concelier.Persistence.Tests.Linksets; public sealed class AdvisoryLinksetCacheRepositoryTests : IAsyncLifetime { private readonly ConcelierPostgresFixture _fixture; + private readonly ConcelierDataSource _dataSource; private readonly AdvisoryLinksetCacheRepository _repository; public AdvisoryLinksetCacheRepositoryTests(ConcelierPostgresFixture fixture) { _fixture = fixture; - PostgresOptions options = fixture.Fixture.CreateOptions(); + PostgresOptions options = fixture.CreateOptions(); options.SchemaName = fixture.SchemaName; - var dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); - _repository = new AdvisoryLinksetCacheRepository(dataSource, NullLogger.Instance); + _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); + _repository = new AdvisoryLinksetCacheRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Fact] public async Task Upsert_NormalizesTenantAndReplaces() @@ -36,10 +37,16 @@ public sealed class AdvisoryLinksetCacheRepositoryTests : IAsyncLifetime var initial = BuildLinkset("Tenant-A", "ghsa", "GHSA-1", new[] { "obs-1" }, createdAt, confidence: 0.5); var replacement = BuildLinkset("tenant-a", "ghsa", "GHSA-1", new[] { "obs-2" }, createdAt.AddMinutes(5), confidence: 0.9); - await _repository.UpsertAsync(initial, CancellationToken.None); - await _repository.UpsertAsync(replacement, CancellationToken.None); + await _repository.UpsertAsync(initial, TestContext.Current.CancellationToken); + await _repository.UpsertAsync(replacement, TestContext.Current.CancellationToken); - var results = await _repository.FindByTenantAsync("TENANT-A", null, null, cursor: null, limit: 10, CancellationToken.None); + var results = await _repository.FindByTenantAsync( + "TENANT-A", + null, + null, + cursor: null, + limit: 10, + TestContext.Current.CancellationToken); results.Should().ContainSingle(); results[0].TenantId.Should().Be("tenant-a"); @@ -61,14 +68,26 @@ public sealed class AdvisoryLinksetCacheRepositoryTests : IAsyncLifetime foreach (var linkset in linksets) { - await _repository.UpsertAsync(linkset, CancellationToken.None); + await _repository.UpsertAsync(linkset, TestContext.Current.CancellationToken); } - var firstPage = await _repository.FindByTenantAsync("tenant", null, null, cursor: null, limit: 10, CancellationToken.None); + var firstPage = await _repository.FindByTenantAsync( + "tenant", + null, + null, + cursor: null, + limit: 10, + TestContext.Current.CancellationToken); firstPage.Select(ls => ls.AdvisoryId).Should().ContainInOrder("ADV-001", "ADV-002", "ADV-003"); var cursor = new AdvisoryLinksetCursor(firstPage[1].CreatedAt, firstPage[1].AdvisoryId); - var secondPage = await _repository.FindByTenantAsync("tenant", null, null, cursor, limit: 10, CancellationToken.None); + var secondPage = await _repository.FindByTenantAsync( + "tenant", + null, + null, + cursor, + limit: 10, + TestContext.Current.CancellationToken); secondPage.Should().ContainSingle(); secondPage[0].AdvisoryId.Should().Be("ADV-003"); @@ -112,9 +131,15 @@ public sealed class AdvisoryLinksetCacheRepositoryTests : IAsyncLifetime CreatedAt: DateTimeOffset.Parse("2025-11-20T00:00:00Z"), BuiltByJobId: "job-42"); - await _repository.UpsertAsync(linkset, CancellationToken.None); + await _repository.UpsertAsync(linkset, TestContext.Current.CancellationToken); - var results = await _repository.FindByTenantAsync("tenant-x", new[] { "GHSA-9999" }, null, cursor: null, limit: 1, CancellationToken.None); + var results = await _repository.FindByTenantAsync( + "tenant-x", + new[] { "GHSA-9999" }, + null, + cursor: null, + limit: 1, + TestContext.Current.CancellationToken); results.Should().ContainSingle(); var cached = results[0]; diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/MergeEventRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/MergeEventRepositoryTests.cs index 7aafd488c..83a656e02 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/MergeEventRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/MergeEventRepositoryTests.cs @@ -25,7 +25,7 @@ public sealed class MergeEventRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _advisoryRepository = new AdvisoryRepository(_dataSource, NullLogger.Instance); _sourceRepository = new SourceRepository(_dataSource, NullLogger.Instance); @@ -33,7 +33,7 @@ public sealed class MergeEventRepositoryTests : IAsyncLifetime } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Performance/AdvisoryPerformanceTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Performance/AdvisoryPerformanceTests.cs index 6566b0977..8e4207420 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Performance/AdvisoryPerformanceTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/Performance/AdvisoryPerformanceTests.cs @@ -31,14 +31,14 @@ public sealed class AdvisoryPerformanceTests : IAsyncLifetime _fixture = fixture; _output = output; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new AdvisoryRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); /// /// Benchmark bulk advisory insertion performance. @@ -375,7 +375,7 @@ public sealed class AdvisoryPerformanceTests : IAsyncLifetime { Id = Guid.NewGuid(), AdvisoryKey = key, - PrimaryVulnId = $"CVE-2025-{key.GetHashCode():X8}"[..20], + PrimaryVulnId = BuildPrimaryVulnId(key), Title = title ?? $"Test Advisory {key}", Severity = "medium", Summary = $"Summary for {key}", @@ -385,6 +385,12 @@ public sealed class AdvisoryPerformanceTests : IAsyncLifetime Provenance = $$$"""{"source": "performance-test", "key": "{{{key}}}"}""" }; + private static string BuildPrimaryVulnId(string key) + { + var baseId = $"CVE-2025-{key}"; + return baseId.Length >= 20 ? baseId[..20] : baseId.PadRight(20, '0'); + } + private static List CreateTestAliases(Guid advisoryId, string cve) => [ new AdvisoryAliasEntity diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ProvenanceScopeRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ProvenanceScopeRepositoryTests.cs index 39d32eb42..bc97c3432 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ProvenanceScopeRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/ProvenanceScopeRepositoryTests.cs @@ -34,13 +34,13 @@ public sealed class ProvenanceScopeRepositoryTests : IAsyncLifetime public ProvenanceScopeRepositoryTests(ConcelierPostgresFixture fixture) { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new ProvenanceScopeRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); #region Migration Validation diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/RepositoryIntegrationTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/RepositoryIntegrationTests.cs index d4f2330f9..64a196e06 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/RepositoryIntegrationTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/RepositoryIntegrationTests.cs @@ -3,7 +3,6 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Persistence.Postgres.Models; -using StellaOps.Concelier.Persistence.Postgres; using StellaOps.Concelier.Persistence.Postgres.Repositories; using Xunit; @@ -33,7 +32,7 @@ public sealed class RepositoryIntegrationTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); options.SchemaName = fixture.SchemaName; _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); @@ -53,7 +52,7 @@ public sealed class RepositoryIntegrationTests : IAsyncLifetime } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceRepositoryTests.cs index bb6ae491d..0df7469bf 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceRepositoryTests.cs @@ -23,13 +23,13 @@ public sealed class SourceRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new SourceRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceStateRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceStateRepositoryTests.cs index 56f8ceda2..eccb8c71d 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceStateRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SourceStateRepositoryTests.cs @@ -24,14 +24,14 @@ public sealed class SourceStateRepositoryTests : IAsyncLifetime { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _sourceRepository = new SourceRepository(_dataSource, NullLogger.Instance); _repository = new SourceStateRepository(_dataSource, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); [Trait("Category", TestCategories.Unit)] [Fact] diff --git a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SyncLedgerRepositoryTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SyncLedgerRepositoryTests.cs index 574845ec3..cdf222001 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SyncLedgerRepositoryTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.Persistence.Tests/SyncLedgerRepositoryTests.cs @@ -36,14 +36,14 @@ public sealed class SyncLedgerRepositoryTests : IAsyncLifetime public SyncLedgerRepositoryTests(ConcelierPostgresFixture fixture) { _fixture = fixture; - var options = fixture.Fixture.CreateOptions(); + var options = fixture.CreateOptions(); _dataSource = new ConcelierDataSource(Options.Create(options), NullLogger.Instance); _repository = new SyncLedgerRepository(_dataSource, NullLogger.Instance); _policyService = new SitePolicyEnforcementService(_repository, NullLogger.Instance); } public ValueTask InitializeAsync() => new(_fixture.TruncateAllTablesAsync()); - public ValueTask DisposeAsync() => ValueTask.CompletedTask; + public async ValueTask DisposeAsync() => await _dataSource.DisposeAsync(); #region Task 3: Migration Validation diff --git a/src/Concelier/__Tests/StellaOps.Concelier.WebService.Tests/Aoc/AocVerifyRegressionTests.cs b/src/Concelier/__Tests/StellaOps.Concelier.WebService.Tests/Aoc/AocVerifyRegressionTests.cs index f51864a43..6a137d594 100644 --- a/src/Concelier/__Tests/StellaOps.Concelier.WebService.Tests/Aoc/AocVerifyRegressionTests.cs +++ b/src/Concelier/__Tests/StellaOps.Concelier.WebService.Tests/Aoc/AocVerifyRegressionTests.cs @@ -24,7 +24,7 @@ public sealed class AocVerifyRegressionTests var result = guard.Validate(json.RootElement, GuardOptions); Assert.False(result.IsValid); - var violation = Assert.Single(result.Violations.Where(v => v.Path == "/severity")); + var violation = Assert.Single(result.Violations, v => v.Path == "/severity"); Assert.Equal("ERR_AOC_001", violation.ErrorCode); Assert.Equal(AocViolationCode.ForbiddenField, violation.Code); } @@ -95,8 +95,8 @@ public sealed class AocVerifyRegressionTests var result = guard.Validate(json.RootElement, GuardOptions); Assert.False(result.IsValid); - var violation = Assert.Single(result.Violations.Where(v => - v.Path == "/completely_unknown_field" && v.ErrorCode == "ERR_AOC_007")); + var violation = Assert.Single(result.Violations, v => + v.Path == "/completely_unknown_field" && v.ErrorCode == "ERR_AOC_007"); Assert.Equal(AocViolationCode.UnknownField, violation.Code); } diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 63fa042e9..8e19ebfa9 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -136,12 +136,6 @@ true - - - - diff --git a/src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Tests/EvidencePortableBundleServiceTests.cs b/src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Tests/EvidencePortableBundleServiceTests.cs index 9a0fac2f6..52dcb6235 100644 --- a/src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Tests/EvidencePortableBundleServiceTests.cs +++ b/src/EvidenceLocker/StellaOps.EvidenceLocker/StellaOps.EvidenceLocker.Tests/EvidencePortableBundleServiceTests.cs @@ -76,7 +76,7 @@ public sealed class EvidencePortableBundleServiceTests var incidentMetadata = root.GetProperty("incidentMetadata"); Assert.Equal(JsonValueKind.Object, incidentMetadata.ValueKind); - Assert.True(incidentMetadata.EnumerateObject().Any(p => p.Name.StartsWith("incident.", StringComparison.Ordinal))); + Assert.Contains(incidentMetadata.EnumerateObject(), p => p.Name.StartsWith("incident.", StringComparison.Ordinal)); var instructions = entries["instructions-portable.txt"]; Assert.Contains("Portable Evidence Bundle Instructions", instructions, StringComparison.Ordinal); diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/BootstrapPackBuilderTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/BootstrapPackBuilderTests.cs index fc715845b..193d6d0ab 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/BootstrapPackBuilderTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/BootstrapPackBuilderTests.cs @@ -149,8 +149,8 @@ public sealed class BootstrapPackBuilderTests : IDisposable Assert.Contains("checksums.txt", fileNames); Assert.Contains("images/oci-layout", fileNames); Assert.Contains("images/index.json", fileNames); - Assert.True(fileNames.Any(f => f.StartsWith("charts/"))); - Assert.True(fileNames.Any(f => f.StartsWith("images/blobs/"))); + Assert.Contains(fileNames, f => f.StartsWith("charts/")); + Assert.Contains(fileNames, f => f.StartsWith("images/blobs/")); } [Trait("Category", TestCategories.Unit)] diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Db/MigrationScriptTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Db/MigrationScriptTests.cs index 2fc84d84a..6781a835f 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Db/MigrationScriptTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Db/MigrationScriptTests.cs @@ -15,10 +15,11 @@ public sealed class MigrationScriptTests Assert.True(result); Assert.NotNull(script); - Assert.Equal(1, script.Version); - Assert.Equal("001_initial_schema.sql", script.Name); - Assert.Equal(sql, script.Sql); - Assert.NotEmpty(script.Sha256); + var scriptValue = script!; + Assert.Equal(1, scriptValue.Version); + Assert.Equal("001_initial_schema.sql", scriptValue.Name); + Assert.Equal(sql, scriptValue.Sql); + Assert.NotEmpty(scriptValue.Sha256); } [Fact] @@ -31,7 +32,7 @@ public sealed class MigrationScriptTests Assert.True(result); Assert.NotNull(script); - Assert.Equal(123, script.Version); + Assert.Equal(123, script!.Version); } [Fact] @@ -44,7 +45,7 @@ public sealed class MigrationScriptTests Assert.True(result); Assert.NotNull(script); - Assert.Equal(1000, script.Version); + Assert.Equal(1000, script!.Version); } [Fact] @@ -82,7 +83,7 @@ public sealed class MigrationScriptTests Assert.NotNull(script1); Assert.NotNull(script2); - Assert.Equal(script1.Sha256, script2.Sha256); + Assert.Equal(script1!.Sha256, script2!.Sha256); } [Fact] @@ -97,7 +98,7 @@ public sealed class MigrationScriptTests Assert.NotNull(scriptUnix); Assert.NotNull(scriptWindows); - Assert.Equal(scriptUnix.Sha256, scriptWindows.Sha256); + Assert.Equal(scriptUnix!.Sha256, scriptWindows!.Sha256); } [Fact] @@ -112,7 +113,7 @@ public sealed class MigrationScriptTests Assert.NotNull(script1); Assert.NotNull(script2); - Assert.NotEqual(script1.Sha256, script2.Sha256); + Assert.NotEqual(script1!.Sha256, script2!.Sha256); } [Fact] @@ -124,7 +125,7 @@ public sealed class MigrationScriptTests _ = TryCreateMigrationScript(resourceName, sql, out var script); Assert.NotNull(script); - Assert.Matches("^[0-9a-f]{64}$", script.Sha256); + Assert.Matches("^[0-9a-f]{64}$", script!.Sha256); } // Helper to access internal MigrationScript via reflection diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineBundleBuilderTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineBundleBuilderTests.cs index 11db12bf6..6215df0be 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineBundleBuilderTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineBundleBuilderTests.cs @@ -1,10 +1,11 @@ using System.Formats.Tar; using System.IO.Compression; +using System.Linq; using System.Security.Cryptography; using System.Text; -using System.Linq; +using System.Threading; using StellaOps.ExportCenter.Core.DevPortalOffline; - +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -55,7 +56,7 @@ public sealed class DevPortalOfflineBundleBuilderTests var fixedNow = new DateTimeOffset(2025, 11, 4, 12, 30, 0, TimeSpan.Zero); var builder = new DevPortalOfflineBundleBuilder(new FakeCryptoHash(), new FixedTimeProvider(fixedNow)); - var result = builder.Build(request, CancellationToken.None); + var result = builder.Build(request, TestContext.Current.CancellationToken); Assert.Equal(request.BundleId, result.Manifest.BundleId); Assert.Equal("devportal-offline/v1", result.Manifest.Version); @@ -136,7 +137,7 @@ public sealed class DevPortalOfflineBundleBuilderTests var builder = new DevPortalOfflineBundleBuilder(new FakeCryptoHash(), new FixedTimeProvider(DateTimeOffset.UtcNow)); var request = new DevPortalOfflineBundleRequest(Guid.NewGuid()); - var exception = Assert.Throws(() => builder.Build(request, CancellationToken.None)); + var exception = Assert.Throws(() => builder.Build(request, TestContext.Current.CancellationToken)); Assert.Contains("does not contain any files", exception.Message, StringComparison.Ordinal); } @@ -153,7 +154,7 @@ public sealed class DevPortalOfflineBundleBuilderTests File.WriteAllText(Path.Combine(portalRoot, "index.html"), ""); var builder = new DevPortalOfflineBundleBuilder(new FakeCryptoHash(), new FixedTimeProvider(DateTimeOffset.UtcNow)); - var result = builder.Build(new DevPortalOfflineBundleRequest(Guid.NewGuid(), portalRoot), CancellationToken.None); + var result = builder.Build(new DevPortalOfflineBundleRequest(Guid.NewGuid(), portalRoot), TestContext.Current.CancellationToken); Assert.Single(result.Manifest.Entries); Assert.True(result.Manifest.Sources.PortalIncluded); @@ -178,7 +179,7 @@ public sealed class DevPortalOfflineBundleBuilderTests var missing = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N")); var request = new DevPortalOfflineBundleRequest(Guid.NewGuid(), missing); - Assert.Throws(() => builder.Build(request, CancellationToken.None)); + Assert.Throws(() => builder.Build(request, TestContext.Current.CancellationToken)); } private static string CalculateFileHash(string path) diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineJobTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineJobTests.cs index 8702d77e1..423ea6eb7 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineJobTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/DevPortalOfflineJobTests.cs @@ -6,9 +6,9 @@ using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using StellaOps.ExportCenter.Core.DevPortalOffline; using Microsoft.Extensions.Logging.Abstractions; - +using StellaOps.ExportCenter.Core.DevPortalOffline; +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -56,7 +56,7 @@ public class DevPortalOfflineJobTests var outcome = await job.ExecuteAsync( new DevPortalOfflineJobRequest(request, "exports/devportal", "bundle.tgz"), - CancellationToken.None); + TestContext.Current.CancellationToken); var expectedPrefix = $"exports/devportal/{bundleId:D}"; Assert.Equal($"{expectedPrefix}/manifest.json", outcome.ManifestStorage.StorageKey); @@ -103,7 +103,7 @@ public class DevPortalOfflineJobTests var request = new DevPortalOfflineBundleRequest(Guid.NewGuid(), portalRoot); var outcome = await job.ExecuteAsync( new DevPortalOfflineJobRequest(request, "exports", "../bundle.tgz"), - CancellationToken.None); + TestContext.Current.CancellationToken); var expectedPrefix = $"exports/{request.BundleId:D}"; Assert.Equal($"{expectedPrefix}/bundle.tgz", outcome.BundleStorage.StorageKey); diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/EvidenceCache/LocalEvidenceCacheServiceTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/EvidenceCache/LocalEvidenceCacheServiceTests.cs index 591012636..56438acab 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/EvidenceCache/LocalEvidenceCacheServiceTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/EvidenceCache/LocalEvidenceCacheServiceTests.cs @@ -1,6 +1,8 @@ using System.Text.Json; +using System.Threading; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.ExportCenter.Core.EvidenceCache; +using Xunit; namespace StellaOps.ExportCenter.Tests.EvidenceCache; @@ -38,7 +40,7 @@ public sealed class LocalEvidenceCacheServiceTests } }; - var cacheResult = await service.CacheEvidenceAsync(temp.Path, bundle, CancellationToken.None); + var cacheResult = await service.CacheEvidenceAsync(temp.Path, bundle, TestContext.Current.CancellationToken); Assert.True(cacheResult.Success); var cacheDir = Path.Combine(temp.Path, ".evidence"); @@ -47,7 +49,7 @@ public sealed class LocalEvidenceCacheServiceTests Assert.True(File.Exists(Path.Combine(cacheDir, "bundles", "alert-1.evidence.json"))); Assert.True(File.Exists(Path.Combine(cacheDir, "enrichment_queue.json"))); - var statistics = await service.GetStatisticsAsync(temp.Path, CancellationToken.None); + var statistics = await service.GetStatisticsAsync(temp.Path, TestContext.Current.CancellationToken); Assert.Equal(1, statistics.TotalBundles); Assert.Equal(0, statistics.FullyAvailable); @@ -73,13 +75,13 @@ public sealed class LocalEvidenceCacheServiceTests AttemptCount = 0 }; - await service.QueueEnrichmentAsync(temp.Path, request, CancellationToken.None); - await service.QueueEnrichmentAsync(temp.Path, request with { Reason = "still missing" }, CancellationToken.None); + await service.QueueEnrichmentAsync(temp.Path, request, TestContext.Current.CancellationToken); + await service.QueueEnrichmentAsync(temp.Path, request with { Reason = "still missing" }, TestContext.Current.CancellationToken); var queuePath = Path.Combine(temp.Path, ".evidence", "enrichment_queue.json"); Assert.True(File.Exists(queuePath)); - using var document = JsonDocument.Parse(await File.ReadAllTextAsync(queuePath, CancellationToken.None)); + using var document = JsonDocument.Parse(await File.ReadAllTextAsync(queuePath, TestContext.Current.CancellationToken)); var requests = document.RootElement.GetProperty("requests"); Assert.Equal(1, requests.GetArrayLength()); Assert.Equal("alert-1", requests[0].GetProperty("alert_id").GetString()); @@ -102,16 +104,16 @@ public sealed class LocalEvidenceCacheServiceTests QueuedAt = DateTimeOffset.MinValue, AttemptCount = 0 }, - CancellationToken.None); + TestContext.Current.CancellationToken); - var result = await service.ProcessEnrichmentQueueAsync(temp.Path, CancellationToken.None); + var result = await service.ProcessEnrichmentQueueAsync(temp.Path, TestContext.Current.CancellationToken); Assert.Equal(0, result.ProcessedCount); Assert.Equal(1, result.FailedCount); Assert.Equal(1, result.RemainingCount); var queuePath = Path.Combine(temp.Path, ".evidence", "enrichment_queue.json"); - using var document = JsonDocument.Parse(await File.ReadAllTextAsync(queuePath, CancellationToken.None)); + using var document = JsonDocument.Parse(await File.ReadAllTextAsync(queuePath, TestContext.Current.CancellationToken)); var requests = document.RootElement.GetProperty("requests"); Assert.Equal(1, requests.GetArrayLength()); Assert.Equal(1, requests[0].GetProperty("attempt_count").GetInt32()); diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/ExportNotificationEmitterTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/ExportNotificationEmitterTests.cs index 6c8c3c73d..0cf57c191 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/ExportNotificationEmitterTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/ExportNotificationEmitterTests.cs @@ -35,7 +35,7 @@ public sealed class ExportNotificationEmitterTests Assert.True(result.Success); Assert.Equal(1, result.AttemptCount); - Assert.Equal(1, _sink.Count); + Assert.Single(_sink); } [Trait("Category", TestCategories.Unit)] @@ -84,7 +84,7 @@ public sealed class ExportNotificationEmitterTests var result = await emitter.EmitAirgapReadyAsync(notification); Assert.False(result.Success); - Assert.Equal(1, _dlq.Count); + Assert.Single(_dlq); } [Trait("Category", TestCategories.Unit)] @@ -132,7 +132,7 @@ public sealed class ExportNotificationEmitterTests Assert.True(result.Success); Assert.Equal(3, result.AttemptCount); - Assert.Equal(0, _dlq.Count); + Assert.Empty(_dlq); } [Trait("Category", TestCategories.Unit)] @@ -221,7 +221,7 @@ public sealed class ExportNotificationEmitterTests var result = await emitter.EmitAirgapReadyAsync(notification); Assert.False(result.Success); - Assert.Equal(1, _dlq.Count); + Assert.Single(_dlq); } [Trait("Category", TestCategories.Unit)] @@ -451,7 +451,7 @@ public sealed class InMemoryExportNotificationSinkTests await sink.PublishAsync("test.channel", "{\"test\":true}"); - Assert.Equal(1, sink.Count); + Assert.Single(sink); } [Trait("Category", TestCategories.Unit)] @@ -481,7 +481,7 @@ public sealed class InMemoryExportNotificationSinkTests await sink.PublishAsync("test", "message2"); sink.Clear(); - Assert.Equal(0, sink.Count); + Assert.Empty(sink); } } @@ -496,7 +496,7 @@ public sealed class InMemoryExportNotificationDlqTests await dlq.EnqueueAsync(entry); - Assert.Equal(1, dlq.Count); + Assert.Single(dlq); } [Trait("Category", TestCategories.Unit)] diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/HmacDevPortalOfflineManifestSignerTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/HmacDevPortalOfflineManifestSignerTests.cs index 7d0c507d6..dafd88f17 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/HmacDevPortalOfflineManifestSignerTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/HmacDevPortalOfflineManifestSignerTests.cs @@ -7,7 +7,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using StellaOps.ExportCenter.Core.DevPortalOffline; using StellaOps.ExportCenter.Infrastructure.DevPortalOffline; - +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -37,7 +37,7 @@ public class HmacDevPortalOfflineManifestSignerTests var rootHash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(manifest))).ToLowerInvariant(); var bundleId = Guid.Parse("9ca2aafb-42b7-4df9-85f7-5a1d46c4e0ef"); - var document = await signer.SignAsync(bundleId, manifest, rootHash, CancellationToken.None); + var document = await signer.SignAsync(bundleId, manifest, rootHash, TestContext.Current.CancellationToken); Assert.Equal(bundleId, document.BundleId); Assert.Equal(rootHash, document.RootHash); @@ -73,7 +73,7 @@ public class HmacDevPortalOfflineManifestSignerTests NullLogger.Instance); await Assert.ThrowsAsync(() => - signer.SignAsync(Guid.NewGuid(), "{}", "root", CancellationToken.None)); + signer.SignAsync(Guid.NewGuid(), "{}", "root", TestContext.Current.CancellationToken)); } private static string ComputeExpectedSignature(DevPortalOfflineManifestSigningOptions options, string manifest) diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleBuilderTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleBuilderTests.cs index f61fb6550..4259c9c01 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleBuilderTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleBuilderTests.cs @@ -1,6 +1,7 @@ using System.IO.Compression; +using System.Threading; using StellaOps.ExportCenter.RiskBundles; - +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -25,7 +26,7 @@ public sealed class RiskBundleBuilderTests }); var builder = new RiskBundleBuilder(); - var cancellation = CancellationToken.None; + var cancellation = TestContext.Current.CancellationToken; var result = builder.Build(request, cancellation); Assert.Equal(2, result.Manifest.Providers.Count); @@ -66,7 +67,7 @@ public sealed class RiskBundleBuilderTests var builder = new RiskBundleBuilder(); - Assert.Throws(() => builder.Build(request, CancellationToken.None)); + Assert.Throws(() => builder.Build(request, TestContext.Current.CancellationToken)); } private sealed class TempDir : IDisposable diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleJobTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleJobTests.cs index 82b72f799..c7f0b65c5 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleJobTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleJobTests.cs @@ -4,7 +4,7 @@ using System.Text; using System.Text.Json; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.ExportCenter.RiskBundles; - +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -31,7 +31,7 @@ public sealed class RiskBundleJobTests store, NullLogger.Instance); - var outcome = await job.ExecuteAsync(new RiskBundleJobRequest(buildRequest), CancellationToken.None); + var outcome = await job.ExecuteAsync(new RiskBundleJobRequest(buildRequest), TestContext.Current.CancellationToken); Assert.Equal("risk-bundles/provider-manifest.json", outcome.ManifestStorage.StorageKey); Assert.Equal("risk-bundles/signatures/provider-manifest.dsse", outcome.ManifestSignatureStorage.StorageKey); diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleSignerTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleSignerTests.cs index b442139cf..21d39b07c 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleSignerTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/RiskBundleSignerTests.cs @@ -1,6 +1,8 @@ using System.Text.Json; +using System.Threading; using StellaOps.Cryptography; using StellaOps.ExportCenter.RiskBundles; +using Xunit; using StellaOps.TestKit; namespace StellaOps.ExportCenter.Tests; @@ -14,7 +16,7 @@ public class RiskBundleSignerTests var signer = new HmacRiskBundleManifestSigner(new FakeCryptoHmac(), "secret-key", "test-key"); const string manifest = "{\"foo\":1}"; - var doc = await signer.SignAsync(manifest, CancellationToken.None); + var doc = await signer.SignAsync(manifest, TestContext.Current.CancellationToken); Assert.Equal("application/stellaops.risk-bundle.provider-manifest+json", doc.PayloadType); Assert.NotNull(doc.Payload); diff --git a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Verification/ExportVerificationServiceTests.cs b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Verification/ExportVerificationServiceTests.cs index c59b92191..7872611ea 100644 --- a/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Verification/ExportVerificationServiceTests.cs +++ b/src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Tests/Verification/ExportVerificationServiceTests.cs @@ -370,7 +370,7 @@ public class ExportVerificationServiceTests var result = await _service.VerifyAsync(request); // The existing file should verify fine - Assert.True(result.FileHashes.Any(h => h.IsValid)); + Assert.Contains(result.FileHashes, h => h.IsValid); } [Fact] diff --git a/src/Notify/__Tests/StellaOps.Notify.Connectors.Email.Tests/ErrorHandling/EmailConnectorErrorTests.cs b/src/Notify/__Tests/StellaOps.Notify.Connectors.Email.Tests/ErrorHandling/EmailConnectorErrorTests.cs index 370df153b..6a17e5ffd 100644 --- a/src/Notify/__Tests/StellaOps.Notify.Connectors.Email.Tests/ErrorHandling/EmailConnectorErrorTests.cs +++ b/src/Notify/__Tests/StellaOps.Notify.Connectors.Email.Tests/ErrorHandling/EmailConnectorErrorTests.cs @@ -605,7 +605,7 @@ internal sealed class EmailConnector result.FailedRecipients = ex.InnerExceptions .OfType() .Select(e => e.FailedRecipient) - .ToList(); + .Where(r => r is not null).Cast().ToList(); return result; } catch (SmtpFailedRecipientException ex) @@ -616,7 +616,7 @@ internal sealed class EmailConnector // Classify recipient failure (result.ErrorCode, result.ShouldRetry) = ex.StatusCode switch { - SmtpStatusCode.MailboxUnavailable when ex.FailedRecipient.Contains('@') == false + SmtpStatusCode.MailboxUnavailable when ex.FailedRecipient?.Contains('@') == false => ("INVALID_RECIPIENT", false), SmtpStatusCode.MailboxUnavailable => ("MAILBOX_NOT_FOUND", false), SmtpStatusCode.ExceededStorageAllocation => ("MAILBOX_FULL", true), diff --git a/src/Notify/__Tests/StellaOps.Notify.Connectors.Slack.Tests/SlackChannelTestProviderTests.cs b/src/Notify/__Tests/StellaOps.Notify.Connectors.Slack.Tests/SlackChannelTestProviderTests.cs index 4952ff7d0..0a789b778 100644 --- a/src/Notify/__Tests/StellaOps.Notify.Connectors.Slack.Tests/SlackChannelTestProviderTests.cs +++ b/src/Notify/__Tests/StellaOps.Notify.Connectors.Slack.Tests/SlackChannelTestProviderTests.cs @@ -47,6 +47,7 @@ public sealed class SlackChannelTestProviderTests Assert.Equal("slack", result.Preview.ChannelType.ToString().ToLowerInvariant()); Assert.Equal(channel.Config.Target, result.Preview.Target); + Assert.NotNull(result.Metadata); Assert.Equal("chat:write,chat:write.public", result.Metadata["slack.scopes.required"]); Assert.Equal("stellaops-sec", result.Metadata["slack.config.workspace"]); @@ -89,6 +90,7 @@ public sealed class SlackChannelTestProviderTests var result = await provider.BuildPreviewAsync(context, CancellationToken.None); + Assert.NotNull(result.Metadata); Assert.Equal("***", result.Metadata["slack.config.SigningSecret"]); Assert.DoesNotContain("xoxs-000000000000-super", result.Metadata["slack.config.apiToken"]); Assert.Equal("https://hooks.slack.com/services/T000/B000/AAA", result.Metadata["slack.config.endpoint"]); diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Domain/Mirror/MirrorOperationRecorderTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Domain/Mirror/MirrorOperationRecorderTests.cs index 2d43dd58b..f23859f92 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Domain/Mirror/MirrorOperationRecorderTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Domain/Mirror/MirrorOperationRecorderTests.cs @@ -450,7 +450,7 @@ public sealed class InMemoryMirrorEvidenceStoreTests await store.StoreAsync(evidence); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Fact] @@ -502,7 +502,7 @@ public sealed class InMemoryMirrorEvidenceStoreTests store.Clear(); - Assert.Equal(0, store.Count); + Assert.Empty(store); } } @@ -731,7 +731,7 @@ public sealed class MirrorOperationRecorderTests Assert.NotNull(result.EvidencePointer); // Verify evidence was stored - Assert.Equal(1, _evidenceStore.Count); + Assert.Single(_evidenceStore); var evidence = await _evidenceStore.GetAsync(context.OperationId); Assert.NotNull(evidence); Assert.Equal(MirrorOperationType.BundleExport, evidence.OperationType); diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/EventPublishingTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/EventPublishingTests.cs index 4cc7a12df..89ef905ac 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/EventPublishingTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/EventPublishingTests.cs @@ -417,7 +417,7 @@ public class EventPublishingTests var result = await store.TryMarkAsync("key-1", TimeSpan.FromMinutes(5), CT); Assert.True(result); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Fact] @@ -429,7 +429,7 @@ public class EventPublishingTests var result = await store.TryMarkAsync("key-1", TimeSpan.FromMinutes(5), CT); Assert.False(result); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Fact] @@ -451,7 +451,7 @@ public class EventPublishingTests await store.RemoveAsync("key-1", CT); Assert.False(await store.ExistsAsync("key-1", CT)); - Assert.Equal(0, store.Count); + Assert.Empty(store); } [Fact] @@ -463,7 +463,7 @@ public class EventPublishingTests store.Clear(); - Assert.Equal(0, store.Count); + Assert.Empty(store); } [Fact] diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/TimelineEventTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/TimelineEventTests.cs index b7f5897e4..8fc90235a 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/TimelineEventTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Events/TimelineEventTests.cs @@ -243,7 +243,7 @@ public sealed class TimelineEventTests // Assert Assert.True(result.Success); Assert.False(result.Deduplicated); - Assert.Equal(1, sink.Count); + Assert.Single(sink); var stored = sink.GetEvents()[0]; Assert.Equal(evt.EventId, stored.EventId); @@ -281,7 +281,7 @@ public sealed class TimelineEventTests Assert.True(result2.Success); Assert.True(result2.Deduplicated); - Assert.Equal(1, sink.Count); + Assert.Single(sink); } [Fact] diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobAttestationTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobAttestationTests.cs index db10bc6c9..60fe40500 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobAttestationTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobAttestationTests.cs @@ -414,7 +414,7 @@ public sealed class InMemoryJobAttestationStoreTests await store.StoreAsync(attestation); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Fact] @@ -482,7 +482,7 @@ public sealed class InMemoryJobAttestationStoreTests store.Clear(); - Assert.Equal(0, store.Count); + Assert.Empty(store); } } @@ -552,7 +552,7 @@ public sealed class JobAttestationServiceTests var result = await _service.GenerateJobCompletionAttestationAsync(request); - Assert.Equal(1, _store.Count); + Assert.Single(_store); var stored = await _store.GetAsync(result.Attestation!.AttestationId); Assert.NotNull(stored); } diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobCapsuleTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobCapsuleTests.cs index d8543a03a..f9ab34ab6 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobCapsuleTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Evidence/JobCapsuleTests.cs @@ -302,7 +302,7 @@ public sealed class InMemoryJobCapsuleStoreTests await store.StoreAsync(capsule, CancellationToken.None); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Fact] @@ -358,10 +358,10 @@ public sealed class InMemoryJobCapsuleStoreTests var capsule = JobCapsule.Create("tenant-1", Guid.NewGuid(), "test.job", JobCapsuleKind.JobScheduling, inputs); await store.StoreAsync(capsule, CancellationToken.None); - Assert.Equal(1, store.Count); + Assert.Single(store); store.Clear(); - Assert.Equal(0, store.Count); + Assert.Empty(store); } } diff --git a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Scale/ScaleMetricsTests.cs b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Scale/ScaleMetricsTests.cs index fe1757d19..54bc2df81 100644 --- a/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Scale/ScaleMetricsTests.cs +++ b/src/Orchestrator/StellaOps.Orchestrator/StellaOps.Orchestrator.Tests/Scale/ScaleMetricsTests.cs @@ -18,7 +18,7 @@ public sealed class ScaleMetricsTests // Assert var percentiles = metrics.GetDispatchLatencyPercentiles("tenant-1"); - Assert.Equal(1, percentiles.Count); + Assert.Single(percentiles); Assert.Equal(100, percentiles.P95); } @@ -58,7 +58,7 @@ public sealed class ScaleMetricsTests var percentiles = metrics.GetDispatchLatencyPercentiles(); // Assert - Assert.Equal(0, percentiles.Count); + Assert.Empty(percentiles); Assert.Equal(0, percentiles.P95); } @@ -77,7 +77,7 @@ public sealed class ScaleMetricsTests // Assert Assert.Equal(2, tenant1Percentiles.Count); - Assert.Equal(1, tenant2Percentiles.Count); + Assert.Single(tenant2Percentiles); Assert.Equal(100, tenant2Percentiles.P95); } @@ -95,7 +95,7 @@ public sealed class ScaleMetricsTests // Assert var percentiles = metrics.GetDispatchLatencyPercentiles("tenant-1"); - Assert.Equal(1, percentiles.Count); + Assert.Single(percentiles); Assert.True(percentiles.P95 >= 10); } @@ -210,7 +210,7 @@ public sealed class ScaleMetricsTests // Assert Assert.Equal(50, snapshot.TotalQueueDepth); Assert.Equal(10, snapshot.TotalActiveJobs); - Assert.Equal(1, snapshot.DispatchLatency.Count); + Assert.Single(snapshot.DispatchLatency); Assert.Single(snapshot.QueueDepthByKey); Assert.Single(snapshot.ActiveJobsByKey); } @@ -229,7 +229,7 @@ public sealed class ScaleMetricsTests // Assert var snapshot = metrics.GetSnapshot(); Assert.Equal(0, snapshot.TotalQueueDepth); - Assert.Equal(0, snapshot.DispatchLatency.Count); + Assert.Empty(snapshot.DispatchLatency); } [Fact] diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Attestation/VerdictAttestationIntegrationTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Attestation/VerdictAttestationIntegrationTests.cs index 362be45e5..0f3efde73 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Attestation/VerdictAttestationIntegrationTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Attestation/VerdictAttestationIntegrationTests.cs @@ -89,7 +89,7 @@ public class VerdictAttestationIntegrationTests NullLogger.Instance); // Act - var verdictId = await service.AttestVerdictAsync(trace, CancellationToken.None); + var verdictId = await service.AttestVerdictAsync(trace, TestContext.Current.CancellationToken); // Assert verdictId.Should().NotBeNullOrEmpty(); @@ -155,7 +155,7 @@ public class VerdictAttestationIntegrationTests NullLogger.Instance); // Act - var verdictId = await service.AttestVerdictAsync(trace, CancellationToken.None); + var verdictId = await service.AttestVerdictAsync(trace, TestContext.Current.CancellationToken); // Assert - Service returns null on failure verdictId.Should().BeNull(); @@ -200,7 +200,7 @@ public class VerdictAttestationIntegrationTests NullLogger.Instance); // Act - var verdictId = await service.AttestVerdictAsync(trace, CancellationToken.None); + var verdictId = await service.AttestVerdictAsync(trace, TestContext.Current.CancellationToken); // Assert - Service returns null on timeout/failure verdictId.Should().BeNull(); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Gates/BudgetEnforcementIntegrationTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Gates/BudgetEnforcementIntegrationTests.cs index 0f65e7f80..8f5ec5ecc 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Gates/BudgetEnforcementIntegrationTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Gates/BudgetEnforcementIntegrationTests.cs @@ -330,7 +330,7 @@ public sealed class BudgetEnforcementIntegrationTests ReleaseId = "jan-release", RiskPoints = 50, ConsumedAt = DateTimeOffset.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await _ledger.GetBudgetAsync(serviceId, window2); await _store.AddEntryAsync(new BudgetEntry @@ -341,7 +341,7 @@ public sealed class BudgetEnforcementIntegrationTests ReleaseId = "feb-release", RiskPoints = 30, ConsumedAt = DateTimeOffset.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Act var historyW1 = await _ledger.GetHistoryAsync(serviceId, window1); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/IncrementalOrchestrator/IncrementalOrchestratorTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/IncrementalOrchestrator/IncrementalOrchestratorTests.cs index c4ce92c2f..a5eed05b7 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/IncrementalOrchestrator/IncrementalOrchestratorTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/IncrementalOrchestrator/IncrementalOrchestratorTests.cs @@ -149,7 +149,7 @@ public sealed class IncrementalOrchestratorTests "tenant1", "ADV-001", "CVE-001", ["pkg:npm/test"], "test", timeProvider.GetUtcNow(), timeProvider.GetUtcNow())); - var result = await orchestrator.ProcessAsync(CancellationToken.None); + var result = await orchestrator.ProcessAsync(TestContext.Current.CancellationToken); result.TotalEventsRead.Should().Be(1); result.BatchesProcessed.Should().Be(1); @@ -173,11 +173,11 @@ public sealed class IncrementalOrchestratorTests "test", timeProvider.GetUtcNow(), timeProvider.GetUtcNow()); // Mark as already seen - await idempotencyStore.MarkSeenAsync(evt.EventId, timeProvider.GetUtcNow(), CancellationToken.None); + await idempotencyStore.MarkSeenAsync(evt.EventId, timeProvider.GetUtcNow(), TestContext.Current.CancellationToken); eventSource.Enqueue(evt); - var result = await orchestrator.ProcessAsync(CancellationToken.None); + var result = await orchestrator.ProcessAsync(TestContext.Current.CancellationToken); result.TotalEventsRead.Should().Be(1); result.EventsSkippedDuplicate.Should().Be(1); @@ -208,7 +208,7 @@ public sealed class IncrementalOrchestratorTests eventSource.Enqueue(evt); - var result = await orchestrator.ProcessAsync(CancellationToken.None); + var result = await orchestrator.ProcessAsync(TestContext.Current.CancellationToken); result.TotalEventsRead.Should().Be(1); result.EventsSkippedOld.Should().Be(1); @@ -235,7 +235,7 @@ public sealed class IncrementalOrchestratorTests "tenant2", "ADV-002", "CVE-002", [], "test", timeProvider.GetUtcNow(), timeProvider.GetUtcNow())); - var result = await orchestrator.ProcessAsync(CancellationToken.None); + var result = await orchestrator.ProcessAsync(TestContext.Current.CancellationToken); result.BatchesProcessed.Should().Be(2); // One per tenant submitter.SubmittedBatches.Select(b => b.TenantId).Should() @@ -266,7 +266,7 @@ public sealed class IncrementalOrchestratorTests timeProvider.GetUtcNow(), timeProvider.GetUtcNow(), priority: PolicyChangePriority.Emergency)); - await orchestrator.ProcessAsync(CancellationToken.None); + await orchestrator.ProcessAsync(TestContext.Current.CancellationToken); // Emergency should be processed first (separate batch due to priority) submitter.SubmittedBatches.Should().HaveCount(2); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Notifications/PolicyProfileNotificationServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Notifications/PolicyProfileNotificationServiceTests.cs index 5eed5a645..94a6fa384 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Notifications/PolicyProfileNotificationServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Notifications/PolicyProfileNotificationServiceTests.cs @@ -48,7 +48,7 @@ public sealed class PolicyProfileNotificationServiceTests profile, "alice@example.com", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -76,7 +76,7 @@ public sealed class PolicyProfileNotificationServiceTests profile, "alice@example.com", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -97,7 +97,7 @@ public sealed class PolicyProfileNotificationServiceTests "alice@example.com", "Deprecated in favor of v2.0.0", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -119,7 +119,7 @@ public sealed class PolicyProfileNotificationServiceTests "alice@example.com", "Increased high/critical thresholds", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -143,7 +143,7 @@ public sealed class PolicyProfileNotificationServiceTests "suppress", "False positive confirmed by security team", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -167,7 +167,7 @@ public sealed class PolicyProfileNotificationServiceTests "alice@example.com", "override-001", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -190,7 +190,7 @@ public sealed class PolicyProfileNotificationServiceTests highImpactCount: 5, completedAt: _timeProvider.GetUtcNow(), "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -224,7 +224,7 @@ public sealed class PolicyProfileNotificationServiceTests lifecycleEvent, profile, "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -254,7 +254,7 @@ public sealed class PolicyProfileNotificationServiceTests lifecycleEvent, profile, "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -283,7 +283,7 @@ public sealed class PolicyProfileNotificationServiceTests lifecycleEvent, profile: null, "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Single(_publisher.PublishedEvents); @@ -311,7 +311,7 @@ public sealed class PolicyProfileNotificationServiceTests profile, "alice@example.com", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert Assert.Empty(_publisher.PublishedEvents); @@ -336,7 +336,7 @@ public sealed class PolicyProfileNotificationServiceTests profile, "alice@example.com", "abc123hash", - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert - no exception thrown Assert.True(true); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyBundleServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyBundleServiceTests.cs index 2af546f26..0e2322bbc 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyBundleServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyBundleServiceTests.cs @@ -26,7 +26,7 @@ public sealed class PolicyBundleServiceTests var services = CreateServices(); var request = new PolicyBundleRequest(new PolicyDslPayload("stella-dsl@1", BaselineDsl), SigningKeyId: "test-key"); - var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, CancellationToken.None); + var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, TestContext.Current.CancellationToken); Assert.True(response.Success); Assert.NotNull(response.Digest); @@ -41,7 +41,7 @@ public sealed class PolicyBundleServiceTests var services = CreateServices(); var request = new PolicyBundleRequest(new PolicyDslPayload("unknown", "policy bad"), SigningKeyId: null); - var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, CancellationToken.None); + var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, TestContext.Current.CancellationToken); Assert.False(response.Success); Assert.Null(response.Digest); @@ -55,7 +55,7 @@ public sealed class PolicyBundleServiceTests var services = CreateServices(); var request = new PolicyBundleRequest(new PolicyDslPayload("stella-dsl@1", BaselineDsl), SigningKeyId: "test-key"); - var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, CancellationToken.None); + var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, TestContext.Current.CancellationToken); Assert.True(response.Success); Assert.NotNull(response.AocMetadata); @@ -83,13 +83,13 @@ public sealed class PolicyBundleServiceTests SigningKeyId: "test-key", Provenance: provenance); - var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, CancellationToken.None); + var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, TestContext.Current.CancellationToken); Assert.True(response.Success); Assert.NotNull(response.AocMetadata); // Verify bundle record has provenance stored - var bundle = await services.Repository.GetBundleAsync("pack-1", 1, CancellationToken.None); + var bundle = await services.Repository.GetBundleAsync("pack-1", 1, TestContext.Current.CancellationToken); Assert.NotNull(bundle); Assert.NotNull(bundle!.AocMetadata); Assert.NotNull(bundle.AocMetadata!.Provenance); @@ -107,7 +107,7 @@ public sealed class PolicyBundleServiceTests var services = CreateServices(); var request = new PolicyBundleRequest(new PolicyDslPayload("unknown", "policy bad"), SigningKeyId: null); - var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, CancellationToken.None); + var response = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request, TestContext.Current.CancellationToken); Assert.False(response.Success); Assert.Null(response.AocMetadata); @@ -121,8 +121,8 @@ public sealed class PolicyBundleServiceTests var request1 = new PolicyBundleRequest(new PolicyDslPayload("stella-dsl@1", BaselineDsl), SigningKeyId: "test-key"); var request2 = new PolicyBundleRequest(new PolicyDslPayload("stella-dsl@1", BaselineDsl), SigningKeyId: "test-key"); - var response1 = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request1, CancellationToken.None); - var response2 = await services.BundleService.CompileAndStoreAsync("pack-2", 1, request2, CancellationToken.None); + var response1 = await services.BundleService.CompileAndStoreAsync("pack-1", 1, request1, TestContext.Current.CancellationToken); + var response2 = await services.BundleService.CompileAndStoreAsync("pack-2", 1, request2, TestContext.Current.CancellationToken); Assert.NotNull(response1.AocMetadata); Assert.NotNull(response2.AocMetadata); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyPackRepositoryTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyPackRepositoryTests.cs index 0bf5e08f4..8a8dba270 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyPackRepositoryTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyPackRepositoryTests.cs @@ -13,10 +13,10 @@ public class PolicyPackRepositoryTests [Fact] public async Task ActivateRevision_WithSingleApprover_ActivatesImmediately() { - await repository.CreateAsync("pack-1", "Pack", CancellationToken.None); - await repository.UpsertRevisionAsync("pack-1", 1, requiresTwoPersonApproval: false, PolicyRevisionStatus.Approved, CancellationToken.None); + await repository.CreateAsync("pack-1", "Pack", TestContext.Current.CancellationToken); + await repository.UpsertRevisionAsync("pack-1", 1, requiresTwoPersonApproval: false, PolicyRevisionStatus.Approved, TestContext.Current.CancellationToken); - var result = await repository.RecordActivationAsync("pack-1", 1, "alice", DateTimeOffset.UtcNow, null, CancellationToken.None); + var result = await repository.RecordActivationAsync("pack-1", 1, "alice", DateTimeOffset.UtcNow, null, TestContext.Current.CancellationToken); Assert.Equal(PolicyActivationResultStatus.Activated, result.Status); Assert.NotNull(result.Revision); @@ -28,18 +28,18 @@ public class PolicyPackRepositoryTests [Fact] public async Task ActivateRevision_WithTwoPersonRequirement_ReturnsPendingUntilSecondApproval() { - await repository.CreateAsync("pack-2", "Pack", CancellationToken.None); - await repository.UpsertRevisionAsync("pack-2", 1, requiresTwoPersonApproval: true, PolicyRevisionStatus.Approved, CancellationToken.None); + await repository.CreateAsync("pack-2", "Pack", TestContext.Current.CancellationToken); + await repository.UpsertRevisionAsync("pack-2", 1, requiresTwoPersonApproval: true, PolicyRevisionStatus.Approved, TestContext.Current.CancellationToken); - var first = await repository.RecordActivationAsync("pack-2", 1, "alice", DateTimeOffset.UtcNow, null, CancellationToken.None); + var first = await repository.RecordActivationAsync("pack-2", 1, "alice", DateTimeOffset.UtcNow, null, TestContext.Current.CancellationToken); Assert.Equal(PolicyActivationResultStatus.PendingSecondApproval, first.Status); Assert.Equal(PolicyRevisionStatus.Approved, first.Revision!.Status); Assert.Single(first.Revision.Approvals); - var duplicate = await repository.RecordActivationAsync("pack-2", 1, "alice", DateTimeOffset.UtcNow, null, CancellationToken.None); + var duplicate = await repository.RecordActivationAsync("pack-2", 1, "alice", DateTimeOffset.UtcNow, null, TestContext.Current.CancellationToken); Assert.Equal(PolicyActivationResultStatus.DuplicateApproval, duplicate.Status); - var second = await repository.RecordActivationAsync("pack-2", 1, "bob", DateTimeOffset.UtcNow, null, CancellationToken.None); + var second = await repository.RecordActivationAsync("pack-2", 1, "bob", DateTimeOffset.UtcNow, null, TestContext.Current.CancellationToken); Assert.Equal(PolicyActivationResultStatus.Activated, second.Status); Assert.Equal(PolicyRevisionStatus.Active, second.Revision!.Status); Assert.Equal(2, second.Revision.Approvals.Length); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluationServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluationServiceTests.cs index 10734d295..d5f8b5ece 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluationServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluationServiceTests.cs @@ -48,7 +48,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request = CreateRequest("pack-1", 1, severity: "Critical"); - var response = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal("pack-1", response.PackId); Assert.Equal(1, response.Version); @@ -67,11 +67,11 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request = CreateRequest("pack-1", 1, severity: "High"); // First call - cache miss - var response1 = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response1 = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.False(response1.Cached); // Second call - cache hit - var response2 = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response2 = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.True(response2.Cached); Assert.Equal(CacheSource.InMemory, response2.CacheSource); Assert.Equal(response1.Status, response2.Status); @@ -88,12 +88,12 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request = CreateRequest("pack-1", 1, severity: "Medium"); // First call - var response1 = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response1 = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.False(response1.Cached); // Second call with bypass var bypassRequest = request with { BypassCache = true }; - var response2 = await harness.Service.EvaluateAsync(bypassRequest, CancellationToken.None); + var response2 = await harness.Service.EvaluateAsync(bypassRequest, TestContext.Current.CancellationToken); Assert.False(response2.Cached); } @@ -105,7 +105,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request = CreateRequest("non-existent", 1, severity: "Low"); await Assert.ThrowsAsync( - () => harness.Service.EvaluateAsync(request, CancellationToken.None)); + () => harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken)); } [Trait("Category", TestCategories.Unit)] @@ -117,13 +117,13 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request = CreateRequest("pack-1", 1, severity: "High"); - var response1 = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response1 = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); // Create a new harness with fresh cache var harness2 = CreateHarness(); await harness2.StoreTestPolicyAsync("pack-1", 1, TestPolicy); - var response2 = await harness2.Service.EvaluateAsync(request, CancellationToken.None); + var response2 = await harness2.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); // Same inputs should produce same correlation ID Assert.Equal(response1.CorrelationId, response2.CorrelationId); @@ -143,7 +143,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests CreateRequest("pack-1", 1, severity: "Medium", subjectPurl: "pkg:npm/axios@1.0.0"), }; - var responses = await harness.Service.EvaluateBatchAsync(requests, CancellationToken.None); + var responses = await harness.Service.EvaluateBatchAsync(requests, TestContext.Current.CancellationToken); Assert.Equal(3, responses.Count); } @@ -157,7 +157,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests // Pre-populate cache var request = CreateRequest("pack-1", 1, severity: "Critical"); - await harness.Service.EvaluateAsync(request, CancellationToken.None); + await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); var requests = new[] { @@ -165,7 +165,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests CreateRequest("pack-1", 1, severity: "High"), // New }; - var responses = await harness.Service.EvaluateBatchAsync(requests, CancellationToken.None); + var responses = await harness.Service.EvaluateBatchAsync(requests, TestContext.Current.CancellationToken); Assert.Equal(2, responses.Count); Assert.Contains(responses, r => r.Cached); @@ -182,8 +182,8 @@ public sealed class PolicyRuntimeEvaluationServiceTests var request1 = CreateRequest("pack-1", 1, severity: "High"); var request2 = CreateRequest("pack-1", 1, severity: "Critical"); - var response1 = await harness.Service.EvaluateAsync(request1, CancellationToken.None); - var response2 = await harness.Service.EvaluateAsync(request2, CancellationToken.None); + var response1 = await harness.Service.EvaluateAsync(request1, TestContext.Current.CancellationToken); + var response2 = await harness.Service.EvaluateAsync(request2, TestContext.Current.CancellationToken); // Both should be cache misses (different severity = different context) Assert.False(response1.Cached); @@ -233,11 +233,11 @@ public sealed class PolicyRuntimeEvaluationServiceTests Metadata = new Dictionary() }; - await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None); + await harness.ReachabilityStore.SaveAsync(fact, TestContext.Current.CancellationToken); var request = CreateRequest("pack-2", 1, severity: "Low"); - var response = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal("warn", response.Status); } @@ -289,10 +289,10 @@ public sealed class PolicyRuntimeEvaluationServiceTests Metadata = new Dictionary() }; - await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None); + await harness.ReachabilityStore.SaveAsync(fact, TestContext.Current.CancellationToken); var request = CreateRequest("pack-3", 1, severity: "Low"); - var response = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal("under_investigation", response.Status); } @@ -344,10 +344,10 @@ public sealed class PolicyRuntimeEvaluationServiceTests Metadata = new Dictionary() }; - await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None); + await harness.ReachabilityStore.SaveAsync(fact, TestContext.Current.CancellationToken); var request = CreateRequest("pack-4", 1, severity: "Low"); - var response = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal("under_investigation", response.Status); } @@ -399,10 +399,10 @@ public sealed class PolicyRuntimeEvaluationServiceTests Metadata = new Dictionary() }; - await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None); + await harness.ReachabilityStore.SaveAsync(fact, TestContext.Current.CancellationToken); var request = CreateRequest("pack-5", 1, severity: "Low"); - var response = await harness.Service.EvaluateAsync(request, CancellationToken.None); + var response = await harness.Service.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal("not_affected", response.Status); } @@ -489,7 +489,7 @@ public sealed class PolicyRuntimeEvaluationServiceTests { var bundleService = new PolicyBundleService(CompilationService, Repository, TimeProvider.System); var request = new PolicyBundleRequest(new PolicyDslPayload("stella-dsl@1", dsl), SigningKeyId: null); - await bundleService.CompileAndStoreAsync(packId, version, request, CancellationToken.None); + await bundleService.CompileAndStoreAsync(packId, version, request, TestContext.Current.CancellationToken); } } diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluatorTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluatorTests.cs index 9a62938a2..98101bc96 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluatorTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyRuntimeEvaluatorTests.cs @@ -22,13 +22,13 @@ public sealed class PolicyRuntimeEvaluatorTests Size: 4, CreatedAt: DateTimeOffset.UnixEpoch, Payload: new byte[] { 1, 2, 3, 4 }.ToImmutableArray()), - CancellationToken.None); + TestContext.Current.CancellationToken); var evaluator = new PolicyRuntimeEvaluator(repo); var request = new PolicyEvaluationRequest("pack-1", 1, "subject-a"); - var first = await evaluator.EvaluateAsync(request, CancellationToken.None); - var second = await evaluator.EvaluateAsync(request, CancellationToken.None); + var first = await evaluator.EvaluateAsync(request, TestContext.Current.CancellationToken); + var second = await evaluator.EvaluateAsync(request, TestContext.Current.CancellationToken); Assert.Equal(first.Decision, second.Decision); Assert.False(first.Cached); @@ -44,6 +44,6 @@ public sealed class PolicyRuntimeEvaluatorTests var evaluator = new PolicyRuntimeEvaluator(new InMemoryPolicyPackRepository()); var request = new PolicyEvaluationRequest("pack-x", 1, "subject-a"); - await Assert.ThrowsAsync(() => evaluator.EvaluateAsync(request, CancellationToken.None)); + await Assert.ThrowsAsync(() => evaluator.EvaluateAsync(request, TestContext.Current.CancellationToken)); } } diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyWorkerServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyWorkerServiceTests.cs index 37c9380ac..77311b7f2 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyWorkerServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/PolicyWorkerServiceTests.cs @@ -35,7 +35,7 @@ public sealed class PolicyWorkerServiceTests await jobStore.SaveAsync(job); - var result = await service.ExecuteAsync(new WorkerRunRequest(job.JobId), CancellationToken.None); + var result = await service.ExecuteAsync(new WorkerRunRequest(job.JobId), TestContext.Current.CancellationToken); Assert.Equal(job.JobId, result.JobId); Assert.Equal("worker-stub", result.WorkerId); diff --git a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Workers/ExceptionLifecycleServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Workers/ExceptionLifecycleServiceTests.cs index 389447fb7..ea0ddfcba 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Workers/ExceptionLifecycleServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Engine.Tests/Workers/ExceptionLifecycleServiceTests.cs @@ -22,7 +22,7 @@ public sealed class ExceptionLifecycleServiceTests options, NullLogger.Instance); - await service.ProcessOnceAsync(CancellationToken.None); + await service.ProcessOnceAsync(TestContext.Current.CancellationToken); repository.ExpiredTenants.Should().BeEmpty(); } @@ -42,7 +42,7 @@ public sealed class ExceptionLifecycleServiceTests Reason = "test-fixture", ExpiresAt = new DateTimeOffset(2000, 1, 1, 0, 0, 0, TimeSpan.Zero), CreatedAt = new DateTimeOffset(2025, 12, 1, 0, 0, 0, TimeSpan.Zero) - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); var configured = new PolicyEngineOptions(); configured.ResourceServer.RequiredTenants.Add("tenant-b"); @@ -52,9 +52,9 @@ public sealed class ExceptionLifecycleServiceTests Microsoft.Extensions.Options.Options.Create(configured), NullLogger.Instance); - await service.ProcessOnceAsync(CancellationToken.None); + await service.ProcessOnceAsync(TestContext.Current.CancellationToken); - var updated = await repo.GetByIdAsync("tenant-b", id, CancellationToken.None); + var updated = await repo.GetByIdAsync("tenant-b", id, TestContext.Current.CancellationToken); updated!.Status.Should().Be(ExceptionStatus.Expired); updated.RevokedAt.Should().NotBeNull(); } diff --git a/src/Policy/__Tests/StellaOps.Policy.Persistence.Tests/RecheckEvidenceMigrationTests.cs b/src/Policy/__Tests/StellaOps.Policy.Persistence.Tests/RecheckEvidenceMigrationTests.cs index 7bb487e47..711a080c9 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Persistence.Tests/RecheckEvidenceMigrationTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Persistence.Tests/RecheckEvidenceMigrationTests.cs @@ -33,7 +33,7 @@ public sealed class RecheckEvidenceMigrationTests : IAsyncLifetime [Fact] public async Task Migration_CreatesRecheckAndEvidenceTables() { - await using var connection = await _dataSource.OpenConnectionAsync("default", "reader", CancellationToken.None); + await using var connection = await _dataSource.OpenConnectionAsync("default", "reader", TestContext.Current.CancellationToken); await AssertTableExistsAsync(connection, "policy.recheck_policies"); await AssertTableExistsAsync(connection, "policy.evidence_hooks"); diff --git a/src/Policy/__Tests/StellaOps.Policy.Tests/Gates/BudgetLedgerTests.cs b/src/Policy/__Tests/StellaOps.Policy.Tests/Gates/BudgetLedgerTests.cs index 74f68a06e..db1697f58 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Tests/Gates/BudgetLedgerTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Tests/Gates/BudgetLedgerTests.cs @@ -32,7 +32,7 @@ public sealed class BudgetLedgerTests public async Task GetBudget_ReturnsExistingBudget() { var existing = CreateBudget("existing-service", consumed: 50); - await _store.CreateAsync(existing, CancellationToken.None); + await _store.CreateAsync(existing, TestContext.Current.CancellationToken); var budget = await _ledger.GetBudgetAsync("existing-service", _currentWindow); @@ -43,7 +43,7 @@ public sealed class BudgetLedgerTests public async Task Consume_DeductsBudget() { var initial = CreateBudget("test-service", consumed: 50); - await _store.CreateAsync(initial, CancellationToken.None); + await _store.CreateAsync(initial, TestContext.Current.CancellationToken); var result = await _ledger.ConsumeAsync("test-service", 20, "release-1"); @@ -58,7 +58,7 @@ public sealed class BudgetLedgerTests public async Task Consume_FailsWhenInsufficientBudget() { var initial = CreateBudget("test-service", consumed: 190); - await _store.CreateAsync(initial, CancellationToken.None); + await _store.CreateAsync(initial, TestContext.Current.CancellationToken); var result = await _ledger.ConsumeAsync("test-service", 20, "release-1"); diff --git a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs index c7d165961..a2116f819 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyBinderTests.cs @@ -148,7 +148,7 @@ public sealed class PolicyBinderTests Strict = true, }; - var exitCode = await cli.RunAsync(options, CancellationToken.None); + var exitCode = await cli.RunAsync(options, TestContext.Current.CancellationToken); Assert.Equal(2, exitCode); Assert.Contains("WARNING", output.ToString()); diff --git a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyPreviewServiceTests.cs b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyPreviewServiceTests.cs index b9bf0d47d..9ff580a6c 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyPreviewServiceTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicyPreviewServiceTests.cs @@ -35,7 +35,7 @@ rules: var timeProvider = new FakeTimeProvider(); var store = new PolicySnapshotStore(snapshotRepo, auditRepo, timeProvider, null, NullLogger.Instance); - await store.SaveAsync(new PolicySnapshotContent(yaml, PolicyDocumentFormat.Yaml, "tester", null, null), CancellationToken.None); + await store.SaveAsync(new PolicySnapshotContent(yaml, PolicyDocumentFormat.Yaml, "tester", null, null), TestContext.Current.CancellationToken); var service = new PolicyPreviewService(store, NullLogger.Instance); @@ -51,11 +51,11 @@ rules: "sha256:abc", findings, baseline), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.True(response.Success); Assert.Equal(1, response.ChangedCount); - var diff1 = Assert.Single(response.Diffs.Where(diff => diff.Projected.FindingId == "finding-1")); + var diff1 = Assert.Single(response.Diffs, diff => diff.Projected.FindingId == "finding-1"); Assert.Equal(PolicyVerdictStatus.Pass, diff1.Baseline.Status); Assert.Equal(PolicyVerdictStatus.Blocked, diff1.Projected.Status); Assert.Equal("Block Critical", diff1.Projected.RuleName); @@ -94,7 +94,7 @@ rules: baseline, SnapshotOverride: null, ProposedPolicy: new PolicySnapshotContent(yaml, PolicyDocumentFormat.Yaml, "tester", null, "dev override")), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.True(response.Success); var diff = Assert.Single(response.Diffs); @@ -122,7 +122,7 @@ rules: SnapshotOverride: null, ProposedPolicy: new PolicySnapshotContent(invalid, PolicyDocumentFormat.Yaml, null, null, null)); - var response = await service.PreviewAsync(request, CancellationToken.None); + var response = await service.PreviewAsync(request, TestContext.Current.CancellationToken); Assert.False(response.Success); Assert.NotEmpty(response.Issues); @@ -160,7 +160,7 @@ rules: Assert.True(binding.Document.Rules[0].Action.Quiet); var store = new PolicySnapshotStore(new InMemoryPolicySnapshotRepository(), new InMemoryPolicyAuditRepository(), TimeProvider.System, null, NullLogger.Instance); - await store.SaveAsync(new PolicySnapshotContent(yaml, PolicyDocumentFormat.Yaml, "tester", null, "quiet test"), CancellationToken.None); + await store.SaveAsync(new PolicySnapshotContent(yaml, PolicyDocumentFormat.Yaml, "tester", null, "quiet test"), TestContext.Current.CancellationToken); var snapshot = await store.GetLatestAsync(); Assert.NotNull(snapshot); Assert.True(snapshot!.Document.Rules[0].Action.Quiet); @@ -178,7 +178,7 @@ rules: "sha256:quiet", findings, baseline), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.True(response.Success); var verdict = Assert.Single(response.Diffs).Projected; diff --git a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicySnapshotStoreTests.cs b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicySnapshotStoreTests.cs index d03859634..fca654625 100644 --- a/src/Policy/__Tests/StellaOps.Policy.Tests/PolicySnapshotStoreTests.cs +++ b/src/Policy/__Tests/StellaOps.Policy.Tests/PolicySnapshotStoreTests.cs @@ -29,7 +29,7 @@ rules: var content = new PolicySnapshotContent(BasePolicyYaml, PolicyDocumentFormat.Yaml, "cli", "test", null); - var result = await store.SaveAsync(content, CancellationToken.None); + var result = await store.SaveAsync(content, TestContext.Current.CancellationToken); Assert.True(result.Success); Assert.True(result.Created); @@ -59,11 +59,11 @@ rules: var store = new PolicySnapshotStore(snapshotRepo, auditRepo, timeProvider, null, NullLogger.Instance); var content = new PolicySnapshotContent(BasePolicyYaml, PolicyDocumentFormat.Yaml, "cli", "test", null); - var first = await store.SaveAsync(content, CancellationToken.None); + var first = await store.SaveAsync(content, TestContext.Current.CancellationToken); Assert.True(first.Created); timeProvider.Advance(TimeSpan.FromHours(1)); - var second = await store.SaveAsync(content, CancellationToken.None); + var second = await store.SaveAsync(content, TestContext.Current.CancellationToken); Assert.True(second.Success); Assert.False(second.Created); @@ -86,7 +86,7 @@ rules: const string invalidYaml = "version: '1.0'\nrules: []"; var content = new PolicySnapshotContent(invalidYaml, PolicyDocumentFormat.Yaml, null, null, null); - var result = await store.SaveAsync(content, CancellationToken.None); + var result = await store.SaveAsync(content, TestContext.Current.CancellationToken); Assert.False(result.Success); Assert.False(result.Created); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/Bun/BunLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/Bun/BunLanguageAnalyzerTests.cs index 7980a4edd..fb212945a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/Bun/BunLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/Bun/BunLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Bun; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -9,7 +10,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task StandardInstallProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "standard"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -28,7 +29,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task IsolatedLinkerInstallIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "isolated"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -47,7 +48,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task LockfileOnlyIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "lockfile-only"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -66,7 +67,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task BinaryLockfileEmitsRemediationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "binary-lockfile"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -85,7 +86,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task WorkspacesAreParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "workspaces"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -104,7 +105,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task SymlinkSafetyIsEnforcedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "symlinks"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -123,7 +124,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task ScopedPackagesAreParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "scoped-packages"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -142,7 +143,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task GitDependenciesAreParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "git-dependencies"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -161,7 +162,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task CustomRegistryIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "custom-registry"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -180,7 +181,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task PatchedPackagesAreParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "patched-packages"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -199,7 +200,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task PatchedMultiVersionIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "patched-multi-version"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -218,7 +219,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task DeepDependencyTreeIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "deep-tree"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -237,7 +238,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task MultiWorkspaceIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "multi-workspace"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -256,7 +257,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task JsoncLockfileIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "jsonc-lockfile"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -275,7 +276,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task ContainerLayersAreDiscoveredAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "container-layers"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -294,7 +295,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task BunfigOnlyEmitsDeclaredOnlyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "bunfig-only"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -313,7 +314,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task LockfileDevClassificationIsDeterministicAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "lockfile-dev-classification"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -332,7 +333,7 @@ public sealed class BunLanguageAnalyzerTests [Fact] public async Task NonConcreteVersionsUseExplicitKeyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "bun", "non-concrete-versions"); var goldenPath = Path.Combine(fixturePath, "expected.json"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/ErrorHandling/BunAnalyzerErrorHandlingTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/ErrorHandling/BunAnalyzerErrorHandlingTests.cs index 939bfa96d..21d93b27d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/ErrorHandling/BunAnalyzerErrorHandlingTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Bun.Tests/ErrorHandling/BunAnalyzerErrorHandlingTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Bun.Internal; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Bun.Tests.ErrorHandling; @@ -88,7 +89,7 @@ public sealed class BunAnalyzerErrorHandlingTests : IDisposable { var nonExistentPath = Path.Combine(_tempDir, "nonexistent", "bun.lock"); - var result = await BunLockParser.ParseAsync(nonExistentPath, CancellationToken.None); + var result = await BunLockParser.ParseAsync(nonExistentPath, TestContext.Current.CancellationToken); Assert.Empty(result.AllEntries); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Bundles/BundleInspectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Bundles/BundleInspectorTests.cs index 49fc45232..1881edb34 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Bundles/BundleInspectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Bundles/BundleInspectorTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Deno.Fixtures; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Deno.Internal; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestFixtures; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestUtilities; @@ -14,7 +15,7 @@ public sealed class BundleInspectorTests try { var eszipPath = BundleFixtureBuilder.CreateSampleEszip(temp); - var result = DenoBundleInspector.TryInspect(eszipPath, CancellationToken.None); + var result = DenoBundleInspector.TryInspect(eszipPath, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("eszip", result!.BundleType); @@ -36,7 +37,7 @@ public sealed class BundleInspectorTests try { var binaryPath = BundleFixtureBuilder.CreateSampleCompiledBinary(temp); - var result = DenoCompileInspector.TryInspect(binaryPath, CancellationToken.None); + var result = DenoCompileInspector.TryInspect(binaryPath, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("deno-compile", result!.BundleType); @@ -60,7 +61,7 @@ public sealed class BundleInspectorTests Assert.True(File.Exists(eszip)); Assert.True(File.Exists(binary)); - var scan = DenoBundleScanner.Scan(temp, CancellationToken.None); + var scan = DenoBundleScanner.Scan(temp, TestContext.Current.CancellationToken); var observations = DenoBundleScanner.ToObservations(scan); Assert.Single(scan.EszipBundles); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Containers/ContainerAdapterTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Containers/ContainerAdapterTests.cs index ca811eb46..102ef32e4 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Containers/ContainerAdapterTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Containers/ContainerAdapterTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Deno.Internal; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestFixtures; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestUtilities; @@ -15,8 +16,8 @@ public sealed class ContainerAdapterTests { Environment.SetEnvironmentVariable("DENO_DIR", envDir); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, CancellationToken.None); - var bundleScan = DenoBundleScanner.Scan(root, CancellationToken.None); + var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, TestContext.Current.CancellationToken); + var bundleScan = DenoBundleScanner.Scan(root, TestContext.Current.CancellationToken); var observations = DenoBundleScanner.ToObservations(bundleScan); var inputs = DenoContainerAdapter.CollectInputs(workspace, observations); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoLanguageAnalyzerRuntimeTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoLanguageAnalyzerRuntimeTests.cs index 937ce8d50..e54d1e770 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoLanguageAnalyzerRuntimeTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoLanguageAnalyzerRuntimeTests.cs @@ -1,4 +1,5 @@ using System.Text; +using Xunit; using StellaOps.Scanner.Analyzers.Lang; using StellaOps.Scanner.Analyzers.Lang.Deno; using StellaOps.Scanner.Core.Contracts; @@ -22,14 +23,14 @@ public sealed class DenoLanguageAnalyzerRuntimeTests .AppendLine("{\"type\":\"deno.npm.resolution\",\"ts\":\"2025-11-18T00:00:03Z\",\"specifier\":\"npm:chalk@5\",\"package\":\"chalk\",\"version\":\"5.3.0\",\"resolved\":\"file:///cache/chalk\",\"exists\":true}") .ToString(); - await File.WriteAllTextAsync(runtimePath, ndjson, CancellationToken.None); + await File.WriteAllTextAsync(runtimePath, ndjson, TestContext.Current.CancellationToken); var store = new ScanAnalysisStore(); var context = new LanguageAnalyzerContext(root, TimeProvider.System, usageHints: null, services: null, analysisStore: store); var analyzer = new DenoLanguageAnalyzer(); var engine = new LanguageAnalyzerEngine(new[] { analyzer }); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); Assert.True(store.TryGet(ScanAnalysisKeys.DenoRuntimePayload, out AnalyzerObservationPayload runtimePayload)); Assert.Equal("deno.runtime.v1", runtimePayload.Kind); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeShimTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeShimTests.cs index ed1195f26..568be6d31 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeShimTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeShimTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Deno.Internal.Runtime; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Deno.Tests.Deno; @@ -10,10 +11,10 @@ public sealed class DenoRuntimeShimTests var root = TestPaths.CreateTemporaryDirectory(); try { - var path = await DenoRuntimeShim.WriteAsync(root, CancellationToken.None); + var path = await DenoRuntimeShim.WriteAsync(root, TestContext.Current.CancellationToken); Assert.True(File.Exists(path)); - var content = await File.ReadAllTextAsync(path, CancellationToken.None); + var content = await File.ReadAllTextAsync(path, TestContext.Current.CancellationToken); Assert.Contains("deno-runtime.ndjson", content); Assert.Contains("deno.module.load", content); Assert.Contains("deno.permission.use", content); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeTraceRunnerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeTraceRunnerTests.cs index 64ed8cc98..6d3d67738 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeTraceRunnerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoRuntimeTraceRunnerTests.cs @@ -1,4 +1,5 @@ using System.Runtime.InteropServices; +using Xunit; using StellaOps.Scanner.Analyzers.Lang; using StellaOps.Scanner.Analyzers.Lang.Deno.Internal.Runtime; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestUtilities; @@ -16,7 +17,7 @@ public sealed class DenoRuntimeTraceRunnerTests try { var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, CancellationToken.None); + var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, TestContext.Current.CancellationToken); Assert.False(result); Assert.False(File.Exists(Path.Combine(root, "deno-runtime.ndjson"))); @@ -37,7 +38,7 @@ public sealed class DenoRuntimeTraceRunnerTests using var env = new EnvironmentVariableScope("STELLA_DENO_ENTRYPOINT", "app/main.ts"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, CancellationToken.None); + var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, TestContext.Current.CancellationToken); Assert.False(result); Assert.False(File.Exists(Path.Combine(root, DenoRuntimeShim.FileName))); @@ -57,13 +58,13 @@ public sealed class DenoRuntimeTraceRunnerTests try { var entrypoint = Path.Combine(root, "main.ts"); - await File.WriteAllTextAsync(entrypoint, "console.log('hi')", CancellationToken.None); + await File.WriteAllTextAsync(entrypoint, "console.log('hi')", TestContext.Current.CancellationToken); using var entryEnv = new EnvironmentVariableScope("STELLA_DENO_ENTRYPOINT", entrypoint); using var binaryEnv = new EnvironmentVariableScope("STELLA_DENO_BINARY", Guid.NewGuid().ToString("N")); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, CancellationToken.None); + var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, TestContext.Current.CancellationToken); Assert.False(result); Assert.True(File.Exists(Path.Combine(root, DenoRuntimeShim.FileName))); @@ -90,14 +91,14 @@ public sealed class DenoRuntimeTraceRunnerTests using var denoDirEnv = new EnvironmentVariableScope("DENO_DIR", Path.Combine(root, ".deno-cache")); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, CancellationToken.None); + var result = await DenoRuntimeTraceRunner.TryExecuteAsync(context, logger: null, TestContext.Current.CancellationToken); Assert.True(result); var runtimePath = Path.Combine(root, "deno-runtime.ndjson"); Assert.True(File.Exists(runtimePath)); - var content = await File.ReadAllTextAsync(runtimePath, CancellationToken.None); + var content = await File.ReadAllTextAsync(runtimePath, TestContext.Current.CancellationToken); Assert.Contains("deno.runtime.start", content); Assert.Contains("deno.module.load", content); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoWorkspaceNormalizerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoWorkspaceNormalizerTests.cs index 391e2ce86..9a2943f3d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoWorkspaceNormalizerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Deno/DenoWorkspaceNormalizerTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Deno.Internal; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestFixtures; using StellaOps.Scanner.Analyzers.Lang.Deno.Tests.TestUtilities; @@ -19,7 +20,7 @@ public sealed class DenoWorkspaceNormalizerTests Environment.SetEnvironmentVariable("DENO_DIR", envDenoDir); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, CancellationToken.None); + var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, TestContext.Current.CancellationToken); var config = Assert.Single(workspace.Configurations); Assert.EndsWith("deno.jsonc", config.AbsolutePath, StringComparison.OrdinalIgnoreCase); @@ -65,12 +66,12 @@ public sealed class DenoWorkspaceNormalizerTests Environment.SetEnvironmentVariable("DENO_DIR", envDenoDir); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, CancellationToken.None); + var workspace = await DenoWorkspaceNormalizer.NormalizeAsync(context, TestContext.Current.CancellationToken); var lockFile = workspace.LockFiles.Single(lf => string.Equals(lf.RelativePath, "deno.lock", StringComparison.OrdinalIgnoreCase)); Assert.Contains(lockFile.RemoteEntries, entry => entry.Key.Contains("server.ts", StringComparison.Ordinal)); - var graph = DenoModuleGraphResolver.Resolve(workspace, CancellationToken.None); - var compatibility = DenoNpmCompatibilityAdapter.Analyze(workspace, graph, CancellationToken.None); + var graph = DenoModuleGraphResolver.Resolve(workspace, TestContext.Current.CancellationToken); + var compatibility = DenoNpmCompatibilityAdapter.Analyze(workspace, graph, TestContext.Current.CancellationToken); var cacheSummary = string.Join(";", workspace.CacheLocations.Select(cache => $"{cache.Kind}:{cache.AbsolutePath}")); Assert.NotEmpty(graph.Nodes); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Golden/DenoAnalyzerGoldenTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Golden/DenoAnalyzerGoldenTests.cs index 4a0a1ff13..147742bd3 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Golden/DenoAnalyzerGoldenTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Golden/DenoAnalyzerGoldenTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Nodes; @@ -17,7 +18,7 @@ public sealed class DenoAnalyzerGoldenTests var fixtureRoot = TestPaths.ResolveFixture("lang", "deno", "full"); var golden = Path.Combine(fixtureRoot, "expected.json"); var analyzers = new ILanguageAnalyzer[] { new DenoLanguageAnalyzer() }; - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var (workspaceRoot, envDir) = DenoWorkspaceTestFixture.Create(); var previousDenoDir = Environment.GetEnvironmentVariable("DENO_DIR"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Observations/DenoLanguageAnalyzerObservationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Observations/DenoLanguageAnalyzerObservationTests.cs index d10c14c65..0127a2a1a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Observations/DenoLanguageAnalyzerObservationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Deno.Tests/Observations/DenoLanguageAnalyzerObservationTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -36,7 +37,7 @@ public sealed class DenoLanguageAnalyzerObservationTests var analyzer = new DenoLanguageAnalyzer(); var engine = new LanguageAnalyzerEngine(new[] { analyzer }); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); Assert.True(store.TryGet(ScanAnalysisKeys.DenoObservationPayload, out AnalyzerObservationPayload payload)); Assert.Equal("deno.observation", payload.Kind); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/ILMergedAssemblyDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/ILMergedAssemblyDetectorTests.cs index b7769e582..938f9d2fd 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/ILMergedAssemblyDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/ILMergedAssemblyDetectorTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Bundling; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.DotNet.Bundling; @@ -139,7 +140,7 @@ public sealed class ILMergedAssemblyDetectorTests var results = ILMergedAssemblyDetector.AnalyzeMany( [mergedPath, normalPath], - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Single(results); Assert.True(results[0].IsMerged); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/SingleFileAppDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/SingleFileAppDetectorTests.cs index 881039499..01e68406e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/SingleFileAppDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Bundling/SingleFileAppDetectorTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Bundling; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.DotNet.Bundling; @@ -115,7 +116,7 @@ public sealed class SingleFileAppDetectorTests var results = SingleFileAppDetector.AnalyzeMany( [bundlePath, normalPath], - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Single(results); Assert.True(results[0].IsSingleFile); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/GlobalJsonParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/GlobalJsonParserTests.cs index 82d5ce1ad..eed03a845 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/GlobalJsonParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/GlobalJsonParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Config; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.DotNet.Config; @@ -117,7 +118,7 @@ public sealed class GlobalJsonParserTests [Fact] public async Task HandlesNonExistentFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await GlobalJsonParser.ParseAsync("/nonexistent/global.json", cancellationToken); Assert.Equal(GlobalJsonResult.Empty, result); @@ -217,7 +218,7 @@ public sealed class GlobalJsonParserTests [Fact] public async Task ParsesFileAsyncSuccessfullyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = DotNetFixtureBuilder.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/NuGetConfigParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/NuGetConfigParserTests.cs index 6f6f848b1..b8eb45bea 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/NuGetConfigParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Config/NuGetConfigParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Config; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; namespace StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.DotNet.Config; @@ -352,7 +353,7 @@ public sealed class NuGetConfigParserTests [Fact] public async Task ParsesFileAsyncSuccessfullyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = DotNetFixtureBuilder.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/MsBuildProjectParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/MsBuildProjectParserTests.cs index 9d88bc161..1979f7df6 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/MsBuildProjectParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/MsBuildProjectParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.BuildMetadata; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Parsing; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; @@ -377,7 +378,7 @@ public sealed class MsBuildProjectParserTests [Fact] public async Task HandlesFileNotFoundAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await MsBuildProjectParser.ParseAsync("/nonexistent/path.csproj", cancellationToken); Assert.Equal(MsBuildProjectParser.Empty, result); @@ -455,7 +456,7 @@ public sealed class MsBuildProjectParserTests [Fact] public async Task ParsesFileAsyncSuccessfullyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = DotNetFixtureBuilder.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/PackagesConfigParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/PackagesConfigParserTests.cs index 95c68784c..f42f81116 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/PackagesConfigParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.DotNet.Tests/DotNet/Parsing/PackagesConfigParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.BuildMetadata; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.DotNet.Internal.Parsing; using StellaOps.Scanner.Analyzers.Lang.DotNet.Tests.TestUtilities; @@ -116,7 +117,7 @@ public sealed class PackagesConfigParserTests [Fact] public async Task HandlesNonExistentFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await PackagesConfigParser.ParseAsync("/nonexistent/packages.config", cancellationToken); Assert.Equal(PackagesConfigResult.Empty, result); @@ -189,7 +190,7 @@ public sealed class PackagesConfigParserTests [Fact] public async Task ParsesFileAsyncSuccessfullyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = DotNetFixtureBuilder.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Go.Tests/Go/GoLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Go.Tests/Go/GoLanguageAnalyzerTests.cs index 0b5cf2d9b..b537c2ae0 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Go.Tests/Go/GoLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Go.Tests/Go/GoLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using System; +using Xunit; using System.Diagnostics.Metrics; using System.IO; using System.Linq; @@ -13,7 +14,7 @@ public sealed class GoLanguageAnalyzerTests [Fact] public async Task BuildInfoFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "go", "basic"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -32,7 +33,7 @@ public sealed class GoLanguageAnalyzerTests [Fact] public async Task DwarfOnlyFixtureFallsBackToMetadataAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "go", "dwarf-only"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -51,7 +52,7 @@ public sealed class GoLanguageAnalyzerTests [Fact] public async Task StrippedBinaryFallsBackToHeuristicBinHashAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "go", "stripped"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -70,7 +71,7 @@ public sealed class GoLanguageAnalyzerTests [Fact] public async Task ParallelRunsRemainDeterministicAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "go", "basic"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -93,7 +94,7 @@ public sealed class GoLanguageAnalyzerTests [Fact] public async Task HeuristicMetricCounterIncrementsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "go", "stripped"); var analyzers = new ILanguageAnalyzer[] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaClassPathBuilderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaClassPathBuilderTests.cs index 3322acee4..894f5ac86 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaClassPathBuilderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaClassPathBuilderTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Xunit; using System.IO.Compression; using System.Linq; using System.Text; @@ -20,8 +21,8 @@ public sealed class JavaClassPathBuilderTests JavaFixtureBuilder.CreateSampleJar(root, "libs/simple.jar"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); - var analysis = JavaClassPathBuilder.Build(workspace, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); + var analysis = JavaClassPathBuilder.Build(workspace, TestContext.Current.CancellationToken); var segment = Assert.Single(analysis.Segments); Assert.Equal("libs/simple.jar", segment.Identifier.Replace('\\', '/')); @@ -54,8 +55,8 @@ public sealed class JavaClassPathBuilderTests CreateJarWithClasses(root, "libs/spi.jar", new[] { "com.example.DriverImpl" }, services); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); - var analysis = JavaClassPathBuilder.Build(workspace, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); + var analysis = JavaClassPathBuilder.Build(workspace, TestContext.Current.CancellationToken); var segment = Assert.Single(analysis.Segments); var providers = Assert.Single(segment.ServiceDefinitions); @@ -77,8 +78,8 @@ public sealed class JavaClassPathBuilderTests JavaFixtureBuilder.CreateSpringBootFatJar(root, "apps/app-fat.jar"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); - var analysis = JavaClassPathBuilder.Build(workspace, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); + var analysis = JavaClassPathBuilder.Build(workspace, TestContext.Current.CancellationToken); Assert.Equal(2, analysis.Segments.Length); @@ -106,8 +107,8 @@ public sealed class JavaClassPathBuilderTests CreateJarWithClasses(root, "libs/b.jar", "com.example.Demo", "com.example.Other"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); - var analysis = JavaClassPathBuilder.Build(workspace, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); + var analysis = JavaClassPathBuilder.Build(workspace, TestContext.Current.CancellationToken); Assert.Equal(2, analysis.Segments.Length); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaEntrypointResolverTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaEntrypointResolverTests.cs index d6ea1b848..434341fd9 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaEntrypointResolverTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaEntrypointResolverTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using System.IO.Compression; using System.Text; using StellaOps.Scanner.Analyzers.Lang.Java.Internal; @@ -24,7 +25,7 @@ public sealed class JavaEntrypointResolverTests ImmutableArray.Empty, ImmutableArray.Empty, ImmutableArray.Empty); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var resolution = JavaEntrypointResolver.Resolve( classPath, @@ -58,7 +59,7 @@ public sealed class JavaEntrypointResolverTests writer.Write("\r\n"); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -107,7 +108,7 @@ public sealed class JavaEntrypointResolverTests writer.Write("\r\n"); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -155,7 +156,7 @@ public sealed class JavaEntrypointResolverTests writer.Write("\r\n"); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -204,7 +205,7 @@ public sealed class JavaEntrypointResolverTests Details: "System.loadLibrary(\"mylib\")")); var jniAnalysis = new JavaJniAnalysis(jniEdges, ImmutableArray.Empty); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var resolution = JavaEntrypointResolver.Resolve( classPath, @@ -243,7 +244,7 @@ public sealed class JavaEntrypointResolverTests Details: "Class.forName(\"com.example.Plugin\")")); var reflectionAnalysis = new JavaReflectionAnalysis(reflectEdges, ImmutableArray.Empty); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var resolution = JavaEntrypointResolver.Resolve( classPath, @@ -278,7 +279,7 @@ public sealed class JavaEntrypointResolverTests writer.Write("\r\n"); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -324,7 +325,7 @@ public sealed class JavaEntrypointResolverTests writer.Write("\r\n"); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -383,7 +384,7 @@ public sealed class JavaEntrypointResolverTests Warnings: ImmutableArray.Empty); using var stream = new MemoryStream(); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; await JavaEntrypointAocWriter.WriteNdjsonAsync( resolution, diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaJniAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaJniAnalyzerTests.cs index 9eececda3..aad1e743c 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaJniAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaJniAnalyzerTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Threading; using StellaOps.Scanner.Analyzers.Lang.Java.Internal; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.ClassPath; @@ -28,7 +29,7 @@ public sealed class JavaJniAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -65,7 +66,7 @@ public sealed class JavaJniAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -101,7 +102,7 @@ public sealed class JavaJniAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -146,7 +147,7 @@ public sealed class JavaJniAnalyzerTests } } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -168,7 +169,7 @@ public sealed class JavaJniAnalyzerTests var root = TestPaths.CreateTemporaryDirectory(); try { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -198,7 +199,7 @@ public sealed class JavaJniAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaLanguageAnalyzerTests.cs index db2900ca8..821e3651d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -14,7 +15,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactFromJarAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try { @@ -39,7 +40,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactsFromSpringBootFatJarEmbeddedLibrariesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try { @@ -64,7 +65,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactsFromWarEmbeddedLibrariesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try { @@ -89,7 +90,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactsFromPomXmlOnlyJarAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try { @@ -114,7 +115,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task LockfilesProduceDeclaredOnlyComponentsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -149,7 +150,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task CapturesFrameworkConfigurationHintsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -219,7 +220,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task CapturesJniHintsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -272,7 +273,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactFromEmbeddedJarAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -334,7 +335,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ExtractsMavenArtifactFromPomXmlWhenPomPropertiesMissingAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -389,7 +390,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task PomXmlWithIncompleteCoordinatesEmitsUnresolvedComponentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -460,7 +461,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesGradleGroovyBuildFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "gradle-groovy"); var goldenPath = TestPaths.ResolveFixture("java", "gradle-groovy", "expected.json"); @@ -471,9 +472,9 @@ public sealed class JavaLanguageAnalyzerTests var components = document.RootElement.EnumerateArray().ToArray(); // Verify key dependencies are detected - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "guava")); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "commons-lang3")); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "slf4j-api")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "guava"); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "commons-lang3"); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "slf4j-api"); // Verify declaredOnly flag is set for build file dependencies var guava = components.First(c => c.GetProperty("name").GetString() == "guava"); @@ -484,7 +485,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesGradleKotlinBuildFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "gradle-kotlin"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -494,17 +495,17 @@ public sealed class JavaLanguageAnalyzerTests var components = document.RootElement.EnumerateArray().ToArray(); // Verify Kotlin DSL dependencies are detected - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "kotlin-stdlib")); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "jackson-databind")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "kotlin-stdlib"); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "jackson-databind"); // Verify kapt/ksp dependencies are detected - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "mapstruct-processor")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "mapstruct-processor"); } [Fact] public async Task ParsesGradleVersionCatalogAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "gradle-catalog"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -513,7 +514,7 @@ public sealed class JavaLanguageAnalyzerTests using var document = JsonDocument.Parse(json); var components = document.RootElement.EnumerateArray().ToArray(); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "logback-classic")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "logback-classic"); var logback = components.First(c => c.GetProperty("name").GetString() == "logback-classic"); Assert.Equal("1.4.14", logback.GetProperty("version").GetString()); } @@ -521,7 +522,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesMavenParentPomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "maven-parent"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -531,8 +532,8 @@ public sealed class JavaLanguageAnalyzerTests var components = document.RootElement.EnumerateArray().ToArray(); // Verify dependencies with inherited versions are detected - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "slf4j-api")); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "spring-core")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "slf4j-api"); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "spring-core"); // Verify version is inherited from parent var springCore = components.First(c => c.GetProperty("name").GetString() == "spring-core"); @@ -542,7 +543,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesMavenBomImportsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "maven-bom"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -551,8 +552,8 @@ public sealed class JavaLanguageAnalyzerTests using var document = JsonDocument.Parse(json); var components = document.RootElement.EnumerateArray().ToArray(); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "commons-lang3")); - Assert.True(components.Any(c => c.GetProperty("name").GetString() == "lombok")); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "commons-lang3"); + Assert.Contains(components, c => c.GetProperty("name").GetString() == "lombok"); var commonsLang = components.First(c => c.GetProperty("name").GetString() == "commons-lang3"); Assert.Equal("3.14.0", commonsLang.GetProperty("version").GetString()); @@ -561,7 +562,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesMavenPropertyPlaceholdersAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "maven-properties"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -584,7 +585,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task ParsesMavenScopesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "maven-scopes"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -615,7 +616,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task DetectsVersionConflictsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("java", "version-conflict"); var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() }; @@ -650,7 +651,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task MultiModuleGradleLockFilesEmitLockModulePathMetadataAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -729,7 +730,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task RuntimeImageEmitsExplicitKeyComponentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -798,7 +799,7 @@ public sealed class JavaLanguageAnalyzerTests [Fact] public async Task DuplicateRuntimeImagesAreDeduplicatedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaReflectionAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaReflectionAnalyzerTests.cs index 94fce599d..e7f768f3d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaReflectionAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaReflectionAnalyzerTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Threading; using StellaOps.Scanner.Analyzers.Lang.Java.Internal; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.ClassPath; @@ -25,7 +26,7 @@ public sealed class JavaReflectionAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -59,7 +60,7 @@ public sealed class JavaReflectionAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -84,7 +85,7 @@ public sealed class JavaReflectionAnalyzerTests { JavaFixtureBuilder.CreateSpringBootFatJar(root, "apps/app-fat.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -116,13 +117,13 @@ public sealed class JavaReflectionAnalyzerTests stream.Write(bytes); } - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); var analysis = JavaReflectionAnalyzer.Analyze(classPath, cancellationToken); - var edge = Assert.Single(analysis.Edges.Where(edge => edge.Reason == JavaReflectionReason.ResourceLookup)); + var edge = Assert.Single(analysis.Edges, edge => edge.Reason == JavaReflectionReason.ResourceLookup); Assert.Equal("com.example.Resources", edge.SourceClass); Assert.Equal("/META-INF/plugin.properties", edge.TargetType); Assert.Equal(JavaReflectionConfidence.High, edge.Confidence); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaServiceProviderScannerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaServiceProviderScannerTests.cs index 8aa36faeb..516608c1a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaServiceProviderScannerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaServiceProviderScannerTests.cs @@ -32,7 +32,7 @@ public sealed class JavaServiceProviderScannerTests CreateJarWithClasses(root, "libs/a.jar", new[] { "com.example.ADriver" }, servicesA); CreateJarWithClasses(root, "libs/b.jar", new[] { "com.example.BDriver" }, servicesB); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -41,7 +41,7 @@ public sealed class JavaServiceProviderScannerTests var service = Assert.Single(analysis.Services, record => record.ServiceId == "java.sql.Driver"); Assert.Equal("jdk", service.Category); - var selected = Assert.Single(service.Candidates.Where(candidate => candidate.IsSelected)); + var selected = Assert.Single(service.Candidates, candidate => candidate.IsSelected); Assert.Equal("com.example.ADriver", selected.ProviderClass); Assert.Empty(service.Warnings); } @@ -65,7 +65,7 @@ public sealed class JavaServiceProviderScannerTests CreateJarWithClasses(root, "libs/a.jar", new[] { "com.example.DuplicateDriver" }, services); CreateJarWithClasses(root, "libs/b.jar", new[] { "com.example.Other" }, services); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); @@ -89,14 +89,14 @@ public sealed class JavaServiceProviderScannerTests { JavaFixtureBuilder.CreateSpringBootFatJar(root, "apps/app-fat.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var context = new LanguageAnalyzerContext(root, TimeProvider.System); var workspace = JavaWorkspaceNormalizer.Normalize(context, cancellationToken); var classPath = JavaClassPathBuilder.Build(workspace, cancellationToken); var analysis = JavaServiceProviderScanner.Scan(classPath, JavaSpiCatalog.Default, cancellationToken); var service = Assert.Single(analysis.Services, record => record.ServiceId == "java.sql.Driver"); - var selected = Assert.Single(service.Candidates.Where(candidate => candidate.IsSelected)); + var selected = Assert.Single(service.Candidates, candidate => candidate.IsSelected); Assert.Equal("com.example.AppDriver", selected.ProviderClass); Assert.Contains(service.Candidates.Select(candidate => candidate.ProviderClass), provider => provider == "com.example.LibDriver"); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaSignatureManifestAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaSignatureManifestAnalyzerTests.cs index f86be89b1..35408f72e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaSignatureManifestAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaSignatureManifestAnalyzerTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Text; using StellaOps.Scanner.Analyzers.Lang.Java.Internal; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Signature; @@ -31,7 +32,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/app.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var attributes = JavaSignatureManifestAnalyzer.ExtractLoaderAttributes(javaArchive, cancellationToken); @@ -69,7 +70,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/boot.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var attributes = JavaSignatureManifestAnalyzer.ExtractLoaderAttributes(javaArchive, cancellationToken); @@ -103,7 +104,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/agent.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var attributes = JavaSignatureManifestAnalyzer.ExtractLoaderAttributes(javaArchive, cancellationToken); @@ -138,7 +139,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/mrjar.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var attributes = JavaSignatureManifestAnalyzer.ExtractLoaderAttributes(javaArchive, cancellationToken); @@ -172,7 +173,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/empty.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var attributes = JavaSignatureManifestAnalyzer.ExtractLoaderAttributes(javaArchive, cancellationToken); @@ -294,7 +295,7 @@ public sealed class JavaSignatureManifestAnalyzerTests } var javaArchive = JavaArchive.Load(jarPath, "libs/app.jar"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var analysis = JavaSignatureManifestAnalyzer.Analyze(javaArchive, cancellationToken); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaWorkspaceNormalizerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaWorkspaceNormalizerTests.cs index b84b16727..e25f8dd3c 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaWorkspaceNormalizerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/JavaWorkspaceNormalizerTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Threading; using StellaOps.Scanner.Analyzers.Lang.Java.Internal; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests; @@ -18,7 +19,7 @@ public sealed class JavaWorkspaceNormalizerTests JavaFixtureBuilder.CreateWarArchive(root, "apps/sample.war"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); var archivesByPath = workspace.Archives.ToDictionary( archive => archive.RelativePath.Replace('\\', '/'), @@ -52,7 +53,7 @@ public sealed class JavaWorkspaceNormalizerTests JavaFixtureBuilder.CreateMultiReleaseJar(root, "libs/mr.jar"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); var archive = Assert.Single(workspace.Archives); @@ -78,7 +79,7 @@ public sealed class JavaWorkspaceNormalizerTests JavaFixtureBuilder.CreateRuntimeImage(root, "runtime/jre"); var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var workspace = JavaWorkspaceNormalizer.Normalize(context, CancellationToken.None); + var workspace = JavaWorkspaceNormalizer.Normalize(context, TestContext.Current.CancellationToken); var runtime = Assert.Single(workspace.RuntimeImages); Assert.Equal("17.0.8", runtime.JavaVersion); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleGroovyParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleGroovyParserTests.cs index 56ac17abc..cf6eb33bf 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleGroovyParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleGroovyParserTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Gradle; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -8,7 +9,7 @@ public sealed class GradleGroovyParserTests [Fact] public async Task ParsesStringNotationDependenciesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation 'org.slf4j:slf4j-api:1.7.36' @@ -50,7 +51,7 @@ public sealed class GradleGroovyParserTests [Fact] public async Task ParsesMapNotationDependenciesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; // Parser supports map notation without parentheses var content = """ dependencies { @@ -86,7 +87,7 @@ public sealed class GradleGroovyParserTests [Fact] public async Task ResolvesPropertyPlaceholdersAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation "org.slf4j:slf4j-api:${slf4jVersion}" diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleKotlinParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleKotlinParserTests.cs index 615426bcd..accdd460d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleKotlinParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleKotlinParserTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Gradle; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -8,7 +9,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesStringNotationDependenciesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation("org.slf4j:slf4j-api:1.7.36") @@ -49,7 +50,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesNamedArgumentsNotationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation(group = "org.apache.commons", name = "commons-lang3", version = "3.12.0") @@ -82,7 +83,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesPlatformDependencyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation(platform("org.springframework.boot:spring-boot-dependencies:3.1.0")) @@ -112,7 +113,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesEnforcedPlatformDependencyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { api(enforcedPlatform("org.springframework.cloud:spring-cloud-dependencies:2022.0.3")) @@ -139,7 +140,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task TracksVersionCatalogReferencesAsUnresolvedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation(libs.guava) @@ -166,7 +167,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesAllConfigurationTypesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation("com.example:impl:1.0") @@ -205,7 +206,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesPluginsBlockAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ plugins { id("org.springframework.boot") version "3.1.0" @@ -240,7 +241,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ExtractsGroupAndVersionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ group = "com.example" version = "1.0.0-SNAPSHOT" @@ -267,7 +268,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ParsesClassifierAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation("com.example:library:1.0.0:sources") @@ -303,7 +304,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task HandlesNonExistentFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await GradleKotlinParser.ParseAsync("/nonexistent/path/build.gradle.kts", null, cancellationToken); @@ -313,7 +314,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task ResolvesPropertyPlaceholderAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; // The Kotlin parser treats any coordinate containing $ as unresolved // because string interpolation happens at Gradle evaluation time. // Use a coordinate without $ to test basic parsing @@ -342,7 +343,7 @@ public sealed class GradleKotlinParserTests [Fact] public async Task TracksUnresolvedStringInterpolationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ dependencies { implementation("$myGroup:$myArtifact:$myVersion") diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradlePropertiesParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradlePropertiesParserTests.cs index eeea7d844..76f1c4b83 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradlePropertiesParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradlePropertiesParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Gradle; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -175,7 +176,7 @@ public sealed class GradlePropertiesParserTests [Fact] public async Task HandlesNonExistentFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await GradlePropertiesParser.ParseAsync("/nonexistent/gradle.properties", cancellationToken); @@ -185,7 +186,7 @@ public sealed class GradlePropertiesParserTests [Fact] public async Task ParsesFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ group=com.example version=1.0.0 diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleVersionCatalogParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleVersionCatalogParserTests.cs index ad28badd3..312892798 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleVersionCatalogParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/GradleVersionCatalogParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Gradle; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -7,7 +8,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesVersionSectionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] guava = "31.1-jre" @@ -33,7 +34,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesLibrariesSectionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [libraries] guava = "com.google.guava:guava:31.1-jre" @@ -62,7 +63,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesModuleNotationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] guava = "31.1-jre" @@ -93,7 +94,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesGroupNameNotationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] commons = "3.12.0" @@ -124,7 +125,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ResolvesVersionRefAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] slf4j = "2.0.7" @@ -159,7 +160,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task HandlesInlineVersionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [libraries] junit = { module = "junit:junit", version = "4.13.2" } @@ -185,7 +186,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesRichVersionsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] guava = { strictly = "31.1-jre" } @@ -212,7 +213,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesBundlesSectionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [libraries] guava = "com.google.guava:guava:31.1-jre" @@ -249,7 +250,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesPluginsSectionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] kotlin = "1.9.0" @@ -286,7 +287,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task GetLibraryByAliasAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [libraries] guava = "com.google.guava:guava:31.1-jre" @@ -321,7 +322,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ToDependenciesConvertsAllLibrariesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] guava = "31.1-jre" @@ -361,7 +362,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task HandlesNonExistentFileAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var result = await GradleVersionCatalogParser.ParseAsync("/nonexistent/libs.versions.toml", cancellationToken); @@ -371,7 +372,7 @@ public sealed class GradleVersionCatalogParserTests [Fact] public async Task ParsesCompleteVersionCatalogAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ [versions] kotlin = "1.9.0" diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenBomImporterTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenBomImporterTests.cs index 3373985c9..4ccc31aa2 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenBomImporterTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenBomImporterTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Maven; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -7,7 +8,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task ImportsSimpleBomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -71,7 +72,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task ReturnsNullForMissingBomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -91,7 +92,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task CachesImportedBomsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -141,7 +142,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task HandlesNestedBomImportsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -200,7 +201,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task ChildBomOverridesParentVersionsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -283,7 +284,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task RespectsMaxDepthLimitAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -346,7 +347,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task HandlesCircularBomReferencesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -435,7 +436,7 @@ public sealed class MavenBomImporterTests [Fact] public async Task ExtractsBomPropertiesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenEffectivePomBuilderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenEffectivePomBuilderTests.cs index 527bebd9e..95883b6ec 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenEffectivePomBuilderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenEffectivePomBuilderTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.BuildMetadata; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Maven; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -9,7 +10,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task BuildsEffectivePomWithParentPropertiesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -73,7 +74,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task MergesParentDependencyManagementAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -152,7 +153,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task ChildDependencyManagementOverridesParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -224,7 +225,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task HandlesStandalonePomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -266,7 +267,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task ResolvesPropertyInDependencyManagementVersionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -315,7 +316,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task TracksVersionSourceCorrectlyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -404,7 +405,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task CollectsAllLicensesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -458,7 +459,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task GetsUnresolvedDependenciesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -502,7 +503,7 @@ public sealed class MavenEffectivePomBuilderTests [Fact] public async Task PopulatesManagedVersionsIndexAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenLocalRepositoryTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenLocalRepositoryTests.cs index e74c54363..ad1efeb94 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenLocalRepositoryTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenLocalRepositoryTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Maven; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -308,7 +309,7 @@ public sealed class MavenLocalRepositoryTests [Fact] public async Task ReadPomAsyncReturnsNullForMissingPomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); @@ -329,7 +330,7 @@ public sealed class MavenLocalRepositoryTests [Fact] public async Task ReadPomAsyncReturnsParsedPomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenParentResolverTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenParentResolverTests.cs index 2b129b672..b9b9119f7 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenParentResolverTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenParentResolverTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Maven; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -8,7 +9,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ResolvesRelativePathParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -63,7 +64,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ResolvesDefaultRelativePathAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -111,7 +112,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ResolvesMultiLevelParentChainAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -182,7 +183,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ReturnsUnresolvedForMissingParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -218,7 +219,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task HandlesNoParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -251,7 +252,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task InheritsGroupIdFromParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -298,7 +299,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task InheritsVersionFromParentAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -343,7 +344,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ResolvesDependencyVersionFromManagementAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -407,7 +408,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ResolvesPropertyInDependencyVersionAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -449,7 +450,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task CollectsLicensesFromChainAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try @@ -503,7 +504,7 @@ public sealed class MavenParentResolverTests [Fact] public async Task ChildPropertyOverridesParentPropertyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var root = TestPaths.CreateTemporaryDirectory(); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenPomParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenPomParserTests.cs index 541def086..f5f5ef4f5 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenPomParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/MavenPomParserTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Maven; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Java.Tests.Parsers; @@ -7,7 +8,7 @@ public sealed class MavenPomParserTests [Fact] public async Task ParsesDependenciesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ @@ -59,7 +60,7 @@ public sealed class MavenPomParserTests [Fact] public async Task ParsesPropertiesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ @@ -99,7 +100,7 @@ public sealed class MavenPomParserTests [Fact] public async Task ParsesLicensesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ @@ -136,7 +137,7 @@ public sealed class MavenPomParserTests [Fact] public async Task ParsesParentReferenceAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ @@ -169,7 +170,7 @@ public sealed class MavenPomParserTests [Fact] public async Task ParsesDependencyManagementAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var content = """ diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/ShadedJarDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/ShadedJarDetectorTests.cs index 36eded60a..6dd13748c 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/ShadedJarDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Java.Tests/Java/Parsers/ShadedJarDetectorTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Text; using StellaOps.Scanner.Analyzers.Lang.Java.Internal.Shading; @@ -9,7 +10,7 @@ public sealed class ShadedJarDetectorTests [Fact] public async Task DetectsMultiplePomPropertiesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var jarPath = Path.Combine(Path.GetTempPath(), $"shaded-{Guid.NewGuid()}.jar"); try @@ -36,7 +37,7 @@ public sealed class ShadedJarDetectorTests [Fact] public async Task DetectsDependencyReducedPomAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var jarPath = Path.Combine(Path.GetTempPath(), $"shade-plugin-{Guid.NewGuid()}.jar"); try @@ -63,7 +64,7 @@ public sealed class ShadedJarDetectorTests [Fact] public async Task DetectsRelocatedPackagesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var jarPath = Path.Combine(Path.GetTempPath(), $"relocated-{Guid.NewGuid()}.jar"); try @@ -91,7 +92,7 @@ public sealed class ShadedJarDetectorTests [Fact] public async Task ReturnsNotShadedForRegularJarAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var jarPath = Path.Combine(Path.GetTempPath(), $"regular-{Guid.NewGuid()}.jar"); try diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.SmokeTests/Phase22SmokeTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.SmokeTests/Phase22SmokeTests.cs index d9d017375..a9cc010ff 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.SmokeTests/Phase22SmokeTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.SmokeTests/Phase22SmokeTests.cs @@ -11,7 +11,7 @@ public class Phase22SmokeTests [Fact] public async Task Phase22_Fixture_Matches_Golden() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var baseDir = AppContext.BaseDirectory; var repoRoot = Path.GetFullPath(Path.Combine(baseDir, "..", "..", "..", "..", "..", "..", "..")); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeDeterminismTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeDeterminismTests.cs index a0691ca2c..c29c15107 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeDeterminismTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeDeterminismTests.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Node; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; @@ -427,7 +428,7 @@ public sealed class NodeDeterminismTests : IDisposable return await LanguageAnalyzerTestHarness.RunToJsonAsync( _tempDir, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } private static List ExtractPackageNames(string json) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEdgeCaseAndErrorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEdgeCaseAndErrorTests.cs index add6fee92..41f23ed31 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEdgeCaseAndErrorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEdgeCaseAndErrorTests.cs @@ -1,4 +1,5 @@ using System.Text; +using Xunit; using System.Text.Json; using StellaOps.Scanner.Analyzers.Lang.Node; using StellaOps.Scanner.Analyzers.Lang.Node.Internal; @@ -609,6 +610,6 @@ public sealed class NodeEdgeCaseAndErrorTests : IDisposable return await LanguageAnalyzerTestHarness.RunToJsonAsync( _tempDir, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEntrypointDetectionTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEntrypointDetectionTests.cs index fb2e136b4..28435296f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEntrypointDetectionTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeEntrypointDetectionTests.cs @@ -1,4 +1,5 @@ using System.Text.Json; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Node; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; @@ -552,8 +553,8 @@ public sealed class NodeEntrypointDetectionTests : IDisposable .Where(e => e.TryGetProperty("source", out var src) && src.GetString() == "package.json:entrypoint") .ToList(); // Should have entrypoint evidence with normalized path (starts with dist/, not ./dist/) - Assert.True(evidence.Any(e => e.TryGetProperty("value", out var val) && - val.GetString()!.StartsWith("dist/", StringComparison.Ordinal))); + Assert.Contains(evidence, e => e.TryGetProperty("value", out var val) && + val.GetString()!.StartsWith("dist/", StringComparison.Ordinal)); } [Fact] @@ -680,6 +681,6 @@ public sealed class NodeEntrypointDetectionTests : IDisposable return await LanguageAnalyzerTestHarness.RunToJsonAsync( _tempDir, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLanguageAnalyzerTests.cs index 2b8f4eda7..57f6dbf0b 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Node; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -9,7 +10,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task WorkspaceFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "workspaces"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -28,7 +29,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task VersionTargetsAreCapturedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "version-targets"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -47,7 +48,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task TarballPackageIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "version-targets"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -66,7 +67,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task YarnPnpCachePackagesAreParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "yarn-pnp"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -85,7 +86,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task YarnPnpFlagIsEmittedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "yarn-pnp"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -104,7 +105,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task EntrypointsAreCapturedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "entrypoints"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -123,7 +124,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task ShebangEntrypointsAreCapturedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "shebang"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -142,7 +143,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task Phase22BundleNativeWasmObservationAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "phase22"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -161,7 +162,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task ContainerLayersAreScannedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "container-layers"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -177,7 +178,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task DynamicImportsEmitEvidenceAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "imports-dynamic"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -193,7 +194,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task LockOnlyPackageLockEmitsDeclaredOnlyComponentsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-package-lock"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -209,7 +210,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task LockOnlyYarnBerryEmitsDeclaredOnlyComponentsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-yarn-berry"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -225,7 +226,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task LockOnlyPnpmEmitsDeclaredOnlyComponentsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-pnpm"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -241,7 +242,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task PnpmVirtualStoreIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "pnpm-store"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -257,7 +258,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task RuntimeEvidenceIsIngestedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "runtime-evidence"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -273,7 +274,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task DockerfileNodeOptionsWarningIsEmittedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "container-env"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -289,7 +290,7 @@ public sealed class NodeLanguageAnalyzerTests [Fact] public async Task PackageJsonDeclaredOnlyDependenciesUseExplicitKeyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "node", "declared-only-package-json"); var goldenPath = Path.Combine(fixturePath, "expected.json"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLockDataTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLockDataTests.cs index 771b112cd..8263f48e1 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLockDataTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodeLockDataTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Node.Internal; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Node.Tests.Node; @@ -33,7 +34,7 @@ public sealed class NodeLockDataTests : IDisposable public async Task LoadAsync_NoLockfiles_ReturnsEmpty() { // No lockfiles, no package.json - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Empty(result.DeclaredPackages); } @@ -56,7 +57,7 @@ public sealed class NodeLockDataTests : IDisposable Environment.CurrentDirectory = tempDirectory; - var result = await NodeLockData.LoadAsync(string.Empty, CancellationToken.None); + var result = await NodeLockData.LoadAsync(string.Empty, TestContext.Current.CancellationToken); Assert.Empty(result.DeclaredPackages); } finally @@ -79,7 +80,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -101,7 +102,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); var names = result.DeclaredPackages.Select(x => x.Name).ToArray(); Assert.Equal(["alpha", "beta", "zeta"], names); @@ -131,7 +132,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -179,7 +180,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -203,7 +204,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("express", result.DeclaredPackages.First().Name); @@ -226,7 +227,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "@angular/core" && e.Version == "17.0.0"); @@ -251,7 +252,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("valid", result.DeclaredPackages.First().Name); @@ -274,7 +275,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "parent"); @@ -302,7 +303,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "parent"); @@ -328,7 +329,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("actual-package", result.DeclaredPackages.First().Name); @@ -354,7 +355,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -381,7 +382,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "parent"); @@ -402,7 +403,7 @@ public sealed class NodeLockDataTests : IDisposable } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("@babel/core", result.DeclaredPackages.First().Name); @@ -420,7 +421,7 @@ public sealed class NodeLockDataTests : IDisposable """); // Should continue with yarn.lock parsing - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("lodash", result.DeclaredPackages.First().Name); @@ -443,7 +444,7 @@ lodash@^4.17.21: integrity ""sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -464,7 +465,7 @@ lodash@^4.17.21: version ""20.10.0"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "@babel/core"); @@ -479,7 +480,7 @@ lodash@^4.17.21: version ""4.17.21"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("lodash", result.DeclaredPackages.First().Name); @@ -493,7 +494,7 @@ lodash@^4.17.21: version ""4.18.2"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("express", result.DeclaredPackages.First().Name); @@ -506,7 +507,7 @@ lodash@^4.17.21: await File.WriteAllTextAsync(Path.Combine(_tempDir, "yarn.lock"), "lodash@^4.17.21:\n version \"4.17.21\"\n resolved \"https://example.com/lodash.tgz\"\n integrity \"sha512-abc\""); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("lodash", result.DeclaredPackages.First().Name); @@ -526,7 +527,7 @@ axios@^1.6.0: version ""1.6.2"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(3, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "express"); @@ -546,7 +547,7 @@ valid@^2.0.0: version ""2.0.0"" "); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "@scope/package"); @@ -566,7 +567,7 @@ valid@^2.0.0: checksum: 10c0deadbeef """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.DoesNotContain(result.DeclaredPackages, e => e.Name == "__metadata"); @@ -598,7 +599,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.First(); @@ -621,7 +622,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-def456}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "@angular/core"); @@ -638,7 +639,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-xyz}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("4.18.2", result.DeclaredPackages.First().Version); @@ -653,7 +654,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-xyz}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.Single(); @@ -672,7 +673,7 @@ valid@^2.0.0: " resolution: {tarball: https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz, integrity: sha512-abc}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Contains("lodash-4.17.21.tgz", result.DeclaredPackages.First().Resolved); @@ -687,7 +688,7 @@ valid@^2.0.0: " resolution: {tarball: file:../local-file-1.0.0.tgz}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.Single(); @@ -706,7 +707,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-snap}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); var entry = result.DeclaredPackages.Single(); @@ -725,7 +726,7 @@ valid@^2.0.0: " integrity: sha512-separate-line-integrity\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("sha512-separate-line-integrity", result.DeclaredPackages.First().Integrity); @@ -743,7 +744,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-valid}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(2, result.DeclaredPackages.Count); @@ -776,7 +777,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-axios}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(3, result.DeclaredPackages.Count); } @@ -799,7 +800,7 @@ valid@^2.0.0: } """); - var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.True(lockData.TryGet("node_modules/lodash", "lodash", out var entry)); Assert.NotNull(entry); @@ -814,7 +815,7 @@ valid@^2.0.0: version "4.17.21" """); - var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.True(lockData.TryGet("", "lodash", out var entry)); Assert.NotNull(entry); @@ -835,7 +836,7 @@ valid@^2.0.0: } """); - var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.False(lockData.TryGet("node_modules/express", "express", out var entry)); Assert.Null(entry); @@ -855,7 +856,7 @@ valid@^2.0.0: } """); - var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.True(lockData.TryGet("node_modules\\lodash", "lodash", out var entry)); Assert.NotNull(entry); @@ -892,7 +893,7 @@ valid@^2.0.0: } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); var lodash = result.DeclaredPackages.First(e => e.Name == "lodash"); Assert.Equal(NodeDependencyScope.Production, lodash.Scope); @@ -918,7 +919,7 @@ valid@^2.0.0: } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.True(result.DependencyIndex.TryGetScope("express", out var scope)); Assert.Equal(NodeDependencyScope.Production, scope); @@ -938,7 +939,7 @@ valid@^2.0.0: } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Empty(result.DeclaredPackages); } @@ -963,7 +964,7 @@ valid@^2.0.0: " resolution: {integrity: sha512-pnpm}\n"; await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), pnpmContent); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Equal(3, result.DeclaredPackages.Count); Assert.Contains(result.DeclaredPackages, e => e.Name == "from-npm"); @@ -983,7 +984,7 @@ valid@^2.0.0: } """); - var lockData = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var lockData = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.True(lockData.TryGet("node_modules/lodash", "lodash", out var entry)); Assert.NotNull(entry); @@ -1005,7 +1006,7 @@ valid@^2.0.0: version "4.0.0" """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); // Both entries are kept in DeclaredPackages with different version keys Assert.Equal(2, result.DeclaredPackages.Count(e => e.Name == "lodash")); @@ -1039,7 +1040,7 @@ valid@^2.0.0: } """); - var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None); + var result = await NodeLockData.LoadAsync(_tempDir, TestContext.Current.CancellationToken); Assert.Single(result.DeclaredPackages); Assert.Equal("日本語", result.DeclaredPackages.First().Name); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodePackageCollectorTraversalTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodePackageCollectorTraversalTests.cs index a4bb3893e..8374baaf4 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodePackageCollectorTraversalTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/Node/NodePackageCollectorTraversalTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Text.Json; using StellaOps.Scanner.Analyzers.Lang.Node; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; @@ -838,6 +839,6 @@ public sealed class NodePackageCollectorTraversalTests : IDisposable return await LanguageAnalyzerTestHarness.RunToJsonAsync( _tempDir, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/NodePhase22SampleLoaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/NodePhase22SampleLoaderTests.cs index 03f76f841..957cddde4 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/NodePhase22SampleLoaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Node.Tests/NodePhase22SampleLoaderTests.cs @@ -15,7 +15,7 @@ public class NodePhase22SampleLoaderTests public async Task TryLoadAsync_ReadsComponentsFromNdjson() { var root = Path.Combine("Fixtures"); - var records = await NodePhase22SampleLoader.TryLoadAsync(root, CancellationToken.None); + var records = await NodePhase22SampleLoader.TryLoadAsync(root, TestContext.Current.CancellationToken); Assert.Equal(3, records.Count); var native = records.Single(r => r.Type == "node:native"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/ComposerLockReaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/ComposerLockReaderTests.cs index 8e737962c..74c410ece 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/ComposerLockReaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/ComposerLockReaderTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Php.Internal; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Php.Tests.Internal; @@ -31,7 +32,7 @@ public sealed class ComposerLockReaderTests : IDisposable public async Task LoadAsync_NoLockFile_ReturnsEmpty() { var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.True(result.IsEmpty); Assert.Empty(result.Packages); @@ -56,7 +57,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.False(result.IsEmpty); Assert.Single(result.Packages); @@ -82,7 +83,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.DevPackages); Assert.Equal("phpunit/phpunit", result.DevPackages[0].Name); @@ -100,7 +101,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Equal("a1b2c3d4e5f6", result.ContentHash); Assert.Equal("2.3.0", result.PluginApiVersion); @@ -125,7 +126,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal("git", result.Packages[0].SourceType); @@ -151,7 +152,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal("sha256hashhere", result.Packages[0].DistSha256); @@ -177,7 +178,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.NotEmpty(result.Packages[0].Autoload.Psr4); @@ -204,7 +205,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal(2, result.Packages[0].Autoload.Classmap.Count); @@ -232,7 +233,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal(2, result.Packages[0].Autoload.Files.Count); @@ -255,7 +256,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Equal(3, result.Packages.Count); Assert.Single(result.DevPackages); @@ -268,7 +269,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.NotNull(result.LockSha256); Assert.Equal(64, result.LockSha256.Length); // SHA256 hex string length @@ -283,7 +284,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(lockPath, lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Equal(lockPath, result.LockPath); } @@ -301,7 +302,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal("valid/package", result.Packages[0].Name); @@ -340,7 +341,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Equal(2, result.Packages[0].Autoload.Psr4.Count); @@ -363,7 +364,7 @@ public sealed class ComposerLockReaderTests : IDisposable await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.lock"), lockContent); var context = CreateContext(_testDir); - var result = await ComposerLockData.LoadAsync(context, CancellationToken.None); + var result = await ComposerLockData.LoadAsync(context, TestContext.Current.CancellationToken); Assert.Single(result.Packages); Assert.Contains("src/helpers.php", result.Packages[0].Autoload.Files); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpComposerManifestReaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpComposerManifestReaderTests.cs index df280a96b..e1066267e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpComposerManifestReaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpComposerManifestReaderTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Php.Internal; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Php.Tests.Internal; @@ -32,7 +33,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable [Fact] public async Task LoadAsync_NullPath_ReturnsNull() { - var result = await PhpComposerManifestReader.LoadAsync(null!, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(null!, TestContext.Current.CancellationToken); Assert.Null(result); } @@ -40,7 +41,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable [Fact] public async Task LoadAsync_EmptyPath_ReturnsNull() { - var result = await PhpComposerManifestReader.LoadAsync("", CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync("", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -48,7 +49,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable [Fact] public async Task LoadAsync_NonExistentDirectory_ReturnsNull() { - var result = await PhpComposerManifestReader.LoadAsync("/nonexistent/path", CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync("/nonexistent/path", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -56,7 +57,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable [Fact] public async Task LoadAsync_NoComposerJson_ReturnsNull() { - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.Null(result); } @@ -66,7 +67,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable { await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), "{ invalid json }"); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.Null(result); } @@ -83,7 +84,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("vendor/package", result.Name); @@ -102,7 +103,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("MIT OR Apache-2.0", result.License); @@ -120,7 +121,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.Authors.Count); @@ -141,7 +142,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(3, result.Require.Count); @@ -162,7 +163,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.RequireDev.Count); @@ -183,7 +184,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.NotEmpty(result.Autoload.Psr4); @@ -201,7 +202,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.Autoload.Classmap.Count); @@ -220,7 +221,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.Autoload.Files.Count); @@ -240,7 +241,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.Scripts.Count); @@ -259,7 +260,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Single(result.Scripts); @@ -276,7 +277,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(2, result.Bin.Count); @@ -293,7 +294,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal("dev", result.MinimumStability); @@ -305,7 +306,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable var manifest = @"{ ""name"": ""vendor/package"" }"; await File.WriteAllTextAsync(Path.Combine(_testDir, "composer.json"), manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.NotNull(result.Sha256); @@ -320,7 +321,7 @@ public sealed class PhpComposerManifestReaderTests : IDisposable var manifestPath = Path.Combine(_testDir, "composer.json"); await File.WriteAllTextAsync(manifestPath, manifest); - var result = await PhpComposerManifestReader.LoadAsync(_testDir, CancellationToken.None); + var result = await PhpComposerManifestReader.LoadAsync(_testDir, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.Equal(manifestPath, result.ManifestPath); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpPharScannerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpPharScannerTests.cs index 4b57ff98d..8e782d607 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpPharScannerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Internal/PhpPharScannerTests.cs @@ -1,4 +1,5 @@ using System.Text; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Php.Internal; namespace StellaOps.Scanner.Analyzers.Lang.Php.Tests.Internal; @@ -36,7 +37,7 @@ public sealed class PhpPharScannerTests : IDisposable var result = await PhpPharScanner.ScanFileAsync( Path.Combine(_testDir, "nonexistent.phar"), "nonexistent.phar", - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.Null(result); } @@ -44,7 +45,7 @@ public sealed class PhpPharScannerTests : IDisposable [Fact] public async Task ScanFileAsync_NullPath_ReturnsNull() { - var result = await PhpPharScanner.ScanFileAsync(null!, "test.phar", CancellationToken.None); + var result = await PhpPharScanner.ScanFileAsync(null!, "test.phar", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -52,7 +53,7 @@ public sealed class PhpPharScannerTests : IDisposable [Fact] public async Task ScanFileAsync_EmptyPath_ReturnsNull() { - var result = await PhpPharScanner.ScanFileAsync("", "test.phar", CancellationToken.None); + var result = await PhpPharScanner.ScanFileAsync("", "test.phar", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -63,7 +64,7 @@ public sealed class PhpPharScannerTests : IDisposable var filePath = Path.Combine(_testDir, "invalid.phar"); await File.WriteAllTextAsync(filePath, "This is not a valid PHAR file"); - var result = await PhpPharScanner.ScanFileAsync(filePath, "invalid.phar", CancellationToken.None); + var result = await PhpPharScanner.ScanFileAsync(filePath, "invalid.phar", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -77,7 +78,7 @@ public sealed class PhpPharScannerTests : IDisposable var filePath = Path.Combine(_testDir, "minimal.phar"); await File.WriteAllBytesAsync(filePath, pharContent); - var result = await PhpPharScanner.ScanFileAsync(filePath, "minimal.phar", CancellationToken.None); + var result = await PhpPharScanner.ScanFileAsync(filePath, "minimal.phar", TestContext.Current.CancellationToken); // May return null if manifest parsing fails, but should not throw // The minimal PHAR may not have a valid manifest @@ -95,7 +96,7 @@ public sealed class PhpPharScannerTests : IDisposable var filePath = Path.Combine(_testDir, "hash.phar"); await File.WriteAllBytesAsync(filePath, pharContent); - var result = await PhpPharScanner.ScanFileAsync(filePath, "hash.phar", CancellationToken.None); + var result = await PhpPharScanner.ScanFileAsync(filePath, "hash.phar", TestContext.Current.CancellationToken); if (result is not null) { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Php/PhpLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Php/PhpLanguageAnalyzerTests.cs index a77aad0e9..46f94d260 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Php/PhpLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Php.Tests/Php/PhpLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Php; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -11,7 +12,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task ComposerLockPackagesAreEmittedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "basic"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -25,7 +26,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task LaravelExtendedFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "laravel-extended"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -39,7 +40,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task SymfonyFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "symfony"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -53,7 +54,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task WordPressFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "wordpress"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -67,7 +68,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task LegacyPhpFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "legacy"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -81,7 +82,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task PharFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "phar"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -95,7 +96,7 @@ public sealed class PhpLanguageAnalyzerTests [Fact] public async Task ContainerFixtureAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "php", "container"); var goldenPath = Path.Combine(fixturePath, "expected.json"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Capabilities/PythonCapabilityDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Capabilities/PythonCapabilityDetectorTests.cs index 2b9ac7994..ad5e11497 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Capabilities/PythonCapabilityDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Capabilities/PythonCapabilityDetectorTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Capabilities; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.Capabilities; @@ -8,7 +9,7 @@ public sealed class PythonCapabilityDetectorTests [Fact] public async Task DetectAsync_SubprocessImport_FindsProcessExecution() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -41,7 +42,7 @@ public sealed class PythonCapabilityDetectorTests [Fact] public async Task DetectAsync_EvalUsage_FindsCodeExecution() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -75,7 +76,7 @@ public sealed class PythonCapabilityDetectorTests [Fact] public async Task DetectAsync_CtypesImport_FindsNativeCodeExecution() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -108,7 +109,7 @@ public sealed class PythonCapabilityDetectorTests [Fact] public async Task DetectAsync_MultipleCapabilities_FindsAll() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -146,7 +147,7 @@ public sealed class PythonCapabilityDetectorTests [Fact] public async Task DetectAsync_EnvironmentAccess_FindsEnvironmentCapability() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Entrypoints/PythonEntrypointDiscoveryTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Entrypoints/PythonEntrypointDiscoveryTests.cs index 74987474f..b201e00d8 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Entrypoints/PythonEntrypointDiscoveryTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Entrypoints/PythonEntrypointDiscoveryTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Entrypoints; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; using System.IO.Compression; @@ -9,7 +10,7 @@ public sealed class PythonEntrypointDiscoveryTests [Fact] public async Task DiscoverAsync_FindsPackageMain() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -41,7 +42,7 @@ public sealed class PythonEntrypointDiscoveryTests [Fact] public async Task DiscoverAsync_FindsConsoleScripts() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -90,7 +91,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsZipappMain() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -124,7 +125,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsDjangoManage() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -153,7 +154,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsDjangoWsgiAsgi() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -199,7 +200,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsLambdaHandler() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -228,7 +229,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsStandaloneScriptsWithMainGuard() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -258,7 +259,7 @@ mygui = mypackage.gui:start [Fact] public async Task DiscoverAsync_FindsClickCliApp() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -293,7 +294,7 @@ if __name__ == '__main__': [Fact] public async Task DiscoverAsync_FindsProcfileEntrypoints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -326,7 +327,7 @@ if __name__ == '__main__': [Fact] public async Task PythonEntrypointAnalysis_ReturnsOrganizedResults() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures/PythonFixtureTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures/PythonFixtureTests.cs index 279e22430..dfe6e2800 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures/PythonFixtureTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Fixtures/PythonFixtureTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using System.Text.Json; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Capabilities; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Entrypoints; @@ -25,7 +26,7 @@ public sealed class PythonFixtureTests [Fact] public async Task NamespacePackage_DetectsMultipleSubpackages() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "namespace-pkg"); if (!Directory.Exists(fixturePath)) @@ -57,7 +58,7 @@ public sealed class PythonFixtureTests [Fact] public async Task SimpleVenv_DetectsPackageWithEntrypoints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "simple-venv"); if (!Directory.Exists(fixturePath)) @@ -88,7 +89,7 @@ public sealed class PythonFixtureTests [Fact] public async Task LayeredEditable_DetectsEditableInstall() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "layered-editable"); if (!Directory.Exists(fixturePath)) @@ -117,7 +118,7 @@ public sealed class PythonFixtureTests [Fact] public async Task Container_DetectsPackagesAcrossLayers() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "container"); if (!Directory.Exists(fixturePath)) @@ -170,7 +171,7 @@ public sealed class PythonFixtureTests [Fact] public async Task FrameworkDetection_DetectsFlask() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "container", "layer2", "app"); if (!Directory.Exists(fixturePath)) @@ -194,7 +195,7 @@ public sealed class PythonFixtureTests [Fact] public async Task CapabilityDetection_DetectsNetworkAccess() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "lambda-handler", "app"); if (!Directory.Exists(fixturePath)) @@ -219,7 +220,7 @@ public sealed class PythonFixtureTests [Fact] public async Task ObservationBuilder_ProducesValidDocument() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = Path.Combine(FixturesPath, "simple-venv"); if (!Directory.Exists(fixturePath)) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Framework/PythonFrameworkDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Framework/PythonFrameworkDetectorTests.cs index 6bd37e42a..2c0f91a8b 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Framework/PythonFrameworkDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Framework/PythonFrameworkDetectorTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Framework; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; @@ -9,7 +10,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_DjangoProject_FindsDjangoHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -66,7 +67,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_FlaskApp_FindsFlaskHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -106,7 +107,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_FastAPIApp_FindsFastAPIHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -147,7 +148,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_CeleryApp_FindsCeleryHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -185,7 +186,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_AwsLambdaHandler_FindsLambdaHint() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -221,7 +222,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_ClickCli_FindsClickHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -261,7 +262,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_TyperCli_FindsTyperHints() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -300,7 +301,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_GunicornConfig_FindsGunicornHint() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -332,7 +333,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_LoggingConfig_FindsLoggingHint() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -372,7 +373,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_JupyterNotebook_FindsJupyterHint() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -408,7 +409,7 @@ public sealed class PythonFrameworkDetectorTests [Fact] public async Task DetectAsync_StreamlitApp_FindsStreamlitHint() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -513,7 +514,7 @@ public sealed class PythonProjectConfigParserTests [Fact] public async Task ParsePyprojectAsync_WithOptionalDependencies_ExtractsExtras() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -564,7 +565,7 @@ public sealed class PythonProjectConfigParserTests [Fact] public async Task ParsePyprojectAsync_PoetryExtras_ExtractsExtras() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Imports/PythonImportGraphTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Imports/PythonImportGraphTests.cs index 679e682c0..00e51f7fa 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Imports/PythonImportGraphTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Imports/PythonImportGraphTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Imports; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.Imports; @@ -8,7 +9,7 @@ public sealed class PythonImportGraphTests [Fact] public async Task BuildAsync_DiscoversModules() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -40,7 +41,7 @@ public sealed class PythonImportGraphTests [Fact] public async Task BuildAsync_ExtractsImports() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -83,7 +84,7 @@ from . import other [Fact] public async Task BuildAsync_BuildsEdges() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -133,7 +134,7 @@ from . import other [Fact] public async Task BuildAsync_ResolvesRelativeImports() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -180,7 +181,7 @@ from . import other [Fact] public async Task BuildAsync_DetectsCycles() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -223,7 +224,7 @@ from . import other [Fact] public async Task BuildAsync_TopologicalOrder_NoCycles() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -272,7 +273,7 @@ from . import other [Fact] public async Task BuildAsync_TopologicalOrder_WithCycles_ReturnsNull() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -306,7 +307,7 @@ from . import other [Fact] public async Task GetDependencies_ReturnsDirectDependencies() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -346,7 +347,7 @@ from . import other [Fact] public async Task GetDependents_ReturnsModulesThatImportThis() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -386,7 +387,7 @@ from . import other [Fact] public async Task PythonImportAnalysis_CategoriesImports() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -438,7 +439,7 @@ mod = importlib.import_module('dynamic') [Fact] public async Task PythonImportAnalysis_ToMetadata_GeneratesExpectedKeys() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -468,7 +469,7 @@ mod = importlib.import_module('dynamic') [Fact] public async Task PythonImportAnalysis_GetTransitiveDependencies_ReturnsAllDeps() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Observations/PythonObservationSerializerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Observations/PythonObservationSerializerTests.cs index 1db43e33a..a5aa2b6f5 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Observations/PythonObservationSerializerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Observations/PythonObservationSerializerTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using System.Text.Json; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Observations; @@ -140,7 +141,7 @@ public sealed class PythonObservationSerializerTests [Fact] public async Task SerializeAsync_WritesToStream() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var document = new PythonObservationBuilder() .AddWarning("PY001", "Test") .Build(); @@ -159,7 +160,7 @@ public sealed class PythonObservationSerializerTests [Fact] public async Task DeserializeAsync_ReadsFromStream() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var json = """ { "schema": "python-aoc-v1", diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Packaging/PythonPackageDiscoveryTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Packaging/PythonPackageDiscoveryTests.cs index 5f50177cb..e40c7dbbf 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Packaging/PythonPackageDiscoveryTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Packaging/PythonPackageDiscoveryTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Packaging; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.Packaging; @@ -8,7 +9,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_DistInfo_FindsPackages() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -117,7 +118,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_EggLink_FindsEditableInstall() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); var projectPath = Path.Combine(tempPath, "myproject"); try @@ -178,7 +179,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_Poetry_FindsPoetryProject() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -262,7 +263,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_BuildsDependencyGraph() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -319,7 +320,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_EggInfo_FindsLegacySetuptoolsPackages() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -392,7 +393,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_EggInfo_WithInstalledFiles_HasDefinitiveConfidence() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -441,7 +442,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_EggInfo_ParsesRequiresTxtExtras() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -497,7 +498,7 @@ public sealed class PythonPackageDiscoveryTests [Fact] public async Task DiscoverAsync_EggInfo_PrefersDistInfo_WhenBothExist() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Python/PythonLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Python/PythonLanguageAnalyzerTests.cs index 1d2e3890e..e7c9d2862 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Python/PythonLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Python/PythonLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using System.IO.Compression; +using Xunit; using System.Security.Cryptography; using System.Text; using System.Text.Json; @@ -13,7 +14,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task SimpleVenvFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "simple-venv"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -38,7 +39,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task PipCacheFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "pip-cache"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -63,7 +64,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task LayeredEditableFixtureMergesAcrossLayersAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "layered-editable"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -88,7 +89,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task CondaEnvFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "conda-env"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -107,7 +108,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task RequirementsIncludesEditableFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "requirements-includes-editable"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -126,7 +127,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task PipfileLockDefaultDevelopFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "pipfile-lock-default-develop"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -145,7 +146,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task WheelWorkspaceFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "wheel-workspace"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -170,7 +171,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task ZipappEmbeddedRequirementsFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "zipapp-embedded-requirements"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -192,7 +193,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task ContainerWhiteoutsFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "container-whiteouts"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -211,7 +212,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task VendoredDirectoryFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "vendored-directory"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -230,7 +231,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task LockfileCollectorEmitsDeclaredOnlyComponentsAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -271,7 +272,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task EditableRequirementsUseExplicitKeyWithoutHostPathLeakAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try @@ -332,7 +333,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task WheelArchiveDistInfo_IsVerifiedFromRecordAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -476,7 +477,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task DetectsSitecustomizeStartupHooksAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -515,7 +516,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task DetectsPthFilesWithImportDirectivesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -554,7 +555,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task DetectsOciLayerSitePackagesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -618,7 +619,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task EggInfoPackagesAreDetectedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "python", "egg-info"); var analyzers = new ILanguageAnalyzer[] @@ -645,7 +646,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task DetectsPythonEnvironmentVariablesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -682,7 +683,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task DetectsPyvenvConfigAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -798,7 +799,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task RequirementsWithIncludesAreFollowedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -841,7 +842,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task PipfileLockDevelopSectionIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -890,7 +891,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task RequirementsDevTxtGetsScopeDevAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -930,7 +931,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task Pep508DirectReferenceIsParsedAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { @@ -966,7 +967,7 @@ public sealed class PythonLanguageAnalyzerTests [Fact] public async Task RequirementsCycleIsDetectedAndHandledAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Resolver/PythonModuleResolverTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Resolver/PythonModuleResolverTests.cs index 326bedf7a..799337749 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Resolver/PythonModuleResolverTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Resolver/PythonModuleResolverTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Resolver; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.Resolver; @@ -8,7 +9,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_BuiltinModule_ReturnsBuiltin() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -36,7 +37,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_SourceModule_FindsModule() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -64,7 +65,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_Package_FindsPackage() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -95,7 +96,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_SubModule_FindsSubModule() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -126,7 +127,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_NamespacePackage_FindsNamespacePackage() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -159,7 +160,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolve_NotFound_ReturnsNotFound() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -186,7 +187,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task ResolveRelative_Level1_ResolvesFromPackage() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -218,7 +219,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task ResolveRelative_Level2_ResolvesFromParentPackage() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -254,7 +255,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task ProcessPthFiles_AddsPaths() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -359,7 +360,7 @@ public sealed class PythonModuleResolverTests [Fact] public async Task Resolver_CachesResults() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Vendoring/VendoredPackageDetectorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Vendoring/VendoredPackageDetectorTests.cs index 21024b26f..d81aece36 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Vendoring/VendoredPackageDetectorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/Vendoring/VendoredPackageDetectorTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Packaging; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Vendoring; using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; @@ -16,7 +17,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.False(result.IsVendored); Assert.Equal(VendoringConfidence.None, result.Confidence); @@ -34,7 +35,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.True(result.Confidence >= VendoringConfidence.Low); @@ -53,7 +54,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("pip", "23.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.True(result.EmbeddedCount >= 3); @@ -76,7 +77,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("pip", "23.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.Contains("known-vendored-package", result.Markers); @@ -92,7 +93,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.Contains(result.Markers, m => m.Contains("third_party")); @@ -108,7 +109,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.Contains(result.Markers, m => m.Contains("extern")); @@ -126,7 +127,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); var embeddedNames = result.EmbeddedPackages.Select(p => p.Name).ToList(); Assert.DoesNotContain("__pycache__", embeddedNames); @@ -143,7 +144,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("pip", "23.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); var urllib3 = result.EmbeddedPackages.FirstOrDefault(p => p.Name == "urllib3"); Assert.NotNull(urllib3); @@ -160,7 +161,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("pip", "23.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); var urllib3 = result.EmbeddedPackages.FirstOrDefault(p => p.Name == "urllib3"); Assert.NotNull(urllib3); @@ -182,7 +183,7 @@ public class VendoredPackageDetectorTests var package = CreatePackageWithRecords("mypackage", "1.0.0", "/site-packages", recordFiles); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.Contains("record-vendor-entries", result.Markers); @@ -200,7 +201,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); Assert.True(result.VendorPaths.Length >= 2); @@ -216,7 +217,7 @@ public class VendoredPackageDetectorTests var package = CreatePackage("mypackage", "1.0.0", "/site-packages"); - var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, CancellationToken.None); + var result = await VendoredPackageDetector.AnalyzeAsync(vfs, package, TestContext.Current.CancellationToken); Assert.True(result.IsVendored); var embeddedNames = result.EmbeddedPackages.Select(p => p.Name).ToList(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/VirtualFileSystem/PythonInputNormalizerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/VirtualFileSystem/PythonInputNormalizerTests.cs index 87e2bcd3c..d983f626e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/VirtualFileSystem/PythonInputNormalizerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Python.Tests/VirtualFileSystem/PythonInputNormalizerTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.VirtualFileSystem; @@ -7,7 +8,7 @@ public sealed class PythonInputNormalizerTests [Fact] public async Task AnalyzeAsync_DetectsVirtualenvLayout() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -40,7 +41,7 @@ version = 3.11.4 [Fact] public async Task AnalyzeAsync_DetectsPoetryLayout() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -66,7 +67,7 @@ version = ""2.28.0"" [Fact] public async Task AnalyzeAsync_DetectsPipenvLayout() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -88,7 +89,7 @@ version = ""2.28.0"" [Fact] public async Task AnalyzeAsync_DetectsCondaLayout() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -110,7 +111,7 @@ version = ""2.28.0"" [Fact] public async Task AnalyzeAsync_DetectsLambdaLayout() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -132,7 +133,7 @@ version = ""2.28.0"" [Fact] public async Task AnalyzeAsync_ExtractsVersionFromPyprojectToml() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -161,7 +162,7 @@ python = ""^3.11"" [Fact] public async Task AnalyzeAsync_ExtractsVersionFromRuntimeTxt() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -185,7 +186,7 @@ python = ""^3.11"" [Fact] public async Task AnalyzeAsync_ExtractsVersionFromDockerfile() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -212,7 +213,7 @@ COPY . . [Fact] public async Task AnalyzeAsync_ExtractsVersionFromSetupPy() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -243,7 +244,7 @@ setup( [Fact] public async Task AnalyzeAsync_DetectsSitePackagesInMultipleLocations() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -272,7 +273,7 @@ setup( [Fact] public async Task AnalyzeAsync_DetectsWheelsInDistDirectory() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -299,7 +300,7 @@ setup( [Fact] public async Task AnalyzeAsync_DetectsZipapps() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -323,7 +324,7 @@ setup( [Fact] public async Task AnalyzeAsync_PrimaryVersionTargetHasHighestConfidence() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -353,7 +354,7 @@ requires-python = "">=3.10""", cancellationToken); [Fact] public async Task BuildVirtualFileSystem_IncludesAllDetectedSources() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { @@ -394,7 +395,7 @@ requires-python = "">=3.10""", cancellationToken); [Fact] public async Task PythonProjectAnalysis_AnalyzeAsync_ReturnsCompleteAnalysis() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var tempPath = CreateTemporaryWorkspace(); try { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyBenchmarks.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyBenchmarks.cs index 50c22d30f..bfe6e4d69 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyBenchmarks.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyBenchmarks.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using Xunit; using FluentAssertions; using StellaOps.Scanner.Analyzers.Lang; using StellaOps.Scanner.Analyzers.Lang.Ruby; @@ -31,7 +32,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -39,7 +40,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -61,7 +62,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -69,7 +70,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -91,7 +92,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -99,7 +100,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -121,7 +122,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -129,7 +130,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -151,7 +152,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -159,7 +160,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -181,7 +182,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -189,7 +190,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -211,7 +212,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < WarmupIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } // Benchmark @@ -219,7 +220,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < BenchmarkIterations; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - await engine.AnalyzeAsync(context, CancellationToken.None); + await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); } sw.Stop(); @@ -243,7 +244,7 @@ public sealed class RubyBenchmarks for (var i = 0; i < 5; i++) { var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); - var result = await engine.AnalyzeAsync(context, CancellationToken.None); + var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); results.Add(result.ToJson(indent: false)); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyLanguageAnalyzerTests.cs index e2c4c5680..0014d0e29 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/RubyLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ -using System.Text.Json; +using System.Text.Json; +using Xunit; using StellaOps.Scanner.Analyzers.Lang; using StellaOps.Scanner.Analyzers.Lang.Ruby; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; @@ -23,7 +24,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -41,7 +42,7 @@ public sealed class RubyLanguageAnalyzerTests services: null, analysisStore: store); - var result = await engine.AnalyzeAsync(context, CancellationToken.None); + var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshots = result.ToSnapshots(); var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation"); @@ -89,7 +90,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -104,7 +105,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -119,7 +120,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -134,7 +135,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -149,7 +150,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -167,7 +168,7 @@ public sealed class RubyLanguageAnalyzerTests services: null, analysisStore: store); - var result = await engine.AnalyzeAsync(context, CancellationToken.None); + var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshots = result.ToSnapshots(); var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation"); @@ -207,7 +208,7 @@ public sealed class RubyLanguageAnalyzerTests fixturePath, goldenPath, analyzers, - CancellationToken.None); + TestContext.Current.CancellationToken); } [Trait("Category", TestCategories.Unit)] @@ -225,7 +226,7 @@ public sealed class RubyLanguageAnalyzerTests services: null, analysisStore: store); - var result = await engine.AnalyzeAsync(context, CancellationToken.None); + var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshots = result.ToSnapshots(); var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerContextTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerContextTests.cs index 7e767e540..dd5538555 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerContextTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerContextTests.cs @@ -46,7 +46,7 @@ public sealed class LanguageAnalyzerContextTests var context = new LanguageAnalyzerContext(workspace.Path, TimeProvider.System, services: serviceProvider); Assert.True(context.Secrets.IsAvailable); - using var retrieved = await context.Secrets.GetAsync("registry", "default", CancellationToken.None); + using var retrieved = await context.Secrets.GetAsync("registry", "default", TestContext.Current.CancellationToken); Assert.Same(handle, retrieved); Assert.Equal("test", retrieved.Metadata["source"]); Assert.Equal("token", Encoding.UTF8.GetString(retrieved.AsBytes().Span)); @@ -59,7 +59,7 @@ public sealed class LanguageAnalyzerContextTests var context = new LanguageAnalyzerContext(workspace.Path, TimeProvider.System); Assert.False(context.Secrets.IsAvailable); - var secret = await context.Secrets.TryGetAsync("registry", cancellationToken: CancellationToken.None); + var secret = await context.Secrets.TryGetAsync("registry", cancellationToken: TestContext.Current.CancellationToken); Assert.Null(secret); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerResultTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerResultTests.cs index d42c9f2b1..c0a546722 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerResultTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Core/LanguageAnalyzerResultTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; +using Xunit; namespace StellaOps.Scanner.Analyzers.Lang.Tests.Core; @@ -13,7 +14,7 @@ public sealed class LanguageAnalyzerResultTests try { var context = new LanguageAnalyzerContext(root, TimeProvider.System); - var result = await engine.AnalyzeAsync(context, CancellationToken.None); + var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken); var component = Assert.Single(result.Components); Assert.Equal("purl::pkg:example/acme@2.0.0", component.ComponentKey); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Determinism/LanguageAnalyzerHarnessTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Determinism/LanguageAnalyzerHarnessTests.cs index a8431b356..932038cf9 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Determinism/LanguageAnalyzerHarnessTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Determinism/LanguageAnalyzerHarnessTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -11,7 +12,7 @@ public sealed class LanguageAnalyzerHarnessTests { var fixturePath = TestPaths.ResolveFixture("determinism", "basic", "input"); var goldenPath = TestPaths.ResolveFixture("determinism", "basic", "expected.json"); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var analyzers = new ILanguageAnalyzer[] { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetEntrypointResolverTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetEntrypointResolverTests.cs index c3ec3c85f..068c49414 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetEntrypointResolverTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetEntrypointResolverTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using System.Threading; using System.Threading.Tasks; using StellaOps.Scanner.Analyzers.Lang; @@ -12,7 +13,7 @@ public sealed class DotNetEntrypointResolverTests [Fact] public async Task SimpleFixtureResolvesSingleEntrypointAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "simple"); var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); @@ -33,7 +34,7 @@ public sealed class DotNetEntrypointResolverTests [Fact] public async Task DeterministicOrderingIsStableAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "multi"); var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetLanguageAnalyzerTests.cs index 6a649fbfc..b7e3bf92f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/DotNet/DotNetLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using System; +using Xunit; using System.IO; using System.Linq; using System.Text.Json; @@ -15,7 +16,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task SimpleFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "simple"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -34,7 +35,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task SignedFixtureCapturesAssemblyMetadataAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "signed"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -58,7 +59,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task SelfContainedFixtureHandlesNativeAssetsAndUsageAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "selfcontained"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -84,7 +85,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task AnalyzerIsThreadSafeUnderConcurrencyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "selfcontained"); var analyzers = new ILanguageAnalyzer[] @@ -107,7 +108,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task ConfigEnablesIlMetadataEdgesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var sourceFixture = TestPaths.ResolveFixture("lang", "dotnet", "simple"); var tempRoot = TestPaths.CreateTemporaryDirectory(); @@ -169,7 +170,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task MultiFixtureMergesRuntimeMetadataAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "multi"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -217,7 +218,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task SourceTreeOnlyEmitsDeclaredPackagesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "source-tree-only"); var analyzers = new ILanguageAnalyzer[] @@ -253,7 +254,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task LockfileOnlyEmitsDeclaredPackagesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "lockfile-only"); var analyzers = new ILanguageAnalyzer[] @@ -291,7 +292,7 @@ public sealed class DotNetLanguageAnalyzerTests [Fact] public async Task PackagesConfigOnlyEmitsDeclaredPackagesAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "dotnet", "packages-config-only"); var analyzers = new ILanguageAnalyzer[] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Lang/Ruby/RubyLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Lang/Ruby/RubyLanguageAnalyzerTests.cs index da6718f1f..815abf76a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Lang/Ruby/RubyLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Lang/Ruby/RubyLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using StellaOps.Scanner.Analyzers.Lang; +using Xunit; using StellaOps.Scanner.Analyzers.Lang.Ruby; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities; @@ -18,7 +19,7 @@ public sealed class RubyLanguageAnalyzerTests fixture, golden, new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() }, - cancellationToken: CancellationToken.None, + cancellationToken: TestContext.Current.CancellationToken, usageHints: usageHints); } @@ -32,7 +33,7 @@ public sealed class RubyLanguageAnalyzerTests fixture, golden, new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() }, - cancellationToken: CancellationToken.None); + cancellationToken: TestContext.Current.CancellationToken); } [Fact] @@ -46,7 +47,7 @@ public sealed class RubyLanguageAnalyzerTests fixture, golden, new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() }, - cancellationToken: CancellationToken.None, + cancellationToken: TestContext.Current.CancellationToken, usageHints: usageHints); } } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustHeuristicCoverageComparisonTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustHeuristicCoverageComparisonTests.cs index 6d865f966..381d17ecc 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustHeuristicCoverageComparisonTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustHeuristicCoverageComparisonTests.cs @@ -1,4 +1,5 @@ using System.Linq; +using Xunit; using System.Text.Json; using StellaOps.Scanner.Analyzers.Lang.Rust; using StellaOps.Scanner.Analyzers.Lang.Tests.Harness; @@ -11,7 +12,7 @@ public sealed class RustHeuristicCoverageComparisonTests [Fact] public async Task HeuristicCoverageExceedsCompetitorBaselineAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "rust", "heuristics"); var baselinePath = Path.Combine(fixturePath, "competitor-baseline.json"); RustFixtureBinaries.EnsureHeuristicBinary(fixturePath); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustLanguageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustLanguageAnalyzerTests.cs index 3f3842d9b..e5ba42727 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustLanguageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Tests/Rust/RustLanguageAnalyzerTests.cs @@ -1,4 +1,5 @@ using System; +using Xunit; using System.IO; using System.Linq; using System.Text.Json.Nodes; @@ -13,7 +14,7 @@ public sealed class RustLanguageAnalyzerTests [Fact] public async Task SimpleFixtureProducesDeterministicOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "rust", "simple"); var goldenPath = Path.Combine(fixturePath, "expected.json"); @@ -38,7 +39,7 @@ public sealed class RustLanguageAnalyzerTests [Fact] public async Task AnalyzerIsThreadSafeUnderConcurrencyAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "rust", "simple"); var analyzers = new ILanguageAnalyzer[] @@ -61,7 +62,7 @@ public sealed class RustLanguageAnalyzerTests [Fact] public async Task HeuristicFixtureProducesExpectedOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "rust", "heuristics"); var goldenPath = Path.Combine(fixturePath, "expected.json"); RustFixtureBinaries.EnsureHeuristicBinary(fixturePath); @@ -86,7 +87,7 @@ public sealed class RustLanguageAnalyzerTests [Fact] public async Task FallbackFixtureProducesExpectedOutputAsync() { - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var fixturePath = TestPaths.ResolveFixture("lang", "rust", "fallback"); var goldenPath = Path.Combine(fixturePath, "expected.json"); RustFixtureBinaries.EnsureOpaqueBinary(fixturePath); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexSignatureTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexSignatureTests.cs index 3da8ae3e5..9261b800b 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexSignatureTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexSignatureTests.cs @@ -52,7 +52,7 @@ public sealed class OfflineBuildIdIndexSignatureTests : IDisposable await index.LoadAsync(); Assert.True(index.IsLoaded); - Assert.Equal(1, index.Count); + Assert.Single(index); var result = await index.LookupAsync("gnu-build-id:abc123"); Assert.NotNull(result); @@ -83,7 +83,7 @@ public sealed class OfflineBuildIdIndexSignatureTests : IDisposable await index.LoadAsync(); Assert.True(index.IsLoaded); - Assert.Equal(0, index.Count); + Assert.Empty(index); } [Fact] @@ -108,7 +108,7 @@ public sealed class OfflineBuildIdIndexSignatureTests : IDisposable await index.LoadAsync(); Assert.True(index.IsLoaded); - Assert.Equal(0, index.Count); + Assert.Empty(index); } private static string CreateDsseSignature(string indexPath, string expectedSha256) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexTests.cs index 51289bee2..0e915699c 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Native.Tests/Index/OfflineBuildIdIndexTests.cs @@ -37,7 +37,7 @@ public sealed class OfflineBuildIdIndexTests : IDisposable await index.LoadAsync(); Assert.True(index.IsLoaded); - Assert.Equal(0, index.Count); + Assert.Empty(index); } [Fact] @@ -49,7 +49,7 @@ public sealed class OfflineBuildIdIndexTests : IDisposable await index.LoadAsync(); Assert.True(index.IsLoaded); - Assert.Equal(0, index.Count); + Assert.Empty(index); } [Fact] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Homebrew.Tests/HomebrewPackageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Homebrew.Tests/HomebrewPackageAnalyzerTests.cs index 33020a8f8..00b698716 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Homebrew.Tests/HomebrewPackageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Homebrew.Tests/HomebrewPackageAnalyzerTests.cs @@ -45,7 +45,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -61,7 +61,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var openssl = result.Packages.FirstOrDefault(p => p.Name == "openssl@3"); @@ -79,7 +79,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var jq = result.Packages.FirstOrDefault(p => p.Name == "jq"); @@ -96,7 +96,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var wget = result.Packages.FirstOrDefault(p => p.Name == "wget"); @@ -113,7 +113,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var wget = result.Packages.FirstOrDefault(p => p.Name == "wget"); @@ -130,7 +130,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var openssl = result.Packages.FirstOrDefault(p => p.Name == "openssl@3"); @@ -149,7 +149,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert foreach (var package in result.Packages) @@ -166,7 +166,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var wget = result.Packages.FirstOrDefault(p => p.Name == "wget"); @@ -182,8 +182,8 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result1 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); - var result2 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result1 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); + var result2 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(result1.Packages.Count, result2.Packages.Count); @@ -206,7 +206,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(tempPath); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Empty(result.Packages); @@ -225,7 +225,7 @@ public sealed class HomebrewPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result.Telemetry); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.MacOsBundle.Tests/MacOsBundleAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.MacOsBundle.Tests/MacOsBundleAnalyzerTests.cs index 266dbf46e..a54ab86cc 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.MacOsBundle.Tests/MacOsBundleAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.MacOsBundle.Tests/MacOsBundleAnalyzerTests.cs @@ -45,7 +45,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -61,7 +61,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -80,7 +80,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -101,7 +101,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -119,7 +119,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -137,7 +137,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert foreach (var package in result.Packages) @@ -154,7 +154,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -176,7 +176,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -196,7 +196,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var sandboxedApp = result.Packages.FirstOrDefault(p => @@ -214,7 +214,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var sandboxedApp = result.Packages.FirstOrDefault(p => @@ -236,7 +236,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var sandboxedApp = result.Packages.FirstOrDefault(p => @@ -260,7 +260,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var testApp = result.Packages.FirstOrDefault(p => @@ -286,8 +286,8 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result1 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); - var result2 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result1 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); + var result2 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(result1.Packages.Count, result2.Packages.Count); @@ -310,7 +310,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(tempPath); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Empty(result.Packages); @@ -329,7 +329,7 @@ public sealed class MacOsBundleAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result.Telemetry); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Pkgutil.Tests/PkgutilPackageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Pkgutil.Tests/PkgutilPackageAnalyzerTests.cs index 59242cbf7..80638bf76 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Pkgutil.Tests/PkgutilPackageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Pkgutil.Tests/PkgutilPackageAnalyzerTests.cs @@ -45,7 +45,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -61,7 +61,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var safari = result.Packages.FirstOrDefault(p => p.Name == "Safari"); @@ -78,7 +78,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var safari = result.Packages.FirstOrDefault(p => p.Name == "Safari"); @@ -94,7 +94,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert foreach (var package in result.Packages) @@ -111,7 +111,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert var safari = result.Packages.FirstOrDefault(p => p.Name == "Safari"); @@ -128,8 +128,8 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result1 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); - var result2 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result1 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); + var result2 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(result1.Packages.Count, result2.Packages.Count); @@ -152,7 +152,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(tempPath); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Empty(result.Packages); @@ -171,7 +171,7 @@ public sealed class PkgutilPackageAnalyzerTests var context = CreateContext(FixturesRoot); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result.Telemetry); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/OsAnalyzerDeterminismTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/OsAnalyzerDeterminismTests.cs index 59d352f1a..9700d0672 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/OsAnalyzerDeterminismTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/OsAnalyzerDeterminismTests.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -26,7 +26,7 @@ public sealed class OsAnalyzerDeterminismTests var analyzer = new ApkPackageAnalyzer(NullLogger.Instance); var context = CreateContext(rootPath); - var result = await analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshot = SnapshotSerializer.Serialize(new[] { result }); GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("apk.json")); } @@ -39,7 +39,7 @@ public sealed class OsAnalyzerDeterminismTests var analyzer = new DpkgPackageAnalyzer(NullLogger.Instance); var context = CreateContext(rootPath); - var result = await analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshot = SnapshotSerializer.Serialize(new[] { result }); GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("dpkg.json")); } @@ -75,7 +75,7 @@ public sealed class OsAnalyzerDeterminismTests reader); var context = CreateContext("/tmp/nonexistent"); - var result = await analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); var snapshot = SnapshotSerializer.Serialize(new[] { result }); GoldenAssert.MatchSnapshot(snapshot, FixtureManager.GetGoldenPath("rpm.json")); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/Rpm/RpmDatabaseReaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/Rpm/RpmDatabaseReaderTests.cs index 9bb8f9c6d..5265f7b71 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/Rpm/RpmDatabaseReaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Tests/Rpm/RpmDatabaseReaderTests.cs @@ -26,7 +26,7 @@ public sealed class RpmDatabaseReaderTests CreateSqliteRpmdb(sqlitePath, headerColumnName); var reader = new RpmDatabaseReader(NullLogger.Instance); - var headers = reader.ReadHeaders(root.FullName, CancellationToken.None); + var headers = reader.ReadHeaders(root.FullName, TestContext.Current.CancellationToken); Assert.Single(headers); var header = headers[0]; @@ -59,7 +59,7 @@ public sealed class RpmDatabaseReaderTests File.WriteAllBytes(Path.Combine(packagesPath, "Packages"), data); var reader = new RpmDatabaseReader(NullLogger.Instance); - var headers = reader.ReadHeaders(root.FullName, CancellationToken.None); + var headers = reader.ReadHeaders(root.FullName, TestContext.Current.CancellationToken); Assert.Single(headers); var header = headers[0]; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey.Tests/ChocolateyPackageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey.Tests/ChocolateyPackageAnalyzerTests.cs index f0c70d296..1c1b6c9c7 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey.Tests/ChocolateyPackageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey.Tests/ChocolateyPackageAnalyzerTests.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.Scanner.Analyzers.OS.Windows.Chocolatey; using Xunit; @@ -47,7 +47,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -73,7 +73,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -102,7 +102,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -144,7 +144,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(3, result.Packages.Count); @@ -187,7 +187,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -225,7 +225,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -258,7 +258,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -295,7 +295,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -344,7 +344,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Results should be sorted by PURL Assert.Equal(3, result.Packages.Count); @@ -380,7 +380,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Only valid package should be returned Assert.Single(result.Packages); @@ -409,7 +409,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -439,7 +439,7 @@ public class ChocolateyPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiDatabaseParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiDatabaseParserTests.cs index 056d77c1d..bfbfd6775 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiDatabaseParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiDatabaseParserTests.cs @@ -17,7 +17,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -46,7 +46,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -72,7 +72,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -98,7 +98,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -119,7 +119,7 @@ public class MsiDatabaseParserTests public void Parse_WithNonExistentFile_ReturnsNull() { // Act - var result = _parser.Parse("/nonexistent/path/file.msi", CancellationToken.None); + var result = _parser.Parse("/nonexistent/path/file.msi", TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -136,7 +136,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -152,7 +152,7 @@ public class MsiDatabaseParserTests public void Parse_WithEmptyPath_ReturnsNull() { // Act - var result = _parser.Parse(string.Empty, CancellationToken.None); + var result = _parser.Parse(string.Empty, TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -163,7 +163,7 @@ public class MsiDatabaseParserTests public void Parse_WithNullPath_ReturnsNull() { // Act - var result = _parser.Parse(null!, CancellationToken.None); + var result = _parser.Parse(null!, TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -185,7 +185,7 @@ public class MsiDatabaseParserTests try { // Act - var result = _parser.Parse(tempFile, CancellationToken.None); + var result = _parser.Parse(tempFile, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiPackageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiPackageAnalyzerTests.cs index 8f6ab7e3d..0b7d53950 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiPackageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.Msi.Tests/MsiPackageAnalyzerTests.cs @@ -46,7 +46,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -76,7 +76,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(2, result.Packages.Count); @@ -114,7 +114,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -143,7 +143,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -175,7 +175,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Only valid MSI should be returned Assert.Single(result.Packages); @@ -206,7 +206,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Results should be sorted Assert.Equal(3, result.Packages.Count); @@ -237,8 +237,8 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - Execute twice to ensure no duplicates - var result1 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); - var result2 = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result1 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); + var result2 = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result1.Packages); @@ -266,7 +266,7 @@ public class MsiPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSManifestParserTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSManifestParserTests.cs index 4aaa8d55a..e88e917bb 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSManifestParserTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSManifestParserTests.cs @@ -27,7 +27,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -63,7 +63,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -93,7 +93,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -123,7 +123,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -140,7 +140,7 @@ public class WinSxSManifestParserTests public void Parse_WithNonExistentFile_ReturnsNull() { // Act - var result = _parser.Parse("/nonexistent/path/manifest.manifest", CancellationToken.None); + var result = _parser.Parse("/nonexistent/path/manifest.manifest", TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -156,7 +156,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -180,7 +180,7 @@ public class WinSxSManifestParserTests try { // Act - var result = _parser.Parse(manifestPath, CancellationToken.None); + var result = _parser.Parse(manifestPath, TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -196,7 +196,7 @@ public class WinSxSManifestParserTests public void Parse_WithEmptyPath_ReturnsNull() { // Act - var result = _parser.Parse(string.Empty, CancellationToken.None); + var result = _parser.Parse(string.Empty, TestContext.Current.CancellationToken); // Assert Assert.Null(result); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSPackageAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSPackageAnalyzerTests.cs index ef15ce12c..08369db04 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSPackageAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.OS.Windows.WinSxS.Tests/WinSxSPackageAnalyzerTests.cs @@ -46,7 +46,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.NotNull(result); @@ -78,7 +78,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(2, result.Packages.Count); @@ -118,7 +118,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -154,7 +154,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -187,7 +187,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Single(result.Packages); @@ -229,7 +229,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Only valid manifest should be returned Assert.Single(result.Packages); @@ -263,7 +263,7 @@ public class WinSxSPackageAnalyzerTests var context = CreateContext(tempDir); // Act - var result = await _analyzer.AnalyzeAsync(context, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - Results should be sorted Assert.Equal(3, result.Packages.Count); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Cache.Tests/LayerCacheRoundTripTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Cache.Tests/LayerCacheRoundTripTests.cs index 5a8856177..ed3b9510e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Cache.Tests/LayerCacheRoundTripTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Cache.Tests/LayerCacheRoundTripTests.cs @@ -69,16 +69,16 @@ public sealed class LayerCacheRoundTripTests : IAsyncLifetime new("usage.cdx.json", usageStream, "application/json") }); - var stored = await _layerCache.PutAsync(request, CancellationToken.None); + var stored = await _layerCache.PutAsync(request, TestContext.Current.CancellationToken); stored.LayerDigest.Should().Be(layerDigest); stored.Artifacts.Should().ContainKey("inventory.cdx.json"); stored.TotalSizeBytes.Should().BeGreaterThan(0); - var cached = await _layerCache.TryGetAsync(layerDigest, CancellationToken.None); + var cached = await _layerCache.TryGetAsync(layerDigest, TestContext.Current.CancellationToken); cached.Should().NotBeNull(); cached!.Metadata.Should().ContainKey("image"); - await using (var artifact = await _layerCache.OpenArtifactAsync(layerDigest, "inventory.cdx.json", CancellationToken.None)) + await using (var artifact = await _layerCache.OpenArtifactAsync(layerDigest, "inventory.cdx.json", TestContext.Current.CancellationToken)) { artifact.Should().NotBeNull(); using var reader = new StreamReader(artifact!, Encoding.UTF8); @@ -89,34 +89,34 @@ public sealed class LayerCacheRoundTripTests : IAsyncLifetime // Store file CAS entry and validate export/import lifecycle. var casHash = "sha256:" + new string('f', 64); using var casStream = CreateStream("some-cas-content"); - await _fileCas.PutAsync(new FileCasPutRequest(casHash, casStream), CancellationToken.None); + await _fileCas.PutAsync(new FileCasPutRequest(casHash, casStream), TestContext.Current.CancellationToken); var exportPath = Path.Combine(_rootPath, "export"); - var exportCount = await _fileCas.ExportAsync(exportPath, CancellationToken.None); + var exportCount = await _fileCas.ExportAsync(exportPath, TestContext.Current.CancellationToken); exportCount.Should().Be(1); - await _fileCas.RemoveAsync(casHash, CancellationToken.None); - (await _fileCas.TryGetAsync(casHash, CancellationToken.None)).Should().BeNull(); + await _fileCas.RemoveAsync(casHash, TestContext.Current.CancellationToken); + (await _fileCas.TryGetAsync(casHash, TestContext.Current.CancellationToken)).Should().BeNull(); - var importCount = await _fileCas.ImportAsync(exportPath, CancellationToken.None); + var importCount = await _fileCas.ImportAsync(exportPath, TestContext.Current.CancellationToken); importCount.Should().Be(1); - var imported = await _fileCas.TryGetAsync(casHash, CancellationToken.None); + var imported = await _fileCas.TryGetAsync(casHash, TestContext.Current.CancellationToken); imported.Should().NotBeNull(); imported!.RelativePath.Should().EndWith("content.bin"); // TTL eviction _timeProvider.Advance(TimeSpan.FromHours(2)); - await _layerCache.EvictExpiredAsync(CancellationToken.None); - (await _layerCache.TryGetAsync(layerDigest, CancellationToken.None)).Should().BeNull(); + await _layerCache.EvictExpiredAsync(TestContext.Current.CancellationToken); + (await _layerCache.TryGetAsync(layerDigest, TestContext.Current.CancellationToken)).Should().BeNull(); // Compaction removes CAS entry once over threshold. // Force compaction by writing a large entry. using var largeStream = CreateStream(new string('x', 400_000)); var largeHash = "sha256:" + new string('e', 64); - await _fileCas.PutAsync(new FileCasPutRequest(largeHash, largeStream), CancellationToken.None); + await _fileCas.PutAsync(new FileCasPutRequest(largeHash, largeStream), TestContext.Current.CancellationToken); _timeProvider.Advance(TimeSpan.FromMinutes(1)); - await _fileCas.CompactAsync(CancellationToken.None); - (await _fileCas.TryGetAsync(casHash, CancellationToken.None)).Should().BeNull(); + await _fileCas.CompactAsync(TestContext.Current.CancellationToken); + (await _fileCas.TryGetAsync(casHash, TestContext.Current.CancellationToken)).Should().BeNull(); } public ValueTask InitializeAsync() => ValueTask.CompletedTask; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BenchmarkIntegrationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BenchmarkIntegrationTests.cs index b17df3a3b..5b765361a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BenchmarkIntegrationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BenchmarkIntegrationTests.cs @@ -20,7 +20,7 @@ public class BenchmarkIntegrationTests var snapshot = await extractor.ExtractAsync(new CallGraphExtractionRequest( ScanId: $"bench-{caseName}", Language: "node", - TargetPath: caseDir), CancellationToken.None); + TargetPath: caseDir), TestContext.Current.CancellationToken); var analyzer = new ReachabilityAnalyzer(); var result = analyzer.Analyze(snapshot); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryCallGraphExtractorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryCallGraphExtractorTests.cs index 942acb865..e2098684b 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryCallGraphExtractorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryCallGraphExtractorTests.cs @@ -71,7 +71,7 @@ public class BinaryCallGraphExtractorTests // Act & Assert await Assert.ThrowsAsync(async () => - await reader.ReadAsync("/nonexistent/binary", CancellationToken.None)); + await reader.ReadAsync("/nonexistent/binary", TestContext.Current.CancellationToken)); } [Trait("Category", TestCategories.Unit)] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryTextSectionReaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryTextSectionReaderTests.cs index 948aeaf6f..1dfa9946f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryTextSectionReaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/BinaryTextSectionReaderTests.cs @@ -27,7 +27,7 @@ public class BinaryTextSectionReaderTests var path = WriteTempFile(data); try { - var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.Elf, CancellationToken.None); + var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.Elf, TestContext.Current.CancellationToken); Assert.NotNull(section); Assert.Equal(".text", section!.SectionName); Assert.Equal(DisassemblyArchitecture.X64, section.Architecture); @@ -50,7 +50,7 @@ public class BinaryTextSectionReaderTests var path = WriteTempFile(data); try { - var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.Pe, CancellationToken.None); + var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.Pe, TestContext.Current.CancellationToken); Assert.NotNull(section); Assert.Equal(".text", section!.SectionName); Assert.Equal(DisassemblyArchitecture.X64, section.Architecture); @@ -73,7 +73,7 @@ public class BinaryTextSectionReaderTests var path = WriteTempFile(data); try { - var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.MachO, CancellationToken.None); + var section = await DisassemblyTextSectionReader.TryReadAsync(path, BinaryFormat.MachO, TestContext.Current.CancellationToken); Assert.NotNull(section); Assert.Equal("__text", section!.SectionName); Assert.Equal(DisassemblyArchitecture.Arm64, section.Architecture); @@ -98,7 +98,7 @@ public class BinaryTextSectionReaderTests try { var scanner = new BinaryStringLiteralScanner(); - var candidates = await scanner.ExtractLibraryCandidatesAsync(path, BinaryFormat.Elf, CancellationToken.None); + var candidates = await scanner.ExtractLibraryCandidatesAsync(path, BinaryFormat.Elf, TestContext.Current.CancellationToken); Assert.Contains("libfoo.so", candidates); Assert.Contains("libbar.so.1", candidates); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/DotNetCallGraphExtractorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/DotNetCallGraphExtractorTests.cs index 6fa9462ea..91f75573e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/DotNetCallGraphExtractorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/DotNetCallGraphExtractorTests.cs @@ -1,4 +1,4 @@ -using StellaOps.Scanner.CallGraph; +using StellaOps.Scanner.CallGraph; using StellaOps.Scanner.CallGraph.DotNet; using Xunit; @@ -15,7 +15,7 @@ public class DotNetCallGraphExtractorTests await using var temp = await TempDirectory.CreateAsync(); var csprojPath = Path.Combine(temp.Path, "App.csproj"); - await File.WriteAllTextAsync(csprojPath, cancellationToken: CancellationToken.None, contents: """ + await File.WriteAllTextAsync(csprojPath, cancellationToken: TestContext.Current.CancellationToken, contents: """ net10.0 @@ -26,7 +26,7 @@ public class DotNetCallGraphExtractorTests """); - await File.WriteAllTextAsync(Path.Combine(temp.Path, "Program.cs"), cancellationToken: CancellationToken.None, contents: """ + await File.WriteAllTextAsync(Path.Combine(temp.Path, "Program.cs"), cancellationToken: TestContext.Current.CancellationToken, contents: """ using System; public sealed class HttpGetAttribute : Attribute { } @@ -60,7 +60,7 @@ public class DotNetCallGraphExtractorTests var snapshot = await extractor.ExtractAsync(new CallGraphExtractionRequest( ScanId: "scan-001", Language: "dotnet", - TargetPath: csprojPath), CancellationToken.None); + TargetPath: csprojPath), TestContext.Current.CancellationToken); Assert.Equal("scan-001", snapshot.ScanId); Assert.Equal("dotnet", snapshot.Language); @@ -81,7 +81,7 @@ public class DotNetCallGraphExtractorTests await using var temp = await TempDirectory.CreateAsync(); var csprojPath = Path.Combine(temp.Path, "App.csproj"); - await File.WriteAllTextAsync(csprojPath, cancellationToken: CancellationToken.None, contents: """ + await File.WriteAllTextAsync(csprojPath, cancellationToken: TestContext.Current.CancellationToken, contents: """ net10.0 @@ -92,7 +92,7 @@ public class DotNetCallGraphExtractorTests """); - await File.WriteAllTextAsync(Path.Combine(temp.Path, "Program.cs"), cancellationToken: CancellationToken.None, contents: """ + await File.WriteAllTextAsync(Path.Combine(temp.Path, "Program.cs"), cancellationToken: TestContext.Current.CancellationToken, contents: """ public static class Program { public static void Main() @@ -114,8 +114,8 @@ public class DotNetCallGraphExtractorTests var extractor = new DotNetCallGraphExtractor(); var request = new CallGraphExtractionRequest("scan-001", "dotnet", csprojPath); - var first = await extractor.ExtractAsync(request, CancellationToken.None); - var second = await extractor.ExtractAsync(request, CancellationToken.None); + var first = await extractor.ExtractAsync(request, TestContext.Current.CancellationToken); + var second = await extractor.ExtractAsync(request, TestContext.Current.CancellationToken); Assert.Equal(first.GraphDigest, second.GraphDigest); Assert.Equal(first.Nodes.Select(n => n.NodeId), second.Nodes.Select(n => n.NodeId)); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaCallGraphExtractorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaCallGraphExtractorTests.cs index 3942e2f07..ad2bf8ec9 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaCallGraphExtractorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaCallGraphExtractorTests.cs @@ -1,4 +1,4 @@ -// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- // JavaCallGraphExtractorTests.cs // Sprint: SPRINT_3610_0001_0001_java_callgraph (JCG-018) // Description: Unit tests for the Java bytecode call graph extractor. @@ -452,7 +452,7 @@ public class JavaCallGraphExtractorTests TargetPath: "/nonexistent/path/to/jar"); await Assert.ThrowsAsync( - () => _extractor.ExtractAsync(request, CancellationToken.None)); + () => _extractor.ExtractAsync(request, TestContext.Current.CancellationToken)); } [Trait("Category", TestCategories.Unit)] @@ -467,7 +467,7 @@ public class JavaCallGraphExtractorTests TargetPath: temp.Path); await Assert.ThrowsAsync( - () => _extractor.ExtractAsync(request, CancellationToken.None)); + () => _extractor.ExtractAsync(request, TestContext.Current.CancellationToken)); } [Trait("Category", TestCategories.Unit)] @@ -481,7 +481,7 @@ public class JavaCallGraphExtractorTests Language: "java", TargetPath: temp.Path); - var snapshot = await _extractor.ExtractAsync(request, CancellationToken.None); + var snapshot = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); Assert.Equal("scan-001", snapshot.ScanId); Assert.Equal("java", snapshot.Language); @@ -517,8 +517,8 @@ public class JavaCallGraphExtractorTests TargetPath: temp.Path); // Act: Extract twice with same input - var snapshot1 = await _extractor.ExtractAsync(request, CancellationToken.None); - var snapshot2 = await _extractor.ExtractAsync(request, CancellationToken.None); + var snapshot1 = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); + var snapshot2 = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); // Assert: Same digest Assert.Equal(snapshot1.GraphDigest, snapshot2.GraphDigest); @@ -542,8 +542,8 @@ public class JavaCallGraphExtractorTests TargetPath: temp.Path); // Act: Extract with different scan IDs - var snapshot1 = await _extractor.ExtractAsync(request1, CancellationToken.None); - var snapshot2 = await _extractor.ExtractAsync(request2, CancellationToken.None); + var snapshot1 = await _extractor.ExtractAsync(request1, TestContext.Current.CancellationToken); + var snapshot2 = await _extractor.ExtractAsync(request2, TestContext.Current.CancellationToken); // Assert: Same graph content (nodes, edges, digests match) Assert.Equal(snapshot1.Nodes.Length, snapshot2.Nodes.Length); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaScriptCallGraphExtractorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaScriptCallGraphExtractorTests.cs index 10e54f592..faed03047 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaScriptCallGraphExtractorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/JavaScriptCallGraphExtractorTests.cs @@ -446,7 +446,7 @@ public sealed class JavaScriptCallGraphExtractorTests : IAsyncLifetime TargetPath: temp.Path); await Assert.ThrowsAsync( - () => _extractor.ExtractAsync(request, CancellationToken.None)); + () => _extractor.ExtractAsync(request, TestContext.Current.CancellationToken)); } [Fact(Skip = "Requires isolated test environment - permission issues on Windows")] @@ -461,14 +461,14 @@ public sealed class JavaScriptCallGraphExtractorTests : IAsyncLifetime "version": "1.0.0" } """; - await File.WriteAllTextAsync(Path.Combine(temp.Path, "package.json"), packageJson, CancellationToken.None); + await File.WriteAllTextAsync(Path.Combine(temp.Path, "package.json"), packageJson, TestContext.Current.CancellationToken); var request = new CallGraphExtractionRequest( ScanId: "scan-001", Language: "javascript", TargetPath: temp.Path); - var snapshot = await _extractor.ExtractAsync(request, CancellationToken.None); + var snapshot = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); Assert.Equal("scan-001", snapshot.ScanId); Assert.Equal("javascript", snapshot.Language); @@ -490,15 +490,15 @@ public sealed class JavaScriptCallGraphExtractorTests : IAsyncLifetime "version": "1.0.0" } """; - await File.WriteAllTextAsync(Path.Combine(temp.Path, "package.json"), packageJson, CancellationToken.None); + await File.WriteAllTextAsync(Path.Combine(temp.Path, "package.json"), packageJson, TestContext.Current.CancellationToken); var request = new CallGraphExtractionRequest( ScanId: "scan-001", Language: "javascript", TargetPath: temp.Path); - var snapshot1 = await _extractor.ExtractAsync(request, CancellationToken.None); - var snapshot2 = await _extractor.ExtractAsync(request, CancellationToken.None); + var snapshot1 = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); + var snapshot2 = await _extractor.ExtractAsync(request, TestContext.Current.CancellationToken); Assert.Equal(snapshot1.GraphDigest, snapshot2.GraphDigest); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/ValkeyCallGraphCacheServiceTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/ValkeyCallGraphCacheServiceTests.cs index ff685432b..cedf52e2d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/ValkeyCallGraphCacheServiceTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.CallGraph.Tests/ValkeyCallGraphCacheServiceTests.cs @@ -92,8 +92,8 @@ public class ValkeyCallGraphCacheServiceTests : IAsyncLifetime EntrypointIds: [nodeId], SinkIds: []); - await _cache.SetCallGraphAsync(snapshot, cancellationToken: CancellationToken.None); - var loaded = await _cache.TryGetCallGraphAsync("scan-cache-1", "dotnet", cancellationToken: CancellationToken.None); + await _cache.SetCallGraphAsync(snapshot, cancellationToken: TestContext.Current.CancellationToken); + var loaded = await _cache.TryGetCallGraphAsync("scan-cache-1", "dotnet", cancellationToken: TestContext.Current.CancellationToken); Assert.NotNull(loaded); Assert.Equal(snapshot.ScanId, loaded!.ScanId); @@ -115,8 +115,8 @@ public class ValkeyCallGraphCacheServiceTests : IAsyncLifetime Paths: [], ResultDigest: "sha256:r"); - await _cache.SetReachabilityResultAsync(result, cancellationToken: CancellationToken.None); - var loaded = await _cache.TryGetReachabilityResultAsync("scan-cache-2", "dotnet", cancellationToken: CancellationToken.None); + await _cache.SetReachabilityResultAsync(result, cancellationToken: TestContext.Current.CancellationToken); + var loaded = await _cache.TryGetReachabilityResultAsync("scan-cache-2", "dotnet", cancellationToken: TestContext.Current.CancellationToken); Assert.NotNull(loaded); Assert.Equal(result.ResultDigest, loaded!.ResultDigest); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Core.Tests/Fidelity/FidelityAwareAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Core.Tests/Fidelity/FidelityAwareAnalyzerTests.cs index 46315ad64..f797278dd 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Core.Tests/Fidelity/FidelityAwareAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Core.Tests/Fidelity/FidelityAwareAnalyzerTests.cs @@ -42,7 +42,7 @@ public class FidelityAwareAnalyzerTests { var request = CreateAnalysisRequest(); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Quick, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Quick, TestContext.Current.CancellationToken); result.FidelityLevel.Should().Be(FidelityLevel.Quick); result.CallGraph.Should().BeNull(); @@ -71,7 +71,7 @@ public class FidelityAwareAnalyzerTests HasPathToVulnerable = true }); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Standard, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Standard, TestContext.Current.CancellationToken); result.FidelityLevel.Should().Be(FidelityLevel.Standard); result.CallGraph.Should().NotBeNull(); @@ -110,7 +110,7 @@ public class FidelityAwareAnalyzerTests _binaryMapper.Setup(b => b.MapAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new BinaryMappingResult { HasMapping = true }); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Deep, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Deep, TestContext.Current.CancellationToken); result.FidelityLevel.Should().Be(FidelityLevel.Deep); result.RuntimeCorrelation.Should().NotBeNull(); @@ -136,7 +136,7 @@ public class FidelityAwareAnalyzerTests { var request = CreateAnalysisRequest(); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Quick, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Quick, TestContext.Current.CancellationToken); // Quick base confidence is 0.5, plus 0.1 for exact match result.Confidence.Should().Be(0.6m); @@ -157,7 +157,7 @@ public class FidelityAwareAnalyzerTests HasPathToVulnerable = false }); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Standard, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Standard, TestContext.Current.CancellationToken); // Standard base confidence is 0.75, plus 0.15 for complete call graph result.Confidence.Should().Be(0.9m); @@ -192,7 +192,7 @@ public class FidelityAwareAnalyzerTests HasPathToVulnerable = true }); - var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, CancellationToken.None); + var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, TestContext.Current.CancellationToken); result.Success.Should().BeTrue(); result.PreviousLevel.Should().Be(FidelityLevel.Quick); @@ -213,7 +213,7 @@ public class FidelityAwareAnalyzerTests _repository.Setup(r => r.GetAnalysisAsync(findingId, It.IsAny())) .ReturnsAsync((FidelityAnalysisResult?)null); - var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, CancellationToken.None); + var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, TestContext.Current.CancellationToken); result.Success.Should().BeFalse(); result.Error.Should().Be("Finding not found"); @@ -237,7 +237,7 @@ public class FidelityAwareAnalyzerTests _repository.Setup(r => r.GetAnalysisAsync(findingId, It.IsAny())) .ReturnsAsync(existingResult); - var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, CancellationToken.None); + var result = await _analyzer.UpgradeFidelityAsync(findingId, FidelityLevel.Standard, TestContext.Current.CancellationToken); result.Success.Should().BeTrue(); result.PreviousLevel.Should().Be(FidelityLevel.Standard); @@ -270,7 +270,7 @@ public class FidelityAwareAnalyzerTests _binaryMapper.Setup(b => b.MapAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new BinaryMappingResult { HasMapping = false }); - var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Deep, CancellationToken.None); + var result = await _analyzer.AnalyzeAsync(request, FidelityLevel.Deep, TestContext.Current.CancellationToken); result.Confidence.Should().Be(0.95m); result.IsReachable.Should().BeTrue(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Binary/FingerprintIndexTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Binary/FingerprintIndexTests.cs index 0945afd8f..a16c9d702 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Binary/FingerprintIndexTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Binary/FingerprintIndexTests.cs @@ -227,7 +227,7 @@ public sealed class FingerprintIndexTests var index = new InMemoryFingerprintIndex(); // Assert initial - Assert.Equal(0, index.Count); + Assert.Empty(index); } [Fact] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/EntryTraceAnalyzerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/EntryTraceAnalyzerTests.cs index 140db9788..3ab67e415 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/EntryTraceAnalyzerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/EntryTraceAnalyzerTests.cs @@ -51,7 +51,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/local/bin/puma", terminal.Path); - var bundleNode = Assert.Single(result.Nodes.Where(n => n.DisplayName == "bundle")); + var bundleNode = Assert.Single(result.Nodes, n => n.DisplayName == "bundle"); Assert.Equal("language-launcher", bundleNode.Metadata?["wrapper.category"]); Assert.Equal("bundle exec", bundleNode.Metadata?["wrapper.name"]); Assert.Contains(result.Edges, edge => edge.Relationship == "wrapper" && edge.FromNodeId == bundleNode.Id); @@ -87,7 +87,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/local/sbin/php-fpm", terminal.Path); - var wrapperNode = Assert.Single(result.Nodes.Where(n => n.DisplayName.Contains("docker-php-entrypoint", StringComparison.OrdinalIgnoreCase))); + var wrapperNode = Assert.Single(result.Nodes, n => n.DisplayName.Contains("docker-php-entrypoint", StringComparison.OrdinalIgnoreCase)); Assert.Equal("language-launcher", wrapperNode.Metadata?["wrapper.category"]); Assert.Equal("docker-php-entrypoint", wrapperNode.Metadata?["wrapper.name"]); } @@ -135,7 +135,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/node", terminal.Path); - var npmNode = Assert.Single(result.Nodes.Where(n => n.DisplayName.Contains("npm", StringComparison.OrdinalIgnoreCase))); + var npmNode = Assert.Single(result.Nodes, n => n.DisplayName.Contains("npm", StringComparison.OrdinalIgnoreCase)); Assert.Equal("language-launcher", npmNode.Metadata?["wrapper.category"]); Assert.Equal("npm", npmNode.Metadata?["wrapper.name"]); } @@ -175,7 +175,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/node", terminal.Path); - var yarnNode = Assert.Single(result.Nodes.Where(n => n.DisplayName.Contains("yarn", StringComparison.OrdinalIgnoreCase))); + var yarnNode = Assert.Single(result.Nodes, n => n.DisplayName.Contains("yarn", StringComparison.OrdinalIgnoreCase)); Assert.Equal("language-launcher", yarnNode.Metadata?["wrapper.category"]); Assert.Equal("yarn node", yarnNode.Metadata?["wrapper.name"]); } @@ -215,7 +215,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/python", terminal.Path); - var pipenvNode = Assert.Single(result.Nodes.Where(n => n.DisplayName.Contains("pipenv", StringComparison.OrdinalIgnoreCase))); + var pipenvNode = Assert.Single(result.Nodes, n => n.DisplayName.Contains("pipenv", StringComparison.OrdinalIgnoreCase)); Assert.Equal("language-launcher", pipenvNode.Metadata?["wrapper.category"]); Assert.Equal("pipenv run", pipenvNode.Metadata?["wrapper.name"]); } @@ -255,7 +255,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/python", terminal.Path); - var poetryNode = Assert.Single(result.Nodes.Where(n => n.DisplayName.Contains("poetry", StringComparison.OrdinalIgnoreCase))); + var poetryNode = Assert.Single(result.Nodes, n => n.DisplayName.Contains("poetry", StringComparison.OrdinalIgnoreCase)); Assert.Equal("language-launcher", poetryNode.Metadata?["wrapper.category"]); Assert.Equal("poetry run", poetryNode.Metadata?["wrapper.name"]); } @@ -702,7 +702,7 @@ public sealed class EntryTraceAnalyzerTests Assert.Equal("app", terminal.User); Assert.Contains("/srv/app.py", terminal.Arguments); - var edge = Assert.Single(result.Edges.Where(e => e.Relationship == "wrapper")); + var edge = Assert.Single(result.Edges, e => e.Relationship == "wrapper"); Assert.Equal("true", edge.Metadata?["guarded"]); Assert.Equal("user", edge.Metadata?["state-change"]); Assert.Equal("app", edge.Metadata?["user"]); @@ -739,7 +739,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/python", terminal.Path); - var edge = Assert.Single(result.Edges.Where(e => e.Relationship == "wrapper")); + var edge = Assert.Single(result.Edges, e => e.Relationship == "wrapper"); Assert.Equal("env", edge.Metadata?["state-change"]); Assert.Equal("true", edge.Metadata?["guarded"]); } @@ -804,7 +804,7 @@ public sealed class EntryTraceAnalyzerTests var terminal = Assert.Single(result.Terminals); Assert.Equal("/usr/bin/python", terminal.Path); - var edge = Assert.Single(result.Edges.Where(e => e.Relationship == "wrapper")); + var edge = Assert.Single(result.Edges, e => e.Relationship == "wrapper"); Assert.Equal("true", edge.Metadata?["guarded"]); Assert.Equal("init", edge.Metadata?["shim"]); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Mesh/MeshEntrypointGraphTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Mesh/MeshEntrypointGraphTests.cs index 23b9230d9..684a2c7b6 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Mesh/MeshEntrypointGraphTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Mesh/MeshEntrypointGraphTests.cs @@ -201,6 +201,7 @@ public sealed class MeshEntrypointGraphTests // Assert Assert.NotEmpty(paths); + Assert.NotNull(paths[0]); Assert.True(paths[0].IsIngressExposed); Assert.NotNull(paths[0].IngressPath); Assert.Equal("api.example.com", paths[0].IngressPath.Host); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticAdapterTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticAdapterTests.cs index 1dd50674e..cf7bce6e7 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticAdapterTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticAdapterTests.cs @@ -30,7 +30,7 @@ public sealed class SemanticAdapterTests var adapter = new PythonSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -51,7 +51,7 @@ public sealed class SemanticAdapterTests var adapter = new PythonSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -77,7 +77,7 @@ public sealed class SemanticAdapterTests var adapter = new PythonSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.Worker, result.Intent); @@ -96,7 +96,7 @@ public sealed class SemanticAdapterTests var adapter = new PythonSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.CliTool, result.Intent); @@ -115,7 +115,7 @@ public sealed class SemanticAdapterTests var adapter = new PythonSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.Serverless, result.Intent); @@ -139,7 +139,7 @@ public sealed class SemanticAdapterTests var adapter = new JavaSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -159,7 +159,7 @@ public sealed class SemanticAdapterTests var adapter = new JavaSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -178,7 +178,7 @@ public sealed class SemanticAdapterTests var adapter = new JavaSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.StreamProcessor, result.Intent); @@ -202,7 +202,7 @@ public sealed class SemanticAdapterTests var adapter = new NodeSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -222,7 +222,7 @@ public sealed class SemanticAdapterTests var adapter = new NodeSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -242,7 +242,7 @@ public sealed class SemanticAdapterTests var adapter = new NodeSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.CliTool, result.Intent); @@ -266,7 +266,7 @@ public sealed class SemanticAdapterTests var adapter = new NodeSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.Serverless, result.Intent); @@ -289,7 +289,7 @@ public sealed class SemanticAdapterTests var adapter = new DotNetSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -310,7 +310,7 @@ public sealed class SemanticAdapterTests var adapter = new DotNetSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.Worker, result.Intent); @@ -329,7 +329,7 @@ public sealed class SemanticAdapterTests var adapter = new DotNetSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.CliTool, result.Intent); @@ -352,7 +352,7 @@ public sealed class SemanticAdapterTests var adapter = new GoSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.WebServer, result.Intent); @@ -372,7 +372,7 @@ public sealed class SemanticAdapterTests var adapter = new GoSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.CliTool, result.Intent); @@ -390,7 +390,7 @@ public sealed class SemanticAdapterTests var adapter = new GoSemanticAdapter(); // Act - var result = await adapter.AnalyzeAsync(context, CancellationToken.None); + var result = await adapter.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert Assert.Equal(ApplicationIntent.RpcServer, result.Intent); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticDeterminismTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticDeterminismTests.cs index faa11507f..0708a2064 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticDeterminismTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.EntryTrace.Tests/Semantic/SemanticDeterminismTests.cs @@ -34,7 +34,7 @@ public sealed class SemanticDeterminismTests var results = new List(); for (var i = 0; i < 3; i++) { - var result = await _orchestrator.AnalyzeAsync(context, CancellationToken.None); + var result = await _orchestrator.AnalyzeAsync(context, TestContext.Current.CancellationToken); results.Add(result); } @@ -55,8 +55,8 @@ public sealed class SemanticDeterminismTests var context2 = CreateContext(fs2, "python"); // Act - var result1 = await _orchestrator.AnalyzeAsync(context1, CancellationToken.None); - var result2 = await _orchestrator.AnalyzeAsync(context2, CancellationToken.None); + var result1 = await _orchestrator.AnalyzeAsync(context1, TestContext.Current.CancellationToken); + var result2 = await _orchestrator.AnalyzeAsync(context2, TestContext.Current.CancellationToken); // Assert Assert.Equal(result1.Entrypoint?.Intent, result2.Entrypoint?.Intent); @@ -71,7 +71,7 @@ public sealed class SemanticDeterminismTests var context = CreateContext(fs, "python"); // Act - var result = await _orchestrator.AnalyzeAsync(context, CancellationToken.None); + var result = await _orchestrator.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - capabilities should be ordered consistently (by flag value) if (result.Entrypoint is not null) @@ -90,7 +90,7 @@ public sealed class SemanticDeterminismTests var context = CreateContext(fs, "python"); // Act - var result = await _orchestrator.AnalyzeAsync(context, CancellationToken.None); + var result = await _orchestrator.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - attack surface should be ordered by threat type if (result.Entrypoint is not null && !result.Entrypoint.AttackSurface.IsDefaultOrEmpty) @@ -109,7 +109,7 @@ public sealed class SemanticDeterminismTests var context = CreateContext(fs, "python"); // Act - var result = await _orchestrator.AnalyzeAsync(context, CancellationToken.None); + var result = await _orchestrator.AnalyzeAsync(context, TestContext.Current.CancellationToken); // Assert - data boundaries should be ordered consistently if (result.Entrypoint is not null && !result.Entrypoint.DataBoundaries.IsDefaultOrEmpty) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.MaterialChanges.Tests/MaterialChangesOrchestratorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.MaterialChanges.Tests/MaterialChangesOrchestratorTests.cs index 2aec3f77b..9946ad1eb 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.MaterialChanges.Tests/MaterialChangesOrchestratorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.MaterialChanges.Tests/MaterialChangesOrchestratorTests.cs @@ -196,7 +196,7 @@ public sealed class MaterialChangesOrchestratorTests // Act var report = await _orchestrator.GenerateReportAsync("base", "target"); - var cached = await _cache.GetAsync(report.ReportId, CancellationToken.None); + var cached = await _cache.GetAsync(report.ReportId, TestContext.Current.CancellationToken); // Assert Assert.NotNull(cached); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Reachability.Tests/BinaryReachabilityLifterTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Reachability.Tests/BinaryReachabilityLifterTests.cs index 7c34fc872..e9cd1a6d4 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Reachability.Tests/BinaryReachabilityLifterTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Reachability.Tests/BinaryReachabilityLifterTests.cs @@ -1,4 +1,4 @@ -using System.Buffers.Binary; +using System.Buffers.Binary; using System.Security.Cryptography; using System.Text; using System.Threading; @@ -32,7 +32,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var graph = builder.ToUnionGraph(SymbolId.Lang.Binary); var node = Assert.Single(graph.Nodes); @@ -69,7 +69,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var graph = builder.ToUnionGraph(SymbolId.Lang.Binary); // Should have binary node + entry point node @@ -106,7 +106,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var graph = builder.ToUnionGraph(SymbolId.Lang.Binary); var node = Assert.Single(graph.Nodes); @@ -133,7 +133,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var graph = builder.ToUnionGraph(SymbolId.Lang.Binary); // Should only have the binary node, no entry point @@ -159,7 +159,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var graph = builder.ToUnionGraph(SymbolId.Lang.Binary); var binaryNode = Assert.Single(graph.Nodes, n => n.Kind == "binary"); @@ -193,7 +193,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var union = builder.ToUnionGraph(SymbolId.Lang.Binary); var rich = RichGraphBuilder.FromUnion(union, "test-analyzer", "1.0.0"); @@ -222,7 +222,7 @@ public class BinaryReachabilityLifterTests var builder = new ReachabilityGraphBuilder(); var lifter = new BinaryReachabilityLifter(); - await lifter.LiftAsync(context, builder, CancellationToken.None); + await lifter.LiftAsync(context, builder, TestContext.Current.CancellationToken); var union = builder.ToUnionGraph(SymbolId.Lang.Binary); var rich = RichGraphBuilder.FromUnion(union, "test-analyzer", "1.0.0"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Attestation/AttestorClientTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Attestation/AttestorClientTests.cs index 1d6b546ea..8f75eca2d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Attestation/AttestorClientTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Attestation/AttestorClientTests.cs @@ -23,7 +23,7 @@ public sealed class AttestorClientTests var document = BuildDescriptorDocument(); var attestorUri = new Uri("https://attestor.example.com/api/v1/provenance"); - await client.SendPlaceholderAsync(attestorUri, document, CancellationToken.None); + await client.SendPlaceholderAsync(attestorUri, document, TestContext.Current.CancellationToken); Assert.NotNull(handler.CapturedRequest); Assert.Equal(HttpMethod.Post, handler.CapturedRequest!.Method); @@ -49,7 +49,7 @@ public sealed class AttestorClientTests var document = BuildDescriptorDocument(); var attestorUri = new Uri("https://attestor.example.com/api/v1/provenance"); - await Assert.ThrowsAsync(() => client.SendPlaceholderAsync(attestorUri, document, CancellationToken.None)); + await Assert.ThrowsAsync(() => client.SendPlaceholderAsync(attestorUri, document, TestContext.Current.CancellationToken)); } private static DescriptorDocument BuildDescriptorDocument() diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Cas/LocalCasClientTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Cas/LocalCasClientTests.cs index 623c74421..a831d65ca 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Cas/LocalCasClientTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Cas/LocalCasClientTests.cs @@ -21,7 +21,7 @@ public sealed class LocalCasClientTests Algorithm = "sha256" }, CryptoHashFactory.CreateDefault()); - var result = await client.VerifyWriteAsync(CancellationToken.None); + var result = await client.VerifyWriteAsync(TestContext.Current.CancellationToken); Assert.Equal("sha256", result.Algorithm); Assert.True(File.Exists(result.Path)); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGeneratorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGeneratorTests.cs index 63f4a03ea..0a67937db 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGeneratorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGeneratorTests.cs @@ -44,7 +44,7 @@ public sealed class DescriptorGeneratorTests AttestorUri = "https://attestor.local/api/v1/provenance" }.Validate(); - var document = await generator.CreateAsync(request, CancellationToken.None); + var document = await generator.CreateAsync(request, TestContext.Current.CancellationToken); Assert.Equal(DescriptorGenerator.Schema, document.Schema); Assert.Equal(fakeTime.GetUtcNow(), document.GeneratedAt); @@ -93,8 +93,8 @@ public sealed class DescriptorGeneratorTests AttestorUri = "https://attestor.local/api/v1/provenance" }.Validate(); - var first = await generator.CreateAsync(request, CancellationToken.None); - var second = await generator.CreateAsync(request, CancellationToken.None); + var first = await generator.CreateAsync(request, TestContext.Current.CancellationToken); + var second = await generator.CreateAsync(request, TestContext.Current.CancellationToken); Assert.Equal(first.Provenance.Nonce, second.Provenance.Nonce); Assert.Equal(first.Provenance.ExpectedDsseSha256, second.Provenance.ExpectedDsseSha256); @@ -127,8 +127,8 @@ public sealed class DescriptorGeneratorTests }; variant = variant.Validate(); - var baselineDocument = await generator.CreateAsync(baseline, CancellationToken.None); - var variantDocument = await generator.CreateAsync(variant, CancellationToken.None); + var baselineDocument = await generator.CreateAsync(baseline, TestContext.Current.CancellationToken); + var variantDocument = await generator.CreateAsync(variant, TestContext.Current.CancellationToken); Assert.NotEqual(baselineDocument.Provenance.Nonce, variantDocument.Provenance.Nonce); Assert.NotEqual(baselineDocument.Provenance.ExpectedDsseSha256, variantDocument.Provenance.ExpectedDsseSha256); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGoldenTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGoldenTests.cs index ee2784f72..fac3ff567 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGoldenTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Descriptor/DescriptorGoldenTests.cs @@ -50,7 +50,7 @@ public sealed class DescriptorGoldenTests var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 18, 12, 0, 0, TimeSpan.Zero)); var generator = CreateGenerator(fakeTime); - var document = await generator.CreateAsync(request, CancellationToken.None); + var document = await generator.CreateAsync(request, TestContext.Current.CancellationToken); var actualJson = JsonSerializer.Serialize(document, SerializerOptions); var normalizedJson = NormalizeDescriptorJson(actualJson, Path.GetFileName(sbomPath)); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Manifest/BuildxPluginManifestLoaderTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Manifest/BuildxPluginManifestLoaderTests.cs index 11528e883..ebc273a75 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Manifest/BuildxPluginManifestLoaderTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Manifest/BuildxPluginManifestLoaderTests.cs @@ -24,7 +24,7 @@ public sealed class BuildxPluginManifestLoaderTests await File.WriteAllTextAsync(manifestPath, BuildSampleManifestJson("stellaops.sbom-indexer")); var loader = new BuildxPluginManifestLoader(temp.Path); - var manifests = await loader.LoadAsync(CancellationToken.None); + var manifests = await loader.LoadAsync(TestContext.Current.CancellationToken); var manifest = Assert.Single(manifests); Assert.Equal("stellaops.sbom-indexer", manifest.Id); @@ -39,7 +39,7 @@ public sealed class BuildxPluginManifestLoaderTests await using var temp = new TempDirectory(); var loader = new BuildxPluginManifestLoader(temp.Path); - await Assert.ThrowsAsync(() => loader.LoadDefaultAsync(CancellationToken.None)); + await Assert.ThrowsAsync(() => loader.LoadDefaultAsync(TestContext.Current.CancellationToken)); } [Fact] @@ -51,7 +51,7 @@ public sealed class BuildxPluginManifestLoaderTests var loader = new BuildxPluginManifestLoader(temp.Path); - await Assert.ThrowsAsync(() => loader.LoadAsync(CancellationToken.None)); + await Assert.ThrowsAsync(() => loader.LoadAsync(TestContext.Current.CancellationToken)); } private static string BuildSampleManifestJson(string id, bool requiresRestart = true) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Surface/SurfaceManifestWriterTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Surface/SurfaceManifestWriterTests.cs index a9b480f18..a75c83109 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Surface/SurfaceManifestWriterTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Sbomer.BuildXPlugin.Tests/Surface/SurfaceManifestWriterTests.cs @@ -44,7 +44,7 @@ public sealed class SurfaceManifestWriterTests ManifestOutputPath: manifestOutputPath); var writer = new SurfaceManifestWriter(TimeProvider.System, CryptoHashFactory.CreateDefault()); - var result = await writer.WriteAsync(options, CancellationToken.None); + var result = await writer.WriteAsync(options, TestContext.Current.CancellationToken); Assert.NotNull(result); Assert.NotNull(result!.Document.Source); @@ -90,7 +90,7 @@ public sealed class SurfaceManifestWriterTests ManifestOutputPath: null); var writer = new SurfaceManifestWriter(TimeProvider.System, CryptoHashFactory.CreateDefault()); - var result = await writer.WriteAsync(options, CancellationToken.None); + var result = await writer.WriteAsync(options, TestContext.Current.CancellationToken); Assert.Null(result); } } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.SchemaEvolution.Tests/ScannerSchemaEvolutionTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.SchemaEvolution.Tests/ScannerSchemaEvolutionTests.cs index b831b502f..e4d93a3f2 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.SchemaEvolution.Tests/ScannerSchemaEvolutionTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.SchemaEvolution.Tests/ScannerSchemaEvolutionTests.cs @@ -76,7 +76,7 @@ public class ScannerSchemaEvolutionTests : PostgresSchemaEvolutionTestBase return exists is true or 1 or (long)1; }, result => result, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert results.Should().AllSatisfy(r => r.IsCompatible.Should().BeTrue( @@ -106,7 +106,7 @@ public class ScannerSchemaEvolutionTests : PostgresSchemaEvolutionTestBase await cmd.ExecuteScalarAsync(); }, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert results.Should().AllSatisfy(r => r.IsCompatible.Should().BeTrue( @@ -132,7 +132,7 @@ public class ScannerSchemaEvolutionTests : PostgresSchemaEvolutionTestBase await cmd.ExecuteScalarAsync(); }, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert result.IsCompatible.Should().BeTrue( @@ -160,7 +160,7 @@ public class ScannerSchemaEvolutionTests : PostgresSchemaEvolutionTestBase await cmd.ExecuteScalarAsync(); }, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert result.IsCompatible.Should().BeTrue(); @@ -178,7 +178,7 @@ public class ScannerSchemaEvolutionTests : PostgresSchemaEvolutionTestBase // Act var results = await TestMigrationRollbacksAsync( migrationsToTest: 3, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert - relaxed assertion since migrations may not have down scripts results.Should().NotBeNull(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/DeltaVerdictAttestationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/DeltaVerdictAttestationTests.cs index 4fcc05e41..87cb14922 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/DeltaVerdictAttestationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/DeltaVerdictAttestationTests.cs @@ -64,7 +64,7 @@ public sealed class DeltaVerdictAttestationTests PayloadType = "application/vnd.stellaops.delta-verdict+json", SecretBase64 = Convert.ToBase64String("test-secret-key-32bytes!"u8.ToArray()), Algorithm = SigningAlgorithm.HmacSha256 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Assert - Signing signedDelta.Signature.Should().NotBeNull(); @@ -94,7 +94,7 @@ public sealed class DeltaVerdictAttestationTests PayloadType = "application/vnd.stellaops.delta-verdict+json", SecretBase64 = secret, Algorithm = SigningAlgorithm.HmacSha256 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Act - Verify var verifyResult = await signer.VerifyAsync(signedDelta, new VerificationOptions @@ -102,7 +102,7 @@ public sealed class DeltaVerdictAttestationTests KeyId = "verification-key", SecretBase64 = secret, Algorithm = SigningAlgorithm.HmacSha256 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Assert verifyResult.IsValid.Should().BeTrue(); @@ -127,7 +127,7 @@ public sealed class DeltaVerdictAttestationTests PayloadType = "application/vnd.stellaops.delta-verdict+json", SecretBase64 = Convert.ToBase64String("correct-secret-key-32bytes!"u8.ToArray()), Algorithm = SigningAlgorithm.HmacSha256 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Act - Verify with different key var verifyResult = await signer.VerifyAsync(signedDelta, new VerificationOptions @@ -135,7 +135,7 @@ public sealed class DeltaVerdictAttestationTests KeyId = "signing-key", SecretBase64 = Convert.ToBase64String("wrong-secret-key-32bytes!!"u8.ToArray()), Algorithm = SigningAlgorithm.HmacSha256 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); // Assert verifyResult.IsValid.Should().BeFalse(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/SmartDiffIntegrationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/SmartDiffIntegrationTests.cs index fd906e20c..25edd07ff 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/SmartDiffIntegrationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.SmartDiff.Tests/Integration/SmartDiffIntegrationTests.cs @@ -33,7 +33,7 @@ public sealed class SmartDiffIntegrationTests var current = CreateCurrentScan(); // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.Should().NotBeNull(); @@ -53,7 +53,7 @@ public sealed class SmartDiffIntegrationTests var current = CreateBaselineScan(); // Same as baseline // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.Added.Should().BeEmpty(); @@ -82,7 +82,7 @@ public sealed class SmartDiffIntegrationTests }); // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.Added.Should().ContainSingle(v => v.CveId == "CVE-2024-9999"); @@ -108,7 +108,7 @@ public sealed class SmartDiffIntegrationTests var current = CreateCurrentScan(); // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.Removed.Should().ContainSingle(v => v.CveId == "CVE-2024-8888"); @@ -144,7 +144,7 @@ public sealed class SmartDiffIntegrationTests }); // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.ReachabilityFlips.Should().ContainSingle(f => @@ -177,7 +177,7 @@ public sealed class SmartDiffIntegrationTests }); // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.VexChanges.Should().ContainSingle(v => @@ -197,8 +197,8 @@ public sealed class SmartDiffIntegrationTests var current = CreateCurrentScan(); // Act - run twice - var result1 = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); - var result2 = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); + var result1 = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); + var result2 = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); // Assert - outputs should be identical var json1 = JsonSerializer.Serialize(result1, JsonOptions); @@ -219,8 +219,8 @@ public sealed class SmartDiffIntegrationTests var current = CreateCurrentScan(); // Act - var diff = await diffEngine.ComputeDiffAsync(baseline, current, CancellationToken.None); - var sarif = await sarifGenerator.GenerateAsync(diff, CancellationToken.None); + var diff = await diffEngine.ComputeDiffAsync(baseline, current, TestContext.Current.CancellationToken); + var sarif = await sarifGenerator.GenerateAsync(diff, TestContext.Current.CancellationToken); // Assert sarif.Should().NotBeNull(); @@ -260,7 +260,7 @@ public sealed class SmartDiffIntegrationTests }; // Act - var result = await diffEngine.ComputeDiffAsync(baseline, current, options, CancellationToken.None); + var result = await diffEngine.ComputeDiffAsync(baseline, current, options, TestContext.Current.CancellationToken); // Assert result.MaterialChanges.Added.Should().NotContain(v => v.CveId == "CVE-2024-5555"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/BinaryEvidenceServiceTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/BinaryEvidenceServiceTests.cs index eecea5376..f9839a704 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/BinaryEvidenceServiceTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/BinaryEvidenceServiceTests.cs @@ -76,7 +76,7 @@ public sealed class BinaryEvidenceServiceTests : IAsyncLifetime Assert.Equal(first.Id, second.Id); - var matches = await _repository.GetByFileSha256Async("a1b2c3d4", CancellationToken.None); + var matches = await _repository.GetByFileSha256Async("a1b2c3d4", TestContext.Current.CancellationToken); Assert.NotNull(matches); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/EntryTraceResultStoreTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/EntryTraceResultStoreTests.cs index 4f7e83a86..015c8c214 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/EntryTraceResultStoreTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/EntryTraceResultStoreTests.cs @@ -30,7 +30,7 @@ public sealed class EntryTraceResultStoreTests await Assert.ThrowsAsync(async () => { EntryTraceResult? result = null; - await store.StoreAsync(result!, CancellationToken.None); + await store.StoreAsync(result!, TestContext.Current.CancellationToken); }); } @@ -41,7 +41,7 @@ public sealed class EntryTraceResultStoreTests await _fixture.TruncateAllTablesAsync(); var store = CreateStore(); - var result = await store.GetAsync("scan-missing", CancellationToken.None); + var result = await store.GetAsync("scan-missing", TestContext.Current.CancellationToken); Assert.Null(result); } @@ -101,9 +101,9 @@ public sealed class EntryTraceResultStoreTests var result = new EntryTraceResult(scanId, "sha256:image", generatedAt, graph, ndjson); - await store.StoreAsync(result, CancellationToken.None); + await store.StoreAsync(result, TestContext.Current.CancellationToken); - var stored = await store.GetAsync(scanId, CancellationToken.None); + var stored = await store.GetAsync(scanId, TestContext.Current.CancellationToken); Assert.NotNull(stored); Assert.Equal(result.ScanId, stored!.ScanId); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RubyPackageInventoryStoreTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RubyPackageInventoryStoreTests.cs index 5f6295f99..b341d13fc 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RubyPackageInventoryStoreTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RubyPackageInventoryStoreTests.cs @@ -29,7 +29,7 @@ public sealed class RubyPackageInventoryStoreTests await Assert.ThrowsAsync(async () => { RubyPackageInventory? inventory = null; - await store.StoreAsync(inventory!, CancellationToken.None); + await store.StoreAsync(inventory!, TestContext.Current.CancellationToken); }); } @@ -40,7 +40,7 @@ public sealed class RubyPackageInventoryStoreTests await _fixture.TruncateAllTablesAsync(); var store = CreateStore(); - var inventory = await store.GetAsync("scan-missing", CancellationToken.None); + var inventory = await store.GetAsync("scan-missing", TestContext.Current.CancellationToken); Assert.Null(inventory); } @@ -81,9 +81,9 @@ public sealed class RubyPackageInventoryStoreTests var inventory = new RubyPackageInventory(scanId, "sha256:image", generatedAt, packages); - await store.StoreAsync(inventory, CancellationToken.None); + await store.StoreAsync(inventory, TestContext.Current.CancellationToken); - var stored = await store.GetAsync(scanId, CancellationToken.None); + var stored = await store.GetAsync(scanId, TestContext.Current.CancellationToken); Assert.NotNull(stored); Assert.Equal(scanId, stored!.ScanId); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RustFsArtifactObjectStoreTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RustFsArtifactObjectStoreTests.cs index c780d17a1..b16a2419d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RustFsArtifactObjectStoreTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/RustFsArtifactObjectStoreTests.cs @@ -44,7 +44,7 @@ public sealed class RustFsArtifactObjectStoreTests var payload = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("rustfs artifact payload")); var descriptor = new ArtifactObjectDescriptor("scanner-artifacts", "scanner/layers/digest/file.bin", true, TimeSpan.FromHours(1)); - await store.PutAsync(descriptor, payload, CancellationToken.None); + await store.PutAsync(descriptor, payload, TestContext.Current.CancellationToken); Assert.True(payload.CanRead); Assert.Equal(0, payload.Position); @@ -86,7 +86,7 @@ public sealed class RustFsArtifactObjectStoreTests var store = new RustFsArtifactObjectStore(factory, options, NullLogger.Instance); var descriptor = new ArtifactObjectDescriptor("scanner-artifacts", "scanner/indexes/digest/index.bin", false); - var result = await store.GetAsync(descriptor, CancellationToken.None); + var result = await store.GetAsync(descriptor, TestContext.Current.CancellationToken); Assert.Null(result); var request = Assert.Single(handler.CapturedRequests); @@ -120,7 +120,7 @@ public sealed class RustFsArtifactObjectStoreTests var store = new RustFsArtifactObjectStore(factory, options, NullLogger.Instance); var descriptor = new ArtifactObjectDescriptor("scanner-artifacts", "scanner/attest/digest/attest.bin", false); - await store.DeleteAsync(descriptor, CancellationToken.None); + await store.DeleteAsync(descriptor, TestContext.Current.CancellationToken); var request = Assert.Single(handler.CapturedRequests); Assert.Equal(HttpMethod.Delete, request.Method); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/ScanMetricsRepositoryTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/ScanMetricsRepositoryTests.cs index 16f368590..7e7234b95 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/ScanMetricsRepositoryTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/ScanMetricsRepositoryTests.cs @@ -51,10 +51,10 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime var metrics = CreateTestMetrics(); // Act - await _repository.SaveAsync(metrics, CancellationToken.None); + await _repository.SaveAsync(metrics, TestContext.Current.CancellationToken); // Assert - var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, CancellationToken.None); + var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.Equal(metrics.ScanId, retrieved.ScanId); Assert.Equal(metrics.TenantId, retrieved.TenantId); @@ -67,7 +67,7 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime { // Arrange var metrics = CreateTestMetrics(); - await _repository.SaveAsync(metrics, CancellationToken.None); + await _repository.SaveAsync(metrics, TestContext.Current.CancellationToken); var phases = new[] { @@ -92,10 +92,10 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime }; // Act - await _repository.SavePhasesAsync(phases, CancellationToken.None); + await _repository.SavePhasesAsync(phases, TestContext.Current.CancellationToken); // Assert - var retrieved = await _repository.GetPhasesAsync(metrics.MetricsId, CancellationToken.None); + var retrieved = await _repository.GetPhasesAsync(metrics.MetricsId, TestContext.Current.CancellationToken); Assert.Equal(2, retrieved.Count); Assert.Contains(retrieved, p => p.PhaseName == ScanPhaseNames.Ingest); Assert.Contains(retrieved, p => p.PhaseName == ScanPhaseNames.Analyze); @@ -106,7 +106,7 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime public async Task GetByScanIdAsync_ReturnsNullForNonexistent() { // Act - var result = await _repository.GetByScanIdAsync(Guid.NewGuid(), CancellationToken.None); + var result = await _repository.GetByScanIdAsync(Guid.NewGuid(), TestContext.Current.CancellationToken); // Assert Assert.Null(result); @@ -122,12 +122,12 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime var metrics2 = CreateTestMetrics(tenantId: tenantId); var metricsOther = CreateTestMetrics(tenantId: Guid.NewGuid()); - await _repository.SaveAsync(metrics1, CancellationToken.None); - await _repository.SaveAsync(metrics2, CancellationToken.None); - await _repository.SaveAsync(metricsOther, CancellationToken.None); + await _repository.SaveAsync(metrics1, TestContext.Current.CancellationToken); + await _repository.SaveAsync(metrics2, TestContext.Current.CancellationToken); + await _repository.SaveAsync(metricsOther, TestContext.Current.CancellationToken); // Act - var result = await _repository.GetRecentAsync(tenantId, limit: 10, includeReplays: true, cancellationToken: CancellationToken.None); + var result = await _repository.GetRecentAsync(tenantId, limit: 10, includeReplays: true, cancellationToken: TestContext.Current.CancellationToken); // Assert Assert.Equal(2, result.Count); @@ -144,12 +144,12 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime var metrics2 = CreateTestMetrics(artifactDigest: artifactDigest); var other = CreateTestMetrics(); - await _repository.SaveAsync(metrics1, CancellationToken.None); - await _repository.SaveAsync(metrics2, CancellationToken.None); - await _repository.SaveAsync(other, CancellationToken.None); + await _repository.SaveAsync(metrics1, TestContext.Current.CancellationToken); + await _repository.SaveAsync(metrics2, TestContext.Current.CancellationToken); + await _repository.SaveAsync(other, TestContext.Current.CancellationToken); // Act - var result = await _repository.GetByArtifactAsync(artifactDigest, CancellationToken.None); + var result = await _repository.GetByArtifactAsync(artifactDigest, TestContext.Current.CancellationToken); // Assert Assert.Equal(2, result.Count); @@ -189,11 +189,11 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime ScannerVersion = "1.0.0", CreatedAt = baseTime }; - await _repository.SaveAsync(metrics, CancellationToken.None); + await _repository.SaveAsync(metrics, TestContext.Current.CancellationToken); } // Act - var p50 = await _repository.GetTtePercentileAsync(tenantId, percentile: 0.50m, since: baseTime.AddHours(-1), cancellationToken: CancellationToken.None); + var p50 = await _repository.GetTtePercentileAsync(tenantId, percentile: 0.50m, since: baseTime.AddHours(-1), cancellationToken: TestContext.Current.CancellationToken); // Assert Assert.NotNull(p50); @@ -216,10 +216,10 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime }); // Act - await _repository.SaveAsync(metrics, CancellationToken.None); + await _repository.SaveAsync(metrics, TestContext.Current.CancellationToken); // Assert - var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, CancellationToken.None); + var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.Equal(100, retrieved.Phases.IngestMs); Assert.Equal(200, retrieved.Phases.AnalyzeMs); @@ -237,10 +237,10 @@ public sealed class ScanMetricsRepositoryTests : IAsyncLifetime var metrics = CreateTestMetrics(isReplay: true, replayManifestHash: "sha256:replay123"); // Act - await _repository.SaveAsync(metrics, CancellationToken.None); + await _repository.SaveAsync(metrics, TestContext.Current.CancellationToken); // Assert - var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, CancellationToken.None); + var retrieved = await _repository.GetByScanIdAsync(metrics.ScanId, TestContext.Current.CancellationToken); Assert.NotNull(retrieved); Assert.True(retrieved.IsReplay); Assert.Equal("sha256:replay123", retrieved.ReplayManifestHash); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/StorageDualWriteFixture.cs b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/StorageDualWriteFixture.cs index af32fbc71..6f69db777 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/StorageDualWriteFixture.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Storage.Tests/StorageDualWriteFixture.cs @@ -1,4 +1,4 @@ -using System.Security.Cryptography; +using System.Security.Cryptography; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Microsoft.Extensions.Time.Testing; @@ -59,14 +59,14 @@ public sealed class StorageDualWriteFixture immutable: true, ttlClass: "compliance", expiresAtUtc: expiresAt, - cancellationToken: CancellationToken.None); + cancellationToken: TestContext.Current.CancellationToken); var digest = Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant(); var expectedKey = $"{options.ObjectStore.RootPrefix.TrimEnd('/')}/layers/{digest}/sbom.cdx.json"; Assert.Contains(objectStore.Objects.Keys, key => key.Bucket == options.ObjectStore.BucketName && key.Key == expectedKey); Assert.Contains(objectStore.Objects.Keys, key => key.Bucket == options.DualWrite.MirrorBucket && key.Key == expectedKey); - var artifact = await artifactRepository.GetAsync(document.Id, CancellationToken.None); + var artifact = await artifactRepository.GetAsync(document.Id, TestContext.Current.CancellationToken); Assert.NotNull(artifact); Assert.Equal($"sha256:{digest}", artifact!.BytesSha256); Assert.Equal(1, artifact.RefCount); @@ -75,7 +75,7 @@ public sealed class StorageDualWriteFixture Assert.Equal(expectedTimestamp, artifact.CreatedAtUtc); Assert.Equal(expectedTimestamp, artifact.UpdatedAtUtc); - var lifecycle = await lifecycleRepository.ListExpiredAsync(DateTime.MaxValue, CancellationToken.None); + var lifecycle = await lifecycleRepository.ListExpiredAsync(DateTime.MaxValue, TestContext.Current.CancellationToken); var lifecycleEntry = lifecycle.SingleOrDefault(x => x.ArtifactId == document.Id); Assert.NotNull(lifecycleEntry); Assert.Equal("compliance", lifecycleEntry!.Class); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealE2ETests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealE2ETests.cs index 5d7615e85..50045270f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealE2ETests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealE2ETests.cs @@ -18,6 +18,7 @@ using System.Text.Json; using FluentAssertions; using Microsoft.Extensions.Time.Testing; using StellaOps.Facet; +using Xunit; namespace StellaOps.Scanner.Surface.FS.Tests; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealExtractorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealExtractorTests.cs index 8ef970a51..d72227353 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealExtractorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealExtractorTests.cs @@ -13,6 +13,7 @@ using System.Text; using FluentAssertions; using Microsoft.Extensions.Time.Testing; using StellaOps.Facet; +using Xunit; namespace StellaOps.Scanner.Surface.FS.Tests; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealIntegrationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealIntegrationTests.cs index 0ba0573db..40aec531a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealIntegrationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Surface.FS.Tests/FacetSealIntegrationTests.cs @@ -15,6 +15,7 @@ using System.Text; using FluentAssertions; using Microsoft.Extensions.Time.Testing; using StellaOps.Facet; +using Xunit; namespace StellaOps.Scanner.Surface.FS.Tests; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/BaselineEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/BaselineEndpointsTests.cs index 94f1c4d53..aec5f75dc 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/BaselineEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/BaselineEndpointsTests.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Http.Json; using System.Text.Json; using StellaOps.Scanner.WebService.Contracts; +using Xunit; using StellaOps.TestKit; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/CounterfactualEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/CounterfactualEndpointsTests.cs index 0b3bc8894..d28ebac31 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/CounterfactualEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/CounterfactualEndpointsTests.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Http.Json; using System.Text.Json; using StellaOps.Scanner.WebService.Endpoints; +using Xunit; using StellaOps.TestKit; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/DeltaCompareEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/DeltaCompareEndpointsTests.cs index 771259dee..892fe5b5f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/DeltaCompareEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/DeltaCompareEndpointsTests.cs @@ -8,6 +8,7 @@ using System.Net; using System.Net.Http.Json; using System.Text.Json; using StellaOps.Scanner.WebService.Contracts; +using Xunit; using StellaOps.TestKit; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/LinksetResolverTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/LinksetResolverTests.cs index 762d9f55f..d8b4bdbed 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/LinksetResolverTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/LinksetResolverTests.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using Xunit; using System.Linq; using System.Security.Cryptography.X509Certificates; using Microsoft.Extensions.Logging.Abstractions; @@ -51,7 +52,7 @@ public sealed class LinksetResolverTests var result = await resolver.ResolveAsync(new[] { new PolicyPreviewFindingDto { Id = "CVE-2025-0001" } - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); var summary = Assert.Single(result); Assert.Equal("CVE-2025-0001", summary.AdvisoryId); @@ -79,7 +80,7 @@ public sealed class LinksetResolverTests new FakeSurfaceEnvironment(), NullLogger.Instance); - var result = await resolver.ResolveAsync(Array.Empty(), CancellationToken.None); + var result = await resolver.ResolveAsync(Array.Empty(), TestContext.Current.CancellationToken); Assert.Empty(result); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/PolicyEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/PolicyEndpointsTests.cs index 81c9df254..9f99a2adf 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/PolicyEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/PolicyEndpointsTests.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Net; +using Xunit; using System.Net.Http.Json; using System.Text.Json; using System.Threading.Tasks; diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReachabilityDriftEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReachabilityDriftEndpointsTests.cs index 6121617ca..04e640c81 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReachabilityDriftEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReachabilityDriftEndpointsTests.cs @@ -80,7 +80,7 @@ public sealed class ReachabilityDriftEndpointsTests Assert.Equal(DriftDirection.BecameReachable, sinksPayload.Direction); Assert.Equal(0, sinksPayload.Offset); Assert.Equal(10, sinksPayload.Limit); - Assert.Equal(1, sinksPayload.Count); + Assert.Single(sinksPayload.Sinks); Assert.Single(sinksPayload.Sinks); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportEventDispatcherTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportEventDispatcherTests.cs index 61291040d..b3125fd2f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportEventDispatcherTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportEventDispatcherTests.cs @@ -1,4 +1,5 @@ using System; +using Xunit; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -36,7 +37,7 @@ public sealed class ReportEventDispatcherTests var publisher = new RecordingEventPublisher(); var tracker = new RecordingClassificationChangeTracker(); var dispatcher = new ReportEventDispatcher(publisher, tracker, Microsoft.Extensions.Options.Options.Create(new ScannerWebServiceOptions()), TimeProvider.System, NullLogger.Instance); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var request = new ReportRequestDto { @@ -177,7 +178,7 @@ public sealed class ReportEventDispatcherTests var publisher = new RecordingEventPublisher(); var tracker = new RecordingClassificationChangeTracker(); var dispatcher = new ReportEventDispatcher(publisher, tracker, Microsoft.Extensions.Options.Options.Create(new ScannerWebServiceOptions()), TimeProvider.System, NullLogger.Instance); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var request = new ReportRequestDto { @@ -262,7 +263,7 @@ public sealed class ReportEventDispatcherTests ThrowOnTrack = true }; var dispatcher = new ReportEventDispatcher(publisher, tracker, Microsoft.Extensions.Options.Options.Create(new ScannerWebServiceOptions()), TimeProvider.System, NullLogger.Instance); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var request = new ReportRequestDto { @@ -333,7 +334,7 @@ public sealed class ReportEventDispatcherTests var publisher = new RecordingEventPublisher(); var tracker = new RecordingClassificationChangeTracker(); var dispatcher = new ReportEventDispatcher(publisher, tracker, options, TimeProvider.System, NullLogger.Instance); - var cancellationToken = CancellationToken.None; + var cancellationToken = TestContext.Current.CancellationToken; var request = new ReportRequestDto { diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportsEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportsEndpointsTests.cs index 085c10a8a..c3644bf1d 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportsEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/ReportsEndpointsTests.cs @@ -1,4 +1,5 @@ -using System.Net; +using System.Net; +using Xunit; using System.Net.Http.Json; using System.Text; using System.Text.Json; @@ -50,7 +51,7 @@ rules: var store = factory.Services.GetRequiredService(); await store.SaveAsync( new PolicySnapshotContent(policyYaml, PolicyDocumentFormat.Yaml, "tester", "seed", "initial"), - CancellationToken.None); + TestContext.Current.CancellationToken); using var client = factory.CreateClient(); @@ -179,7 +180,7 @@ rules: var store = factory.Services.GetRequiredService(); var saveResult = await store.SaveAsync( new PolicySnapshotContent(policyYaml, PolicyDocumentFormat.Yaml, "tester", "seed", "initial"), - CancellationToken.None); + TestContext.Current.CancellationToken); var revisionId = saveResult.Snapshot?.RevisionId ?? string.Empty; var recorder = factory.Services.GetRequiredService(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RubyPackagesEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RubyPackagesEndpointsTests.cs index 3b3968cc6..de8021db2 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RubyPackagesEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RubyPackagesEndpointsTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; @@ -72,7 +72,7 @@ public sealed class RubyPackagesEndpointsTests } }; - await repository.UpsertAsync(document, CancellationToken.None); + await repository.UpsertAsync(document, TestContext.Current.CancellationToken); } using var client = factory.CreateClient(); @@ -108,10 +108,10 @@ public sealed class RubyPackagesEndpointsTests Force: false, ClientRequestId: null, Metadata: new Dictionary()); - var result = await coordinator.SubmitAsync(submission, CancellationToken.None); + var result = await coordinator.SubmitAsync(submission, TestContext.Current.CancellationToken); scanId = result.Snapshot.ScanId.Value; - var resolved = await coordinator.TryFindByTargetAsync(reference, digest, CancellationToken.None); + var resolved = await coordinator.TryFindByTargetAsync(reference, digest, TestContext.Current.CancellationToken); Assert.NotNull(resolved); var repository = scope.ServiceProvider.GetRequiredService(); @@ -132,7 +132,7 @@ public sealed class RubyPackagesEndpointsTests } }; - await repository.UpsertAsync(document, CancellationToken.None); + await repository.UpsertAsync(document, TestContext.Current.CancellationToken); } using var client = factory.CreateClient(); @@ -166,10 +166,10 @@ public sealed class RubyPackagesEndpointsTests Force: false, ClientRequestId: "cli-test", Metadata: new Dictionary()); - var result = await coordinator.SubmitAsync(submission, CancellationToken.None); + var result = await coordinator.SubmitAsync(submission, TestContext.Current.CancellationToken); scanId = result.Snapshot.ScanId.Value; - var resolved = await coordinator.TryFindByTargetAsync(reference, digest, CancellationToken.None); + var resolved = await coordinator.TryFindByTargetAsync(reference, digest, TestContext.Current.CancellationToken); Assert.NotNull(resolved); var repository = scope.ServiceProvider.GetRequiredService(); @@ -190,7 +190,7 @@ public sealed class RubyPackagesEndpointsTests } }; - await repository.UpsertAsync(document, CancellationToken.None); + await repository.UpsertAsync(document, TestContext.Current.CancellationToken); } using var client = factory.CreateClient(); @@ -262,7 +262,7 @@ public sealed class RubyPackagesEndpointsTests Force: false, ClientRequestId: null, Metadata: new Dictionary()); - var result = await coordinator.SubmitAsync(submission, CancellationToken.None); + var result = await coordinator.SubmitAsync(submission, TestContext.Current.CancellationToken); canonicalScanId = result.Snapshot.ScanId.Value; var store = (RecordingEntryTraceResultStore)scope.ServiceProvider.GetRequiredService(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeEndpointsTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeEndpointsTests.cs index b4cbc6a8c..25bedaee2 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeEndpointsTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeEndpointsTests.cs @@ -1,4 +1,5 @@ -using System; +using System; +using Xunit; using System.Collections.Generic; using System.Linq; using System.Net; @@ -103,7 +104,7 @@ public sealed class RuntimeEndpointsTests using var scope = factory.Services.CreateScope(); var repository = scope.ServiceProvider.GetRequiredService(); - var count = await repository.CountAsync(CancellationToken.None); + var count = await repository.CountAsync(TestContext.Current.CancellationToken); Assert.Equal(0, count); } @@ -126,7 +127,7 @@ public sealed class RuntimeEndpointsTests var links = scope.ServiceProvider.GetRequiredService(); var policyStore = scope.ServiceProvider.GetRequiredService(); var runtimeRepository = scope.ServiceProvider.GetRequiredService(); - await runtimeRepository.TruncateAsync(CancellationToken.None); + await runtimeRepository.TruncateAsync(TestContext.Current.CancellationToken); const string policyYaml = """ version: "1.0" @@ -137,10 +138,10 @@ rules: """; var saveResult = await policyStore.SaveAsync( new PolicySnapshotContent(policyYaml, PolicyDocumentFormat.Yaml, "tester", "tests", "seed"), - CancellationToken.None); + TestContext.Current.CancellationToken); Assert.True(saveResult.Success); - var snapshot = await policyStore.GetLatestAsync(CancellationToken.None); + var snapshot = await policyStore.GetLatestAsync(TestContext.Current.CancellationToken); Assert.NotNull(snapshot); var sbomArtifactId = CatalogIdFactory.CreateArtifactId(ArtifactDocumentType.ImageBom, "sha256:sbomdigest"); @@ -154,7 +155,7 @@ rules: MediaType = "application/json", BytesSha256 = "sha256:sbomdigest", RefCount = 1 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await artifacts.UpsertAsync(new ArtifactDocument { @@ -165,7 +166,7 @@ rules: BytesSha256 = "sha256:attdigest", RefCount = 1, Rekor = new RekorReference { Uuid = "rekor-uuid", Url = "https://rekor.example/uuid/rekor-uuid", Index = 7 } - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -174,7 +175,7 @@ rules: FromDigest = imageDigest, ArtifactId = sbomArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -183,7 +184,7 @@ rules: FromDigest = imageDigest, ArtifactId = attestationArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); } var ingestRequest = new RuntimeEventsIngestRequestDto @@ -257,10 +258,10 @@ rules: [] """; await policyStore.SaveAsync( new PolicySnapshotContent(policyYaml, PolicyDocumentFormat.Yaml, "tester", "tests", "baseline"), - CancellationToken.None); + TestContext.Current.CancellationToken); // Intentionally skip artifacts/links to simulate missing metadata. - await runtimeRepository.TruncateAsync(CancellationToken.None); + await runtimeRepository.TruncateAsync(TestContext.Current.CancellationToken); } var response = await client.PostAsJsonAsync("/api/v1/policy/runtime", new RuntimePolicyRequestDto diff --git a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeReconciliationTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeReconciliationTests.cs index e1b9caac6..aa09488dc 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeReconciliationTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.WebService.Tests/RuntimeReconciliationTests.cs @@ -1,4 +1,5 @@ -using System; +using System; +using Xunit; using System.Collections.Generic; using System.IO; using System.Net; @@ -128,7 +129,7 @@ public sealed class RuntimeReconciliationTests MediaType = "application/json", BytesSha256 = sbomHash, RefCount = 1 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -137,7 +138,7 @@ public sealed class RuntimeReconciliationTests FromDigest = TestImageDigest, ArtifactId = sbomArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); } // Create SBOM content with matching hash @@ -219,7 +220,7 @@ public sealed class RuntimeReconciliationTests MediaType = "application/json", BytesSha256 = sbomHash, RefCount = 1 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -228,7 +229,7 @@ public sealed class RuntimeReconciliationTests FromDigest = imageDigest, ArtifactId = sbomArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); } // Create SBOM with paths but different hashes (path matching) @@ -305,7 +306,7 @@ public sealed class RuntimeReconciliationTests MediaType = "application/json", BytesSha256 = sbomHash, RefCount = 1 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -314,7 +315,7 @@ public sealed class RuntimeReconciliationTests FromDigest = imageDigest, ArtifactId = sbomArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); } var sbom = CreateSbomWithComponents(new[] @@ -433,7 +434,7 @@ public sealed class RuntimeReconciliationTests MediaType = "application/json", BytesSha256 = sbomHash, RefCount = 1 - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); await links.UpsertAsync(new LinkDocument { @@ -442,7 +443,7 @@ public sealed class RuntimeReconciliationTests FromDigest = imageDigest, ArtifactId = sbomArtifactId, CreatedAtUtc = DateTime.UtcNow - }, CancellationToken.None); + }, TestContext.Current.CancellationToken); } // SBOM has 2 components diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/CompositeScanAnalyzerDispatcherTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/CompositeScanAnalyzerDispatcherTests.cs index 7211d576f..577fc0710 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/CompositeScanAnalyzerDispatcherTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/CompositeScanAnalyzerDispatcherTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; @@ -122,14 +122,14 @@ public sealed class CompositeScanAnalyzerDispatcherTests new TestCryptoHash()); var lease = new TestJobLease(metadata); - var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); + var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); - await dispatcher.ExecuteAsync(context, CancellationToken.None); + await dispatcher.ExecuteAsync(context, TestContext.Current.CancellationToken); // Re-run with a new context to exercise cache reuse. var leaseSecond = new TestJobLease(metadata); - var contextSecond = new ScanJobContext(leaseSecond, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); - await dispatcher.ExecuteAsync(contextSecond, CancellationToken.None); + var contextSecond = new ScanJobContext(leaseSecond, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); + await dispatcher.ExecuteAsync(contextSecond, TestContext.Current.CancellationToken); meterListener.RecordObservableInstruments(); @@ -173,7 +173,7 @@ public sealed class CompositeScanAnalyzerDispatcherTests var dpkgStatusPath = Path.Combine(rootfs.Path, "var", "lib", "dpkg", "status"); Directory.CreateDirectory(Path.GetDirectoryName(dpkgStatusPath)!); - await File.WriteAllTextAsync(dpkgStatusPath, "Package: demo\nStatus: install ok installed\n", CancellationToken.None); + await File.WriteAllTextAsync(dpkgStatusPath, "Package: demo\nStatus: install ok installed\n", TestContext.Current.CancellationToken); var metadata = new Dictionary(StringComparer.Ordinal) { @@ -246,13 +246,13 @@ public sealed class CompositeScanAnalyzerDispatcherTests new TestCryptoHash()); var lease = new TestJobLease(metadata); - var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); + var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); - await dispatcher.ExecuteAsync(context, CancellationToken.None); + await dispatcher.ExecuteAsync(context, TestContext.Current.CancellationToken); var leaseSecond = new TestJobLease(metadata); - var contextSecond = new ScanJobContext(leaseSecond, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); - await dispatcher.ExecuteAsync(contextSecond, CancellationToken.None); + var contextSecond = new ScanJobContext(leaseSecond, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); + await dispatcher.ExecuteAsync(contextSecond, TestContext.Current.CancellationToken); Assert.Equal(1, analyzer.InvocationCount); Assert.True(context.Analysis.TryGet>(ScanAnalysisKeys.OsPackageAnalyzers, out var results)); @@ -296,7 +296,7 @@ public sealed class CompositeScanAnalyzerDispatcherTests elfBytes[1] = (byte)'E'; elfBytes[2] = (byte)'L'; elfBytes[3] = (byte)'F'; - await File.WriteAllBytesAsync(binaryPath, elfBytes, CancellationToken.None); + await File.WriteAllBytesAsync(binaryPath, elfBytes, TestContext.Current.CancellationToken); var serviceCollection = new ServiceCollection(); serviceCollection.AddLogging(builder => builder.SetMinimumLevel(LogLevel.Debug)); @@ -335,9 +335,9 @@ public sealed class CompositeScanAnalyzerDispatcherTests new TestCryptoHash()); var lease = new TestJobLease(metadata); - var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); + var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); - await dispatcher.ExecuteAsync(context, CancellationToken.None); + await dispatcher.ExecuteAsync(context, TestContext.Current.CancellationToken); var fragments = context.Analysis.GetLayerFragments(); Assert.True(fragments.Length > 0); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntropyStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntropyStageExecutorTests.cs index c33b9bfcd..bcf70e931 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntropyStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntropyStageExecutorTests.cs @@ -32,13 +32,13 @@ public class EntropyStageExecutorTests }; var lease = new StubLease("job-1", "scan-1", imageDigest: "sha256:test", layerDigest: "sha256:layer"); - var context = new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, CancellationToken.None); + var context = new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, TestContext.Current.CancellationToken); context.Analysis.Set(ScanAnalysisKeys.FileEntries, (IReadOnlyList)fileEntries); var executor = new EntropyStageExecutor(NullLogger.Instance); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.True(context.Analysis.TryGet(ScanAnalysisKeys.EntropyReport, out var report)); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntryTraceExecutionServiceTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntryTraceExecutionServiceTests.cs index 45fd9cb4c..98f7396c2 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntryTraceExecutionServiceTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/EntryTraceExecutionServiceTests.cs @@ -46,7 +46,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable var context = CreateContext(new Dictionary()); - await service.ExecuteAsync(context, CancellationToken.None); + await service.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.False(analyzer.Invoked); Assert.False(context.Analysis.TryGet(ScanAnalysisKeys.EntryTraceGraph, out _)); @@ -64,7 +64,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable var context = CreateContext(metadata); - await service.ExecuteAsync(context, CancellationToken.None); + await service.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.True(analyzer.Invoked); Assert.NotNull(analyzer.LastEntrypoint); @@ -98,13 +98,13 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable var cache = new InMemorySurfaceCache(); var service = CreateService(analyzer, store, surfaceCache: cache); - await service.ExecuteAsync(CreateContext(metadata), CancellationToken.None); + await service.ExecuteAsync(CreateContext(metadata), TestContext.Current.CancellationToken); Assert.True(analyzer.Invoked); analyzer.Reset(); store.Reset(); - await service.ExecuteAsync(CreateContext(metadata), CancellationToken.None); + await service.ExecuteAsync(CreateContext(metadata), TestContext.Current.CancellationToken); Assert.False(analyzer.Invoked); Assert.True(store.Stored); @@ -123,7 +123,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable }); var service = CreateService(analyzer, store, surfaceSecrets: secrets); - await service.ExecuteAsync(CreateContext(metadata), CancellationToken.None); + await service.ExecuteAsync(CreateContext(metadata), TestContext.Current.CancellationToken); Assert.True(analyzer.Invoked); Assert.Equal("resolved-value", analyzer.LastContext!.Environment["API_KEY"]); @@ -143,7 +143,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable }); var service = CreateService(analyzer, store, surfaceSecrets: secrets); - await service.ExecuteAsync(CreateContext(metadata), CancellationToken.None); + await service.ExecuteAsync(CreateContext(metadata), TestContext.Current.CancellationToken); Assert.True(analyzer.Invoked); Assert.Equal(Convert.ToBase64String(payload), analyzer.LastContext!.Environment["BLOB"]); @@ -163,7 +163,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable var validator = new StaticSurfaceValidatorRunner(SurfaceValidationResult.FromIssues(issues)); var service = CreateService(analyzer, store, surfaceValidator: validator); - await service.ExecuteAsync(CreateContext(metadata), CancellationToken.None); + await service.ExecuteAsync(CreateContext(metadata), TestContext.Current.CancellationToken); Assert.False(analyzer.Invoked); Assert.False(store.Stored); @@ -210,7 +210,7 @@ public sealed class EntryTraceExecutionServiceTests : IDisposable private static ScanJobContext CreateContext(IReadOnlyDictionary metadata) { var lease = new TestLease(metadata); - return new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, CancellationToken.None); + return new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, TestContext.Current.CancellationToken); } private Dictionary CreateMetadata(params string[] environmentEntries) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/HmacDsseEnvelopeSignerTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/HmacDsseEnvelopeSignerTests.cs index 6e06319d5..61f52404f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/HmacDsseEnvelopeSignerTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/HmacDsseEnvelopeSignerTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Text; using System.Text.Json; using System.Threading; @@ -35,7 +35,7 @@ public sealed class HmacDsseEnvelopeSignerTests new ServiceCollection().BuildServiceProvider()); var payload = Encoding.UTF8.GetBytes("{\"hello\":\"world\"}"); - var envelope = await signer.SignAsync("application/json", payload, "test.kind", "root", view: null, CancellationToken.None); + var envelope = await signer.SignAsync("application/json", payload, "test.kind", "root", view: null, TestContext.Current.CancellationToken); var json = JsonDocument.Parse(envelope.Content); var sig = json.RootElement.GetProperty("signatures")[0].GetProperty("sig").GetString(); @@ -65,7 +65,7 @@ public sealed class HmacDsseEnvelopeSignerTests new ServiceCollection().BuildServiceProvider()); var payload = Encoding.UTF8.GetBytes("abc"); - var envelope = await signer.SignAsync("text/plain", payload, "kind", "root", view: null, CancellationToken.None); + var envelope = await signer.SignAsync("text/plain", payload, "kind", "root", view: null, TestContext.Current.CancellationToken); var json = JsonDocument.Parse(envelope.Content); var sig = json.RootElement.GetProperty("signatures")[0].GetProperty("sig").GetString(); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/EndToEndJobFlowTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/EndToEndJobFlowTests.cs index fa7a736e4..ff0bac64e 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/EndToEndJobFlowTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/EndToEndJobFlowTests.cs @@ -53,7 +53,7 @@ public sealed class EndToEndJobFlowTests var worker = services.GetRequiredService(); // Act - Start worker and process job - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); // Advance time to allow job completion @@ -66,7 +66,7 @@ public sealed class EndToEndJobFlowTests } await lease.Completed.Task.WaitAsync(TimeSpan.FromSeconds(30)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.Completed.Task.IsCompletedSuccessfully, "Job should complete successfully."); @@ -98,7 +98,7 @@ public sealed class EndToEndJobFlowTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); // Process all jobs var spin = 0; @@ -110,7 +110,7 @@ public sealed class EndToEndJobFlowTests } await Task.WhenAll(leases.Select(l => l.Completed.Task.WaitAsync(TimeSpan.FromSeconds(30)))); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.All(leases, l => Assert.True(l.Completed.Task.IsCompletedSuccessfully)); @@ -137,7 +137,7 @@ public sealed class EndToEndJobFlowTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); var spin = 0; @@ -149,7 +149,7 @@ public sealed class EndToEndJobFlowTests } await lease.Completed.Task.WaitAsync(TimeSpan.FromSeconds(30)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Check for stage events Assert.Contains(eventRecorder.Events, e => e.EventType == "StageStarted" && e.Stage == ScanStageNames.ExecuteAnalyzers); @@ -176,7 +176,7 @@ public sealed class EndToEndJobFlowTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); var spin = 0; @@ -188,7 +188,7 @@ public sealed class EndToEndJobFlowTests } await lease.Completed.Task.WaitAsync(TimeSpan.FromSeconds(30)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert var jobDurationMeasurements = listener.Measurements @@ -218,7 +218,7 @@ public sealed class EndToEndJobFlowTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); // Advance time in small increments to trigger heartbeats @@ -230,7 +230,7 @@ public sealed class EndToEndJobFlowTests } await lease.Completed.Task.WaitAsync(TimeSpan.FromSeconds(30)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Lease should have been renewed at least once Assert.True(lease.RenewalCount >= 1, $"Expected at least 1 renewal, got {lease.RenewalCount}"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerEndToEndJobTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerEndToEndJobTests.cs index 2328a82f1..634edaf01 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerEndToEndJobTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerEndToEndJobTests.cs @@ -57,13 +57,13 @@ public sealed class WorkerEndToEndJobTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); await lease.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Job completed successfully Assert.True(lease.Completed.Task.IsCompletedSuccessfully, "Job should complete successfully"); @@ -106,7 +106,7 @@ public sealed class WorkerEndToEndJobTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); // Process all three jobs foreach (var lease in new[] { lease1, lease2, lease3 }) @@ -114,7 +114,7 @@ public sealed class WorkerEndToEndJobTests await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 30); } - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - All jobs completed Assert.True(lease1.Completed.Task.IsCompletedSuccessfully); @@ -156,10 +156,10 @@ public sealed class WorkerEndToEndJobTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Metadata was captured var evidence = evidenceStore.GetEvidence("scan-meta"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerIdempotencyTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerIdempotencyTests.cs index 246f8a817..c26a54c8f 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerIdempotencyTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerIdempotencyTests.cs @@ -58,7 +58,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - Process both jobs - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); // Process first job await AdvanceUntilComplete(fakeTime, scheduler, lease1, maxIterations: 30); @@ -69,7 +69,7 @@ public sealed class WorkerIdempotencyTests await AdvanceUntilComplete(fakeTime, scheduler, lease2, maxIterations: 30); await lease2.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Only one evidence record should exist Assert.Equal(1, evidenceStore.GetEvidenceCount("scan-shared-001")); @@ -101,7 +101,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); foreach (var lease in leases) { @@ -110,7 +110,7 @@ public sealed class WorkerIdempotencyTests fakeTime.Advance(TimeSpan.FromSeconds(30)); } - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Only one evidence, but 5 processing attempts Assert.Equal(1, evidenceStore.GetEvidenceCount(scanId)); @@ -146,7 +146,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); // Wait for all jobs to be acquired await Task.Delay(50); @@ -162,7 +162,7 @@ public sealed class WorkerIdempotencyTests // Wait for all to complete await Task.WhenAll(leases.Select(l => l.Completed.Task.WaitAsync(TimeSpan.FromSeconds(10)))); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.Equal(1, evidenceStore.GetEvidenceCount(scanId)); @@ -193,7 +193,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await AdvanceUntilComplete(fakeTime, scheduler, lease1, maxIterations: 30); await lease1.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); @@ -202,7 +202,7 @@ public sealed class WorkerIdempotencyTests await AdvanceUntilComplete(fakeTime, scheduler, lease2, maxIterations: 30); await lease2.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Same job ID should not create duplicate Assert.Equal(1, evidenceStore.GetEvidenceCount(scanId)); @@ -237,7 +237,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); foreach (var lease in leases) { @@ -246,7 +246,7 @@ public sealed class WorkerIdempotencyTests fakeTime.Advance(TimeSpan.FromSeconds(30)); } - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Each scan ID should have exactly one evidence Assert.Equal(1, evidenceStore.GetEvidenceCount("scan-distinct-1")); @@ -279,7 +279,7 @@ public sealed class WorkerIdempotencyTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await AdvanceUntilComplete(fakeTime, scheduler, lease1, maxIterations: 30); await lease1.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); @@ -289,7 +289,7 @@ public sealed class WorkerIdempotencyTests await AdvanceUntilComplete(fakeTime, scheduler, lease2, maxIterations: 30); await lease2.Completed.Task.WaitAsync(TimeSpan.FromSeconds(5)); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert - Both runs should produce the same hash var hashes = evidenceStore.GetHashes(scanId); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerRetryTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerRetryTests.cs index deb42ea2f..e55dddfa5 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerRetryTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Integration/WorkerRetryTests.cs @@ -54,10 +54,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasAbandoned, "First attempt failure should abandon, not poison"); @@ -86,10 +86,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasPoisoned, "Should be poisoned after max attempts"); @@ -117,10 +117,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasAbandoned, "Second attempt under max should still abandon for retry"); @@ -147,10 +147,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasPoisoned, "With maxAttempts=1, first failure should poison immediately"); @@ -189,7 +189,7 @@ public sealed class WorkerRetryTests // Stop the worker (simulating host shutdown) cts.Cancel(); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasAbandoned, "Shutdown should abandon the job"); @@ -216,10 +216,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert Assert.True(lease.WasCompleted, "Successful job should be completed"); @@ -252,10 +252,10 @@ public sealed class WorkerRetryTests var worker = services.GetRequiredService(); // Act - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await AdvanceUntilComplete(fakeTime, scheduler, lease, maxIterations: 24); - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); // Assert if (shouldPoison) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEGenerationStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEGenerationStageExecutorTests.cs index 522c1b34b..02c8886f9 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEGenerationStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEGenerationStageExecutorTests.cs @@ -71,7 +71,7 @@ public class PoEGenerationStageExecutorTests : IDisposable var context = CreateScanContext(); // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.False(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out _)); @@ -86,7 +86,7 @@ public class PoEGenerationStageExecutorTests : IDisposable // No vulnerabilities in analysis store // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.False(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out _)); @@ -136,7 +136,7 @@ public class PoEGenerationStageExecutorTests : IDisposable .ReturnsAsync(dsseBytes); // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.True(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out var results)); @@ -197,7 +197,7 @@ public class PoEGenerationStageExecutorTests : IDisposable .ReturnsAsync(dsseBytes); // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.True(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out var results)); @@ -258,7 +258,7 @@ public class PoEGenerationStageExecutorTests : IDisposable .ReturnsAsync(dsseBytes); // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert Assert.True(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out var results)); @@ -312,7 +312,7 @@ public class PoEGenerationStageExecutorTests : IDisposable .ReturnsAsync(dsseBytes); // Act - await _executor.ExecuteAsync(context, CancellationToken.None); + await _executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert - should generate PoE even for unreachable because EmitOnlyReachable = false Assert.True(context.Analysis.TryGet>(ScanAnalysisKeys.PoEResults, out var results)); @@ -329,7 +329,7 @@ public class PoEGenerationStageExecutorTests : IDisposable leaseMock.Object, TimeProvider.System, DateTimeOffset.UtcNow, - CancellationToken.None + TestContext.Current.CancellationToken ); } diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEOrchestratorDirectTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEOrchestratorDirectTests.cs index 0b451c256..392809d9c 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEOrchestratorDirectTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/PoE/PoEOrchestratorDirectTests.cs @@ -131,7 +131,7 @@ public class PoEOrchestratorDirectTests : IDisposable context, vulnerabilities, configuration, - CancellationToken.None); + TestContext.Current.CancellationToken); // Assert _output.WriteLine($"Results count: {results.Count}"); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RedisWorkerSmokeTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RedisWorkerSmokeTests.cs index 091bd326e..acdff5482 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RedisWorkerSmokeTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RedisWorkerSmokeTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; using System.Threading; @@ -96,7 +96,7 @@ public sealed class RedisWorkerSmokeTests var smokeObserver = provider.GetRequiredService(); await smokeObserver.JobCompleted.Task.WaitAsync(TimeSpan.FromSeconds(20)); - await hostedService.StopAsync(CancellationToken.None); + await hostedService.StopAsync(TestContext.Current.CancellationToken); } private static IConfiguration BuildQueueConfiguration(string connection, string stream, string consumerGroup) diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RegistrySecretStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RegistrySecretStageExecutorTests.cs index 3c7a7de1a..9fe08ba56 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RegistrySecretStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/RegistrySecretStageExecutorTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Diagnostics.Metrics; using System.IO; @@ -54,13 +54,13 @@ public sealed class RegistrySecretStageExecutorTests ["surface.registry.secret"] = "primary" }; var lease = new StubLease("job-1", "scan-1", metadata); - using var contextCancellation = CancellationTokenSource.CreateLinkedTokenSource(CancellationToken.None); + using var contextCancellation = CancellationTokenSource.CreateLinkedTokenSource(TestContext.Current.CancellationToken); var context = new ScanJobContext(lease, timeProvider, timeProvider.GetUtcNow(), contextCancellation.Token); var measurements = new List<(long Value, KeyValuePair[] Tags)>(); using var listener = CreateCounterListener("scanner_worker_registry_secret_requests_total", measurements); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); listener.RecordObservableInstruments(); Assert.True(context.Analysis.TryGet(ScanAnalysisKeys.RegistryCredentials, out var secret)); @@ -89,12 +89,12 @@ public sealed class RegistrySecretStageExecutorTests NullLogger.Instance); var lease = new StubLease("job-2", "scan-2", new Dictionary()); - var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); + var context = new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); var measurements = new List<(long Value, KeyValuePair[] Tags)>(); using var listener = CreateCounterListener("scanner_worker_registry_secret_requests_total", measurements); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); listener.RecordObservableInstruments(); Assert.False(context.Analysis.TryGet(ScanAnalysisKeys.RegistryCredentials, out _)); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Replay/ReplaySealedBundleStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Replay/ReplaySealedBundleStageExecutorTests.cs index 1aef8e636..cf9357bb8 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Replay/ReplaySealedBundleStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/Replay/ReplaySealedBundleStageExecutorTests.cs @@ -21,7 +21,7 @@ public sealed class ReplaySealedBundleStageExecutorTests metadata["determinism.policy"] = "rev-1"; metadata["determinism.feed"] = "feed-2"; - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.True(context.Analysis.TryGet(ScanAnalysisKeys.ReplaySealedBundleMetadata, out var sealedMetadata)); Assert.Equal("abc123", sealedMetadata.ManifestHash); @@ -37,7 +37,7 @@ public sealed class ReplaySealedBundleStageExecutorTests var context = TestContexts.Create(out var metadata); metadata["replay.bundle.uri"] = "cas://replay/input.tar.zst"; - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.False(context.Analysis.TryGet(ScanAnalysisKeys.ReplaySealedBundleMetadata, out _)); } @@ -49,7 +49,7 @@ internal static class TestContexts { var lease = new TestScanJobLease(); metadata = lease.MutableMetadata; - return new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), CancellationToken.None); + return new ScanJobContext(lease, TimeProvider.System, TimeProvider.System.GetUtcNow(), TestContext.Current.CancellationToken); } private sealed class TestScanJobLease : IScanJobLease diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/SurfaceManifestStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/SurfaceManifestStageExecutorTests.cs index cdf5a7e60..01ed9e344 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/SurfaceManifestStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/SurfaceManifestStageExecutorTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Collections.ObjectModel; @@ -62,7 +62,7 @@ public sealed class SurfaceManifestStageExecutorTests var context = CreateContext(); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.Equal(0, publisher.PublishCalls); Assert.Empty(cache.Entries); @@ -106,7 +106,7 @@ public sealed class SurfaceManifestStageExecutorTests var context = CreateContext(); PopulateAnalysis(context); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.Equal(1, publisher.PublishCalls); Assert.True(context.Analysis.TryGet(ScanAnalysisKeys.SurfaceManifest, out var result)); @@ -181,7 +181,7 @@ public sealed class SurfaceManifestStageExecutorTests }); PopulateAnalysis(context); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); var determinismPayload = publisher.LastRequest!.Payloads.Single(p => p.Kind == "determinism.json"); var json = JsonDocument.Parse(determinismPayload.Content); @@ -248,7 +248,7 @@ public sealed class SurfaceManifestStageExecutorTests context.Analysis.Set(ScanAnalysisKeys.EntropyReport, entropyReport); context.Analysis.Set(ScanAnalysisKeys.EntropyLayerSummary, entropySummary); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.Equal(1, publisher.PublishCalls); Assert.NotNull(publisher.LastRequest); @@ -262,7 +262,7 @@ public sealed class SurfaceManifestStageExecutorTests private static ScanJobContext CreateContext(Dictionary? metadata = null) { var lease = new FakeJobLease(metadata); - return new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, CancellationToken.None); + return new ScanJobContext(lease, TimeProvider.System, DateTimeOffset.UtcNow, TestContext.Current.CancellationToken); } private static void PopulateAnalysis(ScanJobContext context) @@ -351,7 +351,7 @@ public sealed class SurfaceManifestStageExecutorTests PopulateAnalysis(context); await PopulateRubyAnalyzerResultsAsync(context); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.NotNull(packageStore.LastInventory); Assert.Equal(context.ScanId, packageStore.LastInventory!.ScanId); @@ -385,7 +385,7 @@ public sealed class SurfaceManifestStageExecutorTests var context = CreateContext(); PopulateAnalysis(context); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); var entrytracePayloads = publisher.LastRequest!.Payloads .Where(p => p.Kind.StartsWith("entrytrace", StringComparison.OrdinalIgnoreCase)) @@ -423,7 +423,7 @@ public sealed class SurfaceManifestStageExecutorTests services: null, analysisStore: context.Analysis); - var result = await engine.AnalyzeAsync(analyzerContext, CancellationToken.None); + var result = await engine.AnalyzeAsync(analyzerContext, TestContext.Current.CancellationToken); var dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["ruby"] = result @@ -475,7 +475,7 @@ public sealed class SurfaceManifestStageExecutorTests context.Analysis.Set(ScanAnalysisKeys.DenoObservationPayload, observation); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); Assert.Equal(1, publisher.PublishCalls); Assert.NotNull(publisher.LastRequest); @@ -522,7 +522,7 @@ public sealed class SurfaceManifestStageExecutorTests var context = CreateContext(leaseMetadata); PopulateAnalysis(context); - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); var determinismPayload = Assert.Single(publisher.LastRequest!.Payloads, p => p.Kind == "determinism.json"); using var document = JsonDocument.Parse(determinismPayload.Content); diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/VexGateStageExecutorTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/VexGateStageExecutorTests.cs index 7de764ab1..64132125a 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/VexGateStageExecutorTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/VexGateStageExecutorTests.cs @@ -51,7 +51,7 @@ public sealed class VexGateStageExecutorTests { var tp = timeProvider ?? TimeProvider.System; var lease = new TestJobLease(); - var context = new ScanJobContext(lease, tp, tp.GetUtcNow(), CancellationToken.None); + var context = new ScanJobContext(lease, tp, tp.GetUtcNow(), TestContext.Current.CancellationToken); if (analysisData is not null) { @@ -137,7 +137,7 @@ public sealed class VexGateStageExecutorTests var context = CreateContext(); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGateBypassed, out var bypassed).Should().BeTrue(); @@ -159,7 +159,7 @@ public sealed class VexGateStageExecutorTests var context = CreateContext(); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGateSummary, out var summary).Should().BeTrue(); @@ -178,7 +178,7 @@ public sealed class VexGateStageExecutorTests var context = CreateContext(); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert _mockGateService.Verify( @@ -217,7 +217,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGateSummary, out var summary).Should().BeTrue(); @@ -259,7 +259,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGateSummary, out var summary).Should().BeTrue(); @@ -296,7 +296,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGateSummary, out var summary).Should().BeTrue(); @@ -327,7 +327,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet>(ScanAnalysisKeys.VexGateResults, out var results) @@ -355,7 +355,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGatePolicyVersion, out var version).Should().BeTrue(); @@ -381,7 +381,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert context.Analysis.TryGet(ScanAnalysisKeys.VexGatePolicyVersion, out var version).Should().BeTrue(); @@ -419,7 +419,7 @@ public sealed class VexGateStageExecutorTests }); // Act - await executor.ExecuteAsync(context, CancellationToken.None); + await executor.ExecuteAsync(context, TestContext.Current.CancellationToken); // Assert _mockMetrics.Verify( @@ -468,7 +468,7 @@ public sealed class VexGateStageExecutorTests // Act & Assert await Assert.ThrowsAsync( - () => executor.ExecuteAsync(null!, CancellationToken.None).AsTask()); + () => executor.ExecuteAsync(null!, TestContext.Current.CancellationToken).AsTask()); } [Fact] diff --git a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/WorkerBasicScanScenarioTests.cs b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/WorkerBasicScanScenarioTests.cs index 9905ff856..fea182732 100644 --- a/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/WorkerBasicScanScenarioTests.cs +++ b/src/Scanner/__Tests/StellaOps.Scanner.Worker.Tests/WorkerBasicScanScenarioTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -34,7 +34,7 @@ public sealed class WorkerBasicScanScenarioTests public async Task DelayAsync_CompletesAfterTimeAdvance() { var scheduler = new ControlledDelayScheduler(); - var delayTask = scheduler.DelayAsync(TimeSpan.FromSeconds(5), CancellationToken.None); + var delayTask = scheduler.DelayAsync(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken); scheduler.AdvanceBy(TimeSpan.FromSeconds(5)); await delayTask.WaitAsync(TimeSpan.FromSeconds(1)); } @@ -95,7 +95,7 @@ public sealed class WorkerBasicScanScenarioTests var worker = services.GetRequiredService(); - await worker.StartAsync(CancellationToken.None); + await worker.StartAsync(TestContext.Current.CancellationToken); await jobSource.LeaseIssued.Task.WaitAsync(TimeSpan.FromSeconds(5)); await Task.Yield(); @@ -121,7 +121,7 @@ public sealed class WorkerBasicScanScenarioTests throw new TimeoutException($"Worker did not complete within timeout. Logs:{Environment.NewLine}{stageLogs}", ex); } - await worker.StopAsync(CancellationToken.None); + await worker.StopAsync(TestContext.Current.CancellationToken); Assert.True(lease.Completed.Task.IsCompletedSuccessfully, "Job should complete successfully."); Assert.Single(analyzer.Executions); diff --git a/src/Scheduler/__Tests/StellaOps.Scheduler.Worker.Tests/Heartbeat/HeartbeatTimeoutTests.cs b/src/Scheduler/__Tests/StellaOps.Scheduler.Worker.Tests/Heartbeat/HeartbeatTimeoutTests.cs index ad5769717..700c547ca 100644 --- a/src/Scheduler/__Tests/StellaOps.Scheduler.Worker.Tests/Heartbeat/HeartbeatTimeoutTests.cs +++ b/src/Scheduler/__Tests/StellaOps.Scheduler.Worker.Tests/Heartbeat/HeartbeatTimeoutTests.cs @@ -162,6 +162,7 @@ public sealed class HeartbeatTimeoutTests // Assert var recoveredJob = await jobStore.GetJobAsync(jobId); + Assert.NotNull(recoveredJob); recoveredJob.State.Should().Be(JobState.Pending, "stale job should be reset to pending"); recoveredJob.LockHolder.Should().BeNull("stale lock should be released"); @@ -215,6 +216,7 @@ public sealed class HeartbeatTimeoutTests // Assert var jobAfterCleanup = await jobStore.GetJobAsync(jobId); + Assert.NotNull(jobAfterCleanup); jobAfterCleanup.State.Should().Be(JobState.Processing, "active job should not be reset"); jobAfterCleanup.LockHolder.Should().Be("active-worker", "active lock should be preserved"); diff --git a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/BundleImportEvidenceTests.cs b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/BundleImportEvidenceTests.cs index 9fef1ff9b..2b90a82cb 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/BundleImportEvidenceTests.cs +++ b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/BundleImportEvidenceTests.cs @@ -97,7 +97,7 @@ public sealed class BundleImportEvidenceTests Assert.True(result.Success); Assert.NotNull(result.Snapshot); Assert.NotNull(result.EvidencePointer); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Trait("Category", TestCategories.Unit)] @@ -167,7 +167,7 @@ public sealed class BundleImportEvidenceTests var result = await service.CaptureAsync(evidence, CancellationToken.None); Assert.True(result.Success); - Assert.Equal(1, timelineSink.Count); + Assert.Single(timelineSink); var evt = timelineSink.GetEvents()[0]; Assert.Equal("bundle.import.evidence_captured", evt.EventType); } diff --git a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunAttestationTests.cs b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunAttestationTests.cs index fed67d506..218bfff3e 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunAttestationTests.cs +++ b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunAttestationTests.cs @@ -114,7 +114,7 @@ public sealed class PackRunAttestationTests await service.GenerateAsync(request, CancellationToken.None); - Assert.Equal(1, timelineSink.Count); + Assert.Single(timelineSink); var evt = timelineSink.GetEvents()[0]; Assert.Equal(PackRunAttestationEventTypes.AttestationCreated, evt.EventType); } diff --git a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunEvidenceSnapshotTests.cs b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunEvidenceSnapshotTests.cs index cb357e472..b60c4e899 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunEvidenceSnapshotTests.cs +++ b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunEvidenceSnapshotTests.cs @@ -566,7 +566,7 @@ public sealed class PackRunEvidenceSnapshotTests Assert.NotNull(result.Snapshot); Assert.NotNull(result.EvidencePointer); Assert.Equal(PackRunEvidenceSnapshotKind.RunCompletion, result.Snapshot.Kind); - Assert.Equal(1, store.Count); + Assert.Single(store); } [Trait("Category", TestCategories.Unit)] diff --git a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunIncidentModeTests.cs b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunIncidentModeTests.cs index c833c0887..71dd06211 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunIncidentModeTests.cs +++ b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunIncidentModeTests.cs @@ -87,7 +87,7 @@ public sealed class PackRunIncidentModeTests await service.ActivateAsync(request, CancellationToken.None); - Assert.Equal(1, timelineSink.Count); + Assert.Single(timelineSink); var evt = timelineSink.GetEvents()[0]; Assert.Equal(PackRunIncidentEventTypes.IncidentModeActivated, evt.EventType); } diff --git a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunTimelineEventTests.cs b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunTimelineEventTests.cs index 69b35c250..563e10308 100644 --- a/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunTimelineEventTests.cs +++ b/src/TaskRunner/StellaOps.TaskRunner/StellaOps.TaskRunner.Tests/PackRunTimelineEventTests.cs @@ -322,7 +322,7 @@ public sealed class PackRunTimelineEventTests Assert.True(result.Success); Assert.NotNull(result.Sequence); Assert.False(result.Deduplicated); - Assert.Equal(1, sink.Count); + Assert.Single(sink); } [Trait("Category", TestCategories.Unit)] @@ -347,7 +347,7 @@ public sealed class PackRunTimelineEventTests // Assert Assert.True(result.Success); Assert.True(result.Deduplicated); - Assert.Equal(1, sink.Count); + Assert.Single(sink); } [Trait("Category", TestCategories.Unit)] @@ -461,7 +461,7 @@ public sealed class PackRunTimelineEventTests sink.Clear(); // Assert - Assert.Equal(0, sink.Count); + Assert.Empty(sink); } #endregion @@ -493,7 +493,7 @@ public sealed class PackRunTimelineEventTests Assert.False(result.Deduplicated); Assert.Equal(PackRunEventTypes.PackStarted, result.Event.EventType); Assert.Equal(TestRunId, result.Event.RunId); - Assert.Equal(1, sink.Count); + Assert.Single(sink); } [Trait("Category", TestCategories.Unit)] @@ -695,7 +695,7 @@ public sealed class PackRunTimelineEventTests // Assert Assert.Equal(0, result.Emitted); Assert.Equal(1, result.Deduplicated); - Assert.Equal(1, sink.Count); // Only one event stored + Assert.Single(sink); // Only one event stored } #endregion diff --git a/src/__Libraries/StellaOps.Evidence.Core.Tests/InMemoryEvidenceStoreTests.cs b/src/__Libraries/StellaOps.Evidence.Core.Tests/InMemoryEvidenceStoreTests.cs index 3d744adb7..a18197e18 100644 --- a/src/__Libraries/StellaOps.Evidence.Core.Tests/InMemoryEvidenceStoreTests.cs +++ b/src/__Libraries/StellaOps.Evidence.Core.Tests/InMemoryEvidenceStoreTests.cs @@ -38,7 +38,7 @@ public class InMemoryEvidenceStoreTests var result = await _store.StoreAsync(evidence); Assert.Equal(evidence.EvidenceId, result); - Assert.Equal(1, _store.Count); + Assert.Single(_store); } [Trait("Category", TestCategories.Unit)] @@ -50,7 +50,7 @@ public class InMemoryEvidenceStoreTests await _store.StoreAsync(evidence); await _store.StoreAsync(evidence); - Assert.Equal(1, _store.Count); + Assert.Single(_store); } [Trait("Category", TestCategories.Unit)] @@ -99,7 +99,7 @@ public class InMemoryEvidenceStoreTests var count = await _store.StoreBatchAsync([]); Assert.Equal(0, count); - Assert.Equal(0, _store.Count); + Assert.Empty(_store); } #endregion @@ -283,7 +283,7 @@ public class InMemoryEvidenceStoreTests var deleted = await _store.DeleteAsync(evidence.EvidenceId); Assert.True(deleted); - Assert.Equal(0, _store.Count); + Assert.Empty(_store); } [Trait("Category", TestCategories.Unit)] @@ -348,7 +348,7 @@ public class InMemoryEvidenceStoreTests _store.Clear(); - Assert.Equal(0, _store.Count); + Assert.Empty(_store); } #endregion diff --git a/src/__Libraries/StellaOps.Infrastructure.Postgres/Repositories/RepositoryBase.cs b/src/__Libraries/StellaOps.Infrastructure.Postgres/Repositories/RepositoryBase.cs index 334ed3618..56dfc1c44 100644 --- a/src/__Libraries/StellaOps.Infrastructure.Postgres/Repositories/RepositoryBase.cs +++ b/src/__Libraries/StellaOps.Infrastructure.Postgres/Repositories/RepositoryBase.cs @@ -73,7 +73,10 @@ public abstract class RepositoryBase where TDataSource : DataSource { if (values is null) { - command.Parameters.AddWithValue(name, DBNull.Value); + command.Parameters.Add(new NpgsqlParameter(name, NpgsqlDbType.Array | NpgsqlDbType.Uuid) + { + Value = DBNull.Value + }); } else { @@ -91,7 +94,10 @@ public abstract class RepositoryBase where TDataSource : DataSource { if (values is null) { - command.Parameters.AddWithValue(name, DBNull.Value); + command.Parameters.Add(new NpgsqlParameter(name, NpgsqlDbType.Array | NpgsqlDbType.Text) + { + Value = DBNull.Value + }); } else { diff --git a/src/__Libraries/StellaOps.Replay.Core.Tests/FeedSnapshot/FeedSnapshotCoordinatorTests.cs b/src/__Libraries/StellaOps.Replay.Core.Tests/FeedSnapshot/FeedSnapshotCoordinatorTests.cs index b05b938f9..67b3847ea 100644 --- a/src/__Libraries/StellaOps.Replay.Core.Tests/FeedSnapshot/FeedSnapshotCoordinatorTests.cs +++ b/src/__Libraries/StellaOps.Replay.Core.Tests/FeedSnapshot/FeedSnapshotCoordinatorTests.cs @@ -139,6 +139,7 @@ public sealed class FeedSnapshotCoordinatorTests var result = await coordinator.ValidateSnapshotAsync(snapshot.CompositeDigest); // Assert + Assert.NotNull(result); Assert.True(result.IsValid); Assert.Null(result.MissingSources); Assert.Null(result.DriftedSources); diff --git a/src/__Libraries/StellaOps.Resolver.Tests/CycleDetectionTests.cs b/src/__Libraries/StellaOps.Resolver.Tests/CycleDetectionTests.cs index 3fe64c524..470be5b06 100644 --- a/src/__Libraries/StellaOps.Resolver.Tests/CycleDetectionTests.cs +++ b/src/__Libraries/StellaOps.Resolver.Tests/CycleDetectionTests.cs @@ -114,7 +114,7 @@ public class CycleDetectionTests var result = validator.Validate(graph); Assert.False(result.IsValid); - Assert.Single(result.Errors.Where(e => e.Contains("Cycle detected"))); + Assert.Single(result.Errors, e => e.Contains("Cycle detected")); } [Trait("Category", TestCategories.Unit)] diff --git a/src/__Libraries/__Tests/StellaOps.Signals.Tests/CallgraphIngestionTests.cs b/src/__Libraries/__Tests/StellaOps.Signals.Tests/CallgraphIngestionTests.cs index f2a1c3d2c..bfda4d3dc 100644 --- a/src/__Libraries/__Tests/StellaOps.Signals.Tests/CallgraphIngestionTests.cs +++ b/src/__Libraries/__Tests/StellaOps.Signals.Tests/CallgraphIngestionTests.cs @@ -55,7 +55,7 @@ public class CallgraphIngestionTests : IClassFixture Assert.Equal(component, doc.Component); Assert.Equal("1.0.0", doc.Version); Assert.Equal(2, doc.Nodes.Count); - Assert.Equal(1, doc.Edges.Count); + Assert.Single(doc.Edges); var artifactPath = Path.Combine(factory.StoragePath, body.ArtifactPath); Assert.True(File.Exists(artifactPath)); diff --git a/src/__Tests/Tools/FixtureHarvester/FixtureHarvester.Tests.csproj b/src/__Tests/Tools/FixtureHarvester/FixtureHarvester.Tests.csproj index 454d07d3f..36712b67a 100644 --- a/src/__Tests/Tools/FixtureHarvester/FixtureHarvester.Tests.csproj +++ b/src/__Tests/Tools/FixtureHarvester/FixtureHarvester.Tests.csproj @@ -8,8 +8,14 @@ preview false true + + false + + + +