summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio/tests/macros_select.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/tokio/tests/macros_select.rs')
-rw-r--r--third_party/rust/tokio/tests/macros_select.rs600
1 files changed, 600 insertions, 0 deletions
diff --git a/third_party/rust/tokio/tests/macros_select.rs b/third_party/rust/tokio/tests/macros_select.rs
new file mode 100644
index 0000000000..755365affb
--- /dev/null
+++ b/third_party/rust/tokio/tests/macros_select.rs
@@ -0,0 +1,600 @@
+#![cfg(feature = "macros")]
+#![allow(clippy::blacklisted_name)]
+
+#[cfg(target_arch = "wasm32")]
+use wasm_bindgen_test::wasm_bindgen_test as maybe_tokio_test;
+
+#[cfg(not(target_arch = "wasm32"))]
+use tokio::test as maybe_tokio_test;
+
+use tokio::sync::oneshot;
+use tokio_test::{assert_ok, assert_pending, assert_ready};
+
+use futures::future::poll_fn;
+use std::task::Poll::Ready;
+
+#[maybe_tokio_test]
+async fn sync_one_lit_expr_comma() {
+ let foo = tokio::select! {
+ foo = async { 1 } => foo,
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn nested_one() {
+ let foo = tokio::select! {
+ foo = async { 1 } => tokio::select! {
+ bar = async { foo } => bar,
+ },
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn sync_one_lit_expr_no_comma() {
+ let foo = tokio::select! {
+ foo = async { 1 } => foo
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn sync_one_lit_expr_block() {
+ let foo = tokio::select! {
+ foo = async { 1 } => { foo }
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn sync_one_await() {
+ let foo = tokio::select! {
+ foo = one() => foo,
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn sync_one_ident() {
+ let one = one();
+
+ let foo = tokio::select! {
+ foo = one => foo,
+ };
+
+ assert_eq!(foo, 1);
+}
+
+#[maybe_tokio_test]
+async fn sync_two() {
+ use std::cell::Cell;
+
+ let cnt = Cell::new(0);
+
+ let res = tokio::select! {
+ foo = async {
+ cnt.set(cnt.get() + 1);
+ 1
+ } => foo,
+ bar = async {
+ cnt.set(cnt.get() + 1);
+ 2
+ } => bar,
+ };
+
+ assert_eq!(1, cnt.get());
+ assert!(res == 1 || res == 2);
+}
+
+#[maybe_tokio_test]
+async fn drop_in_fut() {
+ let s = "hello".to_string();
+
+ let res = tokio::select! {
+ foo = async {
+ let v = one().await;
+ drop(s);
+ v
+ } => foo
+ };
+
+ assert_eq!(res, 1);
+}
+
+#[maybe_tokio_test]
+#[cfg(feature = "full")]
+async fn one_ready() {
+ let (tx1, rx1) = oneshot::channel::<i32>();
+ let (_tx2, rx2) = oneshot::channel::<i32>();
+
+ tx1.send(1).unwrap();
+
+ let v = tokio::select! {
+ res = rx1 => {
+ assert_ok!(res)
+ },
+ _ = rx2 => unreachable!(),
+ };
+
+ assert_eq!(1, v);
+}
+
+#[maybe_tokio_test]
+#[cfg(feature = "full")]
+async fn select_streams() {
+ use tokio::sync::mpsc;
+
+ let (tx1, mut rx1) = mpsc::unbounded_channel::<i32>();
+ let (tx2, mut rx2) = mpsc::unbounded_channel::<i32>();
+
+ tokio::spawn(async move {
+ assert_ok!(tx2.send(1));
+ tokio::task::yield_now().await;
+
+ assert_ok!(tx1.send(2));
+ tokio::task::yield_now().await;
+
+ assert_ok!(tx2.send(3));
+ tokio::task::yield_now().await;
+
+ drop((tx1, tx2));
+ });
+
+ let mut rem = true;
+ let mut msgs = vec![];
+
+ while rem {
+ tokio::select! {
+ Some(x) = rx1.recv() => {
+ msgs.push(x);
+ }
+ Some(y) = rx2.recv() => {
+ msgs.push(y);
+ }
+ else => {
+ rem = false;
+ }
+ }
+ }
+
+ msgs.sort_unstable();
+ assert_eq!(&msgs[..], &[1, 2, 3]);
+}
+
+#[maybe_tokio_test]
+async fn move_uncompleted_futures() {
+ let (tx1, mut rx1) = oneshot::channel::<i32>();
+ let (tx2, mut rx2) = oneshot::channel::<i32>();
+
+ tx1.send(1).unwrap();
+ tx2.send(2).unwrap();
+
+ let ran;
+
+ tokio::select! {
+ res = &mut rx1 => {
+ assert_eq!(1, assert_ok!(res));
+ assert_eq!(2, assert_ok!(rx2.await));
+ ran = true;
+ },
+ res = &mut rx2 => {
+ assert_eq!(2, assert_ok!(res));
+ assert_eq!(1, assert_ok!(rx1.await));
+ ran = true;
+ },
+ }
+
+ assert!(ran);
+}
+
+#[maybe_tokio_test]
+async fn nested() {
+ let res = tokio::select! {
+ x = async { 1 } => {
+ tokio::select! {
+ y = async { 2 } => x + y,
+ }
+ }
+ };
+
+ assert_eq!(res, 3);
+}
+
+#[maybe_tokio_test]
+async fn struct_size() {
+ use futures::future;
+ use std::mem;
+
+ let fut = async {
+ let ready = future::ready(0i32);
+
+ tokio::select! {
+ _ = ready => {},
+ }
+ };
+
+ assert!(mem::size_of_val(&fut) <= 32);
+
+ let fut = async {
+ let ready1 = future::ready(0i32);
+ let ready2 = future::ready(0i32);
+
+ tokio::select! {
+ _ = ready1 => {},
+ _ = ready2 => {},
+ }
+ };
+
+ assert!(mem::size_of_val(&fut) <= 40);
+
+ let fut = async {
+ let ready1 = future::ready(0i32);
+ let ready2 = future::ready(0i32);
+ let ready3 = future::ready(0i32);
+
+ tokio::select! {
+ _ = ready1 => {},
+ _ = ready2 => {},
+ _ = ready3 => {},
+ }
+ };
+
+ assert!(mem::size_of_val(&fut) <= 48);
+}
+
+#[maybe_tokio_test]
+async fn mutable_borrowing_future_with_same_borrow_in_block() {
+ let mut value = 234;
+
+ tokio::select! {
+ _ = require_mutable(&mut value) => { },
+ _ = async_noop() => {
+ value += 5;
+ },
+ }
+
+ assert!(value >= 234);
+}
+
+#[maybe_tokio_test]
+async fn mutable_borrowing_future_with_same_borrow_in_block_and_else() {
+ let mut value = 234;
+
+ tokio::select! {
+ _ = require_mutable(&mut value) => { },
+ _ = async_noop() => {
+ value += 5;
+ },
+ else => {
+ value += 27;
+ },
+ }
+
+ assert!(value >= 234);
+}
+
+#[maybe_tokio_test]
+async fn future_panics_after_poll() {
+ use tokio_test::task;
+
+ let (tx, rx) = oneshot::channel();
+
+ let mut polled = false;
+
+ let f = poll_fn(|_| {
+ assert!(!polled);
+ polled = true;
+ Ready(None::<()>)
+ });
+
+ let mut f = task::spawn(async {
+ tokio::select! {
+ Some(_) = f => unreachable!(),
+ ret = rx => ret.unwrap(),
+ }
+ });
+
+ assert_pending!(f.poll());
+ assert_pending!(f.poll());
+
+ assert_ok!(tx.send(1));
+
+ let res = assert_ready!(f.poll());
+ assert_eq!(1, res);
+}
+
+#[maybe_tokio_test]
+async fn disable_with_if() {
+ use tokio_test::task;
+
+ let f = poll_fn(|_| panic!());
+ let (tx, rx) = oneshot::channel();
+
+ let mut f = task::spawn(async {
+ tokio::select! {
+ _ = f, if false => unreachable!(),
+ _ = rx => (),
+ }
+ });
+
+ assert_pending!(f.poll());
+
+ assert_ok!(tx.send(()));
+ assert!(f.is_woken());
+
+ assert_ready!(f.poll());
+}
+
+#[maybe_tokio_test]
+async fn join_with_select() {
+ use tokio_test::task;
+
+ let (tx1, mut rx1) = oneshot::channel();
+ let (tx2, mut rx2) = oneshot::channel();
+
+ let mut f = task::spawn(async {
+ let mut a = None;
+ let mut b = None;
+
+ while a.is_none() || b.is_none() {
+ tokio::select! {
+ v1 = &mut rx1, if a.is_none() => a = Some(assert_ok!(v1)),
+ v2 = &mut rx2, if b.is_none() => b = Some(assert_ok!(v2))
+ }
+ }
+
+ (a.unwrap(), b.unwrap())
+ });
+
+ assert_pending!(f.poll());
+
+ assert_ok!(tx1.send(123));
+ assert!(f.is_woken());
+ assert_pending!(f.poll());
+
+ assert_ok!(tx2.send(456));
+ assert!(f.is_woken());
+ let (a, b) = assert_ready!(f.poll());
+
+ assert_eq!(a, 123);
+ assert_eq!(b, 456);
+}
+
+#[tokio::test]
+#[cfg(feature = "full")]
+async fn use_future_in_if_condition() {
+ use tokio::time::{self, Duration};
+
+ tokio::select! {
+ _ = time::sleep(Duration::from_millis(10)), if false => {
+ panic!("if condition ignored")
+ }
+ _ = async { 1u32 } => {
+ }
+ }
+}
+
+#[tokio::test]
+#[cfg(feature = "full")]
+async fn use_future_in_if_condition_biased() {
+ use tokio::time::{self, Duration};
+
+ tokio::select! {
+ biased;
+ _ = time::sleep(Duration::from_millis(10)), if false => {
+ panic!("if condition ignored")
+ }
+ _ = async { 1u32 } => {
+ }
+ }
+}
+
+#[maybe_tokio_test]
+async fn many_branches() {
+ let num = tokio::select! {
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ x = async { 1 } => x,
+ };
+
+ assert_eq!(1, num);
+}
+
+#[maybe_tokio_test]
+async fn never_branch_no_warnings() {
+ let t = tokio::select! {
+ _ = async_never() => 0,
+ one_async_ready = one() => one_async_ready,
+ };
+ assert_eq!(t, 1);
+}
+
+async fn one() -> usize {
+ 1
+}
+
+async fn require_mutable(_: &mut i32) {}
+async fn async_noop() {}
+
+async fn async_never() -> ! {
+ futures::future::pending().await
+}
+
+// From https://github.com/tokio-rs/tokio/issues/2857
+#[maybe_tokio_test]
+async fn mut_on_left_hand_side() {
+ let v = async move {
+ let ok = async { 1 };
+ tokio::pin!(ok);
+ tokio::select! {
+ mut a = &mut ok => {
+ a += 1;
+ a
+ }
+ }
+ }
+ .await;
+ assert_eq!(v, 2);
+}
+
+#[maybe_tokio_test]
+async fn biased_one_not_ready() {
+ let (_tx1, rx1) = oneshot::channel::<i32>();
+ let (tx2, rx2) = oneshot::channel::<i32>();
+ let (tx3, rx3) = oneshot::channel::<i32>();
+
+ tx2.send(2).unwrap();
+ tx3.send(3).unwrap();
+
+ let v = tokio::select! {
+ biased;
+
+ _ = rx1 => unreachable!(),
+ res = rx2 => {
+ assert_ok!(res)
+ },
+ _ = rx3 => {
+ panic!("This branch should never be activated because `rx2` should be polled before `rx3` due to `biased;`.")
+ }
+ };
+
+ assert_eq!(2, v);
+}
+
+#[maybe_tokio_test]
+#[cfg(feature = "full")]
+async fn biased_eventually_ready() {
+ use tokio::task::yield_now;
+
+ let one = async {};
+ let two = async { yield_now().await };
+ let three = async { yield_now().await };
+
+ let mut count = 0u8;
+
+ tokio::pin!(one, two, three);
+
+ loop {
+ tokio::select! {
+ biased;
+
+ _ = &mut two, if count < 2 => {
+ count += 1;
+ assert_eq!(count, 2);
+ }
+ _ = &mut three, if count < 3 => {
+ count += 1;
+ assert_eq!(count, 3);
+ }
+ _ = &mut one, if count < 1 => {
+ count += 1;
+ assert_eq!(count, 1);
+ }
+ else => break,
+ }
+ }
+
+ assert_eq!(count, 3);
+}
+
+// https://github.com/tokio-rs/tokio/issues/3830
+// https://github.com/rust-lang/rust-clippy/issues/7304
+#[warn(clippy::default_numeric_fallback)]
+pub async fn default_numeric_fallback() {
+ tokio::select! {
+ _ = async {} => (),
+ else => (),
+ }
+}
+
+// https://github.com/tokio-rs/tokio/issues/4182
+#[maybe_tokio_test]
+async fn mut_ref_patterns() {
+ tokio::select! {
+ Some(mut foo) = async { Some("1".to_string()) } => {
+ assert_eq!(foo, "1");
+ foo = "2".to_string();
+ assert_eq!(foo, "2");
+ },
+ };
+
+ tokio::select! {
+ Some(ref foo) = async { Some("1".to_string()) } => {
+ assert_eq!(*foo, "1");
+ },
+ };
+
+ tokio::select! {
+ Some(ref mut foo) = async { Some("1".to_string()) } => {
+ assert_eq!(*foo, "1");
+ *foo = "2".to_string();
+ assert_eq!(*foo, "2");
+ },
+ };
+}