Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 41cca66

Browse files
committed
Add dev-utils feature for inter-crate test code safe reuse
1 parent 689ca50 commit 41cca66

File tree

4 files changed

+96
-1
lines changed

4 files changed

+96
-1
lines changed

ci/buildkite-pipeline.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ wait_step() {
140140
}
141141

142142
all_test_steps() {
143-
command_step checks ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-checks.sh" 20 check
143+
command_step checks1 ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-checks.sh" 20 check
144+
command_step checks2 ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-dev-utils.sh check-bins" 15 check
145+
command_step checks3 ". ci/rust-version.sh; ci/docker-run.sh \$\$rust_nightly_docker_image ci/test-dev-utils.sh check-all-targets" 15 check
144146
wait_step
145147

146148
# Full test suite

ci/test-checks.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ echo --- build environment
4242
cargo clippy --version --verbose
4343
$cargoNightly clippy --version --verbose
4444

45+
$cargoNightly hack --version --verbose
46+
4547
# audit is done only with "$cargo stable"
4648
cargo audit --version
4749

@@ -110,6 +112,8 @@ else
110112
_ scripts/cargo-for-all-lock-files.sh -- "+${rust_nightly}" sort --workspace --check
111113
fi
112114

115+
_ scripts/check-dev-utils.sh tree
116+
113117
_ scripts/cargo-for-all-lock-files.sh -- "+${rust_nightly}" fmt --all -- --check
114118

115119
_ ci/do-audit.sh

ci/test-dev-utils.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/usr/bin/env bash
2+
3+
set -eo pipefail
4+
5+
scripts/check-dev-utils.sh "$@"

scripts/check-dev-utils.sh

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env bash
2+
3+
set -eo pipefail
4+
cd "$(dirname "$0")/.."
5+
source ci/_
6+
# only nightly is used uniformly as we contain good amount of nightly-only code
7+
# (benches, frozen abi...)
8+
source ci/rust-version.sh nightly
9+
10+
# There's a special common feature called `dev-utils` to
11+
# overcome cargo's issue: https://github.com/rust-lang/cargo/issues/8379
12+
# This feature is like `cfg(test)`, which works between crates.
13+
#
14+
# Unfortunately, this in turn needs some special checks to avoid common
15+
# pitfalls of `dev-utils` itself.
16+
#
17+
# Firstly, detect any misuse of dev-utils as normal/build dependencies.
18+
# Also, allow some exceptions for special purpose crates. This white-listing
19+
# mechanism can be used for core-development-oriented crates like bench bins.
20+
#
21+
# Put differently, use of dev-utils is forbidden for non-dev dependencies in
22+
# general. However, allow its use for non-dev dependencies only if its use
23+
# is confined under a dep. subgraph with all nodes being marked as dev-utils.
24+
25+
# Add your troubled package which seems to want to use `dev-utils` as normal (not
26+
# dev) dependencies, only if you're sure that there's good reason to bend
27+
# dev-util's original intention and that listed package isn't part of released
28+
# binaries.
29+
# Note also that dev-utils-ci-marker feature must be added and all of its
30+
# dependencies should be edited likewise if any.
31+
declare dev_util_tainted_packages=(
32+
)
33+
34+
mode=${1:-full}
35+
36+
if [[ $mode = "tree" || $mode = "full" ]]; then
37+
# Run against the entire workspace dep graph (sans $dev_util_tainted_packages)
38+
dev_utils_excludes=$(for tainted in "${dev_util_tainted_packages[@]}"; do
39+
echo "--exclude $tainted"
40+
done)
41+
# shellcheck disable=SC2086 # Don't want to double quote $dev_utils_excludes
42+
_ cargo "+${rust_nightly}" tree --workspace -f "{p} {f}" --edges normal,build \
43+
$dev_utils_excludes | (
44+
if grep -E -C 3 -m 10 "[, ]dev-utils([, ]|$)"; then
45+
echo "dev-utils must not be used as normal dependencies" > /dev/stderr
46+
exit 1
47+
fi
48+
)
49+
50+
# Sanity-check that tainted packages has undergone the proper tedious rituals
51+
# to be justified as such.
52+
for tainted in "${dev_util_tainted_packages[@]}"; do
53+
# dev-utils-ci-marker is special proxy feature needed only when using
54+
# dev-utils code as part of normal dependency. dev-utils will be enabled
55+
# indirectly via this feature only if prepared correctly
56+
_ cargo "+${rust_nightly}" tree --workspace -f "{p} {f}" --edges normal,build \
57+
--invert "$tainted" --features dev-utils-ci-marker | (
58+
if grep -E -C 3 -m 10 -v "[, ]dev-utils([, ]|$)"; then
59+
echo "$tainted: All inverted dependencies must be with dev-utils" \
60+
> /dev/stderr
61+
exit 1
62+
fi
63+
)
64+
done
65+
fi
66+
67+
# Detect possible compilation errors of problematic usage of `dev-utils`-gated code
68+
# without being explicitly declared as such in respective workspace member
69+
# `Cargo.toml`s. This cannot be detected with `--workspace --all-targets`, due
70+
# to unintentional `dev-utils` feature activation by cargo's feature
71+
# unification mechanism.
72+
# So, we use `cargo hack` to exhaustively build each individual workspace
73+
# members in isolation to work around.
74+
#
75+
# 1. Check implicit usage of `dev-utils`-gated code in non-dev (= production) code by
76+
# building without dev dependencies (= tests/benches) for each crate
77+
# 2. Check implicit usage of `dev-utils`-gated code in dev (= test/benches) code by
78+
# building in isolation from other crates, which might happen to enable `dev-utils`
79+
if [[ $mode = "check-bins" || $mode = "full" ]]; then
80+
_ cargo "+${rust_nightly}" hack check --bins
81+
fi
82+
if [[ $mode = "check-all-targets" || $mode = "full" ]]; then
83+
_ cargo "+${rust_nightly}" hack check --all-targets
84+
fi

0 commit comments

Comments
 (0)