Skip to content

Commit 124c778

Browse files
authored
test(subscriber): prefer sleep over yield_now in tests (#475)
A flakiness problem has been discovered with the `console-subscriber` integration tests introduced in #452. Issue #473 is tracking the issue. It has been observed that we only "miss" the wake operation event when it comes from `yield_now()`, but not when it comes from a task that yielded due to `sleep`, even when the duration is zero. it is likely that this is due to nature of the underlying race condition. This change removes all the calls to `yield_now()` from the `framework` tests, except those where we wish to actually test self wakes. Additionally, all the sleeps have been moved out into a separate function which describes why we're using `sleep` instead of `yield_now` when either of them would be sufficient.
1 parent 9f94d22 commit 124c778

File tree

1 file changed

+20
-18
lines changed

1 file changed

+20
-18
lines changed

console-subscriber/tests/framework.rs

+20-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
88
use std::time::Duration;
99

10+
use futures::future;
1011
use tokio::{task, time::sleep};
1112

1213
mod support;
@@ -18,9 +19,7 @@ fn expect_present() {
1819
.match_default_name()
1920
.expect_present();
2021

21-
let future = async {
22-
sleep(Duration::ZERO).await;
23-
};
22+
let future = future::ready(());
2423

2524
assert_task(expected_task, future);
2625
}
@@ -32,9 +31,7 @@ fn expect_present() {
3231
fn fail_no_expectations() {
3332
let expected_task = ExpectedTask::default().match_default_name();
3433

35-
let future = async {
36-
sleep(Duration::ZERO).await;
37-
};
34+
let future = future::ready(());
3835

3936
assert_task(expected_task, future);
4037
}
@@ -43,9 +40,7 @@ fn fail_no_expectations() {
4340
fn wakes() {
4441
let expected_task = ExpectedTask::default().match_default_name().expect_wakes(1);
4542

46-
let future = async {
47-
sleep(Duration::ZERO).await;
48-
};
43+
let future = async { yield_to_runtime().await };
4944

5045
assert_task(expected_task, future);
5146
}
@@ -57,9 +52,7 @@ fn wakes() {
5752
fn fail_wakes() {
5853
let expected_task = ExpectedTask::default().match_default_name().expect_wakes(5);
5954

60-
let future = async {
61-
sleep(Duration::ZERO).await;
62-
};
55+
let future = async { yield_to_runtime().await };
6356

6457
assert_task(expected_task, future);
6558
}
@@ -85,6 +78,7 @@ fn fail_self_wake() {
8578
.expect_self_wakes(1);
8679

8780
let future = async {
81+
// `sleep` doesn't result in a self wake
8882
sleep(Duration::ZERO).await;
8983
};
9084

@@ -100,7 +94,7 @@ fn test_spawned_task() {
10094
let future = async {
10195
task::Builder::new()
10296
.name("another-name")
103-
.spawn(async { task::yield_now().await })
97+
.spawn(async { yield_to_runtime().await })
10498
};
10599

106100
assert_task(expected_task, future);
@@ -113,7 +107,7 @@ fn test_spawned_task() {
113107
fn fail_wrong_task_name() {
114108
let expected_task = ExpectedTask::default().match_name("wrong-name".into());
115109

116-
let future = async { task::yield_now().await };
110+
let future = async { yield_to_runtime().await };
117111

118112
assert_task(expected_task, future);
119113
}
@@ -132,11 +126,11 @@ fn multiple_tasks() {
132126
let future = async {
133127
let task1 = task::Builder::new()
134128
.name("task-1")
135-
.spawn(async { task::yield_now().await })
129+
.spawn(async { yield_to_runtime().await })
136130
.unwrap();
137131
let task2 = task::Builder::new()
138132
.name("task-2")
139-
.spawn(async { task::yield_now().await })
133+
.spawn(async { yield_to_runtime().await })
140134
.unwrap();
141135

142136
tokio::try_join! {
@@ -166,11 +160,11 @@ fn fail_1_of_2_expected_tasks() {
166160
let future = async {
167161
let task1 = task::Builder::new()
168162
.name("task-1")
169-
.spawn(async { task::yield_now().await })
163+
.spawn(async { yield_to_runtime().await })
170164
.unwrap();
171165
let task2 = task::Builder::new()
172166
.name("task-2")
173-
.spawn(async { task::yield_now().await })
167+
.spawn(async { yield_to_runtime().await })
174168
.unwrap();
175169

176170
tokio::try_join! {
@@ -182,3 +176,11 @@ fn fail_1_of_2_expected_tasks() {
182176

183177
assert_tasks(expected_tasks, future);
184178
}
179+
180+
async fn yield_to_runtime() {
181+
// There is a race condition that can occur when tests are run in parallel,
182+
// caused by tokio-rs/tracing#2743. It tends to cause test failures only
183+
// when the test relies on a wake coming from `tokio::task::yield_now()`.
184+
// For this reason, we prefer a zero-duration sleep.
185+
sleep(Duration::ZERO).await;
186+
}

0 commit comments

Comments
 (0)