diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/for_await.rs | 23 | ||||
-rw-r--r-- | tests/stream.rs | 165 | ||||
-rw-r--r-- | tests/try_stream.rs | 80 | ||||
-rw-r--r-- | tests/ui/yield_in_async.rs | 11 | ||||
-rw-r--r-- | tests/ui/yield_in_async.stderr | 76 | ||||
-rw-r--r-- | tests/ui/yield_in_closure.rs | 11 | ||||
-rw-r--r-- | tests/ui/yield_in_closure.stderr | 18 | ||||
-rw-r--r-- | tests/ui/yield_in_nested_fn.rs | 9 | ||||
-rw-r--r-- | tests/ui/yield_in_nested_fn.stderr | 16 |
9 files changed, 409 insertions, 0 deletions
diff --git a/tests/for_await.rs b/tests/for_await.rs new file mode 100644 index 0000000..590ffbd --- /dev/null +++ b/tests/for_await.rs @@ -0,0 +1,23 @@ +use async_stream::stream; + +use futures_util::stream::StreamExt; + +#[tokio::test] +async fn test() { + let s = stream! { + yield "hello"; + yield "world"; + }; + + let s = stream! { + for await x in s { + yield x.to_owned() + "!"; + } + }; + + let values: Vec<_> = s.collect().await; + + assert_eq!(2, values.len()); + assert_eq!("hello!", values[0]); + assert_eq!("world!", values[1]); +} diff --git a/tests/stream.rs b/tests/stream.rs new file mode 100644 index 0000000..e46fc5a --- /dev/null +++ b/tests/stream.rs @@ -0,0 +1,165 @@ +use async_stream::stream; + +use futures_core::stream::{FusedStream, Stream}; +use futures_util::pin_mut; +use futures_util::stream::StreamExt; +use tokio::sync::mpsc; +use tokio_test::assert_ok; + +#[tokio::test] +async fn noop_stream() { + let s = stream! {}; + pin_mut!(s); + + while let Some(_) = s.next().await { + unreachable!(); + } +} + +#[tokio::test] +async fn empty_stream() { + let mut ran = false; + + { + let r = &mut ran; + let s = stream! { + *r = true; + println!("hello world!"); + }; + pin_mut!(s); + + while let Some(_) = s.next().await { + unreachable!(); + } + } + + assert!(ran); +} + +#[tokio::test] +async fn yield_single_value() { + let s = stream! { + yield "hello"; + }; + + let values: Vec<_> = s.collect().await; + + assert_eq!(1, values.len()); + assert_eq!("hello", values[0]); +} + +#[tokio::test] +async fn fused() { + let s = stream! { + yield "hello"; + }; + pin_mut!(s); + + assert!(!s.is_terminated()); + assert_eq!(s.next().await, Some("hello")); + assert_eq!(s.next().await, None); + + assert!(s.is_terminated()); + // This should return None from now on + assert_eq!(s.next().await, None); +} + +#[tokio::test] +async fn yield_multi_value() { + let s = stream! { + yield "hello"; + yield "world"; + yield "dizzy"; + }; + + let values: Vec<_> = s.collect().await; + + assert_eq!(3, values.len()); + assert_eq!("hello", values[0]); + assert_eq!("world", values[1]); + assert_eq!("dizzy", values[2]); +} + +#[tokio::test] +async fn return_stream() { + fn build_stream() -> impl Stream<Item = u32> { + stream! { + yield 1; + yield 2; + yield 3; + } + } + + let s = build_stream(); + + let values: Vec<_> = s.collect().await; + assert_eq!(3, values.len()); + assert_eq!(1, values[0]); + assert_eq!(2, values[1]); + assert_eq!(3, values[2]); +} + +#[tokio::test] +async fn consume_channel() { + let (mut tx, mut rx) = mpsc::channel(10); + + let s = stream! { + while let Some(v) = rx.recv().await { + yield v; + } + }; + + pin_mut!(s); + + for i in 0..3 { + assert_ok!(tx.send(i).await); + assert_eq!(Some(i), s.next().await); + } + + drop(tx); + assert_eq!(None, s.next().await); +} + +#[tokio::test] +async fn borrow_self() { + struct Data(String); + + impl Data { + fn stream<'a>(&'a self) -> impl Stream<Item = &str> + 'a { + stream! { + yield &self.0[..]; + } + } + } + + let data = Data("hello".to_string()); + let s = data.stream(); + pin_mut!(s); + + assert_eq!(Some("hello"), s.next().await); +} + +#[tokio::test] +async fn stream_in_stream() { + let s = stream! { + let s = stream! { + for i in 0..3 { + yield i; + } + }; + + pin_mut!(s); + while let Some(v) = s.next().await { + yield v; + } + }; + + let values: Vec<_> = s.collect().await; + assert_eq!(3, values.len()); +} + +#[test] +fn test() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/*.rs"); +} diff --git a/tests/try_stream.rs b/tests/try_stream.rs new file mode 100644 index 0000000..063e37a --- /dev/null +++ b/tests/try_stream.rs @@ -0,0 +1,80 @@ +use async_stream::try_stream; + +use futures_core::stream::Stream; +use futures_util::stream::StreamExt; + +#[tokio::test] +async fn single_err() { + let s = try_stream! { + if true { + Err("hello")?; + } else { + yield "world"; + } + + unreachable!(); + }; + + let values: Vec<_> = s.collect().await; + assert_eq!(1, values.len()); + assert_eq!(Err("hello"), values[0]); +} + +#[tokio::test] +async fn yield_then_err() { + let s = try_stream! { + yield "hello"; + Err("world")?; + unreachable!(); + }; + + let values: Vec<_> = s.collect().await; + assert_eq!(2, values.len()); + assert_eq!(Ok("hello"), values[0]); + assert_eq!(Err("world"), values[1]); +} + +#[tokio::test] +async fn convert_err() { + struct ErrorA(u8); + #[derive(PartialEq, Debug)] + struct ErrorB(u8); + impl From<ErrorA> for ErrorB { + fn from(a: ErrorA) -> ErrorB { + ErrorB(a.0) + } + } + + fn test() -> impl Stream<Item = Result<&'static str, ErrorB>> { + try_stream! { + if true { + Err(ErrorA(1))?; + } else { + Err(ErrorB(2))?; + } + yield "unreachable"; + } + } + + let values: Vec<_> = test().collect().await; + assert_eq!(1, values.len()); + assert_eq!(Err(ErrorB(1)), values[0]); +} + +#[tokio::test] +async fn multi_try() { + fn test() -> impl Stream<Item = Result<i32, String>> { + try_stream! { + let a = Ok::<_, String>(Ok::<_, String>(123))??; + for _ in (1..10) { + yield a; + } + } + } + let values: Vec<_> = test().collect().await; + assert_eq!(9, values.len()); + assert_eq!( + std::iter::repeat(123).take(9).map(Ok).collect::<Vec<_>>(), + values + ); +} diff --git a/tests/ui/yield_in_async.rs b/tests/ui/yield_in_async.rs new file mode 100644 index 0000000..24e7330 --- /dev/null +++ b/tests/ui/yield_in_async.rs @@ -0,0 +1,11 @@ +use async_stream::stream; + +fn main() { + stream! { + let f = async { + yield 123; + }; + + let v = f.await; + }; +} diff --git a/tests/ui/yield_in_async.stderr b/tests/ui/yield_in_async.stderr new file mode 100644 index 0000000..1e9d8ff --- /dev/null +++ b/tests/ui/yield_in_async.stderr @@ -0,0 +1,76 @@ +error[E0658]: yield syntax is experimental + --> $DIR/yield_in_async.rs:6:13 + | +6 | yield 123; + | ^^^^^^^^^ + | + = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information + +error[E0727]: `async` generators are not yet supported + --> $DIR/yield_in_async.rs:6:13 + | +6 | yield 123; + | ^^^^^^^^^ + +error[E0271]: type mismatch resolving `<[static generator@$DIR/tests/ui/yield_in_async.rs:4:5: 10:7 _] as std::ops::Generator<std::future::ResumeTy>>::Yield == ()` + --> $DIR/yield_in_async.rs:4:5 + | +4 | / stream! { +5 | | let f = async { +6 | | yield 123; +7 | | }; +8 | | +9 | | let v = f.await; +10 | | }; + | |______^ expected `()`, found integer + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/yield_in_async.rs:6:19 + | +6 | yield 123; + | ^^^ cannot infer type for type `{integer}` + | +note: the type is part of the `async` block because of this `yield` + --> $DIR/yield_in_async.rs:6:13 + | +6 | yield 123; + | ^^^^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/yield_in_async.rs:5:13 + | +5 | let f = async { + | ^ cannot infer type for type `{integer}` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/yield_in_async.rs:9:17 + | +9 | let v = f.await; + | ^^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/yield_in_async.rs:9:17 + | +9 | let v = f.await; + | ^ cannot infer type for type `{integer}` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/yield_in_async.rs:9:17 + | +9 | let v = f.await; + | ^^^^^^^ + +error[E0698]: type inside `async` block must be known in this context + --> $DIR/yield_in_async.rs:9:17 + | +9 | let v = f.await; + | ^^^^^^^ cannot infer type for type `{integer}` + | +note: the type is part of the `async` block because of this `await` + --> $DIR/yield_in_async.rs:9:17 + | +9 | let v = f.await; + | ^^^^^^^ + +Some errors have detailed explanations: E0271, E0658, E0698, E0727. +For more information about an error, try `rustc --explain E0271`. diff --git a/tests/ui/yield_in_closure.rs b/tests/ui/yield_in_closure.rs new file mode 100644 index 0000000..cd6ebd9 --- /dev/null +++ b/tests/ui/yield_in_closure.rs @@ -0,0 +1,11 @@ +use async_stream::stream; + +fn main() { + stream! { + Ok("value") + .and_then(|v| { + yield v; + Ok(()) + }); + }; +} diff --git a/tests/ui/yield_in_closure.stderr b/tests/ui/yield_in_closure.stderr new file mode 100644 index 0000000..77092e0 --- /dev/null +++ b/tests/ui/yield_in_closure.stderr @@ -0,0 +1,18 @@ +error[E0658]: yield syntax is experimental + --> $DIR/yield_in_closure.rs:7:17 + | +7 | yield v; + | ^^^^^^^ + | + = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information + +error[E0277]: expected a `std::ops::FnOnce<(&str,)>` closure, found `[generator@$DIR/tests/ui/yield_in_closure.rs:4:5: 10:7 _]` + --> $DIR/yield_in_closure.rs:6:14 + | +6 | .and_then(|v| { + | ^^^^^^^^ expected an `FnOnce<(&str,)>` closure, found `[generator@$DIR/tests/ui/yield_in_closure.rs:4:5: 10:7 _]` + | + = help: the trait `std::ops::FnOnce<(&str,)>` is not implemented for `[generator@$DIR/tests/ui/yield_in_closure.rs:4:5: 10:7 _]` + +Some errors have detailed explanations: E0277, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/yield_in_nested_fn.rs b/tests/ui/yield_in_nested_fn.rs new file mode 100644 index 0000000..9ae6cf2 --- /dev/null +++ b/tests/ui/yield_in_nested_fn.rs @@ -0,0 +1,9 @@ +use async_stream::stream; + +fn main() { + stream! { + fn foo() { + yield "hello"; + } + }; +} diff --git a/tests/ui/yield_in_nested_fn.stderr b/tests/ui/yield_in_nested_fn.stderr new file mode 100644 index 0000000..a562555 --- /dev/null +++ b/tests/ui/yield_in_nested_fn.stderr @@ -0,0 +1,16 @@ +error[E0658]: yield syntax is experimental + --> $DIR/yield_in_nested_fn.rs:6:13 + | +6 | yield "hello"; + | ^^^^^^^^^^^^^ + | + = note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information + +error[E0627]: yield expression outside of generator literal + --> $DIR/yield_in_nested_fn.rs:6:13 + | +6 | yield "hello"; + | ^^^^^^^^^^^^^ + +Some errors have detailed explanations: E0627, E0658. +For more information about an error, try `rustc --explain E0627`. |