Files
pdfcraft/contributors
Nick Nyssen 2ec501fa74 test(cos): property tests for save fidelity, plus credit entry
Adds crates/cos/tests/proptests.rs (464 lines) - three properties over generated catalogs (edit sequence
vs a plain ordered model; full save in both output styles; incremental save over bases built BOTH ways) -
and a self-credit entry in contributors/people.toml committed under the author's own identity. No product
code changes; total +466 lines across two files: people.toml +2; proptests.rs +464.

Two design decisions that came out of adversarial review, each measured rather than asserted:
  * catalog keys insert in a scrambled order ([5,0,7,2,6,1,4,3] filtered to the drawn keys), because with
    ascending insertion "preserves key order" and "sorted by key" are the same observable.
  * incremental expectations derive from the values written, not from reading the writer's own output back,
    so a consistently-wrong implementation cannot pass by agreeing with itself.

Measured against one-line breaks in crates/cos/src/writer.rs, each reverted and byte-compared afterwards
(verdicts from cargo exit codes; "pre-existing" = lib 48 + writer 10 + encryption 8 + shared_streams 3 +
bounded_writer 4, i.e. every target that existed before this PR):

  sort every dictionary by key              CAUGHT (props 1+2)      pre-existing suite FULLY GREEN
  reverse dictionary emission              CAUGHT (all three props)   pre-existing suite FULLY GREEN
  move /Type to the end of every dict     CAUGHT (prop 1)           pre-existing suite FULLY GREEN
                                            - caught only after catalog_keys() was added to pin the full key
                                              sequence; without it this break was green everywhere
  classic-table incremental startxref +1   CAUGHT (prop 2 alone; props 1+3 green), failure message names
                                            "classic-table", confirming the incremental table path executes
  drop null-valued dictionary entries      CAUGHT (all three)        at the pre-fix commit b51381c this same
                                            break left property 2 green - the self-reference it removed

Known limits, stated not hidden: incremental saves are asserted to add bytes and leave the original prefix
untouched - minimality is NOT claimed; catalog key order pins one fixed scramble rather than drawn
permutations, so 25.4% of cases draw too few keys for order to be meaningful; nested dictionary key order
is deliberately not pinned (canon sorts inside values); /Perms and permissions semantics are out of scope
here.

Gates at this tip (upstream 24f93e6, drift 0): cargo test -p pdfcraft-cos 85 passed / 0 failed / 2
ignored; cargo fmt -p pdfcraft-cos --check clean; clippy exit 0 for this crate with
-D warnings -A clippy::chunks_exact_to_as_chunks (that lint fires only in upstream's own
crates/oracle/src/pixels.rs:189 from f988cf8, tracked by #2342/#2324; flags after `--` forward into every
crate in the build graph, and crates/cos itself emits zero warnings under a forced recompile).
cargo xtask layers OK: 37 crates.

Scope: part of #1187 (items 1-3 partly; the reference-following comparison, undo state machine, password
property and damaged-file splices remain open). The encryption-side properties are PR #2358 by the same
author; earlier drafts of this text mis-cited #2014, which is certificate encryption and still open.
2026-10-15 16:41:32 -07:00
..