Skip to content

Commit 99dd3c8

Browse files
committed
Add regression tests
1 parent bed05b8 commit 99dd3c8

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

futures-executor/tests/local_pool.rs

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use futures::channel::oneshot;
22
use futures::executor::LocalPool;
33
use futures::future::{self, lazy, poll_fn, Future};
4-
use futures::task::{Context, LocalSpawn, Poll, Spawn, Waker};
4+
use futures::task::{Context, LocalSpawn, LocalSpawnExt, Poll, Spawn, SpawnExt, Waker};
55
use std::cell::{Cell, RefCell};
66
use std::pin::Pin;
77
use std::rc::Rc;
@@ -435,3 +435,65 @@ fn park_unpark_independence() {
435435

436436
futures::executor::block_on(future)
437437
}
438+
439+
struct SelfWaking {
440+
wakeups_remaining: Arc<RefCell<usize>>,
441+
}
442+
443+
impl Future for SelfWaking {
444+
type Output = ();
445+
446+
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
447+
if *self.wakeups_remaining.borrow() != 0 {
448+
*self.wakeups_remaining.borrow_mut() -= 1;
449+
cx.waker().wake_by_ref();
450+
}
451+
452+
Poll::Pending
453+
}
454+
}
455+
456+
/// Regression test for https://github.com/rust-lang/futures-rs/pull/2593
457+
///
458+
/// The issue was that self-waking futures could cause `run_until_stalled`
459+
/// to exit early, even when progress could still be made.
460+
#[test]
461+
fn self_waking_run_until_stalled() {
462+
let wakeups_remaining = Arc::new(RefCell::new(10));
463+
464+
let mut pool = LocalPool::new();
465+
let spawner = pool.spawner();
466+
for _ in 0..3 {
467+
let wakeups_remaining = Arc::clone(&wakeups_remaining);
468+
spawner.spawn_local(SelfWaking { wakeups_remaining }).unwrap();
469+
}
470+
471+
// This should keep polling until there are no more wakeups.
472+
pool.run_until_stalled();
473+
474+
assert_eq!(*wakeups_remaining.borrow(), 0);
475+
}
476+
477+
/// Regression test for https://github.com/rust-lang/futures-rs/pull/2593
478+
///
479+
/// The issue was that self-waking futures could cause `try_run_one`
480+
/// to exit early, even when progress could still be made.
481+
#[test]
482+
fn self_waking_try_run_one() {
483+
let wakeups_remaining = Arc::new(RefCell::new(10));
484+
485+
let mut pool = LocalPool::new();
486+
let spawner = pool.spawner();
487+
for _ in 0..3 {
488+
let wakeups_remaining = Arc::clone(&wakeups_remaining);
489+
spawner.spawn_local(SelfWaking { wakeups_remaining }).unwrap();
490+
}
491+
492+
spawner.spawn(future::ready(())).unwrap();
493+
494+
// The `ready` future should complete.
495+
assert!(pool.try_run_one());
496+
497+
// The self-waking futures are each polled once.
498+
assert_eq!(*wakeups_remaining.borrow(), 7);
499+
}

0 commit comments

Comments
 (0)