Skip to content

Add comprehensive unit tests with Google Test, PETSc/MPI tests, functional BBPGD solver tests, and CI/CD pipeline with matrix testing #15

Add comprehensive unit tests with Google Test, PETSc/MPI tests, functional BBPGD solver tests, and CI/CD pipeline with matrix testing

Add comprehensive unit tests with Google Test, PETSc/MPI tests, functional BBPGD solver tests, and CI/CD pipeline with matrix testing #15

Workflow file for this run

name: C++ Unit Tests with Coverage
on:
push:
branches: [ main, develop, copilot/** ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
mpi_ranks: [1, 4, 8]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
g++ \
libopenmpi-dev \
openmpi-bin \
petsc-dev \
lcov
- name: Configure CMake
working-directory: ${{github.workspace}}/code/cpp
run: |
mkdir -p build
cd build
cmake -DENABLE_COVERAGE=ON ..
- name: Build main application
working-directory: ${{github.workspace}}/code/cpp/build
run: |
echo "Building main application..."
make -j$(nproc) cellcollectives || exit 1
echo "✅ Main application built successfully"
- name: Build tests
working-directory: ${{github.workspace}}/code/cpp/build
run: make -j$(nproc) unit_tests
- name: Run unit tests (MPI ranks=${{ matrix.mpi_ranks }})
working-directory: ${{github.workspace}}/code/cpp/build
run: |
if [ "${{ matrix.mpi_ranks }}" -eq 1 ]; then
echo "Running tests in single-process mode..."
./tests/unit_tests
else
echo "Running tests with MPI (${{ matrix.mpi_ranks }} ranks)..."
mpirun --allow-run-as-root --oversubscribe -np ${{ matrix.mpi_ranks }} ./tests/unit_tests
fi
echo "✅ Tests completed with ${{ matrix.mpi_ranks }} rank(s)"
- name: Generate coverage report
if: matrix.mpi_ranks == 1
working-directory: ${{github.workspace}}/code/cpp/build
run: |
# Capture coverage data
lcov --capture --directory . --output-file coverage.info --ignore-errors mismatch
# Filter out system files and test files
lcov --remove coverage.info '/usr/*' '*/build/_deps/*' '*/tests/*' \
--output-file coverage_filtered.info --ignore-errors unused
# Generate HTML report
genhtml coverage_filtered.info --output-directory coverage_report
# Print summary
echo "## Code Coverage Summary" >> $GITHUB_STEP_SUMMARY
lcov --summary coverage_filtered.info 2>&1 | tee -a $GITHUB_STEP_SUMMARY
- name: Upload coverage report
if: matrix.mpi_ranks == 1
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: ${{github.workspace}}/code/cpp/build/coverage_report/
retention-days: 30
- name: Comment coverage on PR
if: github.event_name == 'pull_request' && matrix.mpi_ranks == 1
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const coverage = fs.readFileSync('${{github.workspace}}/code/cpp/build/coverage_filtered.info', 'utf8');
// Parse coverage data
const lines = coverage.match(/LF:(\d+)/g);
const linesHit = coverage.match(/LH:(\d+)/g);
if (lines && linesHit) {
const totalLines = lines.reduce((sum, l) => sum + parseInt(l.split(':')[1]), 0);
const hitLines = linesHit.reduce((sum, l) => sum + parseInt(l.split(':')[1]), 0);
const percentage = totalLines > 0 ? ((hitLines / totalLines) * 100).toFixed(2) : 0;
const comment = `## Test Results ✅\n\n` +
`All tests passed! 🎉\n\n` +
`**Coverage:** ${percentage}% (${hitLines}/${totalLines} lines)\n\n` +
`**MPI Testing:** Tests validated with 1, 4, and 8 ranks\n\n` +
`[View detailed coverage report](https://github.com/${{github.repository}}/actions/runs/${{github.run_id}})`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
}