Skip to content

test(zippychord): property-based test suite (documents a backspace under-count bug)#2100

Draft
nightscape wants to merge 1 commit into
jtroo:mainfrom
nightscape:zippychord-pbt
Draft

test(zippychord): property-based test suite (documents a backspace under-count bug)#2100
nightscape wants to merge 1 commit into
jtroo:mainfrom
nightscape:zippychord-pbt

Conversation

@nightscape

Copy link
Copy Markdown
Contributor

Summary

Adds a stateful property-based test suite for zippychord (using proptest-state-machine), plus two small bug fixes the testing surfaced. Treats zippychord as the state machine it is: a generated reference model drives a real Kanata SUT and asserts the net typed text after every transition.

Draft / WIP: the new property tests are RED on purpose — they document a real, pre-existing zippychord backspace under-count bug that is not fixed here. The tests are the spec the fix must satisfy; the fix is intended as a follow-up. CI will show these failing.

Commits

  1. fix(zippychord)zchd_reset didn't clear zchd_same_hold_activation_count (only cleared on a clean all-keys-released). A reset mid-activation left it stale, and it gates the common-prefix backspacing logic.
  2. test(sim_tests) – clear the global PRESSED_KEYS at the start of the sim helper, so the new state-machine test (which drives that global and can panic mid-scenario while shrinking) can't contaminate other tests.
  3. test(zippychord) – the property-based suite itself.

The oracle (why this isn't circular)

The oracle is split between generator and reference: a ChordExpansion transition carries which chord it activates (so the expansion text is known by construction), while the reference state only does coarse placement (fresh append / followup replace / disabled passthrough / free-typing literal). It deliberately does not reimplement the keystroke-level eager/overlap/backspace accounting — that's the code under test — so the bug surfaces instead of being mirrored.

The bug it documents (RED)

When an activation reuses characters from a prior eager activation via the common-prefix optimization, those reused chars aren't counted for deletion, so a following overlapping/followup activation backspaces too few characters and leaves stray text.

  • Deterministic minimal repro (repro_overlap_underdelete): dict b→"c", b→"cfbcc", bd→"fee "; pressing b, SPACE, d yields "cfee " instead of "fee ".
  • The state machine independently shrinks to a fresh 3-chord overlap; the committed proptest regression seed reproduces it deterministically.

Notes

  • Coverage and the deferred dimensions (⌫-in-output, smart-space full punctuation, modifiers/caps-word, multi-key followups, …) are documented in src/tests/sim_tests/ZIPPY_PBT_NOTES.md.
  • The PBT also caught the two issues fixed in commits 1–2, and (during development) demonstrated that a naive one-line fix to the under-count is insufficient — there are multiple manifestations.

🤖 Generated with Claude Code

https://claude.ai/code/session_01D2JYVbtxCmQMMDLL39FeHz

@@ -0,0 +1,75 @@
//! Deterministic regression shrunk from the zippychord property tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we delete minimisation unit tests?
proptest-state-machine stores the seeds of failing tests, so these would reproduce as well.

);
}

// --- Leading-space chord non-determinism reproduction --------------------

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we delete minimisation unit tests?
proptest-state-machine stores the seeds of failing tests, so these would reproduce as well.

}

#[derive(Clone, Debug)]
pub enum Tr {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give this a longer readable name.

pub enum Tr {
ChordExpansion {
target: Target,
press: Vec<char>,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imo ChordExpansion should be even more granular: A Vector of (time_after_initial_keypress, KeyPress / KeyRelease)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant