Skip to content

Commit b9868b2

Browse files
authored
rt: fix spurious yield_defers_until_park test (#5634)
1 parent 623483c commit b9868b2

File tree

1 file changed

+48
-7
lines changed

1 file changed

+48
-7
lines changed

tokio/tests/rt_common.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -695,12 +695,34 @@ rt_test! {
695695
/// Tests that yielded tasks are not scheduled until **after** resource
696696
/// drivers are polled.
697697
///
698-
/// Note: we may have to delete this test as it is not necessarily reliable.
699698
/// The OS does not guarantee when I/O events are delivered, so there may be
700-
/// more yields than anticipated.
699+
/// more yields than anticipated. This makes the test slightly flaky. To
700+
/// help avoid flakiness, we run the test 10 times and only fail it after
701+
/// 10 failures in a row.
702+
///
703+
/// Note that if the test fails by panicking rather than by returning false,
704+
/// then we fail it immediately. That kind of failure should not happen
705+
/// spuriously.
701706
#[test]
702707
#[cfg(not(target_os="wasi"))]
703708
fn yield_defers_until_park() {
709+
for _ in 0..10 {
710+
if yield_defers_until_park_inner() {
711+
// test passed
712+
return;
713+
}
714+
715+
// Wait a bit and run the test again.
716+
std::thread::sleep(std::time::Duration::from_secs(2));
717+
}
718+
719+
panic!("yield_defers_until_park is failing consistently");
720+
}
721+
722+
/// Implementation of `yield_defers_until_park` test. Returns `true` if the
723+
/// test passed.
724+
#[cfg(not(target_os="wasi"))]
725+
fn yield_defers_until_park_inner() -> bool {
704726
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
705727
use std::sync::Barrier;
706728

@@ -727,14 +749,16 @@ rt_test! {
727749

728750
barrier.wait();
729751

730-
tokio::spawn(async move {
752+
let (fail_test, fail_test_recv) = oneshot::channel::<()>();
753+
754+
let jh = tokio::spawn(async move {
731755
// Create a TCP litener
732756
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
733757
let addr = listener.local_addr().unwrap();
734758

735759
tokio::join!(
736760
async {
737-
// Done blocking intentionally
761+
// Done in a blocking manner intentionally.
738762
let _socket = std::net::TcpStream::connect(addr).unwrap();
739763

740764
// Yield until connected
@@ -744,7 +768,12 @@ rt_test! {
744768
cnt += 1;
745769

746770
if cnt >= 10 {
747-
panic!("yielded too many times; TODO: delete this test?");
771+
// yielded too many times; report failure and
772+
// sleep forever so that the `fail_test` branch
773+
// of the `select!` below triggers.
774+
let _ = fail_test.send(());
775+
futures::future::pending::<()>().await;
776+
break;
748777
}
749778
}
750779
},
@@ -753,8 +782,20 @@ rt_test! {
753782
flag.store(true, SeqCst);
754783
}
755784
);
756-
}).await.unwrap();
757-
});
785+
});
786+
787+
// Wait until the spawned task completes or fails. If no message is
788+
// sent on `fail_test`, then the test succeeds. Otherwise, it fails.
789+
let success = fail_test_recv.await.is_err();
790+
791+
if success {
792+
// Check for panics in spawned task.
793+
jh.abort();
794+
jh.await.unwrap();
795+
}
796+
797+
success
798+
})
758799
}
759800

760801
#[cfg(not(target_os="wasi"))] // Wasi does not support threads

0 commit comments

Comments
 (0)