Skip to content

test: direct-mode shadow-buffer invariant over forward/reverse/forward - #78

Merged
willwade merged 2 commits into
mainfrom
test/direct-mode-shadow-invariant
Sep 1, 2026
Merged

test: direct-mode shadow-buffer invariant over forward/reverse/forward#78
willwade merged 2 commits into
mainfrom
test/direct-mode-shadow-invariant

Conversation

@willwade

@willwade willwade commented Aug 31, 2026

Copy link
Copy Markdown

Summary

  • Regression guard for Direct Mode (RFC 0015): replaying the output callback's deltas (0=insert, 1=delete-as-backspaces-per-code-point, 2=clear) into a shadow buffer must always reproduce dasher_get_output_text() byte-for-byte
  • 20 scenarios: shallow (≈one word) through deep reversals, with and without pointer-up pauses

Investigation context

This test was written while investigating a Dasher-Windows build .24 report ("zoom back to delete a word or a bunch of words, zoom forward again — it messes up just the previous word"). The invariant holds on both v0.1.6 (the pin .24 shipped with) and current main — the engine's insert/delete stream is consistent. The corruption was the Windows newline-injection path (fixed in Dasher-Windows bfdafb4: KEYEVENTF_UNICODE 0x0A is ignored by target apps; now mapped to VK_RETURN), which made paragraph-node deletes eat a character of the preceding word.

Kept as a permanent guard: any future engine-side drift in the delete/re-emit path breaks direct mode on every frontend.

Greptile Summary

The PR adds a Direct Mode regression test that replays output callback events into a shadow buffer and checks that it remains byte-for-byte consistent with the engine’s output across forward/reverse/forward navigation.

  • Registers the new test executable with CMake and CTest.
  • Exercises 20 reversal-depth and pointer-pause scenarios.
  • Validates insert, Unicode-aware delete, and clear callback events against polled output text.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
CMakeLists.txt Registers the Direct Mode shadow-buffer regression executable through the existing public C API test helper.
tests/test_direct_mode_shadow.cpp Adds a callback-replay invariant test covering twenty forward/reverse/forward navigation scenarios.

Sequence Diagram

sequenceDiagram
    participant Test
    participant Engine as DasherCore
    participant Shadow as Shadow buffer
    Test->>Engine: Drive forward navigation
    Engine-->>Shadow: Insert callbacks
    Test->>Engine: Drive reverse navigation
    Engine-->>Shadow: Delete callbacks
    Test->>Engine: Drive forward again
    Engine-->>Shadow: Re-emitted insert callbacks
    Test->>Engine: dasher_get_output_text()
    Test->>Shadow: Compare byte-for-byte
    Shadow-->>Test: Matching invariant
Loading

Reviews (2): Last reviewed commit: "style: clang-format; switch to ScopedCon..." | Re-trigger Greptile

Direct Mode (RFC 0015) consumes the output callback as deltas: 0 =
insert, 1 = delete (frontends send one backspace per code point),
2 = clear. Regression guard: replaying those events into a shadow
buffer must always reproduce dasher_get_output_text() byte-for-byte.

Investigation context (Dasher-Windows build .24 reports): the
 invariant holds on both v0.1.6 (the pin .24 shipped with) and
current main across 20 scenarios — shallow and deep reversals, with
and without pointer-up pauses — so the 'zoom back to delete, zoom
forward again, previous word corrupted' report was the Windows
newline-injection path (fixed Dasher-Windows bfdafb4), not the
engine.

Signed-off-by: will wade <willwade@gmail.com>
- Apply the repo clang-format the CI expects
- create_isolated_context() leaks its temp dir by design; new tests
  should use ScopedContext per test_common.h — the sweep now cleans
  up after itself

Signed-off-by: will wade <willwade@gmail.com>
@willwade
willwade merged commit 19c10c3 into main Sep 1, 2026
15 checks passed
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