extern crate std;
use core::cell::Cell;
use std::panic::{AssertUnwindSafe, catch_unwind};
use std::sync::mpsc::{Receiver, SyncSender};
#[derive(Default)]
pub(crate) struct Runs(Cell<usize>);
impl Runs {
pub(crate) fn tick(&self) {
self.0.set(self.0.get() + 1);
}
pub(crate) fn take(&self) -> usize {
self.0.replace(0)
}
}
std::thread_local! {
static BREAK_CLONES: Cell<bool> = const { Cell::new(false) };
}
#[derive(Debug, PartialEq)]
pub(crate) struct Fragile(pub(crate) u64);
impl Clone for Fragile {
fn clone(&self) -> Self {
assert!(!BREAK_CLONES.with(Cell::get), "a clone refused");
Fragile(self.0)
}
}
pub(crate) fn panics(break_clones: bool, op: impl FnOnce()) {
BREAK_CLONES.with(|b| b.set(break_clones));
let unwound = catch_unwind(AssertUnwindSafe(op)).is_err();
BREAK_CLONES.with(|b| b.set(false));
assert!(unwound, "the call was to panic");
}
pub(crate) fn stalled<T>(arrived: SyncSender<()>, go: Receiver<()>, then: T) -> impl FnOnce() -> T {
move || {
arrived.send(()).expect("the test waits for the closure");
go.recv().expect("the test lets the closure go");
then
}
}