#![allow(missing_docs, clippy::missing_const_for_fn, clippy::future_not_send)]
use core::task::Poll;
use future_form::{FutureForm, Local, Sendable, future_form};
use future_form_ffi::poll_once::PollOnce;
use futures::future::{BoxFuture, LocalBoxFuture};
#[test]
fn test_sendable_poll_once_from_future() {
let mut fut = Sendable::from_future(async { 42u32 });
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_local_poll_once_from_future() {
let mut fut = Local::from_future(async { 42u32 });
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_sendable_poll_once_ready() {
let mut fut: BoxFuture<'_, u32> = Sendable::ready(42);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_local_poll_once_ready() {
let mut fut: LocalBoxFuture<'_, u32> = Local::ready(42);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_sendable_poll_once_multi_step() {
use core::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
let shared = Arc::new(AtomicU32::new(0));
let shared2 = Arc::clone(&shared);
let mut fut = Sendable::from_future(core::future::poll_fn(move |_cx| {
let val = shared2.load(Ordering::Acquire);
if val > 0 {
Poll::Ready(val)
} else {
Poll::Pending
}
}));
assert_eq!(fut.poll_once(), Poll::Pending);
shared.store(99, Ordering::Release);
assert_eq!(fut.poll_once(), Poll::Ready(99));
}
#[test]
fn test_local_poll_once_with_non_send() {
use std::rc::Rc;
let data = Rc::new(42u32);
let mut fut = Local::from_future(async move { *data });
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[tokio::test]
async fn test_sendable_future_await() {
let fut = Sendable::from_future(async { 42u32 });
assert_eq!(fut.await, 42);
}
#[tokio::test]
async fn test_local_future_await() {
let fut = Local::from_future(async { 42u32 });
assert_eq!(fut.await, 42);
}
trait Stepper<K: FutureForm> {
fn step(&self) -> K::Future<'_, u32>;
}
struct StepperImpl {
val: u32,
}
#[future_form(Sendable, Local)]
impl<K: FutureForm> Stepper<K> for StepperImpl {
fn step(&self) -> K::Future<'_, u32> {
let val = self.val;
K::from_future(async move { val + 1 })
}
}
#[test]
fn test_macro_sendable_poll_once() {
let s = StepperImpl { val: 41 };
let mut fut = <StepperImpl as Stepper<Sendable>>::step(&s);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_macro_local_poll_once() {
let s = StepperImpl { val: 41 };
let mut fut = <StepperImpl as Stepper<Local>>::step(&s);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
trait HostWithBounds<K: FutureForm, T: Clone> {
fn wrap(&self, val: T) -> K::Future<'_, T>;
}
struct BoundsImpl;
#[future_form(Sendable where T: Send, Local)]
impl<K: FutureForm, T: Clone + 'static> HostWithBounds<K, T> for BoundsImpl {
fn wrap(&self, val: T) -> K::Future<'_, T> {
K::from_future(async move { val })
}
}
#[test]
fn test_sendable_conditional_bounds_poll_once() {
let b = BoundsImpl;
let mut fut = <BoundsImpl as HostWithBounds<Sendable, String>>::wrap(&b, "hi".into());
assert_eq!(fut.poll_once(), Poll::Ready("hi".to_string()));
}
#[test]
fn test_local_conditional_bounds_poll_once() {
use std::rc::Rc;
let b = BoundsImpl;
let val = Rc::new(42u32);
let mut fut = <BoundsImpl as HostWithBounds<Local, Rc<u32>>>::wrap(&b, val);
assert_eq!(fut.poll_once(), Poll::Ready(Rc::new(42)));
}
async fn generic_step<K: FutureForm>(s: &StepperImpl) -> u32
where
StepperImpl: Stepper<K>,
{
Stepper::<K>::step(s).await
}
#[tokio::test]
async fn test_generic_consumer_sendable() {
let s = StepperImpl { val: 41 };
assert_eq!(generic_step::<Sendable>(&s).await, 42);
}
#[tokio::test]
async fn test_generic_consumer_local() {
let s = StepperImpl { val: 41 };
assert_eq!(generic_step::<Local>(&s).await, 42);
}
trait ReadyStepper<K: FutureForm> {
fn cached(&self) -> K::Future<'_, u32>;
}
struct ReadyImpl {
val: u32,
}
#[future_form(Sendable, Local)]
impl<K: FutureForm> ReadyStepper<K> for ReadyImpl {
fn cached(&self) -> K::Future<'_, u32> {
K::ready(self.val)
}
}
#[test]
fn test_macro_sendable_ready_poll_once() {
let r = ReadyImpl { val: 42 };
let mut fut = <ReadyImpl as ReadyStepper<Sendable>>::cached(&r);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}
#[test]
fn test_macro_local_ready_poll_once() {
let r = ReadyImpl { val: 42 };
let mut fut = <ReadyImpl as ReadyStepper<Local>>::cached(&r);
assert_eq!(fut.poll_once(), Poll::Ready(42));
}