Files
Lumotia/docs/architecture-map/03-audio-transcription/tests-and-fixtures.md
Jake 26c7307607
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled
agent: lumotia-rebrand — docs, scripts, root config, residuals
Phase 9 of the rebrand cascade. Sweep covers everything the Phase 8
frontend pass deliberately skipped: docs/, root markdown, scripts,
Cargo.toml descriptions, code comments that survived earlier
word-boundary sed, plus a handful of identifiers caught on the final
verify pass.

transcription-app changes:
- README.md, HANDOVER.md, KNOWN-ISSUES.md, run.sh — magnotia/Magnotia
  -> lumotia/Lumotia.
- docs/ — sweep across all subdirs except docs/handovers/ (preserved
  as immutable audit trail). Includes architecture-map references
  to magnotia_core::*, magnotia_storage::*, etc. now pointing at
  lumotia_*; dev-setup.md tracing output examples (lumotia_startup
  target); brief/ + superpowers/ + issues/ + whisper-ecosystem/ +
  audit/.
- Cargo.toml descriptions on 9 crates (core, audio, cloud-providers,
  hotkey, llm, mcp, plus referenced others).
- crates/core/src/{error,hardware,recommendation,paths}.rs +
  crates/audio/src/wav.rs + crates/llm/src/model_manager.rs +
  crates/cloud-providers/src/keystore.rs + crates/mcp/src/lib.rs —
  doc comments and a model-manager user-agent string.
- Caught on final pass: BroadcastChannel("magnotia_task_sync") -> ...
  ("lumotia_task_sync"); magnotia_locale i18n localStorage key
  renamed + migration shim added; CSS keyframe names
  magnotiaPulse / magnotiaBar / magnotiaFade renamed in the design-
  system kit; magnotia_viewer_item / magnotia_viewer_mode handoff
  keys renamed in HistoryPage + viewer/+page.svelte; src/assets/
  wordmark.svg text.
- src-tauri/src/lib.rs comment cleanup ("magnotia era" was sed'd
  to "lumotia era" earlier — restored).

Preserved (intentional):
- crates/core/src/paths.rs — keeps "magnotia" / "Magnotia" / ".magnotia"
  legacy detection strings in legacy_and_target_paths() so the
  migration shim can still find user data from the magnotia era.
- src/lib/stores/{page,focusTimer}.svelte.ts + src/lib/i18n/index.ts
  — migration call sites reference the legacy magnotia keys
  deliberately.
- docs/handovers/ — historical audit trail.

cargo build --workspace passes. npm run check: 0 errors / 0 warnings
(3958 files). cargo test --workspace: 339 pass / 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 12:38:03 +01:00

7.8 KiB
Raw Blame History

name, type, slice, last_verified
name type slice last_verified
Tests and fixtures architecture-map-page 03-audio-transcription 2026/05/09

Tests and fixtures

Where you are: Architecture mapAudio + Transcription → Tests and fixtures

Plain English summary. This slice has three categories of test. Inline unit tests under #[cfg(test)] mod tests exercise every public type (capture monitor detection, resampler duration preservation, RmsVadChunker state machine, LocalAgreement invariants, buffer trim bounds, model-manager hash and resume paths). Integration tests under crates/transcription/tests/ exercise whisper-rs end-to-end with env-var-gated fixtures so CI without a model checkpoint exits quietly. Test-only fixtures include in-tree tokio::net::TcpListener HTTP servers that simulate Range / 5xx / no-Range-honour servers for the download stack.

At a glance

  • Crate: lumotia-transcription (mostly) and lumotia-audio (inline only).
  • Paths:
    • crates/audio/src/{capture,decode,wav,resample,streaming_resample}.rs — inline #[cfg(test)] modules.
    • crates/transcription/src/{model_manager,local_engine,transcriber,streaming/*}.rs — inline #[cfg(test)] modules.
    • crates/transcription/tests/whisper_rs_smoke.rs — env-gated load + transcribe.
    • crates/transcription/tests/jfk_bench.rs — env-gated benchmark with cold/warm RTF.
    • crates/transcription/tests/thread_sweep.rs — env-gated thread-count scaling sweep.
  • External deps (dev): tempfile 3, tokio (rt, sync, net, io-util, macros), num_cpus 1 (label-only).

Inline unit tests (selected highlights)

lumotia-audio

  • capture.rs:570monitor_pattern_detection for the PulseAudio / PipeWire heuristics.
  • decode.rs:262mid_stream_io_error_propagates_instead_of_returning_partial_audio. RB-09 regression: a flaky MediaSource (FlakyCursor, decode.rs:203) injects an I/O error after the probe header and asserts the function errors instead of returning Ok(partial).
  • wav.rs:170wav_writer_survives_crash. Uses std::mem::forget to skip the hound finaliser, simulating a process kill, then asserts the flushed prefix is recoverable via read_wav.
  • wav.rs:235read_wav_surfaces_truncated_sample_stream_errors. 2026-04-22 regression: the previous filter_map(|s| s.ok()) swallowed errors silently.
  • streaming_resample.rs:182streaming_48k_to_16k_preserves_duration. Pushes 1 s of 48 kHz audio in 700-sample chunks (forcing the residual-buffer path) and asserts the output is within 50 ms of 1 s at 16 kHz.
  • resample.rs:84resample_preserves_approximate_duration.

lumotia-transcription

  • streaming/rms_vad.rs:371:734 — comprehensive state-machine coverage: silence, hysteresis, onset gating, max-chunk continuity (max_chunk_split_preserves_audio_contiguity), padded-final-frame regression (flush_preserves_hit_max_chunk_from_padded_final_frame, flush_preserves_end_of_utterance_chunk_from_padded_final_frame — both 2026-04-22 CRITICAL C2 fixes), idempotent flush.
  • streaming/commit_policy.rs:212:402 — LocalAgreement-n correctness: text-only equality, non-shrinkage invariant, defensive shorter-pass handling (shorter_pass_after_commit_does_not_panic, regression for the latest[committed_count..] panic), n=3 behaviour.
  • streaming/buffer_trim.rs:56:206 — defensive non-finite handling, integration test against LocalAgreement::last_committed_end_secs, the long-session bound proof (trim_bounds_buffer_over_long_session).
  • model_manager.rs:339:615 — three TcpListener-backed fixtures (spawn_range_server, spawn_no_range_server, spawn_500_server) drive download_file through the resume path, the ResumeUnsupported path (server returns 200 to a Range request), the 5xx rejection path, and the SHA-mismatch cleanup path.
  • local_engine.rs:218engine_reports_not_available_before_loading.
  • transcriber.rs:54transcriber_trait_is_object_safe (compile-time witness).

Env-gated integration tests (crates/transcription/tests/)

All three skip silently if the env vars are unset, so cargo test on a fresh machine is a no-op for them.

whisper_rs_smoke.rs

  • Env vars: MAGNOTIA_WHISPER_TEST_MODEL (path to a ggml/gguf Whisper model).
  • Loads the context, builds a state, calls set_initial_prompt("Wren, CORBEL, ADHD") (proves the API still exists), runs inference on 1 s of silence, exercises full_n_segments and get_segment(i).to_str(). Smoke test only; assertion is "did this run without panicking".

jfk_bench.rs

  • Env vars: MAGNOTIA_WHISPER_TEST_MODEL, MAGNOTIA_WHISPER_TEST_AUDIO (path to a 16 kHz mono 16-bit PCM WAV — assertions in the test enforce this format on the fixture, not the runtime).
  • Reports cold-load time, cold-transcribe RTF, warm-transcribe RTF, peak RSS read from /proc/{pid}/status. Hardcodes set_n_threads(6) for both runs (so a sweep across thread counts is a separate test, not this one).

thread_sweep.rs

  • Same env vars as jfk_bench.rs. Adds MAGNOTIA_POWER_STATE_OVERRIDE (set internally per panel to ac or battery) so inference_thread_count returns its predicted pick for each combination of (power state × GPU offload) and the empirical RTF table can be compared against the helper's choice.
  • Runs the JFK clip at n_threads = 1, 2, 4, physical, logical (plus 8 if logical ≥ 8), takes the min of two runs per setting, prints a four-panel table:
    1. AC, CPU.
    2. AC, GPU (Vulkan).
    3. battery, CPU.
    4. battery, GPU (Vulkan).
  • Uses num_cpus::get() and num_cpus::get_physical() purely for the printed labels (thread_sweep.rs:35). The runtime helper inference_thread_count(Workload::Whisper, gpu_offloaded) does the actual prediction.
  • vulkan_runtime_ok snapshot taken once via cfg!(feature = "whisper-vulkan") && vulkan_loader_available().

Watch-outs

  • All three integration tests are quiet on missing env vars. A green cargo test does NOT mean the Whisper path works; it means "either the path works or you didn't set the env vars". CI configurations must explicitly set MAGNOTIA_WHISPER_TEST_MODEL to exercise these.
  • jfk_bench.rs hardcodes n_threads = 6. Production code uses inference_thread_count(Workload::Whisper, gpu_offloaded) which is power-aware. Bench numbers are not directly comparable to runtime numbers without rerunning with the helper-picked thread count.
  • thread_sweep.rs mutates MAGNOTIA_POWER_STATE_OVERRIDE via env::set_var. Globally process-wide. Concurrent tests in the same cargo test invocation that read MAGNOTIA_POWER_STATE_OVERRIDE will race. The test removes the var at the end (thread_sweep.rs:94).
  • tempfile 3 is a dev-dep, not a runtime dep. Production code never creates temp files.
  • num_cpus = "1" (the version, not "one CPU"). Test-only labelling; production uses the slice 5 helper.
  • In-tree HTTP fixtures use ephemeral ports (bind 127.0.0.1:0) and run on a tokio task. No port-collision risk, but a paranoid sandbox that blocks raw TCP loopback would break these tests.
  • ModelFile's &'static str fields force the test helper leak() (model_manager.rs:462). Each test leaks a few small strings. Acceptable for one-shot tests; do not copy this pattern into production code.

See also

  • Transcription model manager — the production code these download tests guard.
  • Transcription whisper — the production code these integration tests guard.
  • Transcription streaming — exhaustive unit-test coverage lives alongside this code.
  • docs/whisper-ecosystem/brief.md — the source of the items (#6, #8, #19, #21, #24, #25) repeatedly referenced in test docstrings.
  • docs/code-review-2026-04-22.md — the audit pass that produced the C2, RB-09, and read_wav regressions captured here.