From 1fbc150fd6392d8268aa35d15380c02e363c4eb8 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Fri, 24 Nov 2023 21:33:30 +0100 Subject: executor: add some tests. --- embassy-executor/tests/test.rs | 137 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 embassy-executor/tests/test.rs (limited to 'embassy-executor/tests') diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs new file mode 100644 index 000000000..0dbd391e8 --- /dev/null +++ b/embassy-executor/tests/test.rs @@ -0,0 +1,137 @@ +#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] + +use std::boxed::Box; +use std::future::poll_fn; +use std::sync::{Arc, Mutex}; +use std::task::Poll; + +use embassy_executor::raw::Executor; +use embassy_executor::task; + +#[export_name = "__pender"] +fn __pender(context: *mut ()) { + unsafe { + let trace = &*(context as *const Trace); + trace.push("pend"); + } +} + +#[derive(Clone)] +struct Trace { + trace: Arc>>, +} + +impl Trace { + fn new() -> Self { + Self { + trace: Arc::new(Mutex::new(Vec::new())), + } + } + fn push(&self, value: &'static str) { + self.trace.lock().unwrap().push(value) + } + + fn get(&self) -> Vec<&'static str> { + self.trace.lock().unwrap().clone() + } +} + +fn setup() -> (&'static Executor, Trace) { + let trace = Trace::new(); + let context = Box::leak(Box::new(trace.clone())) as *mut _ as *mut (); + let executor = &*Box::leak(Box::new(Executor::new(context))); + (executor, trace) +} + +#[test] +fn executor_noop() { + let (executor, trace) = setup(); + unsafe { executor.poll() }; + assert!(trace.get().is_empty()) +} + +#[test] +fn executor_task() { + #[task] + async fn task1(trace: Trace) { + trace.push("poll task1") + } + + let (executor, trace) = setup(); + executor.spawner().spawn(task1(trace.clone())).unwrap(); + + unsafe { executor.poll() }; + unsafe { executor.poll() }; + + assert_eq!( + trace.get(), + &[ + "pend", // spawning a task pends the executor + "poll task1", // poll only once. + ] + ) +} + +#[test] +fn executor_task_self_wake() { + #[task] + async fn task1(trace: Trace) { + poll_fn(|cx| { + trace.push("poll task1"); + cx.waker().wake_by_ref(); + Poll::Pending + }) + .await + } + + let (executor, trace) = setup(); + executor.spawner().spawn(task1(trace.clone())).unwrap(); + + unsafe { executor.poll() }; + unsafe { executor.poll() }; + + assert_eq!( + trace.get(), + &[ + "pend", // spawning a task pends the executor + "poll task1", // + "pend", // task self-wakes + "poll task1", // + "pend", // task self-wakes + ] + ) +} + +#[test] +fn executor_task_self_wake_twice() { + #[task] + async fn task1(trace: Trace) { + poll_fn(|cx| { + trace.push("poll task1"); + cx.waker().wake_by_ref(); + trace.push("poll task1 wake 2"); + cx.waker().wake_by_ref(); + Poll::Pending + }) + .await + } + + let (executor, trace) = setup(); + executor.spawner().spawn(task1(trace.clone())).unwrap(); + + unsafe { executor.poll() }; + unsafe { executor.poll() }; + + assert_eq!( + trace.get(), + &[ + "pend", // spawning a task pends the executor + "poll task1", // + "pend", // task self-wakes + "poll task1 wake 2", // task self-wakes again, shouldn't pend + "poll task1", // + "pend", // task self-wakes + "poll task1 wake 2", // task self-wakes again, shouldn't pend + ] + ) +} -- cgit