use std::{hint::black_box, thread, time::Duration};
use crate::support::{
SMALL_STACK_TIMEOUT, SmallStackFailure, on_small_stack, try_on_small_stack
};
#[test]
fn test_small_stack_passes()
{
on_small_stack(|| assert_eq!(black_box(2) + 2, 4));
}
#[test]
fn test_small_stack_reports_panic()
{
let outcome = try_on_small_stack(SMALL_STACK_TIMEOUT, || {
panic!("deliberate panic in the small-stack child")
});
match outcome
{
Err(SmallStackFailure::Panicked { transcript }) => assert!(
transcript.contains("deliberate panic in the small-stack child"),
"{}",
transcript
),
other => panic!("expected Panicked, got {:?}", other)
}
}
#[test]
fn test_small_stack_reports_overflow()
{
let outcome =
try_on_small_stack(SMALL_STACK_TIMEOUT, || _ = recurse(black_box(0)));
assert!(
matches!(outcome, Err(SmallStackFailure::Overflowed { .. })),
"expected Overflowed, got {:?}",
outcome
);
}
#[test]
fn test_small_stack_reports_timeout()
{
let outcome = try_on_small_stack(Duration::from_secs(1), || {
thread::sleep(Duration::from_secs(60))
});
assert!(
matches!(outcome, Err(SmallStackFailure::TimedOut { .. })),
"expected TimedOut, got {:?}",
outcome
);
}
#[test]
fn test_small_stack_holds_one_mebibyte()
{
on_small_stack(|| _ = big_frame::<{ 1024 * 1024 }>());
}
#[test]
fn test_small_stack_rejects_three_mebibytes()
{
let outcome = try_on_small_stack(SMALL_STACK_TIMEOUT, || {
_ = big_frame::<{ 3 * 1024 * 1024 }>()
});
assert!(
matches!(outcome, Err(SmallStackFailure::Overflowed { .. })),
"expected Overflowed, got {:?}",
outcome
);
}
#[inline(never)]
fn recurse(depth: u64) -> u64
{
let frame = black_box([depth; 16]);
if depth == u64::MAX
{
return frame[0]
}
frame[1].wrapping_add(recurse(depth + 1))
}
#[inline(never)]
fn big_frame<const N: usize>() -> u8
{
let mut frame = [0u8; N];
black_box(&mut frame);
frame[0]
}