sweet 0.4.2

A delightful cross-platform test runner
Documentation
use crate::prelude::*;
use std::cell::RefCell;
use std::future::Future;
use std::pin::Pin;
use std::sync::Arc;
use std::sync::Mutex;
use test::TestDesc;

pub trait SweetTestFuture:
	'static + Future<Output = Result<(), String>>
{
}
impl<T> SweetTestFuture for T where
	T: 'static + Future<Output = Result<(), String>>
{
}


pub type SweetFutFunc =
	Box<dyn Send + Sync + Fn() -> Pin<Box<dyn SweetTestFuture>>>;

type FutCell = Arc<Mutex<Option<SweetFutFunc>>>;
thread_local! {
	static FUTURE: FutCell = Arc::new(Mutex::new(None));
	static CURRENT_TEST_DESC: RefCell<Option<TestDesc>> = RefCell::new(None);
}

pub struct SweetTestCollector;

impl SweetTestCollector {
	pub fn current_test_desc() -> Option<TestDesc> {
		CURRENT_TEST_DESC.with(|cell| cell.borrow().clone())
	}

	/// # Panics
	/// If called outside of [`Self::set`]
	pub fn register<F: SweetTestFuture>(fut: fn() -> F) {
		FUTURE.with(|current_fut| {
			*current_fut.lock().unwrap() =
				Some(Box::new(move || Box::pin(fut())));
		});
	}

	/// This function uses the Error type to represent
	/// that a future has been registered
	pub fn with_scope<F, R>(
		desc: &TestDesc,
		func: F,
	) -> Result<R, TestDescAndFuture>
	where
		F: FnOnce() -> R,
	{
		CURRENT_TEST_DESC.with(|cell| {
			*cell.borrow_mut() = Some(desc.clone());
		});
		FUTURE.with(|val| {
			let out = func();
			if let Some(fut) = val.lock().unwrap().take() {
				Err(TestDescAndFuture::new(desc.clone(), fut))
			} else {
				Ok(out)
			}
		})
	}
}