dioxus/packages/core/tests/task.rs

137 lines
3.6 KiB
Rust
Raw Normal View History

//! Verify that tasks get polled by the virtualdom properly, and that we escape wait_for_work safely
2022-11-06 08:48:34 +00:00
use std::{sync::atomic::AtomicUsize, time::Duration};
use dioxus::prelude::*;
async fn run_vdom(app: fn() -> Element) {
let mut dom = VirtualDom::new(app);
dom.rebuild(&mut dioxus_core::NoOpMutations);
tokio::select! {
_ = dom.wait_for_work() => {}
_ = tokio::time::sleep(Duration::from_millis(500)) => {}
};
}
2022-11-06 08:48:34 +00:00
#[tokio::test]
async fn it_works() {
2023-12-17 22:46:32 +00:00
static POLL_COUNT: AtomicUsize = AtomicUsize::new(0);
fn app() -> Element {
2024-01-15 15:05:46 +00:00
use_hook(|| {
2024-01-11 21:18:11 +00:00
spawn(async {
2023-12-17 22:46:32 +00:00
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(50)).await;
POLL_COUNT.fetch_add(x, std::sync::atomic::Ordering::Relaxed);
}
});
2024-01-11 21:18:11 +00:00
spawn(async {
2023-12-17 22:46:32 +00:00
for x in 0..10 {
tokio::time::sleep(Duration::from_micros(25)).await;
POLL_COUNT.fetch_add(x * 2, std::sync::atomic::Ordering::Relaxed);
}
});
});
2024-01-16 19:18:46 +00:00
rsx!({ () })
2023-12-17 22:46:32 +00:00
}
run_vdom(app).await;
// By the time the tasks are finished, we should've accumulated ticks from two tasks
// Be warned that by setting the delay to too short, tokio might not schedule in the tasks
assert_eq!(
POLL_COUNT.fetch_add(0, std::sync::atomic::Ordering::Relaxed),
135
);
}
/// Prove that yield_now doesn't cause a deadlock
#[tokio::test]
async fn yield_now_works() {
thread_local! {
static SEQUENCE: std::cell::RefCell<Vec<usize>> = std::cell::RefCell::new(Vec::new());
}
fn app() -> Element {
// these two tasks should yield to eachother
use_hook(|| {
spawn(async move {
for x in 0..10 {
tokio::task::yield_now().await;
SEQUENCE.with(|s| s.borrow_mut().push(1));
}
})
});
use_hook(|| {
spawn(async move {
for x in 0..10 {
tokio::task::yield_now().await;
SEQUENCE.with(|s| s.borrow_mut().push(2));
}
})
});
rsx!({ () })
}
run_vdom(app).await;
SEQUENCE.with(|s| assert_eq!(s.borrow().len(), 20));
}
/// Ensure that calling wait_for_flush waits for dioxus to finish its syncrhonous work
#[tokio::test]
async fn flushing() {
thread_local! {
static SEQUENCE: std::cell::RefCell<Vec<usize>> = std::cell::RefCell::new(Vec::new());
}
fn app() -> Element {
use_hook(|| {
spawn(async move {
for x in 0..10 {
flush_sync().await;
SEQUENCE.with(|s| s.borrow_mut().push(1));
}
})
});
use_hook(|| {
spawn(async move {
for x in 0..10 {
flush_sync().await;
SEQUENCE.with(|s| s.borrow_mut().push(2));
}
})
});
rsx!({ () })
}
2022-11-06 08:48:34 +00:00
let mut dom = VirtualDom::new(app);
2024-01-15 17:06:27 +00:00
dom.rebuild(&mut dioxus_core::NoOpMutations);
2022-11-06 08:48:34 +00:00
let fut = async {
// Trigger the flush by waiting for work
for _ in 0..40 {
tokio::select! {
_ = dom.wait_for_work() => {}
_ = tokio::time::sleep(Duration::from_millis(1)) => {}
};
}
};
2022-11-12 02:29:27 +00:00
tokio::select! {
_ = fut => {}
2022-11-29 21:31:04 +00:00
_ = tokio::time::sleep(Duration::from_millis(500)) => {}
2022-11-12 02:29:27 +00:00
};
2022-11-24 07:15:01 +00:00
SEQUENCE.with(|s| assert_eq!(s.borrow().len(), 20));
2022-11-06 08:48:34 +00:00
}