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
@@ -404,6 +404,61 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_value_under_a_key_naming_a_tin_is_masked_whatever_it_looks_like() {
|
||||
// Even a value that doesn't look like a TIN (a last four, a typo):
|
||||
// the key says what it is.
|
||||
for key in [
|
||||
"tin",
|
||||
"TIN",
|
||||
"payee_tin",
|
||||
"Member_TIN",
|
||||
"ssn",
|
||||
"ein",
|
||||
"itin",
|
||||
] {
|
||||
assert_eq!(
|
||||
digest(&serde_json::json!({ key: "6789" })),
|
||||
digest(&serde_json::json!({ key: "1234" })),
|
||||
"{key}"
|
||||
);
|
||||
assert_eq!(
|
||||
digest(&serde_json::json!({ key: {"last4": 6789} })),
|
||||
digest(&serde_json::json!({ key: ["anything"] })),
|
||||
"{key}"
|
||||
);
|
||||
// A TIN not given isn't one: null stays null.
|
||||
assert_ne!(
|
||||
digest(&serde_json::json!({ key: null })),
|
||||
digest(&serde_json::json!({ key: "6789" })),
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
// Only those keys: one that merely holds the letters counts.
|
||||
assert_ne!(
|
||||
digest(&serde_json::json!({"tint": "6789"})),
|
||||
digest(&serde_json::json!({"tint": "1234"}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_files_bytes_are_hashed_as_they_are_even_where_they_spell_digits() {
|
||||
// Base64 can hold a run of nine digits; it is still a file's bytes,
|
||||
// not a TIN, and two files differing there differ.
|
||||
for key in FILE_BYTES {
|
||||
assert_ne!(
|
||||
digest(&serde_json::json!({ key: "QUJD123456789QUJD" })),
|
||||
digest(&serde_json::json!({ key: "QUJD987814321QUJD" })),
|
||||
"{key}"
|
||||
);
|
||||
}
|
||||
// The same text anywhere else is masked.
|
||||
assert_eq!(
|
||||
digest(&serde_json::json!({"memo": "QUJD123456789QUJD"})),
|
||||
digest(&serde_json::json!({"memo": "QUJD987814321QUJD"}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_tin_at_the_cut_is_masked_whole() {
|
||||
// The TIN straddles the 64-character limit.
|
||||
|
||||
Reference in new issue
Block a user