use proc_macro2::TokenStream;
use quote::quote;
pub(crate) fn expand(input_fn: &syn::ItemFn) -> TokenStream {
let fn_name = &input_fn.sig.ident;
let vis = &input_fn.vis;
let block = &input_fn.block;
let attrs = &input_fn.attrs;
let output = &input_fn.sig.output;
quote! {
#(#attrs)*
#[::tokio::test]
#vis async fn #fn_name() #output {
async fn __rullst_test_body() #output #block
let _ = ::rullst_orm::Orm::init(&::std::env::var("DATABASE_URL").unwrap_or_else(|_| "sqlite::memory:".to_string())).await;
let _sqlite_sandbox_guard = if matches!(::rullst_orm::Orm::try_driver(), Ok("sqlite")) {
Some(::rullst_orm::TEST_SANDBOX_LOCK.lock().await)
} else {
None
};
let tx = ::rullst_orm::Orm::begin_transaction().await.expect("Failed to begin sandbox transaction");
let tx_arc = ::std::sync::Arc::new(::tokio::sync::Mutex::new(Some(tx)));
let __rullst_post_commit = ::rullst_orm::post_commit::PostCommitScope::new();
let __rullst_test_result = __rullst_post_commit
.run(::rullst_orm::CURRENT_TX.scope(tx_arc.clone(), __rullst_test_body()))
.await;
if let Some(tx) = tx_arc.lock().await.take() {
let _ = tx.rollback().await;
}
drop(__rullst_post_commit);
__rullst_test_result
}
}
}
#[cfg(test)]
mod tests {
use syn::parse_quote;
#[test]
fn keeps_the_declared_return_type_and_returns_the_body_result() {
let input: syn::ItemFn = parse_quote! {
async fn fallible() -> Result<(), rullst_orm::Error> {
missing().await?;
Ok(())
}
};
let expanded = super::expand(&input).to_string();
assert!(expanded.contains("async fn fallible () -> Result < () , rullst_orm :: Error > {"));
assert!(
expanded.contains(
"async fn __rullst_test_body () -> Result < () , rullst_orm :: Error > {"
)
);
let after_rollback = expanded.split_once("tx . rollback ()").expect("rollback").1;
assert!(
after_rollback
.trim_end()
.ends_with("__rullst_test_result }")
);
}
#[test]
fn runs_the_body_under_a_post_commit_scope_that_is_never_committed() {
let input: syn::ItemFn = parse_quote! {
async fn sandboxed() {}
};
let expanded = super::expand(&input).to_string();
assert!(
expanded.contains("__rullst_post_commit . run (:: rullst_orm :: CURRENT_TX . scope")
);
assert!(expanded.contains("drop (__rullst_post_commit)"));
assert!(!expanded.contains("__rullst_post_commit . commit"));
}
}