aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake/snapshot.rs
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
commitc83604d8f82b6c67a64e3cee6f5c012ee4a10fc1 (patch)
tree556b834c79561e2090b06cf2477117083e05afc5 /src/remake/snapshot.rs
parent2cba03fa6af4aeca176d69514603bce26b9c934a (diff)
tests write through document::testing helpers
Diffstat (limited to 'src/remake/snapshot.rs')
-rw-r--r--src/remake/snapshot.rs166
1 files changed, 84 insertions, 82 deletions
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();