use std::cell::RefCell;
use std::future::Future;
use libtest_mimic::Failed;
use libtest_mimic::Trial;
use rotbl::storage::Storage;
use crate::context::TestContext;
pub(crate) fn ss(x: impl ToString) -> String {
x.to_string()
}
pub(crate) fn bb(x: impl ToString) -> Vec<u8> {
x.to_string().into_bytes()
}
pub trait NewContext<S>
where
S: Storage,
Self: Fn() -> anyhow::Result<TestContext<S>> + Send + Clone + 'static,
{
}
impl<S, T> NewContext<S> for T
where
S: Storage,
T: Fn() -> anyhow::Result<TestContext<S>> + Send + Clone + 'static,
{
}
thread_local! {
pub(crate) static CONTEXT_INFO: RefCell<&'static str> = const { RefCell::new("") };
}
fn get_trial_name(case_name: &str) -> String {
let ctx_info = CONTEXT_INFO.with_borrow_mut(|name| *name);
format!("api::{case_name}/ctx:{ctx_info}")
}
pub fn build_trial<S, F>(name: &str, new_ctx: impl NewContext<S>, f: F) -> Trial
where
S: Storage,
F: FnOnce(TestContext<S>) -> anyhow::Result<()> + Send + 'static,
{
Trial::test(get_trial_name(name), move || {
let ctx = new_ctx()?;
f(ctx).map_err(|err| Failed::from(err.to_string()))?;
Ok(())
})
}
pub fn build_async_trial<S, F, Fut>(name: &str, new_ctx: impl NewContext<S>, f: F) -> Trial
where
S: Storage,
F: FnOnce(TestContext<S>) -> Fut + Send + 'static,
Fut: Future<Output = anyhow::Result<()>>,
{
Trial::test(get_trial_name(name), move || {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.map_err(|err| Failed::from(err.to_string()))?;
let ctx = new_ctx()?;
rt.block_on(f(ctx)).map_err(|err| Failed::from(err.to_string()))?;
Ok(())
})
}
#[macro_export]
macro_rules! trials {
($new_ctx:ident, $($test:ident),*) => {
vec![$(
$crate::utils::build_trial(stringify!($test), $new_ctx.clone(), $test),
)*]
};
}
#[macro_export]
macro_rules! async_trials {
($new_ctx:ident, $($test:ident),*) => {
vec![$(
$crate::utils::build_async_trial(stringify!($test), $new_ctx.clone(), $test),
)*]
};
}