File: build-run-test-coverage-linux.sh

package info (click to toggle)
rust-coreutils 0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 505,620 kB
  • sloc: ansic: 103,594; asm: 28,570; sh: 8,910; python: 5,581; makefile: 472; cpp: 97; javascript: 72
file content (130 lines) | stat: -rwxr-xr-x 4,782 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/env bash

# spell-checker:ignore (env/flags) Ccodegen Cinstrument Coverflow Cpanic Zpanic
# spell-checker:ignore PROFDATA PROFRAW coreutil librairies nextest profdata profraw rustlib

# This script will build, run and generate coverage reports for the whole
# testsuite.
# The biggest challenge of this process is managing the overwhelming generation
# of trace files that are generated after EACH SINGLE invocation of a coreutil
# in the testsuite. Moreover, because we run the testsuite against the multicall
# binary, each trace file contains coverage information about the WHOLE
# multicall binary, dependencies included, which results in a 5-6 MB file.
# Running the testsuite easily creates +80 GB of trace files, which is
# unmanageable in a CI environment.
#
# A workaround is to run the testsuite util per util, generate a report per
# util, and remove the trace files. Therefore, we end up with several reports
# that will get uploaded to codecov afterwards. The issue with this
# approach is that the `grcov` call, which is responsible for transforming
# `.profraw` trace files into a `lcov` file, takes a lot of time (~20s), mainly
# because it has to browse all the sources. So calling it for each of the 100
# utils (with --all-features) results in an absurdly long execution time
# (almost an hour).

# TODO: Do not instrument 3rd party librairies to save space and performance

# Exit the script if an unexpected error arise
set -e
# Treat unset variables as errors
set -u
# Ensure pipeline failures are caught (not just the last command's exit code)
set -o pipefail
# Print expanded commands to stdout before running them
set -x

ME="${0}"
ME_dir="$(dirname -- "$(readlink -fm -- "${ME}")")"
REPO_main_dir="$(dirname -- "${ME_dir}")"

# Features to enable for the `coreutils` package
FEATURES_OPTION=${FEATURES_OPTION:-"--features=feat_os_unix"}
COVERAGE_DIR=${COVERAGE_DIR:-"${REPO_main_dir}/coverage"}

# Find llvm-profdata (which is used for coverage builds)
LLVM_PROFDATA="$(find "$(rustc --print sysroot)" -name llvm-profdata)"
if [ -z "${LLVM_PROFDATA}" ]; then
    echo "Error: llvm-profdata not found. Install it with: rustup component add llvm-tools"
    exit 1
fi

PROFRAW_DIR="${COVERAGE_DIR}/traces"
PROFDATA_DIR="${COVERAGE_DIR}/data"
REPORT_DIR="${COVERAGE_DIR}/report"
REPORT_PATH="${REPORT_DIR}/total.lcov.info"

rm -rf "${PROFRAW_DIR}" && mkdir -p "${PROFRAW_DIR}"
rm -rf "${PROFDATA_DIR}" && mkdir -p "${PROFDATA_DIR}"
rm -rf "${REPORT_DIR}" && mkdir -p "${REPORT_DIR}"

#shellcheck disable=SC2086
UTIL_LIST=$("${ME_dir}"/show-utils.sh ${FEATURES_OPTION})

export RUSTC_BOOTSTRAP=1
export CARGO_INCREMENTAL=0
export RUSTFLAGS="-Cinstrument-coverage -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
export RUSTDOCFLAGS="-Cpanic=abort"
export LLVM_PROFILE_FILE="${PROFRAW_DIR}/coverage-%4m.profraw"

# Disable expanded command printing for the rest of the program
set +x

run_test_and_aggregate() {
    echo "# Running coverage tests for ${1}"

    # Build and run tests for the UTIL
    cargo nextest run \
        --profile coverage \
        --no-fail-fast \
        --color=always \
        2>&1 \
        ${2} \
    | grep -v 'SKIP'
    # Note: Do not print the skipped tests on the output as there will be many.

    echo "## Tests for (${1}) generated $(du -h -d1 ${PROFRAW_DIR} | cut -f 1) of profraw files"

    # Aggregate all the trace files into a profdata file
    PROFDATA_FILE="${PROFDATA_DIR}/${1}.profdata"
    echo "## Aggregating coverage files under ${PROFDATA_FILE}"
    "${LLVM_PROFDATA}" merge \
        -sparse \
        -o ${PROFDATA_FILE} \
        ${PROFRAW_DIR}/*.profraw \
    || true
    # We don't want an error in `llvm-profdata` to abort the whole program
}

for UTIL in ${UTIL_LIST}; do

    if [ "${UTIL}" = "stty" ]; then
        run_test_and_aggregate \
            "${UTIL}" \
            "-p coreutils -p uu_${UTIL} -E test(/^test_${UTIL}::/) ${FEATURES_OPTION}"
    else
        run_test_and_aggregate \
            "${UTIL}" \
            "-p coreutils -E test(/^test_${UTIL}::/) ${FEATURES_OPTION}"
    fi

    echo "## Clear the trace directory to free up space"
    rm -rf "${PROFRAW_DIR}" && mkdir -p "${PROFRAW_DIR}"
done;

echo "Running coverage tests over uucore"
run_test_and_aggregate "uucore" "-p uucore --all-features"

echo "# Aggregating all the profraw files under ${REPORT_PATH}"
grcov \
    "${PROFDATA_DIR}" \
    --binary-path "${REPO_main_dir}/target/debug/" \
    --output-types lcov \
    --output-path ${REPORT_PATH} \
    --llvm \
    --excl-start "^mod test.*\{" \
    --excl-stop "^\}" \
    --keep-only "${REPO_main_dir}"'/src/*'


# Notify the report file to github
echo "report=${REPORT_PATH}" >> $GITHUB_OUTPUT