Skip to content

Commit

Permalink
Merge pull request #1521 from BiagioFesta/wip/bfesta/macro-test-async
Browse files Browse the repository at this point in the history
glib-macros: add test macro for async-glib-context tests
  • Loading branch information
sdroege authored Sep 30, 2024
2 parents 8052e13 + c9c9bc2 commit 1534916
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 2 deletions.
47 changes: 47 additions & 0 deletions glib-macros/src/async_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Take a look at the license at the top of the repository in the LICENSE file.

use proc_macro::TokenStream;
use quote::ToTokens;

pub(crate) fn async_test(_args: TokenStream, mut item: TokenStream) -> TokenStream {
let mut item_fn: syn::ItemFn = match syn::parse(item.clone()) {
Ok(it) => it,
Err(e) => {
item.extend(TokenStream::from(e.into_compile_error()));
return item;
}
};

if item_fn.sig.asyncness.is_none() {
item.extend(TokenStream::from(
syn::Error::new_spanned(
item_fn.sig.ident,
"The 'async' keyword is missing from the test function declaration",
)
.into_compile_error(),
));
return item;
}

item_fn.sig.asyncness = None;

let gen_attr = quote::quote! {
#[::core::prelude::v1::test]
};

let body = &item_fn.block;

item_fn.block = syn::parse2(quote::quote! {
{
let main_ctx = glib::MainContext::new();
main_ctx.block_on(async #body)
}
})
.expect("Body parsing failure");

let mut tokens = TokenStream::new();
tokens.extend(TokenStream::from(gen_attr.to_token_stream()));
tokens.extend(TokenStream::from(item_fn.into_token_stream()));

tokens
}
20 changes: 20 additions & 0 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file.

mod async_test;
mod boxed_derive;
mod clone;
mod closure;
Expand Down Expand Up @@ -1567,3 +1568,22 @@ pub fn derive_value_delegate(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as value_delegate_derive::ValueDelegateInput);
value_delegate_derive::impl_value_delegate(input).unwrap()
}

/// An attribute macro for writing asynchronous test functions.
///
/// This macro is designed to wrap an asynchronous test function and ensure that
/// it runs within a `glib::MainContext`. It helps in writing async tests that
/// require the use of an event loop for the asynchronous execution.
///
/// # Example
///
/// ```
/// #[glib::async_test]
/// async fn my_async_test() {
/// // Test code that runs asynchronously
/// }
/// ```
#[proc_macro_attribute]
pub fn async_test(args: TokenStream, item: TokenStream) -> TokenStream {
async_test::async_test(args, item)
}
5 changes: 3 additions & 2 deletions glib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ pub use bitflags;
#[doc(hidden)]
pub use glib_macros::cstr_bytes;
pub use glib_macros::{
clone, closure, closure_local, derived_properties, flags, object_interface, object_subclass,
Boxed, Downgrade, Enum, ErrorDomain, Properties, SharedBoxed, ValueDelegate, Variant,
async_test, clone, closure, closure_local, derived_properties, flags, object_interface,
object_subclass, Boxed, Downgrade, Enum, ErrorDomain, Properties, SharedBoxed, ValueDelegate,
Variant,
};
pub use glib_sys as ffi;
pub use gobject_sys as gobject_ffi;
Expand Down

0 comments on commit 1534916

Please sign in to comment.