From af84483c06896a346873a0aa122d1336cf540023 Mon Sep 17 00:00:00 2001 From: Gregory Petrosyan Date: Thu, 7 Dec 2023 21:14:12 +0300 Subject: [PATCH] fuzz: assert String equivalence --- fuzz/fuzz_targets/editing.rs | 18 ++++++++++++++---- src/rope/rope.rs | 10 +++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/fuzz/fuzz_targets/editing.rs b/fuzz/fuzz_targets/editing.rs index d0926b8..10a3955 100644 --- a/fuzz/fuzz_targets/editing.rs +++ b/fuzz/fuzz_targets/editing.rs @@ -24,10 +24,12 @@ enum StartingText<'a> { fuzz_target!(|data: (StartingText, Vec)| { let (starting, ops) = data; - let mut rope = Rope::from(match starting { + let start = match starting { StartingText::Custom(s) => s, StartingText::NonAscii => NON_ASCII, - }); + }; + let mut rope = Rope::from(start); + let mut string = String::from(start); for op in ops { match op { @@ -38,6 +40,7 @@ fuzz_target!(|data: (StartingText, Vec)| { byte_offset += 1; } rope.insert(byte_offset, text); + string.insert_str(byte_offset, text); }, EditOp::Delete { mut byte_range } @@ -50,7 +53,8 @@ fuzz_target!(|data: (StartingText, Vec)| { while !rope.is_char_boundary(byte_range.end) { byte_range.end += 1; } - rope.delete(byte_range); + rope.delete(byte_range.clone()); + string.replace_range(byte_range, ""); }, EditOp::Replace { mut byte_range, text } @@ -63,7 +67,8 @@ fuzz_target!(|data: (StartingText, Vec)| { while !rope.is_char_boundary(byte_range.end) { byte_range.end += 1; } - rope.replace(byte_range, text); + rope.replace(byte_range.clone(), text); + string.replace_range(byte_range, text); }, _ => continue, @@ -71,4 +76,9 @@ fuzz_target!(|data: (StartingText, Vec)| { } rope.assert_invariants(); + assert_eq!(rope, string); + assert_eq!( + rope.lines().collect::>(), + string.lines().collect::>(), + ); }); diff --git a/src/rope/rope.rs b/src/rope/rope.rs index 26cc4f3..27c767b 100644 --- a/src/rope/rope.rs +++ b/src/rope/rope.rs @@ -8,16 +8,20 @@ use super::RopeSlice; use crate::range_bounds_to_start_end; use crate::tree::Tree; -#[cfg(any(test, feature = "arity_4"))] +#[cfg(any(test, fuzzing, feature = "arity_4"))] const ARITY: usize = 4; -#[cfg(not(any(test, feature = "arity_4")))] +#[cfg(not(any(test, fuzzing, feature = "arity_4")))] const ARITY: usize = 16; #[cfg(any(test, feature = "small_chunks"))] const CHUNK_MAX_BYTES: usize = 4; -#[cfg(not(any(test, feature = "small_chunks")))] +// With 4-byte chunks, fuzzing is unbearably slow. +#[cfg(fuzzing)] +const CHUNK_MAX_BYTES: usize = 16; + +#[cfg(not(any(test, fuzzing, feature = "small_chunks")))] const CHUNK_MAX_BYTES: usize = 2048; pub(super) type RopeChunk = GapBuffer;