use futures::channel::{mpsc, oneshot}; use futures::executor::block_on; use futures::future::{self, poll_fn, Future, FutureExt, TryFutureExt}; use futures::never::Never; use futures::ready; use futures::sink::{self, Sink, SinkErrInto, SinkExt}; use futures::stream::{self, Stream, StreamExt}; use futures::task::{self, ArcWake, Context, Poll, Waker}; use futures_test::task::panic_context; use std::cell::{Cell, RefCell}; use std::collections::VecDeque; use std::fmt; use std::mem; use std::pin::Pin; use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc;
fn sassert_next<S>(s: &mut S, item: S::Item) where
S: Stream + Unpin,
S::Item: Eq + fmt::Debug,
{ match s.poll_next_unpin(&mut panic_context()) {
Poll::Ready(None) => panic!("stream is at its end"),
Poll::Ready(Some(e)) => assert_eq!(e, item),
Poll::Pending => panic!("stream wasn't ready"),
}
}
fn unwrap<T, E: fmt::Debug>(x: Poll<Result<T, E>>) -> T { match x {
Poll::Ready(Ok(x)) => x,
Poll::Ready(Err(_)) => panic!("Poll::Ready(Err(_))"),
Poll::Pending => panic!("Poll::Pending"),
}
}
// An Unpark struct that records unpark events for inspection struct Flag(AtomicBool);
impl Flag { fn new() -> Arc<Self> {
Arc::new(Self(AtomicBool::new(false)))
}
impl ArcWake for Flag { fn wake_by_ref(arc_self: &Arc<Self>) {
arc_self.set(true)
}
}
fn flag_cx<F, R>(f: F) -> R where
F: FnOnce(Arc<Flag>, &mut Context<'_>) -> R,
{ let flag = Flag::new(); let waker = task::waker_ref(&flag); let cx = &mut Context::from_waker(&waker);
f(flag.clone(), cx)
}
// Sends a value on an i32 channel sink struct StartSendFut<S: Sink<Item> + Unpin, Item: Unpin>(Option<S>, Option<Item>);
// Immediately accepts all requests to start pushing, but completion is managed // by manually flushing struct ManualFlush<T: Unpin> {
data: Vec<T>,
waiting_tasks: Vec<Waker>,
}
impl<T: Unpin> Sink<Option<T>> for ManualFlush<T> { type Error = ();
// Test that `start_send` on an `mpsc` channel does indeed block when the // channel is full #[test] fn mpsc_blocking_start_send() { let (mut tx, mut rx) = mpsc::channel::<i32>(0);
// test `flush` by using `with` to make the first insertion into a sink block // until a oneshot is completed #[test] fn with_flush() { let (tx, rx) = oneshot::channel(); letmut block = rx.boxed(); letmut sink = Vec::new().with(|elem| {
mem::replace(&mut block, future::ok(()).boxed())
.map_ok(move |()| elem + 1)
.map_err(|_| -> Never { panic!() })
});
// test simple use of with to change data #[test] fn with_as_map() { letmut sink = Vec::new().with(|item| future::ok::<i32, Never>(item * 2));
block_on(sink.send(0)).unwrap();
block_on(sink.send(1)).unwrap();
block_on(sink.send(2)).unwrap();
assert_eq!(sink.get_ref(), &[0, 2, 4]);
}
// test simple use of with_flat_map #[test] fn with_flat_map() { letmut sink = Vec::new().with_flat_map(|item| stream::iter(vec![item; item]).map(Ok));
block_on(sink.send(0)).unwrap();
block_on(sink.send(1)).unwrap();
block_on(sink.send(2)).unwrap();
block_on(sink.send(3)).unwrap();
assert_eq!(sink.get_ref(), &[1, 2, 2, 3, 3, 3]);
}
// Check that `with` propagates `poll_ready` to the inner sink. // Regression test for the issue #1834. #[test] fn with_propagates_poll_ready() { let (tx, mut rx) = mpsc::channel::<i32>(0); letmut tx = tx.with(|item: i32| future::ok::<i32, mpsc::SendError>(item + 10));
// Should be ready for the first item.
assert_eq!(tx.as_mut().poll_ready(cx), Poll::Ready(Ok(())));
assert_eq!(tx.as_mut().start_send(0), Ok(()));
// Should be ready for the second item only after the first one is received.
assert_eq!(tx.as_mut().poll_ready(cx), Poll::Pending);
assert!(!flag.take());
sassert_next(&mut rx, 10);
assert!(flag.take());
assert_eq!(tx.as_mut().poll_ready(cx), Poll::Ready(Ok(())));
assert_eq!(tx.as_mut().start_send(1), Ok(()));
})
}));
}
// test that the `with` sink doesn't require the underlying sink to flush, // but doesn't claim to be flushed until the underlying sink is #[test] fn with_flush_propagate() { letmut sink = ManualFlush::new().with(future::ok::<Option<i32>, ()>);
flag_cx(|flag, cx| {
unwrap(Pin::new(&mut sink).poll_ready(cx));
Pin::new(&mut sink).start_send(Some(0)).unwrap();
unwrap(Pin::new(&mut sink).poll_ready(cx));
Pin::new(&mut sink).start_send(Some(1)).unwrap();
// test that a buffer is a no-nop around a sink that always accepts sends #[test] fn buffer_noop() { letmut sink = Vec::new().buffer(0);
block_on(sink.send(0)).unwrap();
block_on(sink.send(1)).unwrap();
assert_eq!(sink.get_ref(), &[0, 1]);
// test basic buffer functionality, including both filling up to capacity, // and writing out when the underlying sink is ready #[test] fn buffer() { let (sink, allow) = manual_allow::<i32>(); let sink = sink.buffer(2);
let sink = block_on(StartSendFut::new(sink, 0)).unwrap(); letmut sink = block_on(StartSendFut::new(sink, 1)).unwrap();
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.