|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# spell-checker:ignore (env/flags) Ccodegen Cinstrument Coverflow Cpanic Zpanic |
| 4 | +# spell-checker:ignore PROFDATA PROFRAW coreutil librairies nextest profdata profraw rustlib |
| 5 | + |
| 6 | +# This script will build, run and generate coverage reports for the whole |
| 7 | +# testsuite. |
| 8 | +# The biggest challenge of this process is managing the overwhelming generation |
| 9 | +# of trace files that are generated after EACH SINGLE invocation of a coreutil |
| 10 | +# in the testsuite. Moreover, because we run the testsuite against the multicall |
| 11 | +# binary, each trace file contains coverage information about the WHOLE |
| 12 | +# multicall binary, dependencies included, which results in a 5-6 MB file. |
| 13 | +# Running the testsuite easily creates +80 GB of trace files, which is |
| 14 | +# unmanageable in a CI environment. |
| 15 | +# |
| 16 | +# A workaround is to run the testsuite util per util, generate a report per |
| 17 | +# util, and remove the trace files. Therefore, we end up with several reports |
| 18 | +# that will get uploaded to codecov afterwards. The issue with this |
| 19 | +# approach is that the `grcov` call, which is responsible for transforming |
| 20 | +# `.profraw` trace files into a `lcov` file, takes a lot of time (~20s), mainly |
| 21 | +# because it has to browse all the sources. So calling it for each of the 100 |
| 22 | +# utils (with --all-features) results in an absurdly long execution time |
| 23 | +# (almost an hour). |
| 24 | + |
| 25 | +# TODO: Do not instrument 3rd party librairies to save space and performance |
| 26 | + |
| 27 | +# Exit the script if an unexpected error arise |
| 28 | +set -e |
| 29 | +# Treat unset variables as errors |
| 30 | +set -u |
| 31 | +# Print expanded commands to stdout before running them |
| 32 | +set -x |
| 33 | + |
| 34 | +ME="${0}" |
| 35 | +ME_dir="$(dirname -- "$(readlink -fm -- "${ME}")")" |
| 36 | +REPO_main_dir="$(dirname -- "${ME_dir}")" |
| 37 | + |
| 38 | +# Features to enable for the `coreutils` package |
| 39 | +FEATURES_OPTION=${FEATURES_OPTION:-"--features=feat_os_unix"} |
| 40 | +COVERAGE_DIR=${COVERAGE_DIR:-"${REPO_main_dir}/coverage"} |
| 41 | + |
| 42 | +LLVM_PROFDATA="$(find "$(rustc --print sysroot)" -name llvm-profdata)" |
| 43 | + |
| 44 | +PROFRAW_DIR="${COVERAGE_DIR}/traces" |
| 45 | +PROFDATA_DIR="${COVERAGE_DIR}/data" |
| 46 | +REPORT_DIR="${COVERAGE_DIR}/report" |
| 47 | +REPORT_PATH="${REPORT_DIR}/total.lcov.info" |
| 48 | + |
| 49 | +rm -rf "${PROFRAW_DIR}" && mkdir -p "${PROFRAW_DIR}" |
| 50 | +rm -rf "${PROFDATA_DIR}" && mkdir -p "${PROFDATA_DIR}" |
| 51 | +rm -rf "${REPORT_DIR}" && mkdir -p "${REPORT_DIR}" |
| 52 | + |
| 53 | +#shellcheck disable=SC2086 |
| 54 | +UTIL_LIST=$("${ME_dir}"/show-utils.sh ${FEATURES_OPTION}) |
| 55 | + |
| 56 | +export CARGO_INCREMENTAL=0 |
| 57 | +export RUSTFLAGS="-Cinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort" |
| 58 | +export RUSTDOCFLAGS="-Cpanic=abort" |
| 59 | +export RUSTUP_TOOLCHAIN="nightly-gnu" |
| 60 | +export LLVM_PROFILE_FILE="${PROFRAW_DIR}/coverage-%m-%p.profraw" |
| 61 | + |
| 62 | +# Disable expanded command printing for the rest of the program |
| 63 | +set +x |
| 64 | + |
| 65 | +run_test_and_aggregate() { |
| 66 | + echo "# Running coverage tests for ${1}" |
| 67 | + |
| 68 | + # Build and run tests for the UTIL |
| 69 | + cargo nextest run \ |
| 70 | + --profile coverage \ |
| 71 | + --no-fail-fast \ |
| 72 | + --color=always \ |
| 73 | + 2>&1 \ |
| 74 | + ${2} \ |
| 75 | + | grep -v 'SKIP' |
| 76 | + # Note: Do not print the skipped tests on the output as there will be many. |
| 77 | + |
| 78 | + echo "## Tests for (${1}) generated $(du -h -d1 ${PROFRAW_DIR} | cut -f 1) of profraw files" |
| 79 | + |
| 80 | + # Aggregate all the trace files into a profdata file |
| 81 | + PROFDATA_FILE="${PROFDATA_DIR}/${1}.profdata" |
| 82 | + echo "## Aggregating coverage files under ${PROFDATA_FILE}" |
| 83 | + "${LLVM_PROFDATA}" merge \ |
| 84 | + -sparse \ |
| 85 | + -o ${PROFDATA_FILE} \ |
| 86 | + ${PROFRAW_DIR}/*.profraw \ |
| 87 | + || true |
| 88 | + # We don't want an error in `llvm-profdata` to abort the whole program |
| 89 | +} |
| 90 | + |
| 91 | +for UTIL in ${UTIL_LIST}; do |
| 92 | + |
| 93 | + run_test_and_aggregate \ |
| 94 | + "${UTIL}" \ |
| 95 | + "-p coreutils -E test(/^test_${UTIL}::/) ${FEATURES_OPTION}" |
| 96 | + |
| 97 | + echo "## Clear the trace directory to free up space" |
| 98 | + rm -rf "${PROFRAW_DIR}" && mkdir -p "${PROFRAW_DIR}" |
| 99 | +done; |
| 100 | + |
| 101 | +echo "Running coverage tests over uucore" |
| 102 | +run_test_and_aggregate "uucore" "-p uucore --all-features" |
| 103 | + |
| 104 | +echo "# Aggregating all the profraw files under ${REPORT_PATH}" |
| 105 | +grcov \ |
| 106 | + "${PROFDATA_DIR}" \ |
| 107 | + --binary-path "${REPO_main_dir}/target/debug/coreutils" \ |
| 108 | + --output-types lcov \ |
| 109 | + --output-path ${REPORT_PATH} \ |
| 110 | + --llvm \ |
| 111 | + --keep-only "${REPO_main_dir}"'/src/*' |
| 112 | + |
| 113 | + |
| 114 | +# Notify the report file to github |
| 115 | +echo "report=${REPORT_PATH}" >> $GITHUB_OUTPUT |
0 commit comments