A model fuzzer: random action, key and resize sequences through update and render

Open
#930 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Active
Tech stack
rust
Domain
testing-qa

Research direction

Start with cursor_never_escapes_the_listing in app/state/tests/navigation.rs and keymap::every_action() to see how actions are enumerated and driven through AppState::apply. Then read App::update, App::handle_key and App::test_app to learn how effects are returned and rendered on a TestBackend. Done means a test-only module under src/app/ that runs random action, key and resize sequences, checks the listed invariants after each step, and shrinks failures to a short replayable sequence.

Written by the indexing model from the issue text.

Description

area:build-ci type:chore

Problem

spyc's bugs cluster where states combine: a split closed while a pager is mounted, a resize to a tiny terminal mid-prompt, a project switch with a filter on. Example tests cover the combinations someone thought of. MVU makes a broader check cheap: any sequence of inputs should leave a valid model that renders.

Where spyc stands

  • proptest is a dev-dependency, used in 12 proptest! blocks. The nearest to a model fuzzer is cursor_never_escapes_the_listing (app/state/tests/navigation.rs): eight motions through AppState::apply, asserting the cursor stays in range.
  • keymap::every_action() enumerates every Action (test-only, via strum::EnumIter). App::update and App::handle_key return their effects as data, and App::test_app renders into a TestBackend in-process.
  • Nothing drives arbitrary actions, keys and resizes together, or renders after each step.

Proposal

A test-only module under src/app/:

  • Alphabet: any Action from every_action() with payloads drawn by proptest (counts, mark letters, project indices); a KeyEvent through App::handle_key, so prompts and confirms get typed into; a resize to w×h, each in 1..=200.
  • Driver: App::test_app on a temp dir with seeded rows. Effects are recorded and dropped, never run, so nothing touches the OS. A handler that touches the OS on its own is left out of the alphabet and listed, as a finding.
  • Invariants after every step: no panic; each column's cursor is in range, or 0 when empty; focus names something that exists (a mounted pager for Focus::Pager, a pane for Focus::Pane, the right column only while it's open); prepare_* and App::render succeed at the current size, 1×1 included.
  • Shrinking: proptest's own. A failure prints the minimal sequence as action names, and its proptest-regressions/ file is committed so it replays.
  • Budget: a fixed case count in make check, a larger PROPTEST_CASES in the weekly fuzz.yml run.

Acceptance

  • Removing the clamp from one motion fails the fuzzer with a sequence of a few steps (watched).
  • Its make check share stays within about 10 seconds.

Prior art: tuios — https://tuios.dev/docs/architecture (internal/fuzz: an action alphabet, a driver and a shrinker over the real update)

Dominant language
Rust
Stars
17
Forks
2
Avg merge
39m
Merged PRs (30d)
413

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Tripstack-Corp/spyc

All issues in Tripstack-Corp/spyc

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.