Skip to content

Instantly share code, notes, and snippets.

@jcbellido
Created March 16, 2024 04:48
Show Gist options
  • Save jcbellido/39640e65f726b638ee8d5e6db1c5a71a to your computer and use it in GitHub Desktop.
Save jcbellido/39640e65f726b638ee8d5e6db1c5a71a to your computer and use it in GitHub Desktop.
jcbellido.info: test sqlite proc macro
extern crate proc_macro;
use quote::{format_ident, quote, ToTokens};
use syn::{ItemFn, LitStr};
#[proc_macro_attribute]
pub fn test_sqlite(
input: proc_macro::TokenStream,
item: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
impl_test_sqlite(input.into(), item.into()).into()
}
// Notice the "proc_macro2" TokenStream
fn impl_test_sqlite(
attr: proc_macro2::TokenStream,
item: proc_macro2::TokenStream,
) -> proc_macro2::TokenStream {
// Supporting the feature #[test_sqlite("../path/to/your/migration")]
// or default to "./migrations"
let migrations_dir = if attr.is_empty() {
"./migrations".to_string()
} else {
// Try to parse a String Literal -> LitStr
let t: LitStr = match syn::parse2(attr.into_token_stream()) {
Ok(i) => i,
Err(e) => return e.into_compile_error(),
};
t.value()
};
// Try to parse an item that's a function -> ItemFn
let mut test_body: ItemFn = match syn::parse2(item.clone()) {
Ok(item) => item,
Err(e) => return e.into_compile_error(),
};
let original_ident = test_body.sig.ident.clone();
// Change the name of the original function by suffixing `_impl`
test_body.sig.ident = format_ident!("{}_impl", test_body.sig.ident);
let test_body_ident = test_body.sig.ident.clone();
quote! {
#[::tokio::test(flavor = "multi_thread")]
async fn #original_ident () {
#test_body
let test_output_path = format!("./tests_output/{}.sqlite", stringify!(#original_ident));
let pool = ::test_sqlite::sqlite_create(
#migrations_dir,
&test_output_path,
4,
)
.await
.expect("test scaffolding DB should be possible to create");
#test_body_ident(&pool).await;
pool.close().await;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment