test: text refactor fuzz

This commit is contained in:
Zixuan Chen 2023-07-17 15:00:40 +08:00
parent e993f1b155
commit ca977fcf39
6 changed files with 138 additions and 30 deletions

View file

@ -25,9 +25,9 @@ dependencies = [
[[package]] [[package]]
name = "arbitrary" name = "arbitrary"
version = "1.2.0" version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29d47fbf90d5149a107494b15a7dc8d69b351be2db3bb9691740e88ec17fd880" checksum = "e2d098ff73c1ca148721f37baad5ea6a465a13f9573aba8641fbbbae8164a54e"
dependencies = [ dependencies = [
"derive_arbitrary", "derive_arbitrary",
] ]
@ -107,6 +107,15 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "compact-bytes"
version = "0.1.0"
dependencies = [
"append-only-bytes",
"fxhash",
"linked-hash-map",
]
[[package]] [[package]]
name = "crdt-list" name = "crdt-list"
version = "0.4.0" version = "0.4.0"
@ -167,13 +176,13 @@ checksum = "364ff57c5031fee39b026dcdfdc9c7dc1d1d79451bfdacba90f040524b766254"
[[package]] [[package]]
name = "derive_arbitrary" name = "derive_arbitrary"
version = "1.2.0" version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4903dff04948f22033ca30232ab8eca2c3fc4c913a8b6a34ee5199699814817f" checksum = "53e0efad4403bfc52dc201159c4b842a246a14b98c64b55dfd0f2d89729dfeb8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.105", "syn 2.0.25",
] ]
[[package]] [[package]]
@ -194,6 +203,18 @@ dependencies = [
"syn 1.0.105", "syn 1.0.105",
] ]
[[package]]
name = "enum-as-inner"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.25",
]
[[package]] [[package]]
name = "enum_dispatch" name = "enum_dispatch"
version = "0.3.11" version = "0.3.11"
@ -352,6 +373,12 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.9" version = "0.4.9"
@ -371,6 +398,19 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "loro-common"
version = "0.1.0"
dependencies = [
"arbitrary",
"enum-as-inner 0.6.0",
"fxhash",
"rle",
"serde",
"string_cache",
"thiserror",
]
[[package]] [[package]]
name = "loro-internal" name = "loro-internal"
version = "0.1.0" version = "0.1.0"
@ -378,15 +418,18 @@ dependencies = [
"append-only-bytes", "append-only-bytes",
"arbitrary", "arbitrary",
"arref", "arref",
"compact-bytes",
"crdt-list", "crdt-list",
"debug-log", "debug-log",
"enum-as-inner", "enum-as-inner 0.5.1",
"enum_dispatch", "enum_dispatch",
"fxhash", "fxhash",
"generic-btree", "generic-btree",
"im", "im",
"itertools", "itertools",
"jumprope", "jumprope",
"loro-common",
"loro-preload",
"num", "num",
"postcard", "postcard",
"rand", "rand",
@ -412,6 +455,15 @@ dependencies = [
"loro-internal", "loro-internal",
] ]
[[package]]
name = "loro-preload"
version = "0.1.0"
dependencies = [
"loro-common",
"serde",
"serde_columnar",
]
[[package]] [[package]]
name = "new_debug_unreachable" name = "new_debug_unreachable"
version = "1.0.4" version = "1.0.4"
@ -709,7 +761,7 @@ dependencies = [
"bumpalo", "bumpalo",
"crdt-list", "crdt-list",
"debug-log", "debug-log",
"enum-as-inner", "enum-as-inner 0.5.1",
"fxhash", "fxhash",
"heapless", "heapless",
"num", "num",
@ -871,9 +923,9 @@ checksum = "5f026164926842ec52deb1938fae44f83dfdb82d0a5b0270c5bd5935ab74d6dd"
[[package]] [[package]]
name = "string_cache" name = "string_cache"
version = "0.8.4" version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
dependencies = [ dependencies = [
"new_debug_unreachable", "new_debug_unreachable",
"once_cell", "once_cell",
@ -937,22 +989,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.37" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.37" version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.105", "syn 2.0.25",
] ]
[[package]] [[package]]

View file

@ -197,6 +197,7 @@ pub(crate) struct IterReturn<'a, T> {
impl<'a, T: DagNode, D: Dag<Node = T>> DagCausalIter<'a, D> { impl<'a, T: DagNode, D: Dag<Node = T>> DagCausalIter<'a, D> {
pub fn new(dag: &'a D, from: Frontiers, target: IdSpanVector) -> Self { pub fn new(dag: &'a D, from: Frontiers, target: IdSpanVector) -> Self {
debug_dbg!(&from, &target);
let mut in_degrees: FxHashMap<ID, usize> = FxHashMap::default(); let mut in_degrees: FxHashMap<ID, usize> = FxHashMap::default();
let mut succ: BTreeMap<ID, Frontiers> = BTreeMap::default(); let mut succ: BTreeMap<ID, Frontiers> = BTreeMap::default();
let mut stack = Vec::new(); let mut stack = Vec::new();

View file

@ -313,12 +313,18 @@ fn check_synced_refactored(sites: &mut [LoroApp]) {
debug_log::group!("checking {} with {}", i, j); debug_log::group!("checking {} with {}", i, j);
let (a, b) = array_mut_ref!(sites, [i, j]); let (a, b) = array_mut_ref!(sites, [i, j]);
{ {
debug_log::group!("Import {}", i); if (i + j) % 2 == 1 {
a.import(&b.export_from(&a.vv_cloned())).unwrap(); debug_log::group!("Import {}'s Snapshot to {}", j, i);
debug_log::group_end!(); a.import(&b.export_snapshot()).unwrap();
debug_log::group_end!();
} else {
debug_log::group!("Import {} to {}", j, i);
a.import(&b.export_from(&a.vv_cloned())).unwrap();
debug_log::group_end!();
}
} }
{ {
debug_log::group!("Import {}", j); debug_log::group!("Import {} to {}", i, j);
b.import(&a.export_from(&b.vv_cloned())).unwrap(); b.import(&a.export_from(&b.vv_cloned())).unwrap();
debug_log::group_end!(); debug_log::group_end!();
} }
@ -1222,6 +1228,30 @@ mod test {
); );
} }
#[test]
fn snapshot() {
test_multi_sites_refactored(
8,
&mut [
Ins {
content: 32818,
pos: 0,
site: 1,
},
Ins {
content: 12850,
pos: 0,
site: 3,
},
Ins {
content: 13621,
pos: 3,
site: 1,
},
],
)
}
#[test] #[test]
fn mini_r() { fn mini_r() {
minify_error(8, vec![], test_multi_sites_refactored, normalize) minify_error(8, vec![], test_multi_sites_refactored, normalize)

View file

@ -1,5 +1,6 @@
use std::{cmp::Ordering, collections::BinaryHeap}; use std::{cmp::Ordering, collections::BinaryHeap};
use debug_log::debug_dbg;
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use fxhash::{FxHashMap, FxHashSet}; use fxhash::{FxHashMap, FxHashSet};
@ -59,10 +60,10 @@ impl DiffCalculator {
let (lca, iter) = let (lca, iter) =
oplog.iter_from_lca_causally(before, before_frontiers, after, after_frontiers); oplog.iter_from_lca_causally(before, before_frontiers, after, after_frontiers);
for (change, vv) in iter { for (change, vv) in iter {
let mut visited = FxHashSet::default();
for op in change.ops.iter() { for op in change.ops.iter() {
let container_id = arena.get_container_id(op.container).unwrap();
let calculator = self.calculators.entry(op.container).or_insert_with(|| { let calculator = self.calculators.entry(op.container).or_insert_with(|| {
let mut new = match container_id.container_type() { let mut new = match op.container.get_type() {
crate::ContainerType::Text => { crate::ContainerType::Text => {
ContainerDiffCalculator::Text(TextDiffCalculator::default()) ContainerDiffCalculator::Text(TextDiffCalculator::default())
} }
@ -77,7 +78,17 @@ impl DiffCalculator {
new new
}); });
calculator.apply_change(oplog, RichOp::new_by_change(change, op), &vv.borrow()); if visited.contains(&op.container) {
// don't checkout if we have already checked out this container in this round
calculator.apply_change(oplog, RichOp::new_by_change(change, op), None);
} else {
calculator.apply_change(
oplog,
RichOp::new_by_change(change, op),
Some(&vv.borrow()),
);
visited.insert(op.container);
}
} }
} }
@ -103,7 +114,12 @@ impl DiffCalculator {
#[enum_dispatch] #[enum_dispatch]
pub trait DiffCalculatorTrait { pub trait DiffCalculatorTrait {
fn start_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector); fn start_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector);
fn apply_change(&mut self, oplog: &OpLog, op: crate::op::RichOp, vv: &crate::VersionVector); fn apply_change(
&mut self,
oplog: &OpLog,
op: crate::op::RichOp,
vv: Option<&crate::VersionVector>,
);
fn stop_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector); fn stop_tracking(&mut self, oplog: &OpLog, vv: &crate::VersionVector);
fn calculate_diff( fn calculate_diff(
&mut self, &mut self,
@ -176,7 +192,7 @@ impl DiffCalculatorTrait for MapDiffCalculator {
&mut self, &mut self,
oplog: &super::oplog::OpLog, oplog: &super::oplog::OpLog,
op: crate::op::RichOp, op: crate::op::RichOp,
_vv: &crate::VersionVector, _vv: Option<&crate::VersionVector>,
) { ) {
let map = op.op().content.as_map().unwrap(); let map = op.op().content.as_map().unwrap();
let value = oplog.arena.get_value(map.value as usize); let value = oplog.arena.get_value(map.value as usize);
@ -252,8 +268,15 @@ impl DiffCalculatorTrait for ListDiffCalculator {
self.tracker.checkout(vv); self.tracker.checkout(vv);
} }
fn apply_change(&mut self, _oplog: &OpLog, op: crate::op::RichOp, vv: &crate::VersionVector) { fn apply_change(
self.tracker.checkout(vv); &mut self,
_oplog: &OpLog,
op: crate::op::RichOp,
vv: Option<&crate::VersionVector>,
) {
if let Some(vv) = vv {
self.tracker.checkout(vv);
}
self.tracker.track_apply(&op); self.tracker.track_apply(&op);
} }
@ -293,9 +316,13 @@ impl DiffCalculatorTrait for TextDiffCalculator {
&mut self, &mut self,
_oplog: &super::oplog::OpLog, _oplog: &super::oplog::OpLog,
op: crate::op::RichOp, op: crate::op::RichOp,
vv: &crate::VersionVector, vv: Option<&crate::VersionVector>,
) { ) {
self.tracker.checkout(vv); if let Some(vv) = vv {
self.tracker.checkout(vv);
}
debug_dbg!(&op, self.tracker.len());
self.tracker.track_apply(&op); self.tracker.track_apply(&op);
} }

View file

@ -157,8 +157,6 @@ impl LoroApp {
} else { } else {
let app = LoroApp::new(); let app = LoroApp::new();
decode_app_snapshot(&app, &input[1..])?; decode_app_snapshot(&app, &input[1..])?;
dbg!(&app.oplog.lock().unwrap());
dbg!(&app.state.lock().unwrap().states);
let oplog = self.oplog.lock().unwrap(); let oplog = self.oplog.lock().unwrap();
let updates = app.export_from(oplog.vv()); let updates = app.export_from(oplog.vv());
drop(oplog); drop(oplog);

View file

@ -448,7 +448,7 @@ impl OpLog {
} }
inner_vv.extend_to_include_end_id(change.id); inner_vv.extend_to_include_end_id(change.id);
// debug_log::debug_dbg!(&change, &inner_vv); debug_log::debug_dbg!(&change, &inner_vv);
Some((change, vv.clone())) Some((change, vv.clone()))
} else { } else {
debug_log::group_end!(); debug_log::group_end!();