P2: tests mutation found, three bugs fixed; plan P12 and P13
Mutation testing pauses until P12 (D-33, owner 2026-10-20), which reruns
the whole max-testing pass over everything since P1. Before the pause,
pass 1 on slices 3-6 and its triage gave tests in ledger-store,
ledger-package and ledger-mcp, and three real bugs, fixed:
- the command line took an admin answer longer than four MiB, or cut off
before its newline, whenever the bytes that came still parsed;
- The CPA package put a twin's number on the last dot of the whole path,
so in a folder with a dot the second file landed in another folder;
- a document or category named of dots alone ("..") could climb out of
its folder when the CPA package is unpacked.
The plan gains P13, bookspec (D-34): a formal, sourced accounting
specification first (rules with symbolic forms and worked examples), then
its own formal validation and a conformance harness any engine can be
tested against, seeded by P3's regression tests. docs/testing.md records
slices 3-8 and what P12 must cover; plan/STATUS.md says where P2 stands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T3gXMVt7XJPi6ens1or9Dj
This commit is contained in:
1 parent
3cf359a0cd
commit
d5c9522ad1
24 files changed
+2937
-20
No files matched your search
@@ -579,6 +579,40 @@ mod tests {
|
||||
assert_eq!(e, AuthError::Newer(1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_replacement_names_the_live_token_of_its_own_book_and_name() {
|
||||
let replacing = |old: &str, book: &str, name: &str| {
|
||||
let mut r = created("tok_2", name);
|
||||
r["book"] = book.into();
|
||||
r["replaces"] = old.into();
|
||||
r
|
||||
};
|
||||
// The right one: it takes the old one's place.
|
||||
let p = open_with(&[created("tok_1", "a"), replacing("tok_1", "acme", "a")]).unwrap();
|
||||
let live: Vec<&str> = p.tokens().iter().map(|t| t.id.as_str()).collect();
|
||||
assert_eq!(live, ["tok_2"]);
|
||||
// Any one of id, book or name wrong: a log that contradicts itself.
|
||||
for wrong in [
|
||||
replacing("tok_9", "acme", "a"),
|
||||
replacing("tok_1", "other", "a"),
|
||||
replacing("tok_1", "acme", "b"),
|
||||
] {
|
||||
let e = open_with(&[created("tok_1", "a"), wrong.clone()]).unwrap_err();
|
||||
assert!(matches!(e, AuthError::Inconsistent(2, _)), "{wrong}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_revocation_ends_the_token_it_names_and_no_other() {
|
||||
let revoked = |id: &str| serde_json::json!({"event": "token.revoked", "id": id});
|
||||
for (gone, left) in [("tok_1", "tok_2"), ("tok_2", "tok_1")] {
|
||||
let p =
|
||||
open_with(&[created("tok_1", "a"), created("tok_2", "b"), revoked(gone)]).unwrap();
|
||||
let live: Vec<&str> = p.tokens().iter().map(|t| t.id.as_str()).collect();
|
||||
assert_eq!(live, [left], "{gone} revoked");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_changed_record_is_found() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
Reference in new issue
Block a user