Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.

PerfectGraphAnalyzer: BitSet Bron-Kerbosch + DSatur, add tests #728

PerfectGraphAnalyzer: BitSet Bron-Kerbosch + DSatur, add tests

PerfectGraphAnalyzer: BitSet Bron-Kerbosch + DSatur, add tests #728

Workflow file for this run

name: Code Coverage
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
permissions:
contents: read
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: 17
distribution: temurin
- name: Download test dependencies
run: |
mkdir -p Gvisual/lib/test
# JUnit 4 + Hamcrest
curl -sL -o Gvisual/lib/test/junit-4.13.2.jar \
https://repo1.maven.org/maven2/junit/junit/4.13.2/junit-4.13.2.jar
curl -sL -o Gvisual/lib/test/hamcrest-core-1.3.jar \
https://repo1.maven.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
# JaCoCo agent + CLI for coverage instrumentation and reporting
curl -sL -o /tmp/jacoco.zip \
https://repo1.maven.org/maven2/org/jacoco/jacoco/0.8.12/jacoco-0.8.12.zip
unzip -o /tmp/jacoco.zip -d /tmp/jacoco
cp /tmp/jacoco/lib/jacocoagent.jar Gvisual/lib/test/jacocoagent.jar
cp /tmp/jacoco/lib/jacococli.jar Gvisual/lib/test/jacococli.jar
- name: Compile source
working-directory: Gvisual
run: |
mkdir -p build/classes
find src -name '*.java' > sources.txt
javac -source 8 -target 8 \
-cp "$(find lib -name '*.jar' -not -path 'lib/test/*' | tr '\n' ':')" \
-d build/classes \
@sources.txt
- name: Compile tests
working-directory: Gvisual
run: |
mkdir -p build/test/classes
find test -name '*.java' > test-sources.txt
javac -source 8 -target 8 \
-cp "build/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
-d build/test/classes \
@test-sources.txt
- name: Discover test classes
id: discover-tests
working-directory: Gvisual
run: |
# Auto-discover all *Test classes from compiled test output
TEST_CLASSES=$(find build/test/classes -name '*Test.class' \
| sed 's|build/test/classes/||;s|\.class$||;s|/|.|g' \
| sort)
echo "Found $(echo "$TEST_CLASSES" | wc -l) test classes"
echo "$TEST_CLASSES"
# Store as space-separated for JUnitCore
echo "classes=$(echo $TEST_CLASSES | tr '\n' ' ')" >> $GITHUB_OUTPUT
- name: Run tests with JaCoCo coverage
working-directory: Gvisual
run: |
java \
-javaagent:lib/test/jacocoagent.jar=destfile=build/jacoco.exec,includes=gvisual.*:app.* \
-cp "build/classes:build/test/classes:$(find lib -name '*.jar' | tr '\n' ':')" \
org.junit.runner.JUnitCore \
${{ steps.discover-tests.outputs.classes }}
- name: Generate coverage report
working-directory: Gvisual
run: |
mkdir -p build/coverage
# Generate HTML report
java -jar lib/test/jacococli.jar report build/jacoco.exec \
--classfiles build/classes \
--sourcefiles src \
--html build/coverage/html \
--xml build/coverage/coverage.xml \
--csv build/coverage/coverage.csv \
--name "GraphVisual Coverage Report"
- name: Coverage summary
working-directory: Gvisual
run: |
echo "## 📊 Code Coverage Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ ! -f build/coverage/coverage.csv ]; then
echo "_No coverage.csv produced._" >> $GITHUB_STEP_SUMMARY
exit 0
fi
# First pass: aggregate totals across all classes.
overall_missed=0
overall_covered=0
branch_missed_t=0
branch_covered_t=0
line_missed_t=0
line_covered_t=0
while IFS=',' read -r group package class inst_missed inst_covered branch_missed branch_covered line_missed line_covered rest; do
overall_missed=$((overall_missed + inst_missed))
overall_covered=$((overall_covered + inst_covered))
branch_missed_t=$((branch_missed_t + branch_missed))
branch_covered_t=$((branch_covered_t + branch_covered))
line_missed_t=$((line_missed_t + line_missed))
line_covered_t=$((line_covered_t + line_covered))
done < <(tail -n +2 build/coverage/coverage.csv)
inst_total=$((overall_missed + overall_covered))
branch_total=$((branch_missed_t + branch_covered_t))
line_total=$((line_missed_t + line_covered_t))
inst_pct=0; [ "$inst_total" -gt 0 ] && inst_pct=$((overall_covered * 100 / inst_total))
branch_pct=0; [ "$branch_total" -gt 0 ] && branch_pct=$((branch_covered_t * 100 / branch_total))
line_pct=0; [ "$line_total" -gt 0 ] && line_pct=$((line_covered_t * 100 / line_total))
echo "**Overall instruction coverage: ${inst_pct}%** (${overall_covered}/${inst_total})" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Covered | Total | % |" >> $GITHUB_STEP_SUMMARY
echo "|--------|---------|-------|---|" >> $GITHUB_STEP_SUMMARY
echo "| Instructions | ${overall_covered} | ${inst_total} | ${inst_pct}% |" >> $GITHUB_STEP_SUMMARY
echo "| Branches | ${branch_covered_t} | ${branch_total} | ${branch_pct}% |" >> $GITHUB_STEP_SUMMARY
echo "| Lines | ${line_covered_t} | ${line_total} | ${line_pct}% |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "<details><summary>Per-class breakdown</summary>" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Package | Class | Instruction Coverage |" >> $GITHUB_STEP_SUMMARY
echo "|---------|-------|---------------------|" >> $GITHUB_STEP_SUMMARY
tail -n +2 build/coverage/coverage.csv | while IFS=',' read -r group package class inst_missed inst_covered rest; do
total=$((inst_missed + inst_covered))
if [ "$total" -gt 0 ]; then
pct=$((inst_covered * 100 / total))
echo "| $package | $class | ${pct}% (${inst_covered}/${total}) |" >> $GITHUB_STEP_SUMMARY
fi
done
echo "" >> $GITHUB_STEP_SUMMARY
echo "</details>" >> $GITHUB_STEP_SUMMARY
- name: Upload coverage report
uses: actions/upload-artifact@v7
with:
name: coverage-report
path: Gvisual/build/coverage/
retention-days: 30
- name: Enforce coverage threshold
working-directory: Gvisual
run: |
if [ -f build/coverage/coverage.csv ]; then
# Calculate overall instruction coverage
total_covered=0
total_missed=0
while IFS=',' read -r group package class inst_missed inst_covered rest; do
total_missed=$((total_missed + inst_missed))
total_covered=$((total_covered + inst_covered))
done < <(tail -n +2 build/coverage/coverage.csv)
total=$((total_missed + total_covered))
if [ "$total" -gt 0 ]; then
pct=$((total_covered * 100 / total))
echo "Overall instruction coverage: ${pct}%"
THRESHOLD=50
if [ "$pct" -lt "$THRESHOLD" ]; then
echo "::error::Coverage ${pct}% is below threshold ${THRESHOLD}%"
exit 1
fi
echo "✅ Coverage ${pct}% meets threshold ${THRESHOLD}%"
fi
fi
- name: Comment coverage on PR
if: github.event_name == 'pull_request'
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');
const csvPath = 'Gvisual/build/coverage/coverage.csv';
if (!fs.existsSync(csvPath)) return;
const lines = fs.readFileSync(csvPath, 'utf8').trim().split('\n').slice(1);
let totalCovered = 0, totalMissed = 0;
const rows = [];
for (const line of lines) {
const cols = line.split(',');
const pkg = cols[1], cls = cols[2];
const missed = parseInt(cols[3]), covered = parseInt(cols[4]);
const total = missed + covered;
const pct = total > 0 ? Math.round(covered * 100 / total) : 0;
totalMissed += missed;
totalCovered += covered;
rows.push(`| ${pkg} | ${cls} | ${pct}% (${covered}/${total}) |`);
}
const overallTotal = totalMissed + totalCovered;
const overallPct = overallTotal > 0 ? Math.round(totalCovered * 100 / overallTotal) : 0;
const body = [
'## 📊 Code Coverage Report',
'',
`**Overall: ${overallPct}%** (${totalCovered}/${overallTotal} instructions)`,
'',
'| Package | Class | Coverage |',
'|---------|-------|----------|',
...rows,
].join('\n');
// Find and update existing comment or create new
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const existing = comments.find(c => c.body.includes('📊 Code Coverage Report'));
if (existing) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existing.id,
body,
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body,
});
}
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v6
with:
files: Gvisual/build/coverage/coverage.xml
fail_ci_if_error: false
continue-on-error: true