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

Commit a1950c7

Browse files
committed
Add a way to print inputs on failure
When there is a panic in an extensive test, tracing down where it came from can be difficult since no information is provides (messeges are e.g. "attempted to subtract with overflow"). Resolve this by calling the functions within `panic::catch_unwind`, printing the input, and continuing.
1 parent 6f0aae8 commit a1950c7

File tree

7 files changed

+27
-8
lines changed

7 files changed

+27
-8
lines changed

crates/libm-test/src/op.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
//! level. `Op` is also used as the name for generic parameters since it is terse.
1515
1616
use std::fmt;
17+
use std::panic::{RefUnwindSafe, UnwindSafe};
1718

1819
pub use shared::{ALL_OPERATIONS, FloatTy, MathOpInfo, Ty};
1920

@@ -64,15 +65,16 @@ pub trait MathOp {
6465
type CRet;
6566

6667
/// The signature of the Rust function as a `fn(...) -> ...` type.
67-
type RustFn: Copy;
68+
type RustFn: Copy + UnwindSafe;
6869

6970
/// Arguments passed to the Rust library function as a tuple.
7071
///
7172
/// The required `TupleCall` bounds ensure this type can be passed either to the C function or
7273
/// to the Rust function.
7374
type RustArgs: Copy
7475
+ TupleCall<Self::RustFn, Output = Self::RustRet>
75-
+ TupleCall<Self::CFn, Output = Self::RustRet>;
76+
+ TupleCall<Self::CFn, Output = Self::RustRet>
77+
+ RefUnwindSafe;
7678

7779
/// Type returned from the Rust function.
7880
type RustRet: CheckOutput<Self::RustArgs>;

crates/libm-test/src/test_traits.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
//! - `CheckOutput`: implemented on anything that is an output type for validation against an
77
//! expected value.
88
9-
use std::fmt;
9+
use std::panic::{RefUnwindSafe, UnwindSafe};
10+
use std::{fmt, panic};
1011

1112
use anyhow::{Context, anyhow, bail, ensure};
1213
use libm::support::Hexf;
@@ -23,6 +24,22 @@ use crate::{
2324
pub trait TupleCall<Func>: fmt::Debug {
2425
type Output;
2526
fn call(self, f: Func) -> Self::Output;
27+
28+
/// Intercept panics and print the input to stderr before continuing.
29+
fn call_intercept_panics(self, f: Func) -> Self::Output
30+
where
31+
Self: RefUnwindSafe + Copy,
32+
Func: UnwindSafe,
33+
{
34+
let res = panic::catch_unwind(|| self.call(f));
35+
match res {
36+
Ok(v) => v,
37+
Err(e) => {
38+
eprintln!("panic with the following input: {self:?}");
39+
panic::resume_unwind(e)
40+
}
41+
}
42+
}
2643
}
2744

2845
/// A trait to implement on any output type so we can verify it in a generic way.

crates/libm-test/tests/compare_built_musl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ fn musl_runner<Op: MathOp>(
2121
) {
2222
for input in cases {
2323
let musl_res = input.call(musl_fn);
24-
let crate_res = input.call(Op::ROUTINE);
24+
let crate_res = input.call_intercept_panics(Op::ROUTINE);
2525

2626
crate_res.validate(musl_res, input, ctx).unwrap();
2727
}

crates/libm-test/tests/multiprecision.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn mp_runner<Op: MathOp + MpOp>(ctx: &CheckCtx, cases: impl Iterator<Item = Op::
1212
let mut mp_vals = Op::new_mp();
1313
for input in cases {
1414
let mp_res = Op::run(&mut mp_vals, input);
15-
let crate_res = input.call(Op::ROUTINE);
15+
let crate_res = input.call_intercept_panics(Op::ROUTINE);
1616

1717
crate_res.validate(mp_res, input, ctx).unwrap();
1818
}

crates/libm-test/tests/standalone.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ fn standalone_runner<Op: MathOp>(
1010
cases: impl Iterator<Item = (Op::RustArgs, Op::RustRet)>,
1111
) {
1212
for (input, expected) in cases {
13-
let crate_res = input.call(Op::ROUTINE);
13+
let crate_res = input.call_intercept_panics(Op::ROUTINE);
1414
crate_res.validate(expected, input, ctx).unwrap();
1515
}
1616
}

crates/libm-test/tests/z_extensive/run.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ where
113113
for input in input_vec {
114114
// Test the input.
115115
let mp_res = Op::run(mp_vals, input);
116-
let crate_res = input.call(Op::ROUTINE);
116+
let crate_res = input.call_intercept_panics(Op::ROUTINE);
117117
crate_res.validate(mp_res, input, ctx)?;
118118

119119
let completed = completed.fetch_add(1, Ordering::Relaxed) + 1;

crates/util/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ macro_rules! handle_call {
5959
let libm_fn: <Op as MathOp>::RustFn = libm::$fn_name;
6060

6161
let output = match $basis {
62-
"libm" => input.call(libm_fn),
62+
"libm" => input.call_intercept_panics(libm_fn),
6363
#[cfg(feature = "build-musl")]
6464
"musl" => {
6565
let musl_fn: <Op as MathOp>::CFn =

0 commit comments

Comments
 (0)