diff --git a/.covdbg.yaml b/.covdbg.yaml new file mode 100644 index 0000000..fbd2b08 --- /dev/null +++ b/.covdbg.yaml @@ -0,0 +1,14 @@ +# MSVC coverage for ci-build.yml: the same sources as before (examples/, src/, tools/), +# without the broker test hook's private copy of the broker. +--- +version: 1 +source_root: "." +coverage: + default: + files: + include: + - "examples/**" + - "src/**" + - "tools/**" + exclude: + - "src/platform/windows/broker/**" diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 182af54..3be6214 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -22,7 +22,6 @@ env: COMMIT: ${{ inputs.release_commit }} FREEBSD_CLANG_VERSION: 19 FREEBSD_VERSION: '15.1' - OPENCPPCOVERAGE_VERSION: '0.9.9.0' PYTHON_VERSION: ${{ inputs.python_version }} jobs: @@ -30,6 +29,7 @@ jobs: name: Build (${{ matrix.name }}) permissions: contents: read + id-token: write # covdbg identifies this repository by the job's OIDC token runs-on: ${{ matrix.os }} defaults: run: @@ -225,20 +225,15 @@ jobs: mingw-w64-${{ matrix.toolchain }}-ninja mingw-w64-${{ matrix.toolchain }}-toolchain - - name: Setup Dependencies Windows MSVC - if: matrix.kind == 'msvc' - run: | - choco install opencppcoverage --version=${{ env.OPENCPPCOVERAGE_VERSION }} --yes --no-progress - - $openCppCoverageDir = "${env:ProgramFiles}\OpenCppCoverage" - if (!(Test-Path (Join-Path $openCppCoverageDir "OpenCppCoverage.exe"))) { - $openCppCoverageDir = "${env:ProgramFiles(x86)}\OpenCppCoverage" - } - if (!(Test-Path (Join-Path $openCppCoverageDir "OpenCppCoverage.exe"))) { - throw "OpenCppCoverage.exe was not found after Chocolatey install." - } - - $openCppCoverageDir | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + # GitHub issues no OIDC token to pull requests from forks, so MSVC coverage is measured on + # pushes and on pull requests from branches of this repository; fork pull requests run the tests only. + - name: Setup covdbg + if: >- + matrix.kind == 'msvc' && + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + uses: liasoft/setup-covdbg@6116a52a8ce697108056ce4b4cd2429424a231b1 # v1.0.0 + with: + version: 'latest' - name: Setup Windows coverage inspection tools if: matrix.kind == 'msvc' @@ -433,59 +428,32 @@ jobs: - name: Run tests MSVC id: test_msvc if: matrix.kind == 'msvc' + env: + MEASURE_COVERAGE: >- + ${{ github.event_name != 'pull_request' || + github.event.pull_request.head.repo.full_name == github.repository }} + working-directory: cmake-build-ci/tests run: | - $openCppCoverage = (Get-Command OpenCppCoverage.exe -ErrorAction SilentlyContinue).Source - if (!$openCppCoverage) { - $candidates = @( - "${env:ProgramFiles}\OpenCppCoverage\OpenCppCoverage.exe", - "${env:ProgramFiles(x86)}\OpenCppCoverage\OpenCppCoverage.exe" - ) - $openCppCoverage = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1 - } - if (!$openCppCoverage) { - throw "OpenCppCoverage.exe was not found." - } - - # The broker test hook compiles a private copy only for failure injection. - & $openCppCoverage ` - --sources "$env:GITHUB_WORKSPACE\examples" ` - --sources "$env:GITHUB_WORKSPACE\src" ` - --sources "$env:GITHUB_WORKSPACE\tools" ` - --excluded_sources "$env:GITHUB_WORKSPACE\src\platform\windows\broker" ` - "--export_type=cobertura:$env:GITHUB_WORKSPACE\cmake-build-ci\reports\coverage.xml" ` - --working_dir "$env:GITHUB_WORKSPACE\cmake-build-ci\tests" ` - -- ` - "$env:GITHUB_WORKSPACE\cmake-build-ci\tests\$env:CMAKE_BUILD_CONFIG\test_libvirtualhid.exe" ` - --gtest_color=yes ` + $testExe = ".\$env:CMAKE_BUILD_CONFIG\test_libvirtualhid.exe" + $testArgs = @( + "--gtest_color=yes", "--gtest_output=xml:$env:GITHUB_WORKSPACE\cmake-build-ci\reports\junit.xml" - - - name: Normalize MSVC coverage paths - if: >- - always() && - matrix.kind == 'msvc' && - (steps.test_msvc.outcome == 'success' || steps.test_msvc.outcome == 'failure') - run: | - $coveragePath = Join-Path $env:GITHUB_WORKSPACE "cmake-build-ci\reports\coverage.xml" - if (!(Test-Path $coveragePath)) { - return - } - - [xml] $coverage = Get-Content $coveragePath - $workspace = $env:GITHUB_WORKSPACE.Replace('\', '/') - foreach ($node in $coverage.SelectNodes('//*[@filename]')) { - $filename = $node.GetAttribute('filename').Replace('\', '/') - if ($filename.StartsWith("${workspace}/")) { - $filename = $filename.Substring($workspace.Length + 1) - } - - $node.SetAttribute('filename', $filename) + ) + if ($env:MEASURE_COVERAGE -ne 'true') { + & $testExe @testArgs + exit $LASTEXITCODE } - foreach ($source in $coverage.SelectNodes('//source')) { - $source.InnerText = '.' + # .covdbg.yaml selects the same sources as before; covdbg writes repository-relative paths. + covdbg --config "$env:GITHUB_WORKSPACE\.covdbg.yaml" --propagate-exit-code ` + --output "$env:GITHUB_WORKSPACE\cmake-build-ci\coverage.covdb" $testExe @testArgs + $testExit = $LASTEXITCODE + covdbg convert --input "$env:GITHUB_WORKSPACE\cmake-build-ci\coverage.covdb" --format COBERTURA ` + --output "$env:GITHUB_WORKSPACE\cmake-build-ci\reports\coverage.xml" + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE } - - $coverage.Save($coveragePath) + exit $testExit - name: Generate gcov report id: test_report diff --git a/.github/workflows/ci-results.yml b/.github/workflows/ci-results.yml index 279ae55..74c5b82 100644 --- a/.github/workflows/ci-results.yml +++ b/.github/workflows/ci-results.yml @@ -51,11 +51,11 @@ jobs: path: _reports - name: Debug coverage file - if: matrix.has_coverage + if: matrix.has_coverage && hashFiles('_reports/coverage.xml') != '' run: cat _reports/coverage.xml - name: Upload test coverage - if: matrix.has_coverage + if: matrix.has_coverage && hashFiles('_reports/coverage.xml') != '' uses: codecov/codecov-action@303a32d7a59b442fa8d48b6a1cc6825c09c847a5 # v7.1.1 with: disable_search: true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9377e47..325a37a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -90,6 +90,7 @@ jobs: - setup_release permissions: contents: read + id-token: write # covdbg identifies this repository by the job's OIDC token uses: ./.github/workflows/ci-build.yml with: python_version: ${{ needs.setup_release.outputs.python_version }} diff --git a/docs/development.md b/docs/development.md index 38df3e9..5de3035 100644 --- a/docs/development.md +++ b/docs/development.md @@ -9,7 +9,8 @@ sources and, when enabled, the diagnostic control model. GCC and Clang coverage instrumentation is confined to the tests directory. The normal library, examples, tools, and brokers remain free of coverage instrumentation, including when they are packaged from a build that also runs tests. MSVC coverage uses -OpenCppCoverage rather than compiler instrumentation. +covdbg, which reads the test binary and its PDB, rather than compiler +instrumentation. ## Windows library and tests diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 78ff24e..0f0a771 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -24,7 +24,7 @@ endif() set(TEST_BINARY test_libvirtualhid) # Recompile the library for coverage without instrumenting installed targets. -# MSVC coverage is collected externally with OpenCppCoverage. +# MSVC coverage is collected externally with covdbg. if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") add_compile_options(-fprofile-arcs -ftest-coverage -ggdb -O0) add_link_options(-fprofile-arcs -ftest-coverage)