Skip to content

Commit

Permalink
glib-macros: add test macro for async-glib-context tests
Browse files Browse the repository at this point in the history
  • Loading branch information
BiagioFesta committed Sep 28, 2024
1 parent 8052e13 commit 23961b5
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
20 changes: 20 additions & 0 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ mod flags_attribute;
mod object_impl_attributes;
mod properties;
mod shared_boxed_derive;
mod test;
mod value_delegate_derive;
mod variant_derive;

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::test]
/// async fn my_async_test() {
/// // Test code that runs asynchronously
/// }
/// ```
#[proc_macro_attribute]
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
test::test(args, item)
}
45 changes: 45 additions & 0 deletions glib-macros/src/test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use proc_macro::TokenStream;
use quote::ToTokens;

pub(crate) fn 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::default();
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
}
2 changes: 1 addition & 1 deletion glib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use bitflags;
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,
test, Boxed, Downgrade, Enum, ErrorDomain, Properties, SharedBoxed, ValueDelegate, Variant,
};
pub use glib_sys as ffi;
pub use gobject_sys as gobject_ffi;
Expand Down
6 changes: 5 additions & 1 deletion glib/tests/log.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::sync::{Arc, Mutex};

use glib::*;
use glib::{
clone, g_critical, g_debug, g_info, g_message, g_warning, log_remove_handler,
log_set_default_handler, log_set_fatal_mask, log_set_handler, log_unset_default_handler,
LogLevel, LogLevels,
};

#[derive(Default)]
struct Counters {
Expand Down
5 changes: 4 additions & 1 deletion glib/tests/print.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::sync::{Arc, Mutex};

use glib::*;
use glib::{
clone, g_print, g_printerr, set_print_handler, set_printerr_handler, unset_print_handler,
unset_printerr_handler,
};

// Funny thing: we can't put those two tests in two different functions, otherwise they might
// conflict with the results of the other one (or it would be mandatory to run the tests on only
Expand Down

0 comments on commit 23961b5

Please sign in to comment.