141 lines
5.7 KiB
Bash
Executable File
141 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# Per-workspace-crate line and branch coverage report.
|
|
#
|
|
# This is deliberately a report over every host-testable workspace package,
|
|
# not a misleading aggregate. STM32F7 platform/board images are target-only:
|
|
# their `panic-halt` handler cannot link into the host test harness, so they
|
|
# are reported as N/A and must be covered by target checks plus bench
|
|
# evidence instead.
|
|
#
|
|
# Prerequisites (kept out of the firmware dependency graph):
|
|
# cargo install cargo-llvm-cov --locked
|
|
# rustup toolchain install nightly --component llvm-tools-preview
|
|
# python3 (standard library only, for strict source-level accounting)
|
|
set -eu
|
|
|
|
if ! cargo llvm-cov --version >/dev/null 2>&1; then
|
|
echo "cargo-llvm-cov is required; install it with: cargo install cargo-llvm-cov --locked" >&2
|
|
exit 127
|
|
fi
|
|
|
|
if ! rustup toolchain list | grep -q '^nightly'; then
|
|
echo "nightly with llvm-tools-preview is required for branch coverage" >&2
|
|
exit 127
|
|
fi
|
|
|
|
if ! python3 --version >/dev/null 2>&1; then
|
|
echo "python3 is required for strict source-level coverage accounting" >&2
|
|
exit 127
|
|
fi
|
|
|
|
python3 scripts/test-summarize-test-coverage.py
|
|
|
|
# Keep instrumentation products outside a possibly shared target directory.
|
|
: "${CARGO_TARGET_DIR:=/tmp/kaptan-test-coverage}"
|
|
export CARGO_TARGET_DIR
|
|
mkdir -p "$CARGO_TARGET_DIR"
|
|
|
|
# `cargo llvm-cov` merges every instrumented object below `CARGO_TARGET_DIR`.
|
|
# A shared target directory therefore makes a later strict-core report include
|
|
# an unexecuted copy of a shared dependency built while testing an earlier
|
|
# package. Keep reports together but isolate each strict-core invocation. The
|
|
# non-core packages retain the shared directory: several intentionally
|
|
# target-only crates have no host-instrumented object to export by themselves.
|
|
coverage_root=$CARGO_TARGET_DIR
|
|
|
|
core_incomplete=0
|
|
|
|
report_package() {
|
|
package=$1
|
|
source_path=$2
|
|
shift 2
|
|
case "$package" in
|
|
kaptan-math|kaptan-navigation|kaptan-control|kaptan-safety)
|
|
package_target_dir="$coverage_root/$package"
|
|
lcov_report="$coverage_root/$package.lcov"
|
|
json_report="$coverage_root/$package.json"
|
|
report_format=strict-core
|
|
;;
|
|
*)
|
|
package_target_dir=$coverage_root
|
|
lcov_report="$coverage_root/$package.lcov"
|
|
report_format=lcov
|
|
;;
|
|
esac
|
|
|
|
case "$report_format" in
|
|
strict-core)
|
|
# Keep the strict core isolated, then export both representations
|
|
# from the same test run. LCOV `DA` defines source lines; JSON
|
|
# coordinates define branch identities across generic instances.
|
|
RUSTC_BOOTSTRAP=1 CARGO_TARGET_DIR="$package_target_dir" cargo llvm-cov \
|
|
--branch \
|
|
--no-report \
|
|
-p "$package" \
|
|
"$@"
|
|
RUSTC_BOOTSTRAP=1 CARGO_TARGET_DIR="$package_target_dir" cargo llvm-cov report \
|
|
--lcov \
|
|
--output-path "$lcov_report"
|
|
RUSTC_BOOTSTRAP=1 CARGO_TARGET_DIR="$package_target_dir" cargo llvm-cov report \
|
|
--json \
|
|
--output-path "$json_report"
|
|
totals=$(python3 scripts/summarize-test-coverage.py \
|
|
"$lcov_report" "$json_report" "$source_path")
|
|
;;
|
|
lcov)
|
|
RUSTC_BOOTSTRAP=1 CARGO_TARGET_DIR="$package_target_dir" cargo llvm-cov \
|
|
--branch \
|
|
--lcov \
|
|
--output-path "$lcov_report" \
|
|
-p "$package" \
|
|
"$@"
|
|
totals=$(awk -v source_path="$source_path" '
|
|
/^SF:/ { selected = index($0, source_path) != 0 }
|
|
selected && /^LF:/ { lines_found += substr($0, 4) }
|
|
selected && /^LH:/ { lines_hit += substr($0, 4) }
|
|
selected && /^BRF:/ { branches_found += substr($0, 5) }
|
|
selected && /^BRH:/ { branches_hit += substr($0, 5) }
|
|
END {
|
|
printf "%d %d %d %d", lines_hit, lines_found, branches_hit, branches_found
|
|
}
|
|
' "$lcov_report")
|
|
;;
|
|
esac
|
|
set -- $totals
|
|
printf '%-26s lines %s/%s, branches %s/%s\n' "$package" "$1" "$2" "$3" "$4"
|
|
|
|
case "$package" in
|
|
kaptan-math|kaptan-navigation|kaptan-control|kaptan-safety)
|
|
if [ "$1" -ne "$2" ] || [ "$3" -ne "$4" ]; then
|
|
core_incomplete=1
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
echo "Host test coverage (reports: $CARGO_TARGET_DIR; strict core unions LCOV DA lines and JSON branches)"
|
|
report_package kaptan-actuator /libs/kaptan-actuator/
|
|
report_package kaptan-control /libs/kaptan-control/
|
|
report_package kaptan-data-channel /libs/kaptan-data-channel/
|
|
report_package kaptan-dma /libs/kaptan-dma/
|
|
report_package kaptan-drivers /libs/kaptan-drivers/
|
|
report_package kaptan-i2c /libs/kaptan-i2c/
|
|
report_package kaptan-math /libs/kaptan-math/
|
|
report_package kaptan-mavlink /libs/kaptan-mavlink/ --features sensor-telemetry
|
|
report_package kaptan-navigation /libs/kaptan-navigation/ --features sitl
|
|
report_package kaptan-safety /libs/kaptan-safety/
|
|
report_package kaptan-sensor /libs/kaptan-sensor/
|
|
report_package kaptan-spi /libs/kaptan-spi/
|
|
report_package kaptan-time /libs/kaptan-time/
|
|
report_package kaptan-tx /libs/kaptan-tx/
|
|
report_package kaptan-sitl /tools/sitl/
|
|
|
|
echo "platform-stm32f7 target-only/N/A (run cargo check -p platform-stm32f7 --lib)"
|
|
echo "kaptan-geprc-f722-v2 target-only/N/A (run its thumbv7em-none-eabihf check)"
|
|
echo "kaptan-kakute-f7-mini-v3 target-only/N/A (run its thumbv7em-none-eabihf check)"
|
|
|
|
if [ "$core_incomplete" -ne 0 ]; then
|
|
echo "Strict core coverage is incomplete; reports above identify each crate." >&2
|
|
exit 1
|
|
fi
|