aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-31 19:03:15 +0100
committertv <tv@krebsco.de>2026-10-31 19:03:15 +0100
commite4f801db5d150fb1bf5540d9ba00f491a6129a5c (patch)
tree38a8b5ffd8233df7d24f9bb5effac58cbd92187e /src/remake
parent4a6403d0242cf730a3f864c8d26e0ba15a98fcf0 (diff)
tests write through document::testing helpers
Diffstat (limited to 'src/remake')
-rw-r--r--src/remake/catchup.rs12
-rw-r--r--src/remake/delta.rs117
-rw-r--r--src/remake/kind.rs34
-rw-r--r--src/remake/records.rs91
-rw-r--r--src/remake/snapshot.rs166
5 files changed, 210 insertions, 210 deletions
diff --git a/src/remake/catchup.rs b/src/remake/catchup.rs
index 0be7dfd..e265d0b 100644
--- a/src/remake/catchup.rs
+++ b/src/remake/catchup.rs
@@ -555,6 +555,7 @@ async fn abandon<H: Host>(host: &H, rejoin: Rejoin, reason: String) {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::document::testing::change;
use crate::remake::snapshot::{SnapshotParams, build};
use automerge::{ActorId, ROOT, transaction::Transactable};
use serde_json::{Value as JsonValue, json};
@@ -563,8 +564,7 @@ mod tests {
/// document of the next epoch (snapshot plus one foreign change).
fn scenario(policy: &JsonValue) -> (AutoCommit, AutoCommit, Epoch) {
let mut old = AutoCommit::new().with_actor(ActorId::from(&b"late-node"[..]));
- old.put(ROOT, "base", 1_i64).unwrap();
- old.commit();
+ change(&mut old, |old| old.put(ROOT, "base", 1_i64).unwrap());
let base = old.get_heads();
let snapshot = build(
@@ -584,11 +584,11 @@ mod tests {
let target = snapshot.epoch;
let mut swarm = snapshot.doc.with_actor(ActorId::from(&b"swarm-node"[..]));
- swarm.put(ROOT, "theirs", 1_i64).unwrap();
- swarm.commit();
+ change(&mut swarm, |swarm| {
+ swarm.put(ROOT, "theirs", 1_i64).unwrap()
+ });
- old.put(ROOT, "mine", 1_i64).unwrap();
- old.commit();
+ change(&mut old, |old| old.put(ROOT, "mine", 1_i64).unwrap());
(old, swarm, target)
}
diff --git a/src/remake/delta.rs b/src/remake/delta.rs
index aebd048..21c07b7 100644
--- a/src/remake/delta.rs
+++ b/src/remake/delta.rs
@@ -251,6 +251,7 @@ pub(crate) fn changed_paths(
#[cfg(test)]
mod tests {
use super::*;
+ use crate::document::testing::{change, try_change};
use automerge::{ObjType, ROOT, ReadDoc, ScalarValue, transaction::Transactable};
use serde_json::json;
@@ -265,8 +266,8 @@ mod tests {
const KEYS: [&str; 3] = ["a", "b", "c"];
let depth = rng.between(1, 3);
let path: Vec<String> = (0..depth).map(|_| rng.pick(&KEYS).to_string()).collect();
- let result = if rng.chance(0.2) {
- store::delete_path(doc, &path, false)
+ let _ = if rng.chance(0.2) {
+ try_change(doc, |doc| store::delete_path(doc, &path, false))
} else {
let value = match rng.below(4) {
0 => json!(rng.below(100)),
@@ -278,16 +279,8 @@ mod tests {
serde_json::Value::Object(map)
}
};
- store::write_path(doc, &path, &value)
+ try_change(doc, |doc| store::write_path(doc, &path, &value))
};
- match result {
- Ok(()) => {
- doc.commit_with(automerge::transaction::CommitOptions::default().with_time(0));
- }
- Err(_) => {
- doc.rollback();
- }
- }
}
/// Compaction's promise: a snapshot of the base plus everything replayed since gives
@@ -302,8 +295,9 @@ mod tests {
}
let base = old.get_heads();
let mut new = AutoCommit::new().with_actor(actor(100));
- store::materialize_into(&old, &mut new, &|_| false).unwrap();
- new.commit();
+ change(&mut new, |new| {
+ store::materialize_into(&old, new, &|_| false).unwrap()
+ });
let mut nodes: Vec<AutoCommit> = (1..=rng.between(1, 3))
.map(|i| old.fork().with_actor(actor(i as u8)))
@@ -395,19 +389,21 @@ mod tests {
#[test]
fn minimal_paths() {
let mut doc = AutoCommit::new();
- doc.put(ROOT, "untouched", 1_i64).unwrap();
+ change(&mut doc, |doc| doc.put(ROOT, "untouched", 1_i64).unwrap());
let before = doc.get_heads();
- let m = doc.put_object(ROOT, "m", ObjType::Map).unwrap();
- doc.put(&m, "a", 1_i64).unwrap();
- doc.put(ROOT, "x", 1_i64).unwrap();
- doc.put(ROOT, "c", ScalarValue::counter(0)).unwrap();
- doc.commit();
+ change(&mut doc, |doc| {
+ let m = doc.put_object(ROOT, "m", ObjType::Map).unwrap();
+ doc.put(&m, "a", 1_i64).unwrap();
+ doc.put(ROOT, "x", 1_i64).unwrap();
+ doc.put(ROOT, "c", ScalarValue::counter(0)).unwrap();
+ });
let middle = doc.get_heads();
- doc.increment(ROOT, "c", 2).unwrap();
- let list = doc.put_object(ROOT, "l", ObjType::List).unwrap();
- doc.insert(&list, 0, "e").unwrap();
- doc.commit();
+ change(&mut doc, |doc| {
+ doc.increment(ROOT, "c", 2).unwrap();
+ let list = doc.put_object(ROOT, "l", ObjType::List).unwrap();
+ doc.insert(&list, 0, "e").unwrap();
+ });
let after = doc.get_heads();
let all = changed_paths(&mut doc, &before, &after);
@@ -429,26 +425,30 @@ mod tests {
fn replays_state_per_key() {
// Base shared by the old document and the snapshot.
let mut old = AutoCommit::new();
- let m = old.put_object(ROOT, "m", ObjType::Map).unwrap();
- old.put(&m, "keep", "base").unwrap();
- old.put(&m, "change", "base").unwrap();
- old.put(ROOT, "gone", true).unwrap();
- old.commit();
+ let m = change(&mut old, |old| {
+ let m = old.put_object(ROOT, "m", ObjType::Map).unwrap();
+ old.put(&m, "keep", "base").unwrap();
+ old.put(&m, "change", "base").unwrap();
+ old.put(ROOT, "gone", true).unwrap();
+ m
+ });
let base = old.get_heads();
let mut new = AutoCommit::new();
- store::materialize_into(&old, &mut new, &|_| false).unwrap();
- // Something the new epoch already holds that the delta must not clobber.
- let Some((_, m_new)) = new.get(ROOT, "m").unwrap() else {
- panic!("m missing");
- };
- new.put(&m_new, "keep", "new epoch").unwrap();
- new.commit();
+ change(&mut new, |new| {
+ store::materialize_into(&old, new, &|_| false).unwrap();
+ // Something the new epoch already holds that the delta must not clobber.
+ let Some((_, m_new)) = new.get(ROOT, "m").unwrap() else {
+ panic!("m missing");
+ };
+ new.put(&m_new, "keep", "new epoch").unwrap();
+ });
// The delta: one key changed, one key deleted.
- old.put(&m, "change", "delta").unwrap();
- old.delete(ROOT, "gone").unwrap();
- old.commit();
+ change(&mut old, |old| {
+ old.put(&m, "change", "delta").unwrap();
+ old.delete(ROOT, "gone").unwrap();
+ });
let after = old.get_heads();
let stats = replay(&mut old, &base, &after, &mut new, &Translator::default());
@@ -465,8 +465,7 @@ mod tests {
let other = ActorId::from(&b"other-actor"[..]);
let mut doc = AutoCommit::new().with_actor(own.clone());
- doc.put(ROOT, "base", 1_i64).unwrap();
- doc.commit();
+ change(&mut doc, |doc| doc.put(ROOT, "base", 1_i64).unwrap());
let base = doc.get_heads();
// The snapshot contains the base only.
@@ -474,14 +473,14 @@ mod tests {
// A foreign change after the base (replayed by its own node) ...
let mut foreign = doc.fork().with_actor(other);
- foreign.put(ROOT, "theirs", 1_i64).unwrap();
- foreign.commit();
+ change(&mut foreign, |foreign| {
+ foreign.put(ROOT, "theirs", 1_i64).unwrap()
+ });
doc.merge(&mut foreign).unwrap();
let with_foreign = doc.get_heads();
// ... and one of ours.
- doc.put(ROOT, "mine", 1_i64).unwrap();
- doc.commit();
+ change(&mut doc, |doc| doc.put(ROOT, "mine", 1_i64).unwrap());
let after = doc.get_heads();
let missing = missing_from_snapshot(&mut doc, &clock, std::slice::from_ref(&own));
@@ -505,28 +504,24 @@ mod tests {
#[test]
fn protocol_metadata_is_never_replayed() {
let mut old = AutoCommit::new();
- old.put(ROOT, "x", 1_i64).unwrap();
- old.commit();
+ change(&mut old, |old| old.put(ROOT, "x", 1_i64).unwrap());
let base = old.get_heads();
let mut new = AutoCommit::new();
- store::write_path(
- &mut new,
- &meta::path(&[EPOCHS, "1"]),
- &json!({ "generation": 1 }),
- )
- .unwrap();
- new.commit();
+ change(&mut new, |new| {
+ store::write_path(
+ new,
+ &meta::path(&[EPOCHS, "1"]),
+ &json!({ "generation": 1 }),
+ )
+ .unwrap()
+ });
// The old epoch replaces `_continuum` wholesale and writes a remake record.
- store::write_path(
- &mut old,
- &meta::path(&[]),
- &json!({ "forgotten": { "pk": 1 } }),
- )
- .unwrap();
- store::write_path(&mut old, &meta::path(&[REMAKES, "c"]), &json!({ "x": 1 })).unwrap();
- old.commit();
+ change(&mut old, |old| {
+ store::write_path(old, &meta::path(&[]), &json!({ "forgotten": { "pk": 1 } })).unwrap();
+ store::write_path(old, &meta::path(&[REMAKES, "c"]), &json!({ "x": 1 })).unwrap();
+ });
let after = old.get_heads();
replay(&mut old, &base, &after, &mut new, &Translator::default());
diff --git a/src/remake/kind.rs b/src/remake/kind.rs
index ca16de0..1df03cb 100644
--- a/src/remake/kind.rs
+++ b/src/remake/kind.rs
@@ -591,17 +591,20 @@ mod tests {
#[test]
fn import_keeps_types_and_drops_protocol_data() {
+ use crate::document::testing::{change, try_change};
use automerge::{ObjType, ROOT, ReadDoc, transaction::Transactable};
use serde_json::json;
let mut source = AutoCommit::new();
- let text = source.put_object(ROOT, "notes", ObjType::Text).unwrap();
- source.splice_text(&text, 0, 0, "hello").unwrap();
- source
- .put(ROOT, "hits", automerge::ScalarValue::counter(3))
- .unwrap();
- let meta = source.put_object(ROOT, meta::ROOT, ObjType::Map).unwrap();
- source.put(&meta, "members", "elsewhere").unwrap();
+ change(&mut source, |source| {
+ let text = source.put_object(ROOT, "notes", ObjType::Text).unwrap();
+ source.splice_text(&text, 0, 0, "hello").unwrap();
+ source
+ .put(ROOT, "hits", automerge::ScalarValue::counter(3))
+ .unwrap();
+ let meta = source.put_object(ROOT, meta::ROOT, ObjType::Map).unwrap();
+ source.put(&meta, "members", "elsewhere").unwrap();
+ });
let encoded = BASE64.encode(source.save());
assert!(
@@ -620,10 +623,10 @@ mod tests {
.unwrap();
let build = || {
let mut target = AutoCommit::new().with_actor(automerge::ActorId::from(&b"fixed"[..]));
- Import
- .build(&AutoCommit::new(), prepared.content.as_deref(), &mut target)
- .unwrap();
- target.commit_with(automerge::transaction::CommitOptions::default().with_time(0));
+ try_change(&mut target, |target| {
+ Import.build(&AutoCommit::new(), prepared.content.as_deref(), target)
+ })
+ .unwrap();
target
};
let mut a = build();
@@ -648,14 +651,15 @@ mod tests {
#[test]
fn replace_builds_the_document_deterministically() {
+ use crate::document::testing::try_change;
use serde_json::json;
let build = |document: serde_json::Value| {
let prepared = replace(json!({ "document": document })).unwrap();
let mut target = AutoCommit::new().with_actor(automerge::ActorId::from(&b"fixed"[..]));
- Replace
- .build(&AutoCommit::new(), prepared.content.as_deref(), &mut target)
- .unwrap();
- target.commit_with(automerge::transaction::CommitOptions::default().with_time(0));
+ try_change(&mut target, |target| {
+ Replace.build(&AutoCommit::new(), prepared.content.as_deref(), target)
+ })
+ .unwrap();
(
target.get_heads(),
store::read_path(&target, &[]).unwrap().unwrap(),
diff --git a/src/remake/records.rs b/src/remake/records.rs
index f22b1e5..40b563a 100644
--- a/src/remake/records.rs
+++ b/src/remake/records.rs
@@ -499,6 +499,7 @@ pub(crate) fn decode_hex32(hex: &str) -> Option<[u8; 32]> {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::document::testing::change;
#[test]
fn retention_covers_until_every_limit_passed() {
@@ -570,16 +571,6 @@ mod tests {
fn round_trip_through_the_document() {
let mut doc = Document::new();
let p = proposal(10_000);
- write_proposal(&mut doc, "c-1", &p).unwrap();
- write_abort_request(
- &mut doc,
- "c-1",
- &AbortRequest {
- by: "x".into(),
- at: UnixMillis(5),
- },
- )
- .unwrap();
let decision = Decision::Committed {
to_epoch: EpochRecord {
generation: 1,
@@ -589,14 +580,25 @@ mod tests {
snapshot_bytes: 123,
decided_at: UnixMillis(11_000),
};
- write_decision(&mut doc, "c-1", &decision).unwrap();
let vote = |remake: &str| Vote {
remake: remake.into(),
at: UnixMillis(7),
};
- write_vote(&mut doc, "node-b", &vote("c-1")).unwrap();
- write_vote(&mut doc, "node-c", &vote("other")).unwrap();
- doc.commit();
+ change(&mut doc, |doc| {
+ write_proposal(doc, "c-1", &p).unwrap();
+ write_abort_request(
+ doc,
+ "c-1",
+ &AbortRequest {
+ by: "x".into(),
+ at: UnixMillis(5),
+ },
+ )
+ .unwrap();
+ write_decision(doc, "c-1", &decision).unwrap();
+ write_vote(doc, "node-b", &vote("c-1")).unwrap();
+ write_vote(doc, "node-c", &vote("other")).unwrap();
+ });
let all = load_all(&doc);
assert_eq!(all.len(), 1);
@@ -617,14 +619,11 @@ mod tests {
remake: remake.into(),
at: UnixMillis(at),
};
- write_vote(&mut a, "node-a", &vote("x", 1)).unwrap();
- a.commit();
+ change(&mut a, |a| write_vote(a, "node-a", &vote("x", 1)).unwrap());
let mut b = a.fork();
// node-b votes in both, never seeing its other vote (a lost vote).
- write_vote(&mut a, "node-b", &vote("x", 2)).unwrap();
- write_vote(&mut b, "node-b", &vote("y", 3)).unwrap();
- a.commit();
- b.commit();
+ change(&mut a, |a| write_vote(a, "node-b", &vote("x", 2)).unwrap());
+ change(&mut b, |b| write_vote(b, "node-b", &vote("y", 3)).unwrap());
a.merge(&mut b).unwrap();
let register = load_register(&a);
@@ -634,8 +633,7 @@ mod tests {
assert_eq!(twice, [vote("x", 2), vote("y", 3)]);
// Seen, a vote is replaced.
- write_vote(&mut a, "node-b", &vote("z", 4)).unwrap();
- a.commit();
+ change(&mut a, |a| write_vote(a, "node-b", &vote("z", 4)).unwrap());
assert_eq!(load_register(&a)["node-b"], [vote("z", 4)]);
}
@@ -686,8 +684,9 @@ mod tests {
#[test]
fn disagreeing_decisions_are_contested() {
let mut base = Document::new();
- write_proposal(&mut base, "c-1", &proposal(10_000)).unwrap();
- base.commit();
+ change(&mut base, |base| {
+ write_proposal(base, "c-1", &proposal(10_000)).unwrap()
+ });
let (mut a, mut b, mut c) = (base.fork(), base.fork(), base.fork());
let committed = Decision::Committed {
to_epoch: EpochRecord {
@@ -698,21 +697,20 @@ mod tests {
snapshot_bytes: 1,
decided_at: UnixMillis(2),
};
- write_decision(&mut a, "c-1", &committed).unwrap();
- write_decision(
- &mut b,
- "c-1",
- &Decision::Aborted {
- reason: "test".into(),
- decided_at: UnixMillis(3),
- },
- )
- .unwrap();
+ change(&mut a, |a| write_decision(a, "c-1", &committed).unwrap());
+ change(&mut b, |b| {
+ write_decision(
+ b,
+ "c-1",
+ &Decision::Aborted {
+ reason: "test".into(),
+ decided_at: UnixMillis(3),
+ },
+ )
+ .unwrap()
+ });
// The same decision, concurrently: they agree.
- write_decision(&mut c, "c-1", &committed).unwrap();
- a.commit();
- b.commit();
- c.commit();
+ change(&mut c, |c| write_decision(c, "c-1", &committed).unwrap());
let mut agreeing = a.fork();
agreeing.merge(&mut c).unwrap();
assert!(!load(&agreeing, "c-1").unwrap().contested);
@@ -726,14 +724,15 @@ mod tests {
#[test]
fn unreadable_records_are_skipped() {
let mut doc = Document::new();
- store::write_path(
- &mut doc,
- &record_path("broken", ""),
- &serde_json::json!({ "proposal": "not an object" }),
- )
- .unwrap();
- write_proposal(&mut doc, "fine", &proposal(1)).unwrap();
- doc.commit();
+ change(&mut doc, |doc| {
+ store::write_path(
+ doc,
+ &record_path("broken", ""),
+ &serde_json::json!({ "proposal": "not an object" }),
+ )
+ .unwrap();
+ write_proposal(doc, "fine", &proposal(1)).unwrap();
+ });
let all = load_all(&doc);
assert_eq!(all.len(), 1);
assert_eq!(all[0].0, "fine");
diff --git a/src/remake/snapshot.rs b/src/remake/snapshot.rs
index b071b74..c818af6 100644
--- a/src/remake/snapshot.rs
+++ b/src/remake/snapshot.rs
@@ -376,6 +376,7 @@ pub(super) fn canonical(value: JsonValue) -> JsonValue {
#[cfg(test)]
mod tests {
use super::*;
+ use crate::document::testing::change;
use automerge::{ObjType, ROOT, ReadDoc, ScalarValue, Value, transaction::Transactable};
fn doc(actor: &[u8]) -> AutoCommit {
@@ -414,28 +415,31 @@ mod tests {
fn same_view_different_history_same_snapshot() {
// One history: overwrites, increments, one-shot text.
let mut a = doc(b"actor-a");
- a.put(ROOT, "x", 1_i64).unwrap();
- a.commit();
- a.put(ROOT, "x", 2_i64).unwrap();
- a.put(ROOT, "c", ScalarValue::counter(0)).unwrap();
- a.increment(ROOT, "c", 5).unwrap();
- let text = a.put_object(ROOT, "t", ObjType::Text).unwrap();
- a.splice_text(&text, 0, 0, "hello").unwrap();
- let m = a.put_object(ROOT, "m", ObjType::Map).unwrap();
- a.put(&m, "k", "v").unwrap();
- a.commit();
+ change(&mut a, |a| a.put(ROOT, "x", 1_i64).unwrap());
+ change(&mut a, |a| {
+ a.put(ROOT, "x", 2_i64).unwrap();
+ a.put(ROOT, "c", ScalarValue::counter(0)).unwrap();
+ a.increment(ROOT, "c", 5).unwrap();
+ let text = a.put_object(ROOT, "t", ObjType::Text).unwrap();
+ a.splice_text(&text, 0, 0, "hello").unwrap();
+ let m = a.put_object(ROOT, "m", ObjType::Map).unwrap();
+ a.put(&m, "k", "v").unwrap();
+ });
// Another actor, other order, other steps, same result.
let mut b = doc(b"actor-b");
- let m = b.put_object(ROOT, "m", ObjType::Map).unwrap();
- b.put(&m, "k", "v").unwrap();
- let text = b.put_object(ROOT, "t", ObjType::Text).unwrap();
- b.splice_text(&text, 0, 0, "hel").unwrap();
- b.commit();
- b.splice_text(&text, 3, 0, "lo").unwrap();
- b.put(ROOT, "c", ScalarValue::counter(5)).unwrap();
- b.put(ROOT, "x", 2_i64).unwrap();
- b.commit();
+ let text = change(&mut b, |b| {
+ let m = b.put_object(ROOT, "m", ObjType::Map).unwrap();
+ b.put(&m, "k", "v").unwrap();
+ let text = b.put_object(ROOT, "t", ObjType::Text).unwrap();
+ b.splice_text(&text, 0, 0, "hel").unwrap();
+ text
+ });
+ change(&mut b, |b| {
+ b.splice_text(&text, 3, 0, "lo").unwrap();
+ b.put(ROOT, "c", ScalarValue::counter(5)).unwrap();
+ b.put(ROOT, "x", 2_i64).unwrap();
+ });
assert_eq!(user_view(&a), user_view(&b));
@@ -452,12 +456,13 @@ mod tests {
#[test]
fn rebuild_is_deterministic() {
let mut a = doc(b"actor-a");
- a.put(ROOT, "x", 1_i64).unwrap();
- let list = a.put_object(ROOT, "l", ObjType::List).unwrap();
- a.insert(&list, 0, "first").unwrap();
- let inner = a.insert_object(&list, 1, ObjType::Map).unwrap();
- a.put(&inner, "k", true).unwrap();
- a.commit();
+ change(&mut a, |a| {
+ a.put(ROOT, "x", 1_i64).unwrap();
+ let list = a.put_object(ROOT, "l", ObjType::List).unwrap();
+ a.insert(&list, 0, "first").unwrap();
+ let inner = a.insert_object(&list, 1, ObjType::Map).unwrap();
+ a.put(&inner, "k", true).unwrap();
+ });
// A second node holding the same changes, received in a different way.
let mut b = doc(b"actor-b");
@@ -475,14 +480,16 @@ mod tests {
#[test]
fn conflicts_collapse_into_the_merged_view() {
let mut a = doc(b"actor-a");
- let cfg = a.put_object(ROOT, "cfg", ObjType::Map).unwrap();
- a.put(&cfg, "x", 1_i64).unwrap();
- a.commit();
+ change(&mut a, |a| {
+ let cfg = a.put_object(ROOT, "cfg", ObjType::Map).unwrap();
+ a.put(&cfg, "x", 1_i64).unwrap();
+ });
let mut b = doc(b"actor-b");
- let cfg = b.put_object(ROOT, "cfg", ObjType::Map).unwrap();
- b.put(&cfg, "y", 2_i64).unwrap();
- b.commit();
+ change(&mut b, |b| {
+ let cfg = b.put_object(ROOT, "cfg", ObjType::Map).unwrap();
+ b.put(&cfg, "y", 2_i64).unwrap();
+ });
a.merge(&mut b).unwrap();
let (_, conflicts) = store::read_path_with_conflicts(&a, &[]).unwrap().unwrap();
@@ -507,22 +514,19 @@ mod tests {
fn base_heads_bound_content_and_clock() {
let mut a = doc(b"actor-a");
for i in 0..3_i64 {
- a.put(ROOT, format!("a{i}"), i).unwrap();
- a.commit();
+ change(&mut a, |a| a.put(ROOT, format!("a{i}"), i).unwrap());
}
let mut b = doc(b"actor-b");
for i in 0..2_i64 {
- b.put(ROOT, format!("b{i}"), i).unwrap();
- b.commit();
+ change(&mut b, |b| b.put(ROOT, format!("b{i}"), i).unwrap());
}
a.merge(&mut b).unwrap();
let base = a.get_heads();
// After the base: must not appear in the snapshot or its clock.
- a.put(ROOT, "late", true).unwrap();
- a.commit();
+ change(&mut a, |a| a.put(ROOT, "late", true).unwrap());
let policy = json!({});
let snap = build(&mut a, &params(&base, &policy)).unwrap();
@@ -541,8 +545,9 @@ mod tests {
#[test]
fn epoch_of_a_backup() {
let mut a = doc(b"actor-a");
- store::write_path(&mut a, &["k".into()], &json!(1)).unwrap();
- a.commit();
+ change(&mut a, |a| {
+ store::write_path(a, &["k".into()], &json!(1)).unwrap()
+ });
assert_eq!(epoch_of(&mut a), Ok(Epoch::GENESIS));
let heads = a.get_heads();
@@ -553,8 +558,9 @@ mod tests {
.doc
.fork()
.with_actor(ActorId::from(b"actor-b".as_slice()));
- store::write_path(&mut later, &["k".into()], &json!(2)).unwrap();
- later.commit();
+ change(&mut later, |later| {
+ store::write_path(later, &["k".into()], &json!(2)).unwrap()
+ });
let mut backup = AutoCommit::load(&later.save()).unwrap();
assert_eq!(epoch_of(&mut backup), Ok(snap.epoch));
}
@@ -562,25 +568,26 @@ mod tests {
#[test]
fn metadata_written_and_remake_records_dropped() {
let mut a = doc(b"actor-a");
- store::write_path(
- &mut a,
- &meta::path(&[REMAKES, "c-1"]),
- &json!({ "state": "committed" }),
- )
- .unwrap();
- store::write_path(
- &mut a,
- &meta::path(&[VOTES, "pk"]),
- &json!({ "remake": "c-1", "at": 1 }),
- )
- .unwrap();
- store::write_path(
- &mut a,
- &meta::path(&[meta::FORGOTTEN, "pk"]),
- &json!({ "at": 1 }),
- )
- .unwrap();
- a.commit();
+ change(&mut a, |a| {
+ store::write_path(
+ a,
+ &meta::path(&[REMAKES, "c-1"]),
+ &json!({ "state": "committed" }),
+ )
+ .unwrap();
+ store::write_path(
+ a,
+ &meta::path(&[VOTES, "pk"]),
+ &json!({ "remake": "c-1", "at": 1 }),
+ )
+ .unwrap();
+ store::write_path(
+ a,
+ &meta::path(&[meta::FORGOTTEN, "pk"]),
+ &json!({ "at": 1 }),
+ )
+ .unwrap();
+ });
let heads = a.get_heads();
let policy = json!({ "replayWindow": { "epochs": 1 } });
@@ -605,16 +612,17 @@ mod tests {
#[test]
fn automerge_types_survive() {
let mut a = doc(b"actor-a");
- a.put(ROOT, "c", ScalarValue::counter(3)).unwrap();
- a.increment(ROOT, "c", 4).unwrap();
- let text = a.put_object(ROOT, "t", ObjType::Text).unwrap();
- a.splice_text(&text, 0, 0, "abc").unwrap();
- a.put(ROOT, "bytes", ScalarValue::Bytes(vec![0, 1, 255]))
- .unwrap();
- a.put(ROOT, "ts", ScalarValue::Timestamp(1_700_000_000_000))
- .unwrap();
- a.put(ROOT, "neg_zero", -0.0_f64).unwrap();
- a.commit();
+ change(&mut a, |a| {
+ a.put(ROOT, "c", ScalarValue::counter(3)).unwrap();
+ a.increment(ROOT, "c", 4).unwrap();
+ let text = a.put_object(ROOT, "t", ObjType::Text).unwrap();
+ a.splice_text(&text, 0, 0, "abc").unwrap();
+ a.put(ROOT, "bytes", ScalarValue::Bytes(vec![0, 1, 255]))
+ .unwrap();
+ a.put(ROOT, "ts", ScalarValue::Timestamp(1_700_000_000_000))
+ .unwrap();
+ a.put(ROOT, "neg_zero", -0.0_f64).unwrap();
+ });
let snap = snapshot_of(&mut a);
let d = &snap.doc;
@@ -655,8 +663,7 @@ mod tests {
#[test]
fn snapshot_is_a_single_change_with_the_epoch_id() {
let mut a = doc(b"actor-a");
- a.put(ROOT, "x", 1_i64).unwrap();
- a.commit();
+ change(&mut a, |a| a.put(ROOT, "x", 1_i64).unwrap());
let mut snap = snapshot_of(&mut a);
let heads = snap.doc.get_heads();
@@ -668,12 +675,10 @@ mod tests {
#[test]
fn missing_base_is_rejected() {
let mut a = doc(b"actor-a");
- a.put(ROOT, "x", 1_i64).unwrap();
- a.commit();
+ change(&mut a, |a| a.put(ROOT, "x", 1_i64).unwrap());
let mut other = doc(b"actor-b");
- other.put(ROOT, "y", 1_i64).unwrap();
- other.commit();
+ change(&mut other, |other| other.put(ROOT, "y", 1_i64).unwrap());
let foreign = other.get_heads();
let policy = json!({});
@@ -698,8 +703,7 @@ mod tests {
// Old epoch: the base, then a late write by this node.
let mut late = doc(b"late-node");
- late.put(ROOT, "shared", "base").unwrap();
- late.commit();
+ change(&mut late, |late| late.put(ROOT, "shared", "base").unwrap());
let base = late.get_heads();
let policy = json!({});
let mut snap = build(&mut late, &params(&base, &policy)).unwrap();
@@ -709,12 +713,10 @@ mod tests {
.doc
.fork()
.with_actor(ActorId::from(&b"swarm-node"[..]));
- swarm.put(ROOT, "new", 1_i64).unwrap();
- swarm.commit();
+ change(&mut swarm, |swarm| swarm.put(ROOT, "new", 1_i64).unwrap());
let bytes = swarm.save();
- late.put(ROOT, "mine", "late").unwrap();
- late.commit();
+ change(&mut late, |late| late.put(ROOT, "mine", "late").unwrap());
let mut fetched = AutoCommit::load(&bytes).unwrap();
let metadata = verify_document(&mut fetched, snap.epoch).unwrap();