#![cfg(feature = "glib")]
use any_spawner::Executor;
use glib::{MainContext, MainLoop};
use serial_test::serial;
use std::{
cell::Cell,
future::Future,
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
time::Duration,
};
fn run_on_glib_context<F>(fut: F)
where
F: Future<Output = ()> + Send + 'static,
{
let _ = Executor::init_glib();
let context = MainContext::default();
let main_loop = MainLoop::new(Some(&context), false);
let main_loop_clone = main_loop.clone();
Executor::spawn(async move {
fut.await;
main_loop_clone.quit();
});
main_loop.run();
}
fn run_local_on_glib_context<F>(fut: F)
where
F: Future<Output = ()> + 'static,
{
let _ = Executor::init_glib();
let context = MainContext::default();
let main_loop = MainLoop::new(Some(&context), false);
let main_loop_clone = main_loop.clone();
Executor::spawn_local(async move {
fut.await;
main_loop_clone.quit();
});
main_loop.run();
}
#[test]
#[serial]
fn test_glib_spawn() {
let success_flag = Arc::new(AtomicBool::new(false));
let flag_clone = success_flag.clone();
run_on_glib_context(async move {
futures_lite::future::yield_now().await;
flag_clone.store(true, Ordering::SeqCst);
glib::timeout_future(Duration::from_millis(10)).await;
});
assert!(
success_flag.load(Ordering::SeqCst),
"Spawned future did not complete successfully"
);
}
#[test]
#[serial]
fn test_glib_spawn_local() {
let success_flag = Rc::new(Cell::new(false));
let flag_clone = success_flag.clone();
run_local_on_glib_context(async move {
let non_send_data = Rc::new(Cell::new(10));
let data = non_send_data.get();
assert_eq!(data, 10, "Rc data should be accessible");
non_send_data.set(20);
futures_lite::future::yield_now().await;
assert_eq!(
non_send_data.get(),
20,
"Rc data should persist modification"
);
flag_clone.set(true);
glib::timeout_future(Duration::from_millis(10)).await;
});
assert!(
success_flag.get(),
"Spawned local future did not complete successfully"
);
}
#[test]
#[serial]
fn test_glib_tick() {
run_on_glib_context(async {
let value = Arc::new(Mutex::new(false));
let value_clone = value.clone();
Executor::spawn(async move {
Executor::tick().await;
*value_clone.lock().unwrap() = true;
});
glib::timeout_future(Duration::from_millis(10)).await;
assert!(*value.lock().unwrap());
});
}
#[test]
#[serial]
fn test_glib_poll_local_is_no_op() {
let _ = Executor::init_glib();
Executor::poll_local();
Executor::poll_local();
println!("Executor::poll_local called successfully (expected no-op).");
}