mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-27 19:17:43 +00:00
Merge pull request #7401 from RenjiSann/coverage
Fix coverage files generation
This commit is contained in:
commit
0b397c469f
11 changed files with 261 additions and 203 deletions
|
@ -4,3 +4,10 @@ status-level = "all"
|
|||
final-status-level = "skip"
|
||||
failure-output = "immediate-final"
|
||||
fail-fast = false
|
||||
|
||||
[profile.coverage]
|
||||
retries = 0
|
||||
status-level = "all"
|
||||
final-status-level = "skip"
|
||||
failure-output = "immediate-final"
|
||||
fail-fast = false
|
||||
|
|
119
.github/workflows/CICD.yml
vendored
119
.github/workflows/CICD.yml
vendored
|
@ -2,7 +2,7 @@ name: CICD
|
|||
|
||||
# spell-checker:ignore (abbrev/names) CICD CodeCOV MacOS MinGW MSVC musl taiki
|
||||
# spell-checker:ignore (env/flags) Awarnings Ccodegen Coverflow Cpanic Dwarnings RUSTDOCFLAGS RUSTFLAGS Zpanic CARGOFLAGS
|
||||
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain fuzzers dedupe devel
|
||||
# spell-checker:ignore (jargon) SHAs deps dequote softprops subshell toolchain fuzzers dedupe devel profdata
|
||||
# spell-checker:ignore (people) Peltoche rivy dtolnay Anson dawidd
|
||||
# spell-checker:ignore (shell/tools) binutils choco clippy dmake dpkg esac fakeroot fdesc fdescfs gmake grcov halium lcov libclang libfuse libssl limactl mkdir nextest nocross pacman popd printf pushd redoxer rsync rustc rustfmt rustup shopt sccache utmpdump xargs
|
||||
# spell-checker:ignore (misc) aarch alnum armhf bindir busytest coreutils defconfig DESTDIR gecos getenforce gnueabihf issuecomment maint manpages msys multisize noconfirm nullglob onexitbegin onexitend pell runtest Swatinem tempfile testsuite toybox uutils
|
||||
|
@ -1001,6 +1001,123 @@ jobs:
|
|||
name: toybox-result.json
|
||||
path: ${{ steps.vars.outputs.TEST_SUMMARY_FILE }}
|
||||
|
||||
coverage:
|
||||
name: Code Coverage
|
||||
runs-on: ${{ matrix.job.os }}
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
SCCACHE_GHA_ENABLED: "true"
|
||||
RUSTC_WRAPPER: "sccache"
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job:
|
||||
- { os: ubuntu-latest , features: unix, toolchain: nightly }
|
||||
# FIXME: Re-enable macos code coverage
|
||||
# - { os: macos-latest , features: macos, toolchain: nightly }
|
||||
# FIXME: Re-enable Code Coverage on windows, which currently fails due to "profiler_builtins". See #6686.
|
||||
# - { os: windows-latest , features: windows, toolchain: nightly-x86_64-pc-windows-gnu }
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ matrix.job.toolchain }}
|
||||
components: rustfmt
|
||||
- uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: nextest,grcov@0.8.24
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
|
||||
- name: Run sccache-cache
|
||||
uses: mozilla-actions/sccache-action@v0.0.6
|
||||
|
||||
# - name: Reattach HEAD ## may be needed for accurate code coverage info
|
||||
# run: git checkout ${{ github.head_ref }}
|
||||
|
||||
- name: Initialize workflow variables
|
||||
id: vars
|
||||
shell: bash
|
||||
run: |
|
||||
## VARs setup
|
||||
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
|
||||
|
||||
# toolchain
|
||||
TOOLCHAIN="nightly" ## default to "nightly" toolchain (required for certain required unstable compiler flags) ## !maint: refactor when stable channel has needed support
|
||||
|
||||
# * specify gnu-type TOOLCHAIN for windows; `grcov` requires gnu-style code coverage data files
|
||||
case ${{ matrix.job.os }} in windows-*) TOOLCHAIN="$TOOLCHAIN-x86_64-pc-windows-gnu" ;; esac;
|
||||
|
||||
# * use requested TOOLCHAIN if specified
|
||||
if [ -n "${{ matrix.job.toolchain }}" ]; then TOOLCHAIN="${{ matrix.job.toolchain }}" ; fi
|
||||
outputs TOOLCHAIN
|
||||
|
||||
# target-specific options
|
||||
|
||||
# * CARGO_FEATURES_OPTION
|
||||
CARGO_FEATURES_OPTION='--all-features' ; ## default to '--all-features' for code coverage
|
||||
if [ -n "${{ matrix.job.features }}" ]; then CARGO_FEATURES_OPTION='--features=${{ matrix.job.features }}' ; fi
|
||||
outputs CARGO_FEATURES_OPTION
|
||||
|
||||
# * CODECOV_FLAGS
|
||||
CODECOV_FLAGS=$( echo "${{ matrix.job.os }}" | sed 's/[^[:alnum:]]/_/g' )
|
||||
outputs CODECOV_FLAGS
|
||||
|
||||
- name: Install/setup prerequisites
|
||||
shell: bash
|
||||
run: |
|
||||
## Install/setup prerequisites
|
||||
case '${{ matrix.job.os }}' in
|
||||
macos-latest) brew install coreutils ;; # needed for testing
|
||||
esac
|
||||
|
||||
case '${{ matrix.job.os }}' in
|
||||
ubuntu-latest)
|
||||
# pinky is a tool to show logged-in users from utmp, and gecos fields from /etc/passwd.
|
||||
# In GitHub Action *nix VMs, no accounts log in, even the "runner" account that runs the commands. The account also has empty gecos fields.
|
||||
# To work around this for pinky tests, we create a fake login entry for the GH runner account...
|
||||
FAKE_UTMP='[7] [999999] [tty2] [runner] [tty2] [] [0.0.0.0] [2022-02-22T22:22:22,222222+00:00]'
|
||||
# ... by dumping the login records, adding our fake line, then reverse dumping ...
|
||||
(utmpdump /var/run/utmp ; echo $FAKE_UTMP) | sudo utmpdump -r -o /var/run/utmp
|
||||
# ... and add a full name to each account with a gecos field but no full name.
|
||||
sudo sed -i 's/:,/:runner name,/' /etc/passwd
|
||||
# We also create a couple optional files pinky looks for
|
||||
touch /home/runner/.project
|
||||
echo "foo" > /home/runner/.plan
|
||||
;;
|
||||
esac
|
||||
|
||||
case '${{ matrix.job.os }}' in
|
||||
# Update binutils if MinGW due to https://github.com/rust-lang/rust/issues/112368
|
||||
windows-latest) C:/msys64/usr/bin/pacman.exe -Sy --needed mingw-w64-x86_64-gcc --noconfirm ; echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH ;;
|
||||
esac
|
||||
|
||||
## Install the llvm-tools component to get access to `llvm-profdata`
|
||||
rustup component add llvm-tools
|
||||
|
||||
- name: Run test and coverage
|
||||
id: run_test_cov
|
||||
run: |
|
||||
outputs() { step_id="${{ github.action }}"; for var in "$@" ; do echo steps.${step_id}.outputs.${var}="${!var}"; echo "${var}=${!var}" >> $GITHUB_OUTPUT; done; }
|
||||
|
||||
# Run the coverage script
|
||||
./util/build-run-test-coverage-linux.sh
|
||||
|
||||
outputs REPORT_FILE
|
||||
env:
|
||||
COVERAGE_DIR: ${{ github.workspace }}/coverage
|
||||
FEATURES_OPTION: ${{ steps.vars.outputs.CARGO_FEATURES_OPTION }}
|
||||
# RUSTUP_TOOLCHAIN: ${{ steps.vars.outputs.TOOLCHAIN }}
|
||||
|
||||
- name: Upload coverage results (to Codecov.io)
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
file: ${{ steps.run_test_cov.outputs.report }}
|
||||
## flags: IntegrationTests, UnitTests, ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
||||
flags: ${{ steps.vars.outputs.CODECOV_FLAGS }}
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: false
|
||||
|
||||
test_separately:
|
||||
name: Separate Builds
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
|||
# spell-checker:ignore (misc) direnv
|
||||
|
||||
target/
|
||||
coverage/
|
||||
/src/*/gen_table
|
||||
/build/
|
||||
/tmp/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<!-- spell-checker:ignore (flags) Ccodegen Coverflow Cpanic Zinstrument Zpanic reimplementing toybox RUNTEST CARGOFLAGS nextest prereq autopoint gettext texinfo automake findutils shellenv libexec gnubin toolchains gsed -->
|
||||
<!-- spell-checker:ignore (flags) Ccodegen Coverflow Cpanic Cinstrument Zpanic reimplementing toybox RUNTEST CARGOFLAGS nextest prereq autopoint gettext texinfo automake findutils shellenv libexec gnubin toolchains gsed -->
|
||||
|
||||
# Setting up your local development environment
|
||||
|
||||
|
@ -253,13 +253,11 @@ pkg install coreutils gsed
|
|||
|
||||
Code coverage report can be generated using [grcov](https://github.com/mozilla/grcov).
|
||||
|
||||
### Using Nightly Rust
|
||||
|
||||
To generate [gcov-based](https://github.com/mozilla/grcov#example-how-to-generate-gcda-files-for-a-rust-project) coverage report
|
||||
|
||||
```shell
|
||||
export CARGO_INCREMENTAL=0
|
||||
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
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"
|
||||
cargo build <options...> # e.g., --features feat_os_unix
|
||||
cargo test <options...> # e.g., --features feat_os_unix test_pathchk
|
||||
|
@ -269,11 +267,6 @@ grcov . -s . --binary-path ./target/debug/ -t html --branch --ignore-not-existin
|
|||
|
||||
if changes are not reflected in the report then run `cargo clean` and run the above commands.
|
||||
|
||||
### Using Stable Rust
|
||||
|
||||
If you are using stable version of Rust that doesn't enable code coverage instrumentation by default
|
||||
then add `-Z-Zinstrument-coverage` flag to `RUSTFLAGS` env variable specified above.
|
||||
|
||||
## Tips for setting up on Mac
|
||||
|
||||
### C Compiler and linker
|
||||
|
|
|
@ -525,14 +525,20 @@ fn test_gnu_e20() {
|
|||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let env_bin = String::from(uutests::util::get_tests_binary()) + " " + util_name!();
|
||||
let input = [
|
||||
String::from("-i"),
|
||||
String::from(r#"-SA="B\_C=D" "#) + env_bin.escape_default().to_string().as_str() + "",
|
||||
];
|
||||
|
||||
let (input, output) = (
|
||||
[
|
||||
String::from("-i"),
|
||||
String::from(r#"-SA="B\_C=D" "#) + env_bin.escape_default().to_string().as_str() + "",
|
||||
],
|
||||
"A=B C=D\n",
|
||||
);
|
||||
let mut output = "A=B C=D\n".to_string();
|
||||
|
||||
// Workaround for the test to pass when coverage is being run.
|
||||
// If enabled, the binary called by env_bin will most probably be
|
||||
// instrumented for coverage, and thus will set the
|
||||
// __LLVM_PROFILE_RT_INIT_ONCE
|
||||
if env::var("__LLVM_PROFILE_RT_INIT_ONCE").is_ok() {
|
||||
output.push_str("__LLVM_PROFILE_RT_INIT_ONCE=__LLVM_PROFILE_RT_INIT_ONCE\n");
|
||||
}
|
||||
|
||||
let out = scene.ucmd().args(&input).succeeds();
|
||||
assert_eq!(out.stdout_str(), output);
|
||||
|
|
|
@ -1762,6 +1762,11 @@ impl UCommand {
|
|||
}
|
||||
}
|
||||
|
||||
// Forward the LLVM_PROFILE_FILE variable to the call, for coverage purposes.
|
||||
if let Some(ld_preload) = env::var_os("LLVM_PROFILE_FILE") {
|
||||
command.env("LLVM_PROFILE_FILE", ld_preload);
|
||||
}
|
||||
|
||||
command
|
||||
.envs(DEFAULT_ENV)
|
||||
.envs(self.env_vars.iter().cloned());
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
@setLocal
|
||||
@echo off
|
||||
set "ERRORLEVEL="
|
||||
|
||||
@rem ::# spell-checker:ignore (abbrevs/acronyms) gcno
|
||||
@rem ::# spell-checker:ignore (CMD) COMSPEC ERRORLEVEL
|
||||
@rem ::# spell-checker:ignore (jargon) toolchain
|
||||
@rem ::# spell-checker:ignore (rust) Ccodegen Cinline Coverflow Cpanic RUSTC RUSTDOCFLAGS RUSTFLAGS RUSTUP Zpanic
|
||||
@rem ::# spell-checker:ignore (utils) genhtml grcov lcov sccache uutils
|
||||
|
||||
@rem ::# ref: https://github.com/uutils/coreutils/pull/1476
|
||||
|
||||
set "FEATURES_OPTION=--features feat_os_windows"
|
||||
|
||||
cd "%~dp0.."
|
||||
call echo [ "%CD%" ]
|
||||
|
||||
for /f "tokens=*" %%G in ('%~dp0\show-utils.BAT %FEATURES_OPTION%') do set UTIL_LIST=%%G
|
||||
REM echo UTIL_LIST=%UTIL_LIST%
|
||||
set "CARGO_INDIVIDUAL_PACKAGE_OPTIONS="
|
||||
for %%H in (%UTIL_LIST%) do (
|
||||
if DEFINED CARGO_INDIVIDUAL_PACKAGE_OPTIONS call set "CARGO_INDIVIDUAL_PACKAGE_OPTIONS=%%CARGO_INDIVIDUAL_PACKAGE_OPTIONS%% "
|
||||
call set "CARGO_INDIVIDUAL_PACKAGE_OPTIONS=%%CARGO_INDIVIDUAL_PACKAGE_OPTIONS%%-puu_%%H"
|
||||
)
|
||||
REM echo CARGO_INDIVIDUAL_PACKAGE_OPTIONS=%CARGO_INDIVIDUAL_PACKAGE_OPTIONS%
|
||||
|
||||
REM call cargo clean
|
||||
|
||||
set "CARGO_INCREMENTAL=0"
|
||||
set "RUSTC_WRAPPER=" &@REM ## NOTE: RUSTC_WRAPPER=='sccache' breaks code coverage calculations (uu_*.gcno files are not created during build)
|
||||
@REM set "RUSTFLAGS=-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
|
||||
set "RUSTFLAGS=-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
set "RUSTDOCFLAGS=-Cpanic=abort"
|
||||
set "RUSTUP_TOOLCHAIN=nightly-gnu"
|
||||
call cargo build %FEATURES_OPTION%
|
||||
call cargo test --no-run %FEATURES_OPTION%
|
||||
call cargo test --quiet %FEATURES_OPTION%
|
||||
call cargo test --quiet %FEATURES_OPTION% %CARGO_INDIVIDUAL_PACKAGE_OPTIONS%
|
||||
|
||||
if NOT DEFINED COVERAGE_REPORT_DIR set COVERAGE_REPORT_DIR=target\debug\coverage-win
|
||||
call rm -r "%COVERAGE_REPORT_DIR%" 2>NUL
|
||||
|
||||
set GRCOV_IGNORE_OPTION=--ignore build.rs --ignore "/*" --ignore "[A-Za-z]:/*" --ignore "C:/Users/*"
|
||||
set GRCOV_EXCLUDE_OPTION=--excl-br-line "^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()"
|
||||
@rem ::# * build LCOV coverage file
|
||||
REM echo call grcov . --output-type lcov --output-path "%COVERAGE_REPORT_DIR%/../lcov.info" --branch %GRCOV_IGNORE_OPTION% %GRCOV_EXCLUDE_OPTION%
|
||||
call grcov . --output-type lcov --output-path "%COVERAGE_REPORT_DIR%/../lcov.info" --branch %GRCOV_IGNORE_OPTION% %GRCOV_EXCLUDE_OPTION%
|
||||
@rem ::# * build HTML
|
||||
@rem ::# -- use `genhtml` if available for display of additional branch coverage information
|
||||
set "ERRORLEVEL="
|
||||
call genhtml --version 2>NUL 1>&2
|
||||
if NOT ERRORLEVEL 1 (
|
||||
echo call genhtml target/debug/lcov.info --prefix "%CD%" --output-directory "%COVERAGE_REPORT_DIR%" --branch-coverage --function-coverage ^| grep ": [0-9]"
|
||||
call genhtml target/debug/lcov.info --prefix "%CD%" --output-directory "%COVERAGE_REPORT_DIR%" --branch-coverage --function-coverage | grep ": [0-9]"
|
||||
) else (
|
||||
echo call grcov . --output-type html --output-path "%COVERAGE_REPORT_DIR%" --branch %GRCOV_IGNORE_OPTION%
|
||||
call grcov . --output-type html --output-path "%COVERAGE_REPORT_DIR%" --branch %GRCOV_IGNORE_OPTION%
|
||||
)
|
||||
if ERRORLEVEL 1 goto _undefined_ 2>NUL || @for %%G in ("%COMSPEC%") do @title %%nG & @"%COMSPEC%" /d/c exit %ERRORLEVEL%
|
|
@ -1,71 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# spell-checker:ignore (abbrevs/acronyms) HTML gcno llvm
|
||||
# spell-checker:ignore (jargon) toolchain
|
||||
# spell-checker:ignore (rust) Ccodegen Cinline Coverflow Cpanic RUSTC RUSTDOCFLAGS RUSTFLAGS RUSTUP Zpanic
|
||||
# spell-checker:ignore (shell) OSID OSTYPE esac
|
||||
# spell-checker:ignore (utils) genhtml grcov lcov greadlink readlink sccache shellcheck uutils
|
||||
|
||||
FEATURES_OPTION="--features feat_os_unix"
|
||||
|
||||
# Use GNU coreutils for readlink on *BSD
|
||||
case "$OSTYPE" in
|
||||
*bsd*)
|
||||
READLINK="greadlink"
|
||||
;;
|
||||
*)
|
||||
READLINK="readlink"
|
||||
;;
|
||||
esac
|
||||
|
||||
ME="${0}"
|
||||
ME_dir="$(dirname -- "$("${READLINK}" -fm -- "${ME}")")"
|
||||
REPO_main_dir="$(dirname -- "${ME_dir}")"
|
||||
|
||||
cd "${REPO_main_dir}" &&
|
||||
echo "[ \"$PWD\" ]"
|
||||
|
||||
#shellcheck disable=SC2086
|
||||
UTIL_LIST=$("${ME_dir}"/show-utils.sh ${FEATURES_OPTION})
|
||||
CARGO_INDIVIDUAL_PACKAGE_OPTIONS=""
|
||||
for UTIL in ${UTIL_LIST}; do
|
||||
if [ -n "${CARGO_INDIVIDUAL_PACKAGE_OPTIONS}" ]; then CARGO_INDIVIDUAL_PACKAGE_OPTIONS="${CARGO_INDIVIDUAL_PACKAGE_OPTIONS} "; fi
|
||||
CARGO_INDIVIDUAL_PACKAGE_OPTIONS="${CARGO_INDIVIDUAL_PACKAGE_OPTIONS}-puu_${UTIL}"
|
||||
done
|
||||
# echo "CARGO_INDIVIDUAL_PACKAGE_OPTIONS=${CARGO_INDIVIDUAL_PACKAGE_OPTIONS}"
|
||||
|
||||
# cargo clean
|
||||
|
||||
export CARGO_INCREMENTAL=0
|
||||
export RUSTC_WRAPPER="" ## NOTE: RUSTC_WRAPPER=='sccache' breaks code coverage calculations (uu_*.gcno files are not created during build)
|
||||
# export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zno-landing-pads"
|
||||
export RUSTFLAGS="-Zprofile -Ccodegen-units=1 -Copt-level=0 -Clink-dead-code -Coverflow-checks=off -Zpanic_abort_tests -Cpanic=abort"
|
||||
export RUSTDOCFLAGS="-Cpanic=abort"
|
||||
export RUSTUP_TOOLCHAIN="nightly-gnu"
|
||||
#shellcheck disable=SC2086
|
||||
{
|
||||
cargo build ${FEATURES_OPTION}
|
||||
cargo test --no-run ${FEATURES_OPTION}
|
||||
cargo test --quiet ${FEATURES_OPTION}
|
||||
cargo test --quiet ${FEATURES_OPTION} ${CARGO_INDIVIDUAL_PACKAGE_OPTIONS}
|
||||
}
|
||||
|
||||
export COVERAGE_REPORT_DIR
|
||||
if [ -z "${COVERAGE_REPORT_DIR}" ]; then COVERAGE_REPORT_DIR="${REPO_main_dir}/target/debug/coverage-nix"; fi
|
||||
rm -r "${COVERAGE_REPORT_DIR}" 2>/dev/null
|
||||
mkdir -p "${COVERAGE_REPORT_DIR}"
|
||||
|
||||
## NOTE: `grcov` is not accepting environment variable contents as options for `--ignore` or `--excl_br_line`
|
||||
# export GRCOV_IGNORE_OPTION="--ignore build.rs --ignore '/*' --ignore '[A-Za-z]:/*' --ignore 'C:/Users/*'"
|
||||
# export GRCOV_EXCLUDE_OPTION="--excl-br-line '^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()'"
|
||||
# * build LCOV coverage file
|
||||
grcov . --output-type lcov --output-path "${COVERAGE_REPORT_DIR}/../lcov.info" --branch --ignore build.rs --ignore '/*' --ignore '[A-Za-z]:/*' --ignore 'C:/Users/*' --excl-br-line '^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()'
|
||||
# * build HTML
|
||||
# -- use `genhtml` if available for display of additional branch coverage information
|
||||
if genhtml --version 2>/dev/null 1>&2; then
|
||||
genhtml "${COVERAGE_REPORT_DIR}/../lcov.info" --output-directory "${COVERAGE_REPORT_DIR}" --branch-coverage --function-coverage | grep ": [0-9]"
|
||||
else
|
||||
grcov . --output-type html --output-path "${COVERAGE_REPORT_DIR}" --branch --ignore build.rs --ignore '/*' --ignore '[A-Za-z]:/*' --ignore 'C:/Users/*' --excl-br-line '^\s*((debug_)?assert(_eq|_ne)?!|#\[derive\()'
|
||||
fi
|
||||
# shellcheck disable=SC2181
|
||||
if [ $? -ne 0 ]; then exit 1; fi
|
115
util/build-run-test-coverage-linux.sh
Executable file
115
util/build-run-test-coverage-linux.sh
Executable file
|
@ -0,0 +1,115 @@
|
|||
#!/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
|
||||
# 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"}
|
||||
|
||||
LLVM_PROFDATA="$(find "$(rustc --print sysroot)" -name llvm-profdata)"
|
||||
|
||||
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 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 RUSTUP_TOOLCHAIN="nightly-gnu"
|
||||
export LLVM_PROFILE_FILE="${PROFRAW_DIR}/coverage-%m-%p.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
|
||||
|
||||
run_test_and_aggregate \
|
||||
"${UTIL}" \
|
||||
"-p coreutils -E test(/^test_${UTIL}::/) ${FEATURES_OPTION}"
|
||||
|
||||
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/coreutils" \
|
||||
--output-types lcov \
|
||||
--output-path ${REPORT_PATH} \
|
||||
--llvm \
|
||||
--keep-only "${REPO_main_dir}"'/src/*'
|
||||
|
||||
|
||||
# Notify the report file to github
|
||||
echo "report=${REPORT_PATH}" >> $GITHUB_OUTPUT
|
|
@ -1,16 +0,0 @@
|
|||
@setLocal
|
||||
@echo off
|
||||
|
||||
@rem:: # spell-checker:ignore (shell/CMD) COMSPEC ERRORLEVEL
|
||||
|
||||
set "ME_dir=%~dp0."
|
||||
set "REPO_main_dir=%ME_dir%\.."
|
||||
|
||||
set "ERRORLEVEL="
|
||||
set "COVERAGE_REPORT_DIR=%REPO_main_dir%\target\debug\coverage-win"
|
||||
|
||||
call "%ME_dir%\build-code_coverage.BAT"
|
||||
if ERRORLEVEL 1 goto _undefined_ 2>NUL || @for %%G in ("%COMSPEC%") do @title %%nG & @"%COMSPEC%" /d/c exit %ERRORLEVEL%
|
||||
|
||||
call start "" "%COVERAGE_REPORT_DIR%"\index.html
|
||||
if ERRORLEVEL 1 goto _undefined_ 2>NUL || @for %%G in ("%COMSPEC%") do @title %%nG & @"%COMSPEC%" /d/c exit %ERRORLEVEL%
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# spell-checker:ignore (vars) OSID OSTYPE binfmt greadlink
|
||||
|
||||
# Use GNU coreutils for readlink on *BSD
|
||||
case "$OSTYPE" in
|
||||
*bsd*)
|
||||
READLINK="greadlink"
|
||||
;;
|
||||
*)
|
||||
READLINK="readlink"
|
||||
;;
|
||||
esac
|
||||
|
||||
ME="${0}"
|
||||
ME_dir="$(dirname -- "$("${READLINK}" -fm -- "${ME}")")"
|
||||
REPO_main_dir="$(dirname -- "${ME_dir}")"
|
||||
|
||||
export COVERAGE_REPORT_DIR="${REPO_main_dir}/target/debug/coverage-nix"
|
||||
|
||||
if ! "${ME_dir}/build-code_coverage.sh"; then exit 1; fi
|
||||
|
||||
# WSL?
|
||||
if [ -z "${OSID_tags}" ]; then
|
||||
if [ -e '/proc/sys/fs/binfmt_misc/WSLInterop' ] && (grep '^enabled$' '/proc/sys/fs/binfmt_misc/WSLInterop' >/dev/null); then
|
||||
__="wsl"
|
||||
case ";${OSID_tags};" in ";;") OSID_tags="$__" ;; *";$__;"*) ;; *) OSID_tags="$__;$OSID_tags" ;; esac
|
||||
unset __
|
||||
# Windows version == <major>.<minor>.<build>.<revision>
|
||||
# Release ID; see [Release ID/Version vs Build](https://winreleaseinfoprod.blob.core.windows.net/winreleaseinfoprod/en-US.html)[`@`](https://archive.is/GOj1g)
|
||||
OSID_wsl_build="$(uname -r | sed 's/^[0-9.][0-9.]*-\([0-9][0-9]*\)-.*$/\1/g')"
|
||||
OSID_wsl_revision="$(uname -v | sed 's/^#\([0-9.][0-9.]*\)-.*$/\1/g')"
|
||||
export OSID_wsl_build OSID_wsl_revision
|
||||
fi
|
||||
fi
|
||||
|
||||
case ";${OSID_tags};" in
|
||||
*";wsl;"*) powershell.exe -c "$(wslpath -w "${COVERAGE_REPORT_DIR}"/index.html)" ;;
|
||||
*) xdg-open --version >/dev/null 2>&1 && xdg-open "${COVERAGE_REPORT_DIR}"/index.html || echo "report available at '\"${COVERAGE_REPORT_DIR}\"/index.html'" ;;
|
||||
esac
|
Loading…
Add table
Add a link
Reference in a new issue