tests.rs

  1use super::*;
  2use clock::ReplicaId;
  3use rand::prelude::*;
  4use std::{
  5    cmp::Ordering,
  6    env,
  7    iter::Iterator,
  8    time::{Duration, Instant},
  9};
 10
 11#[test]
 12fn test_edit() {
 13    let mut buffer = Buffer::new(0, 0, History::new("abc".into()));
 14    assert_eq!(buffer.text(), "abc");
 15    buffer.edit(vec![3..3], "def");
 16    assert_eq!(buffer.text(), "abcdef");
 17    buffer.edit(vec![0..0], "ghi");
 18    assert_eq!(buffer.text(), "ghiabcdef");
 19    buffer.edit(vec![5..5], "jkl");
 20    assert_eq!(buffer.text(), "ghiabjklcdef");
 21    buffer.edit(vec![6..7], "");
 22    assert_eq!(buffer.text(), "ghiabjlcdef");
 23    buffer.edit(vec![4..9], "mno");
 24    assert_eq!(buffer.text(), "ghiamnoef");
 25}
 26
 27#[gpui::test(iterations = 100)]
 28fn test_random_edits(mut rng: StdRng) {
 29    let operations = env::var("OPERATIONS")
 30        .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
 31        .unwrap_or(10);
 32
 33    let reference_string_len = rng.gen_range(0..3);
 34    let mut reference_string = RandomCharIter::new(&mut rng)
 35        .take(reference_string_len)
 36        .collect::<String>();
 37    let mut buffer = Buffer::new(0, 0, History::new(reference_string.clone().into()));
 38    buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
 39    let mut buffer_versions = Vec::new();
 40    log::info!(
 41        "buffer text {:?}, version: {:?}",
 42        buffer.text(),
 43        buffer.version()
 44    );
 45
 46    for _i in 0..operations {
 47        let (old_ranges, new_text, _) = buffer.randomly_edit(&mut rng, 5);
 48        for old_range in old_ranges.iter().rev() {
 49            reference_string.replace_range(old_range.clone(), &new_text);
 50        }
 51        assert_eq!(buffer.text(), reference_string);
 52        log::info!(
 53            "buffer text {:?}, version: {:?}",
 54            buffer.text(),
 55            buffer.version()
 56        );
 57
 58        if rng.gen_bool(0.25) {
 59            buffer.randomly_undo_redo(&mut rng);
 60            reference_string = buffer.text();
 61            log::info!(
 62                "buffer text {:?}, version: {:?}",
 63                buffer.text(),
 64                buffer.version()
 65            );
 66        }
 67
 68        let range = buffer.random_byte_range(0, &mut rng);
 69        assert_eq!(
 70            buffer.text_summary_for_range(range.clone()),
 71            TextSummary::from(&reference_string[range])
 72        );
 73
 74        if rng.gen_bool(0.3) {
 75            buffer_versions.push(buffer.clone());
 76        }
 77    }
 78
 79    for mut old_buffer in buffer_versions {
 80        let edits = buffer
 81            .edits_since::<usize>(&old_buffer.version)
 82            .collect::<Vec<_>>();
 83
 84        log::info!(
 85            "mutating old buffer version {:?}, text: {:?}, edits since: {:?}",
 86            old_buffer.version(),
 87            old_buffer.text(),
 88            edits,
 89        );
 90
 91        for edit in edits {
 92            let new_text: String = buffer.text_for_range(edit.new.clone()).collect();
 93            old_buffer.edit(
 94                Some(edit.new.start..edit.new.start + edit.old.len()),
 95                new_text,
 96            );
 97        }
 98        assert_eq!(old_buffer.text(), buffer.text());
 99    }
100}
101
102#[test]
103fn test_line_len() {
104    let mut buffer = Buffer::new(0, 0, History::new("".into()));
105    buffer.edit(vec![0..0], "abcd\nefg\nhij");
106    buffer.edit(vec![12..12], "kl\nmno");
107    buffer.edit(vec![18..18], "\npqrs\n");
108    buffer.edit(vec![18..21], "\nPQ");
109
110    assert_eq!(buffer.line_len(0), 4);
111    assert_eq!(buffer.line_len(1), 3);
112    assert_eq!(buffer.line_len(2), 5);
113    assert_eq!(buffer.line_len(3), 3);
114    assert_eq!(buffer.line_len(4), 4);
115    assert_eq!(buffer.line_len(5), 0);
116}
117
118#[test]
119fn test_text_summary_for_range() {
120    let buffer = Buffer::new(0, 0, History::new("ab\nefg\nhklm\nnopqrs\ntuvwxyz".into()));
121    assert_eq!(
122        buffer.text_summary_for_range(1..3),
123        TextSummary {
124            bytes: 2,
125            lines: Point::new(1, 0),
126            lines_utf16: PointUtf16::new(1, 0),
127            first_line_chars: 1,
128            last_line_chars: 0,
129            longest_row: 0,
130            longest_row_chars: 1,
131        }
132    );
133    assert_eq!(
134        buffer.text_summary_for_range(1..12),
135        TextSummary {
136            bytes: 11,
137            lines: Point::new(3, 0),
138            lines_utf16: PointUtf16::new(3, 0),
139            first_line_chars: 1,
140            last_line_chars: 0,
141            longest_row: 2,
142            longest_row_chars: 4,
143        }
144    );
145    assert_eq!(
146        buffer.text_summary_for_range(0..20),
147        TextSummary {
148            bytes: 20,
149            lines: Point::new(4, 1),
150            lines_utf16: PointUtf16::new(4, 1),
151            first_line_chars: 2,
152            last_line_chars: 1,
153            longest_row: 3,
154            longest_row_chars: 6,
155        }
156    );
157    assert_eq!(
158        buffer.text_summary_for_range(0..22),
159        TextSummary {
160            bytes: 22,
161            lines: Point::new(4, 3),
162            lines_utf16: PointUtf16::new(4, 3),
163            first_line_chars: 2,
164            last_line_chars: 3,
165            longest_row: 3,
166            longest_row_chars: 6,
167        }
168    );
169    assert_eq!(
170        buffer.text_summary_for_range(7..22),
171        TextSummary {
172            bytes: 15,
173            lines: Point::new(2, 3),
174            lines_utf16: PointUtf16::new(2, 3),
175            first_line_chars: 4,
176            last_line_chars: 3,
177            longest_row: 1,
178            longest_row_chars: 6,
179        }
180    );
181}
182
183#[test]
184fn test_chars_at() {
185    let mut buffer = Buffer::new(0, 0, History::new("".into()));
186    buffer.edit(vec![0..0], "abcd\nefgh\nij");
187    buffer.edit(vec![12..12], "kl\nmno");
188    buffer.edit(vec![18..18], "\npqrs");
189    buffer.edit(vec![18..21], "\nPQ");
190
191    let chars = buffer.chars_at(Point::new(0, 0));
192    assert_eq!(chars.collect::<String>(), "abcd\nefgh\nijkl\nmno\nPQrs");
193
194    let chars = buffer.chars_at(Point::new(1, 0));
195    assert_eq!(chars.collect::<String>(), "efgh\nijkl\nmno\nPQrs");
196
197    let chars = buffer.chars_at(Point::new(2, 0));
198    assert_eq!(chars.collect::<String>(), "ijkl\nmno\nPQrs");
199
200    let chars = buffer.chars_at(Point::new(3, 0));
201    assert_eq!(chars.collect::<String>(), "mno\nPQrs");
202
203    let chars = buffer.chars_at(Point::new(4, 0));
204    assert_eq!(chars.collect::<String>(), "PQrs");
205
206    // Regression test:
207    let mut buffer = Buffer::new(0, 0, History::new("".into()));
208    buffer.edit(vec![0..0], "[workspace]\nmembers = [\n    \"xray_core\",\n    \"xray_server\",\n    \"xray_cli\",\n    \"xray_wasm\",\n]\n");
209    buffer.edit(vec![60..60], "\n");
210
211    let chars = buffer.chars_at(Point::new(6, 0));
212    assert_eq!(chars.collect::<String>(), "    \"xray_wasm\",\n]\n");
213}
214
215#[test]
216fn test_anchors() {
217    let mut buffer = Buffer::new(0, 0, History::new("".into()));
218    buffer.edit(vec![0..0], "abc");
219    let left_anchor = buffer.anchor_before(2);
220    let right_anchor = buffer.anchor_after(2);
221
222    buffer.edit(vec![1..1], "def\n");
223    assert_eq!(buffer.text(), "adef\nbc");
224    assert_eq!(left_anchor.to_offset(&buffer), 6);
225    assert_eq!(right_anchor.to_offset(&buffer), 6);
226    assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
227    assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
228
229    buffer.edit(vec![2..3], "");
230    assert_eq!(buffer.text(), "adf\nbc");
231    assert_eq!(left_anchor.to_offset(&buffer), 5);
232    assert_eq!(right_anchor.to_offset(&buffer), 5);
233    assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
234    assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 1 });
235
236    buffer.edit(vec![5..5], "ghi\n");
237    assert_eq!(buffer.text(), "adf\nbghi\nc");
238    assert_eq!(left_anchor.to_offset(&buffer), 5);
239    assert_eq!(right_anchor.to_offset(&buffer), 9);
240    assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 });
241    assert_eq!(right_anchor.to_point(&buffer), Point { row: 2, column: 0 });
242
243    buffer.edit(vec![7..9], "");
244    assert_eq!(buffer.text(), "adf\nbghc");
245    assert_eq!(left_anchor.to_offset(&buffer), 5);
246    assert_eq!(right_anchor.to_offset(&buffer), 7);
247    assert_eq!(left_anchor.to_point(&buffer), Point { row: 1, column: 1 },);
248    assert_eq!(right_anchor.to_point(&buffer), Point { row: 1, column: 3 });
249
250    // Ensure anchoring to a point is equivalent to anchoring to an offset.
251    assert_eq!(
252        buffer.anchor_before(Point { row: 0, column: 0 }),
253        buffer.anchor_before(0)
254    );
255    assert_eq!(
256        buffer.anchor_before(Point { row: 0, column: 1 }),
257        buffer.anchor_before(1)
258    );
259    assert_eq!(
260        buffer.anchor_before(Point { row: 0, column: 2 }),
261        buffer.anchor_before(2)
262    );
263    assert_eq!(
264        buffer.anchor_before(Point { row: 0, column: 3 }),
265        buffer.anchor_before(3)
266    );
267    assert_eq!(
268        buffer.anchor_before(Point { row: 1, column: 0 }),
269        buffer.anchor_before(4)
270    );
271    assert_eq!(
272        buffer.anchor_before(Point { row: 1, column: 1 }),
273        buffer.anchor_before(5)
274    );
275    assert_eq!(
276        buffer.anchor_before(Point { row: 1, column: 2 }),
277        buffer.anchor_before(6)
278    );
279    assert_eq!(
280        buffer.anchor_before(Point { row: 1, column: 3 }),
281        buffer.anchor_before(7)
282    );
283    assert_eq!(
284        buffer.anchor_before(Point { row: 1, column: 4 }),
285        buffer.anchor_before(8)
286    );
287
288    // Comparison between anchors.
289    let anchor_at_offset_0 = buffer.anchor_before(0);
290    let anchor_at_offset_1 = buffer.anchor_before(1);
291    let anchor_at_offset_2 = buffer.anchor_before(2);
292
293    assert_eq!(
294        anchor_at_offset_0
295            .cmp(&anchor_at_offset_0, &buffer)
296            .unwrap(),
297        Ordering::Equal
298    );
299    assert_eq!(
300        anchor_at_offset_1
301            .cmp(&anchor_at_offset_1, &buffer)
302            .unwrap(),
303        Ordering::Equal
304    );
305    assert_eq!(
306        anchor_at_offset_2
307            .cmp(&anchor_at_offset_2, &buffer)
308            .unwrap(),
309        Ordering::Equal
310    );
311
312    assert_eq!(
313        anchor_at_offset_0
314            .cmp(&anchor_at_offset_1, &buffer)
315            .unwrap(),
316        Ordering::Less
317    );
318    assert_eq!(
319        anchor_at_offset_1
320            .cmp(&anchor_at_offset_2, &buffer)
321            .unwrap(),
322        Ordering::Less
323    );
324    assert_eq!(
325        anchor_at_offset_0
326            .cmp(&anchor_at_offset_2, &buffer)
327            .unwrap(),
328        Ordering::Less
329    );
330
331    assert_eq!(
332        anchor_at_offset_1
333            .cmp(&anchor_at_offset_0, &buffer)
334            .unwrap(),
335        Ordering::Greater
336    );
337    assert_eq!(
338        anchor_at_offset_2
339            .cmp(&anchor_at_offset_1, &buffer)
340            .unwrap(),
341        Ordering::Greater
342    );
343    assert_eq!(
344        anchor_at_offset_2
345            .cmp(&anchor_at_offset_0, &buffer)
346            .unwrap(),
347        Ordering::Greater
348    );
349}
350
351#[test]
352fn test_anchors_at_start_and_end() {
353    let mut buffer = Buffer::new(0, 0, History::new("".into()));
354    let before_start_anchor = buffer.anchor_before(0);
355    let after_end_anchor = buffer.anchor_after(0);
356
357    buffer.edit(vec![0..0], "abc");
358    assert_eq!(buffer.text(), "abc");
359    assert_eq!(before_start_anchor.to_offset(&buffer), 0);
360    assert_eq!(after_end_anchor.to_offset(&buffer), 3);
361
362    let after_start_anchor = buffer.anchor_after(0);
363    let before_end_anchor = buffer.anchor_before(3);
364
365    buffer.edit(vec![3..3], "def");
366    buffer.edit(vec![0..0], "ghi");
367    assert_eq!(buffer.text(), "ghiabcdef");
368    assert_eq!(before_start_anchor.to_offset(&buffer), 0);
369    assert_eq!(after_start_anchor.to_offset(&buffer), 3);
370    assert_eq!(before_end_anchor.to_offset(&buffer), 6);
371    assert_eq!(after_end_anchor.to_offset(&buffer), 9);
372}
373
374#[test]
375fn test_undo_redo() {
376    let mut buffer = Buffer::new(0, 0, History::new("1234".into()));
377    // Set group interval to zero so as to not group edits in the undo stack.
378    buffer.history.group_interval = Duration::from_secs(0);
379
380    buffer.edit(vec![1..1], "abx");
381    buffer.edit(vec![3..4], "yzef");
382    buffer.edit(vec![3..5], "cd");
383    assert_eq!(buffer.text(), "1abcdef234");
384
385    let transactions = buffer.history.undo_stack.clone();
386    assert_eq!(transactions.len(), 3);
387
388    buffer.undo_or_redo(transactions[0].clone()).unwrap();
389    assert_eq!(buffer.text(), "1cdef234");
390    buffer.undo_or_redo(transactions[0].clone()).unwrap();
391    assert_eq!(buffer.text(), "1abcdef234");
392
393    buffer.undo_or_redo(transactions[1].clone()).unwrap();
394    assert_eq!(buffer.text(), "1abcdx234");
395    buffer.undo_or_redo(transactions[2].clone()).unwrap();
396    assert_eq!(buffer.text(), "1abx234");
397    buffer.undo_or_redo(transactions[1].clone()).unwrap();
398    assert_eq!(buffer.text(), "1abyzef234");
399    buffer.undo_or_redo(transactions[2].clone()).unwrap();
400    assert_eq!(buffer.text(), "1abcdef234");
401
402    buffer.undo_or_redo(transactions[2].clone()).unwrap();
403    assert_eq!(buffer.text(), "1abyzef234");
404    buffer.undo_or_redo(transactions[0].clone()).unwrap();
405    assert_eq!(buffer.text(), "1yzef234");
406    buffer.undo_or_redo(transactions[1].clone()).unwrap();
407    assert_eq!(buffer.text(), "1234");
408}
409
410#[test]
411fn test_history() {
412    let mut now = Instant::now();
413    let mut buffer = Buffer::new(0, 0, History::new("123456".into()));
414
415    let set_id = if let Operation::UpdateSelections { set_id, .. } =
416        buffer.add_selection_set(&buffer.selections_from_ranges(vec![4..4]).unwrap())
417    {
418        set_id
419    } else {
420        unreachable!()
421    };
422    buffer.start_transaction_at(Some(set_id), now).unwrap();
423    buffer.edit(vec![2..4], "cd");
424    buffer.end_transaction_at(Some(set_id), now).unwrap();
425    assert_eq!(buffer.text(), "12cd56");
426    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
427
428    buffer.start_transaction_at(Some(set_id), now).unwrap();
429    buffer
430        .update_selection_set(set_id, &buffer.selections_from_ranges(vec![1..3]).unwrap())
431        .unwrap();
432    buffer.edit(vec![4..5], "e");
433    buffer.end_transaction_at(Some(set_id), now).unwrap();
434    assert_eq!(buffer.text(), "12cde6");
435    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
436
437    now += buffer.history.group_interval + Duration::from_millis(1);
438    buffer.start_transaction_at(Some(set_id), now).unwrap();
439    buffer
440        .update_selection_set(set_id, &buffer.selections_from_ranges(vec![2..2]).unwrap())
441        .unwrap();
442    buffer.edit(vec![0..1], "a");
443    buffer.edit(vec![1..1], "b");
444    buffer.end_transaction_at(Some(set_id), now).unwrap();
445    assert_eq!(buffer.text(), "ab2cde6");
446    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
447
448    // Last transaction happened past the group interval, undo it on its
449    // own.
450    buffer.undo();
451    assert_eq!(buffer.text(), "12cde6");
452    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
453
454    // First two transactions happened within the group interval, undo them
455    // together.
456    buffer.undo();
457    assert_eq!(buffer.text(), "123456");
458    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![4..4]);
459
460    // Redo the first two transactions together.
461    buffer.redo();
462    assert_eq!(buffer.text(), "12cde6");
463    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![1..3]);
464
465    // Redo the last transaction on its own.
466    buffer.redo();
467    assert_eq!(buffer.text(), "ab2cde6");
468    assert_eq!(buffer.selection_ranges(set_id).unwrap(), vec![3..3]);
469
470    buffer.start_transaction_at(None, now).unwrap();
471    assert!(buffer.end_transaction_at(None, now).is_none());
472    buffer.undo();
473    assert_eq!(buffer.text(), "12cde6");
474}
475
476#[test]
477fn test_concurrent_edits() {
478    let text = "abcdef";
479
480    let mut buffer1 = Buffer::new(1, 0, History::new(text.into()));
481    let mut buffer2 = Buffer::new(2, 0, History::new(text.into()));
482    let mut buffer3 = Buffer::new(3, 0, History::new(text.into()));
483
484    let buf1_op = buffer1.edit(vec![1..2], "12");
485    assert_eq!(buffer1.text(), "a12cdef");
486    let buf2_op = buffer2.edit(vec![3..4], "34");
487    assert_eq!(buffer2.text(), "abc34ef");
488    let buf3_op = buffer3.edit(vec![5..6], "56");
489    assert_eq!(buffer3.text(), "abcde56");
490
491    buffer1.apply_op(Operation::Edit(buf2_op.clone())).unwrap();
492    buffer1.apply_op(Operation::Edit(buf3_op.clone())).unwrap();
493    buffer2.apply_op(Operation::Edit(buf1_op.clone())).unwrap();
494    buffer2.apply_op(Operation::Edit(buf3_op.clone())).unwrap();
495    buffer3.apply_op(Operation::Edit(buf1_op.clone())).unwrap();
496    buffer3.apply_op(Operation::Edit(buf2_op.clone())).unwrap();
497
498    assert_eq!(buffer1.text(), "a12c34e56");
499    assert_eq!(buffer2.text(), "a12c34e56");
500    assert_eq!(buffer3.text(), "a12c34e56");
501}
502
503#[gpui::test(iterations = 100)]
504fn test_random_concurrent_edits(mut rng: StdRng) {
505    let peers = env::var("PEERS")
506        .map(|i| i.parse().expect("invalid `PEERS` variable"))
507        .unwrap_or(5);
508    let operations = env::var("OPERATIONS")
509        .map(|i| i.parse().expect("invalid `OPERATIONS` variable"))
510        .unwrap_or(10);
511
512    let base_text_len = rng.gen_range(0..10);
513    let base_text = RandomCharIter::new(&mut rng)
514        .take(base_text_len)
515        .collect::<String>();
516    let mut replica_ids = Vec::new();
517    let mut buffers = Vec::new();
518    let mut network = Network::new(rng.clone());
519
520    for i in 0..peers {
521        let mut buffer = Buffer::new(i as ReplicaId, 0, History::new(base_text.clone().into()));
522        buffer.history.group_interval = Duration::from_millis(rng.gen_range(0..=200));
523        buffers.push(buffer);
524        replica_ids.push(i as u16);
525        network.add_peer(i as u16);
526    }
527
528    log::info!("initial text: {:?}", base_text);
529
530    let mut mutation_count = operations;
531    loop {
532        let replica_index = rng.gen_range(0..peers);
533        let replica_id = replica_ids[replica_index];
534        let buffer = &mut buffers[replica_index];
535        match rng.gen_range(0..=100) {
536            0..=50 if mutation_count != 0 => {
537                let ops = buffer.randomly_mutate(&mut rng);
538                network.broadcast(buffer.replica_id, ops);
539                log::info!("buffer {} text: {:?}", buffer.replica_id, buffer.text());
540                mutation_count -= 1;
541            }
542            51..=70 if mutation_count != 0 => {
543                let ops = buffer.randomly_undo_redo(&mut rng);
544                network.broadcast(buffer.replica_id, ops);
545                mutation_count -= 1;
546            }
547            71..=100 if network.has_unreceived(replica_id) => {
548                let ops = network.receive(replica_id);
549                if !ops.is_empty() {
550                    log::info!(
551                        "peer {} applying {} ops from the network.",
552                        replica_id,
553                        ops.len()
554                    );
555                    buffer.apply_ops(ops).unwrap();
556                }
557            }
558            _ => {}
559        }
560
561        if mutation_count == 0 && network.is_idle() {
562            break;
563        }
564    }
565
566    let first_buffer = &buffers[0];
567    for buffer in &buffers[1..] {
568        assert_eq!(
569            buffer.text(),
570            first_buffer.text(),
571            "Replica {} text != Replica 0 text",
572            buffer.replica_id
573        );
574        assert_eq!(
575            buffer.selection_sets().collect::<HashMap<_, _>>(),
576            first_buffer.selection_sets().collect::<HashMap<_, _>>()
577        );
578        assert_eq!(
579            buffer
580                .all_selection_ranges::<usize>()
581                .collect::<HashMap<_, _>>(),
582            first_buffer
583                .all_selection_ranges::<usize>()
584                .collect::<HashMap<_, _>>()
585        );
586    }
587}
588
589#[derive(Clone)]
590struct Envelope<T: Clone> {
591    message: T,
592    sender: ReplicaId,
593}
594
595struct Network<T: Clone, R: rand::Rng> {
596    inboxes: std::collections::BTreeMap<ReplicaId, Vec<Envelope<T>>>,
597    all_messages: Vec<T>,
598    rng: R,
599}
600
601impl<T: Clone, R: rand::Rng> Network<T, R> {
602    fn new(rng: R) -> Self {
603        Network {
604            inboxes: Default::default(),
605            all_messages: Vec::new(),
606            rng,
607        }
608    }
609
610    fn add_peer(&mut self, id: ReplicaId) {
611        self.inboxes.insert(id, Vec::new());
612    }
613
614    fn is_idle(&self) -> bool {
615        self.inboxes.values().all(|i| i.is_empty())
616    }
617
618    fn broadcast(&mut self, sender: ReplicaId, messages: Vec<T>) {
619        for (replica, inbox) in self.inboxes.iter_mut() {
620            if *replica != sender {
621                for message in &messages {
622                    let min_index = inbox
623                        .iter()
624                        .enumerate()
625                        .rev()
626                        .find_map(|(index, envelope)| {
627                            if sender == envelope.sender {
628                                Some(index + 1)
629                            } else {
630                                None
631                            }
632                        })
633                        .unwrap_or(0);
634
635                    // Insert one or more duplicates of this message *after* the previous
636                    // message delivered by this replica.
637                    for _ in 0..self.rng.gen_range(1..4) {
638                        let insertion_index = self.rng.gen_range(min_index..inbox.len() + 1);
639                        inbox.insert(
640                            insertion_index,
641                            Envelope {
642                                message: message.clone(),
643                                sender,
644                            },
645                        );
646                    }
647                }
648            }
649        }
650        self.all_messages.extend(messages);
651    }
652
653    fn has_unreceived(&self, receiver: ReplicaId) -> bool {
654        !self.inboxes[&receiver].is_empty()
655    }
656
657    fn receive(&mut self, receiver: ReplicaId) -> Vec<T> {
658        let inbox = self.inboxes.get_mut(&receiver).unwrap();
659        let count = self.rng.gen_range(0..inbox.len() + 1);
660        inbox
661            .drain(0..count)
662            .map(|envelope| envelope.message)
663            .collect()
664    }
665}