6.6 KiB
Speech queue verification
Ordinary output always appends. Cancellation belongs to configured interruption keys,
reader command dispatch and explicit stop requests. An announcement arriving
later from the same action must let earlier speech finish. This includes focus,
selection, state, notification and delayed review output. Accepted Tentacle
speech follows the same rule when its originating focus/session retires;
admission still rejects stale replies and Braille retains its own ownership.
External SpeakText announcements also queue regardless of their interrupt
flag; CancelSpeech remains an explicit stop request.
Run:
go test ./internal/app ./internal/input ./internal/speech -count=1
python3 tests/check_speech.py
go build -o /tmp/cthulhu-radio-sound ./cmd/cthulhu
CTHULHU_BINARY=/tmp/cthulhu-radio-sound CTHULHU_PREFS_RADIO_RUNTIME_ONLY=1 /usr/bin/python3 tests/native_preferences.py
The required radio-selection test sends Laptop focus and checked-state events through the event loop and speech worker, with a controlled backend that fails on an unexpected cancellation. Existing tests cover the cancellation barrier, Say All, key echo voice ordering, initiating-key timestamps, title repeats, screen lock, internal UI and Tentacle output. These checks establish software ordering, without proving audible completion or physical input on a Pi.
The private GTK radio test drives Right/Left between Desktop and Laptop. It
requires one selected sound per move, with the label retained. It uses private
Xvfb, D-Bus and a fake speech server; GStreamer auto audio is restricted to the
fake audio sink in the child reader. It never uses the desktop speech server or
audio devices. Debug sound records identify playback attempts, not audible
output. GStreamer's Python bindings and fakeaudiosink are required.
Unchecked radio focus sounds wait up to 250 milliseconds for a following checked event. That event replaces the pending sound immediately. Speech and Braille remain immediate, and a radio that stays unchecked gets its original unchecked cue. Fresh input, changed focus/window, lock and handoff retire the pending cue. Native state-only snapshots retain the owned mnemonic so a repeated focus event does not replay the selected sound and label.
Before submission, review the diff and rebuild the reader. Restart the active reader only with the user's authorization. Then listen on the target desktop and Pi:
- In keyboard preferences, change Desktop to Laptop, release the key and wait. Laptop should finish, followed by the role/state announcements. Repeat in the other direction and test radio buttons, checkboxes and combo boxes.
- With All keys interrupt selected, during a long announcement, press Control. Repeat with typing, an arrow, Tab and a reader command. Old speech and its queued feedback should stop; the new action should speak normally. Releasing keys should leave speech alone. Test rapid presses and held arrows, including automatic titles.
- Leave a long announcement playing while a notification or terminal output arrives. Both should finish in order. Repeat during Say All, then stop it with a fresh key and check that the reading position has stopped advancing.
- With a custom echo voice, press Right in an entry. The key name should finish before the caret character. A new key should still stop stale feedback.
- Exercise browser navigation, Where Am I, action/list dialogs and preferences Apply. Check that each fresh command responds promptly and delayed results preserve announcements from the same action. Check Braille focus/state and confirmation restoration separately.
Screen lock still clears speech for privacy. Disabling speech, replacing its configuration/backend and shutdown retain their existing behavior. Protected Tentacle messages retain their explicit timeout and cancellation rules. The bounded queue can discard pending requests on overflow and logs that loss.
Interruption preferences
Build a separate binary and exercise the recorder on a private display:
go build -o /tmp/cthulhu-interruption-test ./cmd/cthulhu
CTHULHU_BINARY=/tmp/cthulhu-interruption-test CTHULHU_PREFS_INTERRUPTION_ONLY=1 /usr/bin/python3 tests/native_preferences.py
CTHULHU_BINARY=/tmp/cthulhu-interruption-test CTHULHU_PREFS_INTERRUPTION_RUNTIME_ONLY=1 /usr/bin/python3 tests/native_preferences.py
This checks all three choices, Tab and Shift+Tab around the new controls, recording Tab/Enter/Space/Escape and separate modifiers, duplicate suppression, Control+Enter finish, Control+Escape cancellation, replacement, empty-recording rejection, Apply and reloading the accepted draft. Direct XTest modifier input avoids extra Control presses synthesized by xdotool. Config tests separately check disk persistence and application profiles. Application tests apply the preference to the live settings and check that unselected keys preserve both queued speech and Say All, while selected keys and reader commands cancel them. The runtime check starts a private reader and fake speech server. It verifies that the read-only summary's contents are spoken on focus and characters are spoken while moving with Left and Right. The generic native text-label test also covers read-only entries and keeps password contents excluded.
After reviewing the diff and authorizing a reader replacement, verify audibly:
- Select All keys interrupt and Apply. During long speech, press a letter, Tab, an arrow, Shift and Control separately; each should stop old speech.
- Select Control, Enter, Space, and Escape and Apply. Letters, arrows, Tab and Shift should let speech continue. Both Control keys, both Enter keys, Space and Escape should stop it. Repeat during Say All.
- Select Define interruption keys. Record Tab, Enter, Escape and Right Control, finishing with Control+Enter. Confirm Left Control was not added. Check the result field, Apply, close, reopen and confirm the list persists. Test each chosen key during long speech and confirm unchosen keys let it continue.
- Record a different list and cancel with Control+Escape; the previous list should remain. Cancel the whole Preferences window and confirm unapplied changes do not alter runtime behavior.
- Tab and Shift+Tab through the interruption group, recorder button, defined keys and speech history. Check spoken instructions and Braille in recording, normal typing/key echo, browser navigation, reader commands, automatic title repeats, and selected/unselected held keys after applying each mode.
The private checks do not establish live speech, physical keyboard, physical Braille or Wayland compositor acceptance.