From 1885016cc512898b93461d021b73ab314e6b7361 Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Tue, 2 Sep 2025 20:43:28 -0400 Subject: [PATCH 1/3] test coverage --- .github/workflows/coverage.yml | 52 +++++++++++++--- scripts/generate_coverage.sh | 110 +++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 10 deletions(-) create mode 100755 scripts/generate_coverage.sh diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ad0ea7a220..fd299a0316 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -5,8 +5,8 @@ on: [push, pull_request, workflow_dispatch] jobs: file-changes: name: Detect File Changes - runs-on: 'ubuntu-latest' - outputs: + runs-on: ubuntu-latest + outputs: checkall: ${{ steps.changes.outputs.checkall }} steps: - name: Clone @@ -15,34 +15,66 @@ jobs: - name: Detect Changes uses: dorny/paths-filter@v3 id: changes - with: + with: filters: ".github/file-filter.yml" run: name: Coverage Test on CodeCov if: needs.file-changes.outputs.checkall == 'true' needs: file-changes - runs-on: "ubuntu-latest" + runs-on: ubuntu-latest steps: - name: Checkouts uses: actions/checkout@v4 - name: Setup Ubuntu run: | - sudo apt update -y - sudo apt install -y tar wget make cmake gcc g++ python3 \ - python3-dev "openmpi-*" libopenmpi-dev hdf5-tools \ - libfftw3-dev libhdf5-dev libblas-dev liblapack-dev + sudo apt update -y + sudo apt install -y tar wget make cmake gcc g++ python3 python3-pip \ + "openmpi-*" libopenmpi-dev hdf5-tools libfftw3-dev libhdf5-dev \ + libblas-dev liblapack-dev + python3 -m pip install --upgrade pip gcovr - - name: Build + - name: Build (with coverage) run: /bin/bash mfc.sh build -j $(nproc) --gcov - name: Test run: /bin/bash mfc.sh test -a -j $(nproc) - - name: Upload coverage reports to Codecov + - name: Generate coverage (gcovr XML) + run: | + # Create a stable, filtered XML that points to build-side files first + gcovr \ + --root "${{ github.workspace }}" \ + --object-directory "${{ github.workspace }}/build" \ + --filter '.*/fypp/.+\.f90$' \ + --exclude '.*(tests|examples|toolchain|docs|benchmarks)/.*' \ + --gcov-ignore-parse-errors \ + --xml-pretty -o coverage.xml + + - name: Rewrite paths from generated .fpp.f90 -> repo .fpp + run: | + python3 - <<'PY' + import os, xml.etree.ElementTree as ET + fn = "coverage.xml" + t = ET.parse(fn) + r = t.getroot() + for c in r.iter('class'): + p = c.get('filename') or '' + if p.endswith('.fpp.f90'): + base = os.path.basename(p).rsplit('.fpp.f90', 1)[0] + '.fpp' + for sub in ('pre_process','simulation','post_process','common'): + cand = os.path.join('src', sub, base) + if os.path.exists(cand): + c.set('filename', cand) + break + t.write(fn, encoding='utf-8', xml_declaration=True) + PY + + - name: Upload coverage to Codecov (XML only) uses: codecov/codecov-action@v4 with: + files: coverage.xml fail_ci_if_error: false verbose: true env: diff --git a/scripts/generate_coverage.sh b/scripts/generate_coverage.sh new file mode 100755 index 0000000000..3a53d0e429 --- /dev/null +++ b/scripts/generate_coverage.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +# MFC Coverage Generation Script +# This script generates coverage reports locally using gcovr with the same +# configuration as the CI workflow. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +MFC_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo "MFC Coverage Generation" +echo "======================" +echo "Root directory: $MFC_ROOT" +echo + +# Check if gcovr is available +if ! command -v gcovr &> /dev/null; then + echo "Error: gcovr is not installed. Install it with:" + echo " pip install gcovr" + exit 1 +fi + +cd "$MFC_ROOT" + +# Check if MFC was built with coverage +if [ ! -d "build" ]; then + echo "Error: No build directory found. Build MFC with coverage first:" + echo " ./mfc.sh build --gcov -j \$(nproc)" + exit 1 +fi + +# Look for gcov files +GCOV_FILES=$(find build -name "*.gcda" 2>/dev/null | wc -l) +if [ "$GCOV_FILES" -eq 0 ]; then + echo "Warning: No coverage data found. Run tests first:" + echo " ./mfc.sh test -j \$(nproc) -f EA8FA07E -t 9E2CA336" + echo +fi + +echo "Generating coverage reports..." + +# Generate XML coverage report (same as CI) +gcovr \ + --root "$MFC_ROOT" \ + --object-directory "$MFC_ROOT/build" \ + --filter '.*/fypp/.+\.f90$' \ + --exclude '.*(tests|examples|toolchain|docs|benchmarks)/.*' \ + --gcov-ignore-parse-errors \ + --xml-pretty -o coverage.xml + +echo "Generated coverage.xml" + +# Also generate a broader report for debugging +gcovr \ + --root "$MFC_ROOT" \ + --object-directory "$MFC_ROOT/build" \ + --exclude '.*(tests|examples|toolchain|docs|benchmarks)/.*' \ + --gcov-ignore-parse-errors \ + --xml-pretty -o coverage_all.xml + +echo "Generated coverage_all.xml (broader scope for debugging)" + +# Generate HTML coverage report for local viewing +gcovr \ + --root "$MFC_ROOT" \ + --object-directory "$MFC_ROOT/build" \ + --filter '.*/fypp/.+\.f90$' \ + --exclude '.*(tests|examples|toolchain|docs|benchmarks)/.*' \ + --gcov-ignore-parse-errors \ + --html-details -o coverage.html + +echo "Generated coverage.html" + +# Rewrite paths from generated .fpp.f90 -> repo .fpp (same as CI) +python3 - <<'PY' +import os, xml.etree.ElementTree as ET + +print("Rewriting XML paths from generated .fpp.f90 to source .fpp files...") + +fn = "coverage.xml" +if not os.path.exists(fn): + print(f"Error: {fn} not found") + exit(1) + +t = ET.parse(fn) +r = t.getroot() +remapped = 0 + +for c in r.iter('class'): + p = c.get('filename') or '' + if p.endswith('.fpp.f90'): + base = os.path.basename(p).rsplit('.fpp.f90', 1)[0] + '.fpp' + for sub in ('pre_process','simulation','post_process','common'): + cand = os.path.join('src', sub, base) + if os.path.exists(cand): + c.set('filename', cand) + remapped += 1 + break + +t.write(fn, encoding='utf-8', xml_declaration=True) +print(f"Remapped {remapped} file paths in coverage.xml") +PY + +echo +echo "Coverage reports generated:" +echo " - coverage.xml (for Codecov upload)" +echo " - coverage.html (for local viewing)" +echo +echo "To view the HTML report, open coverage.html in your browser." From 2456c9dfe40326240310b2e6c865969e49a2ed0e Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Tue, 2 Sep 2025 20:46:07 -0400 Subject: [PATCH 2/3] make coverage run --- src/simulation/m_acoustic_src.fpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/simulation/m_acoustic_src.fpp b/src/simulation/m_acoustic_src.fpp index b14528b9d5..6719643ca5 100644 --- a/src/simulation/m_acoustic_src.fpp +++ b/src/simulation/m_acoustic_src.fpp @@ -17,7 +17,7 @@ module m_acoustic_src use m_helper_basic !< Functions to compare floating point numbers - use m_constants !< Definitions of the constants + use m_constants !< Definitions of constants implicit none private; public :: s_initialize_acoustic_src, s_precalculate_acoustic_spatial_sources, s_acoustic_src_calculations From f189288284d2d838d53d70a60c507e7f68b7b6a6 Mon Sep 17 00:00:00 2001 From: Spencer Bryngelson Date: Wed, 3 Sep 2025 09:04:38 -0400 Subject: [PATCH 3/3] Update gcovr command and add Codecov options --- .github/workflows/coverage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index fd299a0316..9fb5f2c66c 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -43,15 +43,13 @@ jobs: - name: Generate coverage (gcovr XML) run: | - # Create a stable, filtered XML that points to build-side files first gcovr \ --root "${{ github.workspace }}" \ --object-directory "${{ github.workspace }}/build" \ - --filter '.*/fypp/.+\.f90$' \ --exclude '.*(tests|examples|toolchain|docs|benchmarks)/.*' \ --gcov-ignore-parse-errors \ --xml-pretty -o coverage.xml - + - name: Rewrite paths from generated .fpp.f90 -> repo .fpp run: | python3 - <<'PY' @@ -77,6 +75,8 @@ jobs: files: coverage.xml fail_ci_if_error: false verbose: true + disable_search: true + disable_file_fixes: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}