Skip to content

feat(profile): panic behavior can be specified for custom harness #11272

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/cargo/core/compiler/unit_dependencies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,9 +213,9 @@ fn deps_of_roots(roots: &[Unit], state: &mut State<'_, '_>) -> CargoResult<()> {
if unit.target.proc_macro() {
// Special-case for proc-macros, which are forced to for-host
// since they need to link with the proc_macro crate.
UnitFor::new_host_test(state.gctx, root_compile_kind)
UnitFor::new_host_test(state.gctx, &unit.target, root_compile_kind)
} else {
UnitFor::new_test(state.gctx, root_compile_kind)
UnitFor::new_test(state.gctx, &unit.target, root_compile_kind)
}
} else if unit.target.is_custom_build() {
// This normally doesn't happen, except `clean` aggressively
Expand Down
39 changes: 27 additions & 12 deletions src/cargo/core/profiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1109,19 +1109,28 @@ impl UnitFor {
/// whether `panic=abort` is supported for tests. Historical versions of
/// rustc did not support this, but newer versions do with an unstable
/// compiler flag.
pub fn new_test(gctx: &GlobalContext, root_compile_kind: CompileKind) -> UnitFor {
///
/// Moreover, `target` is taken here for determining whether the test is
/// driven by libtest harness. Cargo relaxes the panic behaviour if it is
/// a custom harness, which is not required to be always unwound.
pub fn new_test(
gctx: &GlobalContext,
target: &Target,
root_compile_kind: CompileKind,
) -> UnitFor {
// We're testing out an unstable feature (`-Zpanic-abort-tests`)
// which inherits the panic setting from the dev/release profile
// (basically avoid recompiles) but historical defaults required
// that we always unwound.
let panic_setting = if gctx.cli_unstable().panic_abort_tests || !target.harness() {
PanicSetting::ReadProfile
} else {
PanicSetting::AlwaysUnwind
};
UnitFor {
host: false,
host_features: false,
// We're testing out an unstable feature (`-Zpanic-abort-tests`)
// which inherits the panic setting from the dev/release profile
// (basically avoid recompiles) but historical defaults required
// that we always unwound.
panic_setting: if gctx.cli_unstable().panic_abort_tests {
PanicSetting::ReadProfile
} else {
PanicSetting::AlwaysUnwind
},
panic_setting,
root_compile_kind,
artifact_target_for_features: None,
}
Expand All @@ -1130,8 +1139,14 @@ impl UnitFor {
/// This is a special case for unit tests of a proc-macro.
///
/// Proc-macro unit tests are forced to be run on the host.
pub fn new_host_test(gctx: &GlobalContext, root_compile_kind: CompileKind) -> UnitFor {
let mut unit_for = UnitFor::new_test(gctx, root_compile_kind);
///
/// See [`UnitFor::new_test`] for more.
pub fn new_host_test(
gctx: &GlobalContext,
target: &Target,
root_compile_kind: CompileKind,
) -> UnitFor {
let mut unit_for = UnitFor::new_test(gctx, target, root_compile_kind);
unit_for.host = true;
unit_for.host_features = true;
unit_for
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_compile/unit_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl<'a> UnitGenerator<'a, '_> {
//
// Forcing the lib to be compiled three times during `cargo
// test` is probably also not desirable.
UnitFor::new_test(self.ws.gctx(), kind)
UnitFor::new_test(self.ws.gctx(), target, kind)
} else if target.for_host() {
// Proc macro / plugin should not have `panic` set.
UnitFor::new_compiler(kind)
Expand Down
5 changes: 0 additions & 5 deletions src/cargo/util/toml/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2144,11 +2144,6 @@ pub fn validate_profile(
"doc" => {
warnings.push("profile `doc` is deprecated and has no effect".to_string());
}
"test" | "bench" => {
if root.panic.is_some() {
warnings.push(format!("`panic` setting is ignored for `{}` profile", name))
}
}
_ => {}
}

Expand Down
4 changes: 4 additions & 0 deletions src/doc/src/reference/profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ The `rustc` test harness currently requires `unwind` behavior. See the
Additionally, when using the `abort` strategy and building a test, all of the
dependencies will also be forced to build with the `unwind` strategy.

One exception is that when a test or benchmark target is driven by a custom
harness, panic setting will be applied since the custom harness may not have
the same limitation as the `rustc` test harness requires.

[`-C panic` flag]: ../../rustc/codegen-options/index.html#panic
[`panic-abort-tests`]: unstable.md#panic-abort-tests

Expand Down
57 changes: 47 additions & 10 deletions tests/testsuite/profiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,33 +366,70 @@ must be a boolean (`true`/`false`) or a string (`\"thin\"`/`\"fat\"`/`\"off\"`)
}

#[cargo_test]
fn profile_panic_test_bench() {
fn profile_panic_test_with_custom_harness() {
// Custom harness can have `-C panic="…"` passed in.
let p = project()
.file(
"Cargo.toml",
r#"
[package]
name = "foo"
version = "0.0.1"
edition = "2015"

[[test]]
name = "custom"
harness = false
[[test]]
name = "libtest"
[[bench]]
name = "custom"
harness = false
[[bench]]
name = "libtest"
[profile.test]
panic = "abort"

[profile.bench]
panic = "abort"
"#,
)
.file("src/lib.rs", "")
.file("tests/custom.rs", r#"fn main() { panic!("abort!"); }"#)
.file("tests/libtest.rs", "")
.file("benches/custom.rs", r#"fn main() { panic!("abort!"); }"#)
.file("benches/libtest.rs", "")
.build();

p.cargo("build")
#[cfg(not(windows))]
let exit_code = 101;
#[cfg(windows)]
let exit_code = windows_sys::Win32::Foundation::STATUS_STACK_BUFFER_OVERRUN;

// panic abort on custom harness
p.cargo("test --test custom --verbose")
.with_stderr_contains("[RUNNING] `rustc --crate-name custom [..]-C panic=abort [..]")
.with_stderr_contains("[..]thread '[..]' panicked at [..]")
.with_stderr_contains("[..]abort![..]")
.with_stderr_contains(
"\
[WARNING] `panic` setting is ignored for `bench` profile
[WARNING] `panic` setting is ignored for `test` profile
",
"[..]process didn't exit successfully: `[..]/target/debug/deps/custom-[..]",
)
.with_status(exit_code)
.run();
p.cargo("bench --bench custom --verbose")
.with_stderr_contains("[RUNNING] `rustc --crate-name custom [..]-C panic=abort [..]")
.with_stderr_contains("[..]thread '[..]' panicked at [..]")
.with_stderr_contains("[..]abort![..]")
.with_stderr_contains(
"[..]process didn't exit successfully: `[..]/target/release/deps/custom-[..]",
)
.with_status(exit_code)
.run();

// panic behaviour of libtest cannot be set as `abort` as of now.
p.cargo("test --test libtest --verbose")
.with_stderr_does_not_contain("panic=abort")
.with_stdout_contains("running 0 tests")
.run();
p.cargo("bench --bench libtest --verbose")
.with_stderr_does_not_contain("panic=abort")
.with_stdout_contains("running 0 tests")
.run();
}

Expand Down
2 changes: 1 addition & 1 deletion tests/testsuite/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4690,7 +4690,7 @@ fn panic_abort_only_test() {
.build();

p.cargo("test -Z panic-abort-tests -v")
.with_stderr_contains("warning: `panic` setting is ignored for `test` profile")
.with_stderr_contains("[..]--crate-name foo [..]-C panic=abort[..]")
.masquerade_as_nightly_cargo(&["panic-abort-tests"])
.run();
}
Expand Down