Use Arc<Deterministic> to understand which await points are parking

This commit is contained in:
Antonio Scandurra 2022-06-22 17:39:34 +02:00
parent 62521531a6
commit 9b521d6097
2 changed files with 27 additions and 13 deletions

View file

@ -4400,7 +4400,7 @@ async fn test_random_collaboration(
deterministic: Arc<Deterministic>, deterministic: Arc<Deterministic>,
rng: StdRng, rng: StdRng,
) { ) {
cx.foreground().forbid_parking(); deterministic.forbid_parking();
let max_peers = env::var("MAX_PEERS") let max_peers = env::var("MAX_PEERS")
.map(|i| i.parse().expect("invalid `MAX_PEERS` variable")) .map(|i| i.parse().expect("invalid `MAX_PEERS` variable"))
.unwrap_or(5); .unwrap_or(5);
@ -4626,10 +4626,13 @@ async fn test_random_collaboration(
while operations < max_operations { while operations < max_operations {
if operations == disconnect_host_at { if operations == disconnect_host_at {
server.disconnect_client(user_ids[0]); server.disconnect_client(user_ids[0]);
cx.foreground().advance_clock(RECEIVE_TIMEOUT); deterministic.advance_clock(RECEIVE_TIMEOUT);
drop(op_start_signals); drop(op_start_signals);
deterministic.start_waiting();
let mut clients = futures::future::join_all(clients).await; let mut clients = futures::future::join_all(clients).await;
cx.foreground().run_until_parked(); deterministic.finish_waiting();
deterministic.run_until_parked();
let (host, host_project, mut host_cx, host_err) = clients.remove(0); let (host, host_project, mut host_cx, host_err) = clients.remove(0);
if let Some(host_err) = host_err { if let Some(host_err) = host_err {
@ -4681,6 +4684,8 @@ async fn test_random_collaboration(
cx.leak_detector(), cx.leak_detector(),
next_entity_id, next_entity_id,
); );
deterministic.start_waiting();
let guest = server.create_client(&mut guest_cx, &guest_username).await; let guest = server.create_client(&mut guest_cx, &guest_username).await;
let guest_project = Project::remote( let guest_project = Project::remote(
host_project_id, host_project_id,
@ -4693,6 +4698,8 @@ async fn test_random_collaboration(
) )
.await .await
.unwrap(); .unwrap();
deterministic.finish_waiting();
let op_start_signal = futures::channel::mpsc::unbounded(); let op_start_signal = futures::channel::mpsc::unbounded();
user_ids.push(guest.current_user_id(&guest_cx)); user_ids.push(guest.current_user_id(&guest_cx));
op_start_signals.push(op_start_signal.0); op_start_signals.push(op_start_signal.0);
@ -4715,8 +4722,10 @@ async fn test_random_collaboration(
op_start_signals.remove(guest_ix); op_start_signals.remove(guest_ix);
server.forbid_connections(); server.forbid_connections();
server.disconnect_client(removed_guest_id); server.disconnect_client(removed_guest_id);
cx.foreground().advance_clock(RECEIVE_TIMEOUT); deterministic.advance_clock(RECEIVE_TIMEOUT);
deterministic.start_waiting();
let (guest, guest_project, mut guest_cx, guest_err) = guest.await; let (guest, guest_project, mut guest_cx, guest_err) = guest.await;
deterministic.finish_waiting();
server.allow_connections(); server.allow_connections();
if let Some(guest_err) = guest_err { if let Some(guest_err) = guest_err {
@ -4766,15 +4775,17 @@ async fn test_random_collaboration(
} }
if rng.lock().gen_bool(0.8) { if rng.lock().gen_bool(0.8) {
cx.foreground().run_until_parked(); deterministic.run_until_parked();
} }
} }
} }
} }
drop(op_start_signals); drop(op_start_signals);
deterministic.start_waiting();
let mut clients = futures::future::join_all(clients).await; let mut clients = futures::future::join_all(clients).await;
cx.foreground().run_until_parked(); deterministic.finish_waiting();
deterministic.run_until_parked();
let (host_client, host_project, mut host_cx, host_err) = clients.remove(0); let (host_client, host_project, mut host_cx, host_err) = clients.remove(0);
if let Some(host_err) = host_err { if let Some(host_err) = host_err {

View file

@ -366,6 +366,14 @@ impl Deterministic {
self.state.lock().now = new_now; self.state.lock().now = new_now;
} }
pub fn start_waiting(&self) {
self.state.lock().waiting_backtrace = Some(backtrace::Backtrace::new_unresolved());
}
pub fn finish_waiting(&self) {
self.state.lock().waiting_backtrace.take();
}
pub fn forbid_parking(&self) { pub fn forbid_parking(&self) {
use rand::prelude::*; use rand::prelude::*;
@ -500,10 +508,7 @@ impl Foreground {
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub fn start_waiting(&self) { pub fn start_waiting(&self) {
match self { match self {
Self::Deterministic { executor, .. } => { Self::Deterministic { executor, .. } => executor.start_waiting(),
executor.state.lock().waiting_backtrace =
Some(backtrace::Backtrace::new_unresolved());
}
_ => panic!("this method can only be called on a deterministic executor"), _ => panic!("this method can only be called on a deterministic executor"),
} }
} }
@ -511,9 +516,7 @@ impl Foreground {
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
pub fn finish_waiting(&self) { pub fn finish_waiting(&self) {
match self { match self {
Self::Deterministic { executor, .. } => { Self::Deterministic { executor, .. } => executor.finish_waiting(),
executor.state.lock().waiting_backtrace.take();
}
_ => panic!("this method can only be called on a deterministic executor"), _ => panic!("this method can only be called on a deterministic executor"),
} }
} }