Files
boxmaker/crates/memoryd/tests/honcho_ledger_began.rs
T

153 lines
4.9 KiB
Rust

//! When sync began (M5c spec, section 5): the ledger's first line, `began`, once; a ledger read
//! back that does not start with it, or has a second, is damaged; and conclusions matched by their
//! peer as well as their workspace and text. Do not edit.
#[path = "support/ledger.rs"]
mod ledger;
#[path = "support/tmp.rs"]
mod tmp;
use ledger::{
Home, TIME, began, began_line, conclude, decided, edit, line, sent, time, to_trusted, turn,
};
use memoryd::honcho::ledger::{Action, Ledger, LedgerError, Workspace};
const POINTER: &str = "; see docs/runbook.md#honcho-ledger-damaged";
#[test]
fn the_began_line() {
assert_eq!(
serde_json::to_string(&began()).unwrap(),
format!(r#"{{"type":"began","time":"{TIME}"}}"#)
);
assert_eq!(
began_line(),
format!("{{\"type\":\"began\",\"time\":\"{TIME}\"}}\n")
);
}
#[test]
fn began_is_kept_and_read_back() {
let home = Home::new("began-kept");
let fresh = home.open();
assert_eq!(fresh.began(), None);
let mut ledger = home.begun();
assert_eq!(ledger.began(), Some(time()));
ledger
.append(decided(&turn("chat-1", 1), to_trusted("kyle")))
.unwrap();
assert_eq!(home.text().lines().next(), Some(began_line().trim_end()));
let again = home.open();
assert_eq!(again.began(), Some(time()));
assert_eq!(again.counts().decided, 1, "began is no item");
}
#[test]
fn began_only_first_and_once() {
let home = Home::new("began-once");
let mut ledger = home.begun();
let err = ledger.append(began()).unwrap_err();
assert!(matches!(err, LedgerError::BeganNotFirst), "{err:?}");
assert_eq!(err.to_string(), "sync began, but not on the first line");
let home = Home::new("began-late");
let mut ledger = home.open();
ledger
.append(decided(&turn("chat-1", 1), to_trusted("kyle")))
.unwrap();
assert!(matches!(
ledger.append(began()),
Err(LedgerError::BeganNotFirst)
));
}
/// `open`'s error for `text`: its line and its display.
fn damaged(tag: &str, text: &str) -> (usize, String, Home) {
let home = Home::new(tag);
home.write(text);
let err = Ledger::open(&home.path).unwrap_err();
let shown = err.to_string();
match err {
LedgerError::Damaged { line, .. } => (line, shown, home),
other => panic!("not Damaged: {other:?}"),
}
}
#[test]
fn a_ledger_that_does_not_start_with_began_is_damaged() {
let first = line(&decided(&turn("chat-1", 1), to_trusted("kyle")));
let (number, shown, home) = damaged("began-missing", &first);
assert_eq!(number, 1);
assert_eq!(
shown,
format!(
"{}:1: the first line is not when sync began{POINTER}",
home.path.display()
)
);
let twice = format!("{}{first}{}", began_line(), began_line());
let (number, shown, home) = damaged("began-twice", &twice);
assert_eq!(number, 3);
assert_eq!(
shown,
format!(
"{}:3: sync began, but not on the first line{POINTER}",
home.path.display()
)
);
// An empty ledger has no line to be wrong: it is empty.
let home = Home::new("began-empty");
home.write("");
assert_eq!(home.open().began(), None);
}
fn unconclude_about(peer: &str, text: &str) -> Action {
Action::Unconclude {
workspace: Workspace::Trusted,
peer: peer.to_string(),
text: text.to_string(),
}
}
#[test]
fn a_conclusion_is_found_by_its_peer_too() {
let home = Home::new("began-peer");
let mut ledger = home.begun();
let (owner, agent, undo) = (edit("e1", 0), edit("e2", 0), edit("e3", 0));
ledger
.append(decided(&owner, conclude(Workspace::Trusted, "Uses tabs.")))
.unwrap();
let mut about_agent = conclude(Workspace::Trusted, "Uses tabs.");
if let Action::Conclude { peer, .. } = &mut about_agent {
*peer = "boxmaker0".to_string();
}
ledger.append(decided(&agent, about_agent)).unwrap();
ledger.append(sent(&owner, &["c-owner"])).unwrap();
ledger.append(sent(&agent, &["c-agent"])).unwrap();
assert_eq!(
ledger.conclusion(Workspace::Trusted, "kyle", "Uses tabs."),
Some((owner.clone(), "c-owner".to_string()))
);
assert_eq!(
ledger.conclusion(Workspace::Trusted, "boxmaker0", "Uses tabs."),
Some((agent.clone(), "c-agent".to_string()))
);
// The owner's is undone: the agent's stays.
ledger
.append(decided(&undo, unconclude_about("kyle", "Uses tabs.")))
.unwrap();
ledger.append(sent(&undo, &["c-owner"])).unwrap();
assert_eq!(
ledger.conclusion(Workspace::Trusted, "kyle", "Uses tabs."),
None
);
assert_eq!(
ledger.conclusion(Workspace::Trusted, "boxmaker0", "Uses tabs."),
Some((agent, "c-agent".to_string()))
);
let again = home.open();
assert_eq!(
again.conclusion(Workspace::Trusted, "kyle", "Uses tabs."),
None
);
}