aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/for_await.rs23
-rw-r--r--tests/stream.rs165
-rw-r--r--tests/try_stream.rs80
-rw-r--r--tests/ui/yield_in_async.rs11
-rw-r--r--tests/ui/yield_in_async.stderr76
-rw-r--r--tests/ui/yield_in_closure.rs11
-rw-r--r--tests/ui/yield_in_closure.stderr18
-rw-r--r--tests/ui/yield_in_nested_fn.rs9
-rw-r--r--tests/ui/yield_in_nested_fn.stderr16
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`.