#![allow(clippy::float_cmp)] mod test_util; use crate::test_util::expect_elapsed; use core::time::Duration; use safina::async_test; use safina::select::{ select_ab, select_abc, select_abcd, select_abcde, OptionAb, OptionAbc, OptionAbcd, OptionAbcde, }; use safina::timer::sleep_for; use std::time::Instant; #[async_test] async fn should_return_proper_types() { let _: OptionAb = select_ab(async { 42_u8 }, async { true }).await; let _: OptionAbc = select_abc(async { 42_u8 }, async { true }, async { "s1" }).await; let _: OptionAbcd = select_abcd(async { 42_u8 }, async { true }, async { "s1" }, async { 7_usize }) .await; let _: OptionAbcde = select_abcde( async { 42_u8 }, async { true }, async { "s1" }, async { 7_usize }, async { 0.99_f32 }, ) .await; } #[async_test] async fn all_complete() { select_ab(async { 42_u8 }, async { true }).await.unwrap_a(); select_abc(async { 42_u8 }, async { true }, async { "s1" }) .await .unwrap_a(); select_abcd(async { 42_u8 }, async { true }, async { "s1" }, async { 7_usize }) .await .unwrap_a(); select_abcde( async { 42_u8 }, async { true }, async { "s1" }, async { 7_usize }, async { 0.99_f32 }, ) .await .unwrap_a(); } #[async_test] async fn one_complete() { let ready_a = || async { 42_u8 }; let ready_b = || async { true }; let ready_c = || async { "s1" }; let ready_d = || async { 7_usize }; let ready_e = || async { 0.99_f32 }; let wait_a = || async { sleep_for(Duration::from_millis(10)).await; 42_u8 }; let wait_b = || async { sleep_for(Duration::from_millis(10)).await; true }; let wait_c = || async { sleep_for(Duration::from_millis(10)).await; "s1" }; let wait_d = || async { sleep_for(Duration::from_millis(10)).await; 7_usize }; let wait_e = || async { sleep_for(Duration::from_millis(10)).await; 0.99_f32 }; assert_eq!(42_u8, select_ab(ready_a(), wait_b()).await.unwrap_a()); assert!(select_ab(wait_a(), ready_b()).await.unwrap_b()); assert_eq!( 42_u8, select_abc(ready_a(), wait_b(), wait_c()).await.unwrap_a() ); assert!(select_abc(wait_a(), ready_b(), wait_c()).await.unwrap_b()); assert_eq!( "s1", select_abc(wait_a(), wait_b(), ready_c()).await.unwrap_c() ); assert_eq!( 42_u8, select_abcd(ready_a(), wait_b(), wait_c(), wait_d()) .await .unwrap_a() ); assert!(select_abcd(wait_a(), ready_b(), wait_c(), wait_d()) .await .unwrap_b()); assert_eq!( "s1", select_abcd(wait_a(), wait_b(), ready_c(), wait_d()) .await .unwrap_c() ); assert_eq!( 7_usize, select_abcd(wait_a(), wait_b(), wait_c(), ready_d()) .await .unwrap_d() ); assert_eq!( 42_u8, select_abcde(ready_a(), wait_b(), wait_c(), wait_d(), wait_e()) .await .unwrap_a() ); assert!( select_abcde(wait_a(), ready_b(), wait_c(), wait_d(), wait_e()) .await .unwrap_b() ); assert_eq!( "s1", select_abcde(wait_a(), wait_b(), ready_c(), wait_d(), wait_e()) .await .unwrap_c() ); assert_eq!( 7_usize, select_abcde(wait_a(), wait_b(), wait_c(), ready_d(), wait_e()) .await .unwrap_d() ); assert_eq!( 0.99_f32, select_abcde(wait_a(), wait_b(), wait_c(), wait_d(), ready_e()) .await .unwrap_e() ); } #[async_test] async fn should_poll_all() { let (sender_a, receiver_a) = std::sync::mpsc::channel::<()>(); let (sender_b, receiver_b) = std::sync::mpsc::channel::<()>(); let (sender_c, receiver_c) = std::sync::mpsc::channel::<()>(); let (sender_d, receiver_d) = std::sync::mpsc::channel::<()>(); let (sender_e, receiver_e) = std::sync::mpsc::channel::<()>(); let fut_a = async move { sender_a.send(()).unwrap(); sleep_for(Duration::from_millis(10)).await; }; let fut_b = async move { sender_b.send(()).unwrap(); sleep_for(Duration::from_millis(10)).await; }; let fut_c = async move { sender_c.send(()).unwrap(); sleep_for(Duration::from_millis(10)).await; }; let fut_d = async move { sender_d.send(()).unwrap(); sleep_for(Duration::from_millis(10)).await; }; let fut_e = async move { sender_e.send(()).unwrap(); sleep_for(Duration::from_millis(10)).await; }; select_abcde(fut_a, fut_b, fut_c, fut_d, fut_e).await; receiver_a.recv().unwrap(); receiver_b.recv().unwrap(); receiver_c.recv().unwrap(); receiver_d.recv().unwrap(); receiver_e.recv().unwrap(); } #[async_test] async fn awaits_a() { let before = Instant::now(); select_ab( async move { sleep_for(Duration::from_millis(100)).await; 42_u8 }, async move { sleep_for(Duration::from_millis(200)).await; true }, ) .await .unwrap_a(); expect_elapsed(before, 100..190); } #[async_test] async fn awaits_b() { let before = Instant::now(); select_ab( async move { sleep_for(Duration::from_millis(200)).await; 42_u8 }, async move { sleep_for(Duration::from_millis(100)).await; true }, ) .await .unwrap_b(); expect_elapsed(before, 100..190); } #[async_test] #[allow(clippy::match_same_arms)] async fn match_expression() { match select_ab(async move { 42_u8 }, async move { true }).await { OptionAb::A(42_u8) => {} _ => unreachable!(), } match select_abcde( async { 42_u8 }, async { true }, async { "s1" }, async { 7_usize }, async { 0.99_f32 }, ) .await { OptionAbcde::A(42_u8) => {} OptionAbcde::B(true) | OptionAbcde::C("s1") | OptionAbcde::D(7_usize) => unreachable!(), OptionAbcde::E(value) if value == 0.99_f32 => unreachable!(), _ => unreachable!(), } }