You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
async-std/tests/stream.rs

184 lines
4.3 KiB
Rust

use std::convert::identity;
use std::marker::Unpin;
use std::pin::Pin;
use std::task::{Context, Poll};
use pin_project_lite::pin_project;
use async_std::channel::bounded as channel;
use async_std::prelude::*;
use async_std::stream;
use async_std::task;
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
#[cfg(not(target_os = "unknown"))]
use async_std::task::spawn;
#[cfg(target_os = "unknown")]
use async_std::task::spawn_local as spawn;
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
/// Checks that streams are merged fully even if one of the components
/// experiences delay.
fn merging_delayed_streams_work() {
let (sender, receiver) = channel::<i32>(10);
let mut s = receiver.merge(stream::empty());
let t = spawn(async move {
let mut xs = Vec::new();
while let Some(x) = s.next().await {
xs.push(x);
}
xs
});
task::block_on(async move {
task::sleep(std::time::Duration::from_millis(500)).await;
sender.send(92).await.unwrap();
drop(sender);
let xs = t.await;
assert_eq!(xs, vec![92])
});
let (sender, receiver) = channel::<i32>(10);
let mut s = stream::empty().merge(receiver);
let t = spawn(async move {
let mut xs = Vec::new();
while let Some(x) = s.next().await {
xs.push(x);
}
xs
});
task::block_on(async move {
task::sleep(std::time::Duration::from_millis(500)).await;
sender.send(92).await.unwrap();
drop(sender);
let xs = t.await;
assert_eq!(xs, vec![92])
});
}
pin_project! {
/// The opposite of `Fuse`: makes the stream panic if polled after termination.
struct Explode<S> {
#[pin]
done: bool,
#[pin]
inner: S,
}
}
impl<S: Stream> Stream for Explode<S> {
type Item = S::Item;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let mut this = self.project();
if *this.done {
panic!("KABOOM!")
}
let res = this.inner.poll_next(cx);
if let Poll::Ready(None) = &res {
*this.done = true;
}
res
}
}
fn explode<S: Stream>(s: S) -> Explode<S> {
Explode {
done: false,
inner: s,
}
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
fn merge_works_with_unfused_streams() {
let s1 = explode(stream::once(92));
let s2 = explode(stream::once(92));
let mut s = s1.merge(s2);
task::block_on(async move {
let mut xs = Vec::new();
while let Some(x) = s.next().await {
xs.push(x)
}
assert_eq!(xs, vec![92, 92]);
});
}
struct S<T>(T);
impl<T: Stream + Unpin> Stream for S<T> {
type Item = T::Item;
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
unsafe { Pin::new_unchecked(&mut self.0) }.poll_next(ctx)
}
}
struct StrictOnce {
polled: bool,
}
impl Stream for StrictOnce {
type Item = ();
fn poll_next(mut self: Pin<&mut Self>, _: &mut Context) -> Poll<Option<Self::Item>> {
assert!(!self.polled, "Polled after completion!");
self.polled = true;
Poll::Ready(None)
}
}
struct Interchanger {
polled: bool,
}
impl Stream for Interchanger {
type Item = S<Box<dyn Stream<Item = ()> + Unpin>>;
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context) -> Poll<Option<Self::Item>> {
if self.polled {
self.polled = false;
ctx.waker().wake_by_ref();
Poll::Pending
} else {
self.polled = true;
Poll::Ready(Some(S(Box::new(StrictOnce { polled: false }))))
}
}
}
#[test]
fn flat_map_doesnt_poll_completed_inner_stream() {
task::block_on(async {
assert_eq!(
Interchanger { polled: false }
.take(2)
.flat_map(identity)
.count()
.await,
0
);
});
}
#[test]
fn flatten_doesnt_poll_completed_inner_stream() {
task::block_on(async {
assert_eq!(
Interchanger { polled: false }
.take(2)
.flatten()
.count()
.await,
0
);
});
}