#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_returns_first_completed_future() {
use std::time::Duration;
let result = switchy::unsync::select! {
val = async {
switchy::unsync::time::sleep(Duration::from_millis(10)).await;
1
} => val,
_ = async {
switchy::unsync::time::sleep(Duration::from_millis(100)).await;
} => unreachable!("slower future should not complete first"),
};
assert_eq!(result, 1);
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_cancels_other_branches() {
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
let slow_started = Arc::new(AtomicBool::new(false));
let slow_started_clone = slow_started.clone();
let result = switchy::unsync::select! {
val = async {
switchy::unsync::time::sleep(Duration::from_millis(10)).await;
42
} => val,
_ = async move {
slow_started_clone.store(true, Ordering::SeqCst);
switchy::unsync::time::sleep(Duration::from_millis(500)).await;
panic!("slow branch should not complete");
} => unreachable!(),
};
assert_eq!(result, 42);
assert!(slow_started.load(Ordering::SeqCst));
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_with_immediate_completion() {
let result = switchy::unsync::select! {
val = async { 100 } => val,
_ = switchy::unsync::time::sleep(std::time::Duration::from_secs(10)) => {
unreachable!("sleep should not complete first")
}
};
assert_eq!(result, 100);
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_loop_pattern() {
use std::time::Duration;
let mut counter = 0;
let target = 3;
loop {
switchy::unsync::select! {
_ = async {
switchy::unsync::time::sleep(Duration::from_millis(5)).await;
} => {
counter += 1;
if counter >= target {
break;
}
}
}
}
assert_eq!(counter, target);
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_with_reference_capture() {
use std::time::Duration;
let data = [1, 2, 3];
let result = switchy::unsync::select! {
_ = async {
switchy::unsync::time::sleep(Duration::from_millis(10)).await;
} => data.len(),
_ = async {
switchy::unsync::time::sleep(Duration::from_millis(100)).await;
} => unreachable!(),
};
assert_eq!(result, 3);
assert_eq!(data.len(), 3);
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_multiple_same_time() {
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
use std::time::Duration;
let counter = Arc::new(AtomicU32::new(0));
let c1 = counter.clone();
let c2 = counter.clone();
for _ in 0..3 {
switchy::unsync::select! {
_ = async {
c1.fetch_add(1, Ordering::SeqCst);
switchy::unsync::time::sleep(Duration::from_millis(5)).await;
} => {},
_ = async {
c2.fetch_add(1, Ordering::SeqCst);
switchy::unsync::time::sleep(Duration::from_millis(5)).await;
} => {},
}
}
let final_count = counter.load(Ordering::SeqCst);
assert!(
(3..=6).contains(&final_count),
"Counter should be between 3 and 6, got {final_count}"
);
}
#[cfg(feature = "async")]
#[switchy::unsync::test(real_time)]
async fn unsync_select_with_different_return_types() {
use std::time::Duration;
let result: String = switchy::unsync::select! {
val = async {
switchy::unsync::time::sleep(Duration::from_millis(10)).await;
"fast".to_string()
} => val,
val = async {
switchy::unsync::time::sleep(Duration::from_millis(100)).await;
"slow".to_string()
} => val,
};
assert_eq!(result, "fast");
}