@@ -336,34 +336,39 @@ function coverage {
336336 forge --version
337337
338338 # Default values
339- MATCH_PATH =" "
339+ TEST_MATCH_PATH =" "
340340 LCOV=false
341341 SERVE=false
342342 HELP=false
343343 GOVERNANCE=false
344+ CORE=false
344345
345346 # Help text
346347 show_help () {
347348 echo " Usage: ./bootstrap.sh coverage [options]"
348349 echo " Options:"
349- echo " -p <path> Run coverage only for files matching this path pattern"
350- echo " -l Generate LCOV report"
351- echo " -s Serve coverage report (requires -l)"
350+ echo " -p <path> Run only tests in files matching this path pattern"
351+ echo " -c Run core coverage using only non-governance tests"
352+ echo " -l Generate a fresh LCOV report"
353+ echo " -s Serve the existing coverage report"
352354 echo " -g Run coverage for governance contracts using only gov tests"
353355 echo " -h Show this help message"
354356 echo " "
355357 echo " Examples:"
356358 echo " ./bootstrap.sh coverage # Run coverage for all files"
357- echo " ./bootstrap.sh coverage -p src/core # Run coverage only for src/core"
358- echo " ./bootstrap.sh coverage -l -s # Generate and serve LCOV report"
359+ echo " ./bootstrap.sh coverage -p test/staking_asset_handler/**/*.t.sol # Run only matching tests"
360+ echo " ./bootstrap.sh coverage -c # Run core coverage using only non-governance tests"
361+ echo " ./bootstrap.sh coverage -s # Serve the existing coverage report"
362+ echo " ./bootstrap.sh coverage -l -s # Generate and serve a fresh LCOV report"
359363 echo " ./bootstrap.sh coverage -g # Run coverage for governance contracts using only gov tests"
360364 echo " ./bootstrap.sh coverage -g -l -s # Run coverage for governance contracts using only gov tests with LCOV report and serve"
361365 }
362366
363367 # Parse options
364- while getopts " p:lshg " opt; do
368+ while getopts " p:lcshg " opt; do
365369 case $opt in
366- p) MATCH_PATH=" $OPTARG " ;;
370+ p) TEST_MATCH_PATH=" $OPTARG " ;;
371+ c) CORE=true ;;
367372 l) LCOV=true ;;
368373 s) SERVE=true ;;
369374 h) HELP=true ;;
@@ -378,54 +383,100 @@ function coverage {
378383 exit 0
379384 fi
380385
381- # Validate serve option
382386 if [ " $SERVE " = true ] && [ " $LCOV " = false ]; then
383- echo " Error: -s option requires -l option to be enabled"
387+ if [ -n " $TEST_MATCH_PATH " ] || [ " $GOVERNANCE " = true ] || [ " $CORE " = true ]; then
388+ echo " Warning: -s serves the existing report only; it cannot be combined with -p, -c, or -g without -l"
389+ exit 1
390+ fi
391+
392+ coverage_serve
393+ exit 0
394+ fi
395+
396+ download_solc
397+
398+ local -a ENV_VARS=(" FOUNDRY_PROFILE=coverage" " FORGE_COVERAGE=true" )
399+ local -a CMD=(" forge" " coverage" " --offline" )
400+
401+ if [ " $GOVERNANCE " = true ] && [ " $CORE " = true ]; then
402+ echo " Warning: -c and -g cannot be used together"
384403 exit 1
385404 fi
386405
387- # Build the command
388406 if [ " $GOVERNANCE " = true ]; then
389- CMD=" FORGE_COVERAGE=true forge coverage --match-path \" test/governance/**/*.t.sol\" --no-match-coverage \" (test|script|mock|generated|core|periphery)\" "
407+ CMD+=(
408+ " --match-path" " test/governance/**/*.t.sol"
409+ " --no-match-coverage" " (test|script|mock|generated|core|periphery)"
410+ )
411+ elif [ " $CORE " = true ]; then
412+ CMD+=(
413+ " --no-match-path" " test/governance/**/*.t.sol"
414+ " --no-match-coverage" " (test|script|mock|generated|governance)"
415+ )
390416 else
391- # Default coverage command
392- CMD=" FORGE_COVERAGE=true forge coverage --no-match-coverage \" (test|script|mock|generated)\" "
417+ CMD+=(" --no-match-coverage" " (test|script|mock|generated)" )
393418 fi
394419
395- if [ -n " $MATCH_PATH " ] && [ " $GOVERNANCE " = true ]; then
396- echo " Warning: -p option is not supported in governance mode"
420+ if [ -n " $TEST_MATCH_PATH " ] && { [ " $GOVERNANCE " = true ] || [ " $CORE " = true ] ; } ; then
421+ echo " Warning: -p option is not supported in governance or core mode"
397422 exit 1
398423 fi
399424
400- # Add path filter if specified (only if not in governance mode)
401- if [ -n " $MATCH_PATH " ] && [ " $GOVERNANCE " = false ]; then
402- if [ ! -e " $MATCH_PATH " ]; then
403- echo " Warning: Path '$MATCH_PATH ' does not exist"
425+ # Add a test-file filter if specified (only if not in governance mode).
426+ # This narrows which tests execute via `--match-path`; it does not scope
427+ # coverage output to those paths.
428+ if [ -n " $TEST_MATCH_PATH " ] && [ " $GOVERNANCE " = false ]; then
429+ local -a MATCHED_PATHS=()
430+ shopt -s globstar nullglob
431+ MATCHED_PATHS=($TEST_MATCH_PATH )
432+ shopt -u globstar nullglob
433+
434+ if [ ${# MATCHED_PATHS[@]} -eq 0 ]; then
435+ echo " Warning: Path pattern '$TEST_MATCH_PATH ' did not match any files"
404436 exit 1
405437 fi
406- CMD= " $CMD --match-path \" $MATCH_PATH \" "
438+ CMD+=( " --match-path" " $TEST_MATCH_PATH " )
407439 fi
408440
409441 # Add LCOV report if requested
410442 if [ " $LCOV " = true ]; then
411- CMD= " $CMD --report lcov"
443+ CMD+=( " --report" " lcov" )
412444 fi
413445
414- echo " Running coverage with command: $CMD "
415- eval " $CMD "
446+ local DISPLAY_CMD
447+ printf -v DISPLAY_CMD ' %q ' env " ${ENV_VARS[@]} " " ${CMD[@]} "
448+ echo " Running coverage with command: ${DISPLAY_CMD% } "
449+ env " ${ENV_VARS[@]} " " ${CMD[@]} "
416450
417451 # Serve report if requested
418452 if [ " $SERVE " = true ]; then
419- if ! command -v genhtml & > /dev/null; then
420- echo " Error: genhtml not found. Please install lcov package."
421- exit 1
422- fi
453+ coverage_serve
454+ fi
455+ }
456+
457+ function coverage_serve {
458+ echo_header " l1-contracts coverage serve"
459+
460+ if ! command -v genhtml & > /dev/null; then
461+ echo " Error: genhtml not found. Please install lcov package."
462+ exit 1
463+ fi
423464
424- mkdir -p coverage
425- genhtml lcov.info --branch-coverage --output-dir coverage
426- echo " Serving coverage report at http://localhost:8000"
427- python3 -m http.server --directory " coverage" 8000
465+ if [ ! -f " lcov.info" ]; then
466+ echo " Error: lcov.info not found. Run './bootstrap.sh coverage -l' first."
467+ exit 1
468+ fi
469+
470+ mkdir -p coverage
471+ # Foundry can emit LCOV branch records that genhtml treats as inconsistent
472+ # even when the report is otherwise usable.
473+ if ! genhtml lcov.info --branch-coverage --ignore-errors inconsistent,inconsistent --output-dir coverage; then
474+ echo " Error: failed to generate coverage HTML from lcov.info."
475+ echo " If the source tree has changed since lcov.info was created, rerun './bootstrap.sh coverage -l'."
476+ exit 1
428477 fi
478+ echo " Serving coverage report at http://localhost:8000"
479+ python3 -m http.server --directory " coverage" 8000
429480}
430481
431482function release {
0 commit comments