Re-enable randomized concurrent edits test

This commit is contained in:
Max Brunsfeld 2021-10-20 21:44:26 +02:00
parent 30e2e2014d
commit cdb268e656
5 changed files with 102 additions and 112 deletions

View file

@ -2414,27 +2414,18 @@ impl Buffer {
#[cfg(any(test, feature = "test-support"))] #[cfg(any(test, feature = "test-support"))]
impl Buffer { impl Buffer {
pub fn randomly_edit<T>( pub fn randomly_edit<T>(&mut self, rng: &mut T, old_range_count: usize)
&mut self,
rng: &mut T,
old_range_count: usize,
_: &mut ModelContext<Self>,
) -> (Vec<Range<usize>>, String)
where where
T: rand::Rng, T: rand::Rng,
{ {
self.buffer.randomly_edit(rng, old_range_count) self.buffer.randomly_edit(rng, old_range_count);
} }
pub fn randomly_mutate<T>( pub fn randomly_mutate<T>(&mut self, rng: &mut T)
&mut self,
rng: &mut T,
_: &mut ModelContext<Self>,
) -> (Vec<Range<usize>>, String)
where where
T: rand::Rng, T: rand::Rng,
{ {
self.buffer.randomly_mutate(rng) self.buffer.randomly_mutate(rng);
} }
} }
@ -2450,7 +2441,7 @@ impl TextBuffer {
&mut self, &mut self,
rng: &mut T, rng: &mut T,
old_range_count: usize, old_range_count: usize,
) -> (Vec<Range<usize>>, String) ) -> (Vec<Range<usize>>, String, Operation)
where where
T: rand::Rng, T: rand::Rng,
{ {
@ -2472,17 +2463,17 @@ impl TextBuffer {
old_ranges, old_ranges,
new_text new_text
); );
self.edit(old_ranges.iter().cloned(), new_text.as_str()); let op = self.edit(old_ranges.iter().cloned(), new_text.as_str());
(old_ranges, new_text) (old_ranges, new_text, Operation::Edit(op))
} }
pub fn randomly_mutate<T>(&mut self, rng: &mut T) -> (Vec<Range<usize>>, String) pub fn randomly_mutate<T>(&mut self, rng: &mut T) -> Vec<Operation>
where where
T: rand::Rng, T: rand::Rng,
{ {
use rand::prelude::*; use rand::prelude::*;
let (old_ranges, new_text) = self.randomly_edit(rng, 5); let mut ops = vec![self.randomly_edit(rng, 5).2];
// Randomly add, remove or mutate selection sets. // Randomly add, remove or mutate selection sets.
let replica_selection_sets = &self let replica_selection_sets = &self
@ -2492,7 +2483,7 @@ impl TextBuffer {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let set_id = replica_selection_sets.choose(rng); let set_id = replica_selection_sets.choose(rng);
if set_id.is_some() && rng.gen_bool(1.0 / 6.0) { if set_id.is_some() && rng.gen_bool(1.0 / 6.0) {
self.remove_selection_set(*set_id.unwrap()).unwrap(); ops.push(self.remove_selection_set(*set_id.unwrap()).unwrap());
} else { } else {
let mut ranges = Vec::new(); let mut ranges = Vec::new();
for _ in 0..5 { for _ in 0..5 {
@ -2500,20 +2491,22 @@ impl TextBuffer {
} }
let new_selections = self.selections_from_ranges(ranges).unwrap(); let new_selections = self.selections_from_ranges(ranges).unwrap();
if set_id.is_none() || rng.gen_bool(1.0 / 5.0) { let op = if set_id.is_none() || rng.gen_bool(1.0 / 5.0) {
self.add_selection_set(new_selections); self.add_selection_set(new_selections)
} else { } else {
self.update_selection_set(*set_id.unwrap(), new_selections) self.update_selection_set(*set_id.unwrap(), new_selections)
.unwrap(); .unwrap()
} };
ops.push(op);
} }
(old_ranges, new_text) ops
} }
pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng) { pub fn randomly_undo_redo(&mut self, rng: &mut impl rand::Rng) -> Vec<Operation> {
use rand::prelude::*; use rand::prelude::*;
let mut ops = Vec::new();
for _ in 0..rng.gen_range(1..=5) { for _ in 0..rng.gen_range(1..=5) {
if let Some(transaction) = self.history.undo_stack.choose(rng).cloned() { if let Some(transaction) = self.history.undo_stack.choose(rng).cloned() {
log::info!( log::info!(
@ -2521,9 +2514,10 @@ impl TextBuffer {
self.replica_id, self.replica_id,
transaction transaction
); );
self.undo_or_redo(transaction).unwrap(); ops.push(self.undo_or_redo(transaction).unwrap());
} }
} }
ops
} }
fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>> fn selections_from_ranges<I>(&self, ranges: I) -> Result<Vec<Selection>>

View file

@ -6,7 +6,6 @@ use std::{
cmp::Ordering, cmp::Ordering,
env, env,
iter::Iterator, iter::Iterator,
mem,
rc::Rc, rc::Rc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
@ -104,7 +103,7 @@ fn test_random_edits(mut rng: StdRng) {
); );
for _i in 0..operations { for _i in 0..operations {
let (old_ranges, new_text) = buffer.randomly_mutate(&mut rng); let (old_ranges, new_text, _) = buffer.randomly_edit(&mut rng, 5);
for old_range in old_ranges.iter().rev() { for old_range in old_ranges.iter().rev() {
reference_string.replace_range(old_range.clone(), &new_text); reference_string.replace_range(old_range.clone(), &new_text);
} }
@ -571,92 +570,89 @@ fn test_concurrent_edits() {
assert_eq!(buffer3.text(), "a12c34e56"); assert_eq!(buffer3.text(), "a12c34e56");
} }
// #[gpui::test(iterations = 100)] #[gpui::test(iterations = 100)]
// fn test_random_concurrent_edits(cx: &mut gpui::MutableAppContext, mut rng: StdRng) { fn test_random_concurrent_edits(mut rng: StdRng) {
// let peers = env::var("PEERS") let peers = env::var("PEERS")
// .map(|i| i.parse().expect("invalid `PEERS` variable")) .map(|i| i.parse().expect("invalid `PEERS` variable"))
// .unwrap_or(5); .unwrap_or(5);
// let operations = env::var("OPERATIONS") let operations = env::var("OPERATIONS")
// .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
// .unwrap_or(10); .unwrap_or(10);
// let base_text_len = rng.gen_range(0..10); let base_text_len = rng.gen_range(0..10);
// let base_text = RandomCharIter::new(&mut rng) let base_text = RandomCharIter::new(&mut rng)
// .take(base_text_len) .take(base_text_len)
// .collect::<String>(); .collect::<String>();
// let mut replica_ids = Vec::new(); let mut replica_ids = Vec::new();
// let mut buffers = Vec::new(); let mut buffers = Vec::new();
// let mut network = Network::new(rng.clone()); let mut network = Network::new(rng.clone());
// for i in 0..peers { for i in 0..peers {
// let buffer = cx.add_model(|cx| { let mut buffer = TextBuffer::new(i as ReplicaId, 0, History::new(base_text.clone().into()));
// let mut buf = Buffer::new(i as ReplicaId, base_text.as_str(), cx); buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
// buf.history.group_interval = Duration::from_millis(rng.gen_range(0..=200)); buffers.push(buffer);
// buf replica_ids.push(i as u16);
// }); network.add_peer(i as u16);
// buffers.push(buffer); }
// replica_ids.push(i as u16);
// network.add_peer(i as u16);
// }
// log::info!("initial text: {:?}", base_text); log::info!("initial text: {:?}", base_text);
// let mut mutation_count = operations; let mut mutation_count = operations;
// loop { loop {
// let replica_index = rng.gen_range(0..peers); let replica_index = rng.gen_range(0..peers);
// let replica_id = replica_ids[replica_index]; let replica_id = replica_ids[replica_index];
// buffers[replica_index].update(cx, |buffer, cx| match rng.gen_range(0..=100) { let buffer = &mut buffers[replica_index];
// 0..=50 if mutation_count != 0 => { match rng.gen_range(0..=100) {
// buffer.randomly_mutate(&mut rng, cx); 0..=50 if mutation_count != 0 => {
// network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations)); let ops = buffer.randomly_mutate(&mut rng);
// log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text()); network.broadcast(buffer.replica_id, ops);
// mutation_count -= 1; log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
// } mutation_count -= 1;
// 51..=70 if mutation_count != 0 => { }
// buffer.randomly_undo_redo(&mut rng, cx); 51..=70 if mutation_count != 0 => {
// network.broadcast(buffer.replica_id, mem::take(&mut buffer.operations)); let ops = buffer.randomly_undo_redo(&mut rng);
// mutation_count -= 1; network.broadcast(buffer.replica_id, ops);
// } mutation_count -= 1;
// 71..=100 if network.has_unreceived(replica_id) => { }
// let ops = network.receive(replica_id); 71..=100 if network.has_unreceived(replica_id) => {
// if !ops.is_empty() { let ops = network.receive(replica_id);
// log::info!( if !ops.is_empty() {
// "peer {} applying {} ops from the network.", log::info!(
// replica_id, "peer {} applying {} ops from the network.",
// ops.len() replica_id,
// ); ops.len()
// buffer.apply_ops(ops, cx).unwrap(); );
// } buffer.apply_ops(ops).unwrap();
// } }
// _ => {} }
// }); _ => {}
}
// if mutation_count == 0 && network.is_idle() { if mutation_count == 0 && network.is_idle() {
// break; break;
// } }
// } }
// let first_buffer = buffers[0].read(cx); let first_buffer = &buffers[0];
// for buffer in &buffers[1..] { for buffer in &buffers[1..] {
// let buffer = buffer.read(cx); assert_eq!(
// assert_eq!( buffer.text(),
// buffer.text(), first_buffer.text(),
// first_buffer.text(), "Replica {} text != Replica 0 text",
// "Replica {} text != Replica 0 text", buffer.replica_id
// buffer.replica_id );
// ); assert_eq!(
// assert_eq!( buffer.selection_sets().collect::<HashMap<_, _>>(),
// buffer.selection_sets().collect::<HashMap<_, _>>(), first_buffer.selection_sets().collect::<HashMap<_, _>>()
// first_buffer.selection_sets().collect::<HashMap<_, _>>() );
// ); assert_eq!(
// assert_eq!( buffer.all_selection_ranges().collect::<HashMap<_, _>>(),
// buffer.all_selection_ranges().collect::<HashMap<_, _>>(), first_buffer
// first_buffer .all_selection_ranges()
// .all_selection_ranges() .collect::<HashMap<_, _>>()
// .collect::<HashMap<_, _>>() );
// ); }
// } }
// }
#[derive(Clone)] #[derive(Clone)]
struct Envelope<T: Clone> { struct Envelope<T: Clone> {

View file

@ -436,7 +436,7 @@ mod tests {
} }
} }
_ => { _ => {
buffer.update(&mut cx, |buffer, cx| buffer.randomly_edit(&mut rng, 5, cx)); buffer.update(&mut cx, |buffer, cx| buffer.randomly_edit(&mut rng, 5));
} }
} }

View file

@ -1,4 +1,4 @@
use buffer::{Anchor, Buffer, Point, ToOffset, AnchorRangeExt, HighlightId, TextSummary}; use buffer::{Anchor, AnchorRangeExt, Buffer, HighlightId, Point, TextSummary, ToOffset};
use gpui::{AppContext, ModelHandle}; use gpui::{AppContext, ModelHandle};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
@ -1334,7 +1334,7 @@ mod tests {
let edits = buffer.update(cx, |buffer, cx| { let edits = buffer.update(cx, |buffer, cx| {
let start_version = buffer.version.clone(); let start_version = buffer.version.clone();
let edit_count = rng.gen_range(1..=5); let edit_count = rng.gen_range(1..=5);
buffer.randomly_edit(&mut rng, edit_count, cx); buffer.randomly_edit(&mut rng, edit_count);
buffer.edits_since(start_version).collect::<Vec<_>>() buffer.edits_since(start_version).collect::<Vec<_>>()
}); });
log::info!("editing {:?}", edits); log::info!("editing {:?}", edits);

View file

@ -990,7 +990,7 @@ mod tests {
} }
} }
_ => { _ => {
buffer.update(&mut cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx)); buffer.update(&mut cx, |buffer, cx| buffer.randomly_mutate(&mut rng));
} }
} }