loro/crates/delta/tests/array_delta.rs
Zixuan Chen 9d4f7aa8a3
DeltaRope (#327)
* feat: delta rope support init

* perf: use generic-btree v0.9.0

* refactor: improve readability and maintainability

* fix: fix several issues about composing

* fix: a few more issue about composing deletions

* test: rich text

* fix: cover more edge cases

* refactor: use deltarope for list event

* refactor: replace text delta with DeltaRope

* fix: list fuzz err

* fix: safety issue on insert_many

* chore: refine impl of text delta

* refactor: use Replace instead of insert+del in DeltaItem (#330)

* refactor: use Replace instead of insert+del in DeltaItem

* fix: each deltaitem should have non-zero rle_len
Updated generic-btree dependency to version 0.10.3 and refactored DeltaItem and DeltaRope implementations in loro-delta. Refine compose impl

* fix: update generic-btree to fix the update leaf issue

* chore: lockfile

* chore: clippy fix

* refactor: make composing easier to understand

* refactor: simplify the impl of composing
2024-04-24 13:53:26 +08:00

206 lines
6.9 KiB
Rust

use loro_delta::{array_vec::ArrayVec, DeltaRope, DeltaRopeBuilder};
use tracing_subscriber::fmt::format::FmtSpan;
type TestArrayDelta = DeltaRope<ArrayVec<i32, 10>, ()>;
#[ctor::ctor]
fn init_color_backtrace() {
color_backtrace::install();
use tracing_subscriber::{prelude::*, registry::Registry};
if option_env!("DEBUG").is_some() {
tracing::subscriber::set_global_default(
Registry::default().with(
tracing_subscriber::fmt::Layer::default()
.with_file(true)
.with_line_number(true)
.with_span_events(FmtSpan::ACTIVE),
),
)
.unwrap();
}
}
#[test]
fn delete_eq() {
let a: TestArrayDelta = DeltaRopeBuilder::new().delete(5).build();
let b = DeltaRopeBuilder::new().delete(10).build();
assert_ne!(a, b);
}
#[test]
fn test_delete() {
let mut a: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4]), ())
.build();
let b = DeltaRopeBuilder::new().retain(1, ()).delete(1).build();
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1]), ())
.build();
assert_eq!(a.len(), 4);
a.compose(&b);
assert_eq!(a.len(), 3);
a.compose(&b);
assert_eq!(a.len(), 2);
a.compose(&b);
assert_eq!(a.len(), 1);
assert_eq!(a, expected);
}
#[test]
fn test_basic_deletion() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5]), ())
.build();
let delete_op = DeltaRopeBuilder::new().delete(2).build();
delta.compose(&delete_op);
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([3, 4, 5]), ())
.build();
assert_eq!(delta, expected);
}
#[test]
fn test_composition_of_operations() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3]), ())
.build();
let ops = DeltaRopeBuilder::new()
.retain(1, ())
.delete(1)
.insert(ArrayVec::from([4, 5]), ())
.build();
delta.compose(&ops);
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 4, 5, 3]), ())
.build();
assert_eq!(delta, expected);
}
#[test]
fn test_complex_composition() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4]), ())
.build();
let ops1 = DeltaRopeBuilder::new().retain(1, ()).delete(1).build();
let ops2 = DeltaRopeBuilder::new()
.retain(1, ())
.insert(ArrayVec::from([5, 6]), ())
.build();
delta.compose(&ops1);
delta.compose(&ops2);
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 5, 6, 3, 4]), ())
.build();
assert_eq!(delta, expected);
}
#[test]
fn test_retain_operation() {
let delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4]), ())
.build();
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4]), ())
.build();
assert_eq!(delta, expected);
}
#[test]
fn test_edge_cases_insertion() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([2, 3]), ())
.build();
let insert_begin = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1]), ())
.build();
let insert_end = DeltaRopeBuilder::new()
.retain(3, ())
.insert(ArrayVec::from([4]), ())
.build();
delta.compose(&insert_begin);
delta.compose(&insert_end);
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4]), ())
.build();
assert_eq!(delta, expected);
}
// Test case to verify behavior when attempting to insert beyond capacity
// It should split the insertion into multiple parts to avoid overflow.
#[test]
fn test_insert_overflow_handled() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5, 6, 7, 8, 9]), ())
.build();
// Attempt to insert more elements than the capacity allows, expecting it to handle gracefully
let overflow_op = DeltaRopeBuilder::new()
.insert(ArrayVec::from([10, 11]), ())
.build();
delta.compose(&overflow_op);
// Expected behavior: split the insertion to avoid overflow
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([10, 11]), ())
.insert(ArrayVec::from([1, 2, 3, 4, 5, 6, 7, 8, 9]), ())
.build();
assert_eq!(delta, expected);
}
// Test case to verify behavior when multiple operations lead to overflow
// It should handle the overflow by creating new insertions as needed.
#[test]
fn test_cumulative_insert_overflow_handled() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5]), ())
.build();
// First operation that fits within capacity
let op1 = DeltaRopeBuilder::new()
.retain(5, ())
.insert(ArrayVec::from([6, 7, 8]), ())
.build();
// Second operation that would normally cause overflow
let op2 = DeltaRopeBuilder::new()
.retain(8, ())
.insert(ArrayVec::from([9, 10, 11]), ())
.build();
delta.compose(&op1);
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5, 6, 7, 8]), ())
.build();
assert_eq!(delta, expected);
delta.compose(&op2); // Expect it to handle overflow gracefully
// Expected behavior: handle overflow by creating new insertions
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5, 6, 7, 8, 9]), ())
.insert(ArrayVec::from([10, 11]), ())
.build();
assert_eq!(delta, expected);
}
// Test case for handling deletion followed by insertion that exceeds capacity
// It should correctly handle the overflow by creating a new insertion.
#[test]
fn test_delete_then_insert_overflow_handled() {
let mut delta: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), ())
.build();
// Delete some elements
let delete_op = DeltaRopeBuilder::new().retain(5, ()).delete(5).build();
// Attempt to insert more elements than the remaining capacity allows
let insert_op = DeltaRopeBuilder::new()
.retain(5, ())
.insert(ArrayVec::from([11, 12, 13, 14, 15, 16]), ())
.build();
delta.compose(&delete_op);
delta.compose(&insert_op); // Expect it to handle overflow gracefully
// Expected behavior: handle overflow by creating new insertions
let expected: TestArrayDelta = DeltaRopeBuilder::new()
.insert(ArrayVec::from([1, 2, 3, 4, 5]), ())
.insert(ArrayVec::from([11, 12, 13, 14, 15, 16]), ())
.build();
assert_eq!(delta, expected);
}