mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-08 18:41:48 +00:00
Tweak operation rates
This commit is contained in:
parent
f243633f3e
commit
f1b3692a35
1 changed files with 133 additions and 104 deletions
|
@ -230,11 +230,7 @@ async fn test_random_collaboration(
|
|||
i += 1;
|
||||
}
|
||||
|
||||
Operation::RunUntilParked => {
|
||||
deterministic.run_until_parked();
|
||||
}
|
||||
|
||||
Operation::MutateClients(user_ids) => {
|
||||
Operation::MutateClients { user_ids, quiesce } => {
|
||||
for user_id in user_ids {
|
||||
let client_ix = clients
|
||||
.iter()
|
||||
|
@ -243,6 +239,10 @@ async fn test_random_collaboration(
|
|||
operation_channels[client_ix].unbounded_send(()).unwrap();
|
||||
i += 1;
|
||||
}
|
||||
|
||||
if quiesce {
|
||||
deterministic.run_until_parked();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -444,12 +444,20 @@ struct UserTestPlan {
|
|||
|
||||
#[derive(Debug)]
|
||||
enum Operation {
|
||||
AddConnection { user_id: UserId },
|
||||
RemoveConnection { user_id: UserId },
|
||||
BounceConnection { user_id: UserId },
|
||||
AddConnection {
|
||||
user_id: UserId,
|
||||
},
|
||||
RemoveConnection {
|
||||
user_id: UserId,
|
||||
},
|
||||
BounceConnection {
|
||||
user_id: UserId,
|
||||
},
|
||||
RestartServer,
|
||||
RunUntilParked,
|
||||
MutateClients(Vec<UserId>),
|
||||
MutateClients {
|
||||
user_ids: Vec<UserId>,
|
||||
quiesce: bool,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -490,7 +498,7 @@ impl TestPlan {
|
|||
async fn next_operation(&mut self, clients: &[(Rc<TestClient>, TestAppContext)]) -> Operation {
|
||||
let operation = loop {
|
||||
break match self.rng.gen_range(0..100) {
|
||||
0..=19 if clients.len() < self.users.len() => {
|
||||
0..=29 if clients.len() < self.users.len() => {
|
||||
let user = self
|
||||
.users
|
||||
.iter()
|
||||
|
@ -501,20 +509,19 @@ impl TestPlan {
|
|||
user_id: user.user_id,
|
||||
}
|
||||
}
|
||||
20..=24 if clients.len() > 1 && self.allow_client_disconnection => {
|
||||
30..=34 if clients.len() > 1 && self.allow_client_disconnection => {
|
||||
let (client, cx) = &clients[self.rng.gen_range(0..clients.len())];
|
||||
let user_id = client.current_user_id(cx);
|
||||
Operation::RemoveConnection { user_id }
|
||||
}
|
||||
25..=29 if clients.len() > 1 && self.allow_client_reconnection => {
|
||||
35..=39 if clients.len() > 1 && self.allow_client_reconnection => {
|
||||
let (client, cx) = &clients[self.rng.gen_range(0..clients.len())];
|
||||
let user_id = client.current_user_id(cx);
|
||||
Operation::BounceConnection { user_id }
|
||||
}
|
||||
30..=34 if self.allow_server_restarts && clients.len() > 1 => {
|
||||
40..=44 if self.allow_server_restarts && clients.len() > 1 => {
|
||||
Operation::RestartServer
|
||||
}
|
||||
35..=39 => Operation::RunUntilParked,
|
||||
_ if !clients.is_empty() => {
|
||||
let user_ids = (0..self.rng.gen_range(0..10))
|
||||
.map(|_| {
|
||||
|
@ -523,7 +530,10 @@ impl TestPlan {
|
|||
client.current_user_id(cx)
|
||||
})
|
||||
.collect();
|
||||
Operation::MutateClients(user_ids)
|
||||
Operation::MutateClients {
|
||||
user_ids,
|
||||
quiesce: self.rng.gen(),
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
|
@ -541,78 +551,95 @@ impl TestPlan {
|
|||
let operation = loop {
|
||||
match self.rng.gen_range(0..100) {
|
||||
// Mutate the call
|
||||
0..=19 => match self.rng.gen_range(0..100_u32) {
|
||||
0..=29 => {
|
||||
// Respond to an incoming call
|
||||
0..=39 => {
|
||||
if call.read_with(cx, |call, _| call.incoming().borrow().is_some()) {
|
||||
break if self.rng.gen_bool(0.7) {
|
||||
ClientOperation::AcceptIncomingCall
|
||||
} else {
|
||||
ClientOperation::RejectIncomingCall
|
||||
};
|
||||
}
|
||||
if call.read_with(cx, |call, _| call.incoming().borrow().is_some()) {
|
||||
break if self.rng.gen_bool(0.7) {
|
||||
ClientOperation::AcceptIncomingCall
|
||||
} else {
|
||||
ClientOperation::RejectIncomingCall
|
||||
};
|
||||
}
|
||||
|
||||
// Invite a contact to the current call
|
||||
30..=89 => {
|
||||
let available_contacts =
|
||||
client.user_store.read_with(cx, |user_store, _| {
|
||||
user_store
|
||||
.contacts()
|
||||
.iter()
|
||||
.filter(|contact| contact.online && !contact.busy)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
if !available_contacts.is_empty() {
|
||||
let contact = available_contacts.choose(&mut self.rng).unwrap();
|
||||
break ClientOperation::InviteContactToCall {
|
||||
user_id: UserId(contact.user.id as i32),
|
||||
};
|
||||
match self.rng.gen_range(0..100_u32) {
|
||||
// Invite a contact to the current call
|
||||
0..=70 => {
|
||||
let available_contacts =
|
||||
client.user_store.read_with(cx, |user_store, _| {
|
||||
user_store
|
||||
.contacts()
|
||||
.iter()
|
||||
.filter(|contact| contact.online && !contact.busy)
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
if !available_contacts.is_empty() {
|
||||
let contact = available_contacts.choose(&mut self.rng).unwrap();
|
||||
break ClientOperation::InviteContactToCall {
|
||||
user_id: UserId(contact.user.id as i32),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Leave the current call
|
||||
90.. => {
|
||||
if self.allow_client_disconnection
|
||||
&& call.read_with(cx, |call, _| call.room().is_some())
|
||||
{
|
||||
break ClientOperation::LeaveCall;
|
||||
// Leave the current call
|
||||
71.. => {
|
||||
if self.allow_client_disconnection
|
||||
&& call.read_with(cx, |call, _| call.room().is_some())
|
||||
{
|
||||
break ClientOperation::LeaveCall;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Mutate projects
|
||||
20..=39 => match self.rng.gen_range(0..100_u32) {
|
||||
// Open a remote project
|
||||
0..=30 => {
|
||||
39..=59 => match self.rng.gen_range(0..100_u32) {
|
||||
// Open a new project
|
||||
0..=70 => {
|
||||
// Open a remote project
|
||||
if let Some(room) = call.read_with(cx, |call, _| call.room().cloned()) {
|
||||
let remote_projects = room.read_with(cx, |room, _| {
|
||||
let existing_remote_project_ids = cx.read(|cx| {
|
||||
client
|
||||
.remote_projects()
|
||||
.iter()
|
||||
.map(|p| p.read(cx).remote_id().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let new_remote_projects = room.read_with(cx, |room, _| {
|
||||
room.remote_participants()
|
||||
.values()
|
||||
.flat_map(|participant| {
|
||||
participant.projects.iter().map(|project| {
|
||||
(
|
||||
UserId::from_proto(participant.user.id),
|
||||
project.worktree_root_names[0].clone(),
|
||||
)
|
||||
participant.projects.iter().filter_map(|project| {
|
||||
if existing_remote_project_ids.contains(&project.id) {
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
UserId::from_proto(participant.user.id),
|
||||
project.worktree_root_names[0].clone(),
|
||||
))
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
if !remote_projects.is_empty() {
|
||||
if !new_remote_projects.is_empty() {
|
||||
let (host_id, first_root_name) =
|
||||
remote_projects.choose(&mut self.rng).unwrap().clone();
|
||||
new_remote_projects.choose(&mut self.rng).unwrap().clone();
|
||||
break ClientOperation::OpenRemoteProject {
|
||||
host_id,
|
||||
first_root_name,
|
||||
};
|
||||
}
|
||||
}
|
||||
// Open a local project
|
||||
else {
|
||||
let first_root_name = self.next_root_dir_name(user_id);
|
||||
break ClientOperation::OpenLocalProject { first_root_name };
|
||||
}
|
||||
}
|
||||
|
||||
// Close a remote project
|
||||
31..=40 => {
|
||||
71..=80 => {
|
||||
if !client.remote_projects().is_empty() {
|
||||
let project = client
|
||||
.remote_projects()
|
||||
|
@ -626,14 +653,8 @@ impl TestPlan {
|
|||
}
|
||||
}
|
||||
|
||||
// Open a local project
|
||||
41..=60 => {
|
||||
let first_root_name = self.next_root_dir_name(user_id);
|
||||
break ClientOperation::OpenLocalProject { first_root_name };
|
||||
}
|
||||
|
||||
// Add a worktree to a local project
|
||||
61.. => {
|
||||
81.. => {
|
||||
if !client.local_projects().is_empty() {
|
||||
let project = client
|
||||
.local_projects()
|
||||
|
@ -659,7 +680,7 @@ impl TestPlan {
|
|||
},
|
||||
|
||||
// Mutate buffers
|
||||
40..=79 => {
|
||||
60.. => {
|
||||
let Some(project) = choose_random_project(client, &mut self.rng) else { continue };
|
||||
let project_root_name = root_name_for_project(&project, cx);
|
||||
|
||||
|
@ -871,9 +892,8 @@ async fn simulate_client(
|
|||
let operation = plan.lock().next_client_operation(&client, &cx).await;
|
||||
if let Err(error) = apply_client_operation(&client, plan.clone(), operation, &mut cx).await
|
||||
{
|
||||
log::error!("{} error: {:?}", client.username, error);
|
||||
log::error!("{} error: {}", client.username, error);
|
||||
}
|
||||
|
||||
cx.background().simulate_random_delay().await;
|
||||
}
|
||||
log::info!("{}: done", client.username);
|
||||
|
@ -928,34 +948,7 @@ async fn apply_client_operation(
|
|||
.await
|
||||
.unwrap();
|
||||
let project = client.build_local_project(root_path, cx).await.0;
|
||||
|
||||
let active_call = cx.read(ActiveCall::global);
|
||||
if active_call.read_with(cx, |call, _| call.room().is_some())
|
||||
&& project.read_with(cx, |project, _| project.is_local() && !project.is_shared())
|
||||
{
|
||||
match active_call
|
||||
.update(cx, |call, cx| call.share_project(project.clone(), cx))
|
||||
.await
|
||||
{
|
||||
Ok(project_id) => {
|
||||
log::info!(
|
||||
"{}: shared project {} with id {}",
|
||||
client.username,
|
||||
first_root_name,
|
||||
project_id
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"{}: error sharing project {}: {:?}",
|
||||
client.username,
|
||||
first_root_name,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ensure_project_shared(&project, client, cx).await;
|
||||
client.local_projects_mut().push(project.clone());
|
||||
}
|
||||
|
||||
|
@ -971,6 +964,7 @@ async fn apply_client_operation(
|
|||
);
|
||||
let project = project_for_root_name(client, &project_root_name, cx)
|
||||
.expect("invalid project in test operation");
|
||||
ensure_project_shared(&project, client, cx).await;
|
||||
if !client.fs.paths().await.contains(&new_root_path) {
|
||||
client.fs.create_dir(&new_root_path).await.unwrap();
|
||||
}
|
||||
|
@ -984,13 +978,13 @@ async fn apply_client_operation(
|
|||
|
||||
ClientOperation::CloseRemoteProject { project_root_name } => {
|
||||
log::info!(
|
||||
"{}: dropping project with root path {}",
|
||||
"{}: closing remote project with root path {}",
|
||||
client.username,
|
||||
project_root_name,
|
||||
);
|
||||
let ix = project_ix_for_root_name(&*client.remote_projects(), &project_root_name, cx)
|
||||
.expect("invalid project in test operation");
|
||||
client.remote_projects_mut().remove(ix);
|
||||
cx.update(|_| client.remote_projects_mut().remove(ix));
|
||||
}
|
||||
|
||||
ClientOperation::OpenRemoteProject {
|
||||
|
@ -1027,13 +1021,14 @@ async fn apply_client_operation(
|
|||
full_path,
|
||||
} => {
|
||||
log::info!(
|
||||
"{}: opening path {:?} in project {}",
|
||||
"{}: opening buffer {:?} in project {}",
|
||||
client.username,
|
||||
full_path,
|
||||
project_root_name,
|
||||
);
|
||||
let project = project_for_root_name(client, &project_root_name, cx)
|
||||
.expect("invalid project in test operation");
|
||||
// ensure_project_shared(&project, client, cx).await;
|
||||
let mut components = full_path.components();
|
||||
let root_name = components.next().unwrap().as_os_str().to_str().unwrap();
|
||||
let path = components.as_path();
|
||||
|
@ -1086,10 +1081,10 @@ async fn apply_client_operation(
|
|||
});
|
||||
}
|
||||
|
||||
_ => {
|
||||
ClientOperation::Other => {
|
||||
let choice = plan.lock().rng.gen_range(0..100);
|
||||
match choice {
|
||||
50..=59
|
||||
0..=59
|
||||
if !client.local_projects().is_empty()
|
||||
|| !client.remote_projects().is_empty() =>
|
||||
{
|
||||
|
@ -1147,6 +1142,40 @@ fn root_name_for_project(project: &ModelHandle<Project>, cx: &TestAppContext) ->
|
|||
})
|
||||
}
|
||||
|
||||
async fn ensure_project_shared(
|
||||
project: &ModelHandle<Project>,
|
||||
client: &TestClient,
|
||||
cx: &mut TestAppContext,
|
||||
) {
|
||||
let first_root_name = root_name_for_project(project, cx);
|
||||
let active_call = cx.read(ActiveCall::global);
|
||||
if active_call.read_with(cx, |call, _| call.room().is_some())
|
||||
&& project.read_with(cx, |project, _| project.is_local() && !project.is_shared())
|
||||
{
|
||||
match active_call
|
||||
.update(cx, |call, cx| call.share_project(project.clone(), cx))
|
||||
.await
|
||||
{
|
||||
Ok(project_id) => {
|
||||
log::info!(
|
||||
"{}: shared project {} with id {}",
|
||||
client.username,
|
||||
first_root_name,
|
||||
project_id
|
||||
);
|
||||
}
|
||||
Err(error) => {
|
||||
log::error!(
|
||||
"{}: error sharing project {}: {:?}",
|
||||
client.username,
|
||||
first_root_name,
|
||||
error
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn randomly_mutate_fs(client: &TestClient, plan: &Arc<Mutex<TestPlan>>) {
|
||||
let is_dir = plan.lock().rng.gen::<bool>();
|
||||
let mut new_path = client
|
||||
|
|
Loading…
Reference in a new issue