Skip to content

TUI lib tests share process-global state, so they only pass serially #596

Open

Description

@1jehuang

Follow-up to #592, which enabled the TUI library tests in CI. That gate has to run with --test-threads=1 because the suite is not parallel-safe.

Evidence

  • cargo test -p jcode-tui --lib -- --test-threads=1 → 1977 passed, 0 failed.
  • Default (parallel) → 2-4 failures per run, a different set each run, and every failing test passes when run alone.

Observed failing across runs: overscroll_reveal_does_not_relayout_transcript, test_remote_mixed_catalog_keeps_jcode_subscription_separate_from_other_providers, test_tui_cerebras_paste_key_lifecycle_has_no_degraded_success_messages, test_save_and_restore_reload_state_preserves_split_view_mode, test_tui_openai_compatible_empty_catalog_does_not_switch_to_profile_default, test_changelog_overlay_repeated_renders_are_stable, gather_ambient_info_filters_to_session_reminders_when_ambient_disabled.

Contended state

  • the process-global model catalog / route memo
  • AMBIENT_INFO_CACHE, whose stale-while-revalidate path spawns a background thread that reloads under whatever JCODE_HOME is current when it runs, not when it was queued
  • render state (partly addressed already by the shared render_state_test_lock)
  • JCODE_HOME itself, when a test sets it without holding the shared env lock

helpers_tests.rs already documents this: an "unrelated in-flight cache refresh can otherwise overwrite the cleared process-global cache with data loaded under another test's JCODE_HOME".

What worked in jcode-base

Two tests with exactly this shape were fixed by scoping, not redesign:

  • wrap the body in with_clean_provider_test_env
  • hold the shared test-env lock plus a private JCODE_HOME (matching the neighbouring test that already did)

cargo test -p jcode-base went from 1-2 intermittent failures per run to 1130 passing across three consecutive runs.

Why it is worth doing

  1. Ordering-dependent tests hide real regressions: a genuine break looks like the usual flake.
  2. Serial costs ~40s in CI where parallel would be ~15s.
  3. The --skip list in the CI step is blunt. Six copy_badge_shortcut tests are skipped because they drive a real clipboard; if they were injectable behind a clipboard trait they could run headlessly instead of being excluded.

Suggested order

  1. Scope the catalog/ambient tests the way the jcode-base ones were.
  2. Make the ambient cache refresh capture its JCODE_HOME at queue time, or skip the background path entirely under cfg(test).
  3. Abstract the clipboard so the copy-badge tests can drop out of the CI skip list.
  4. Only then drop --test-threads=1.

Activity

  1. added
    tech-debtCode should probably be refactored / cleaned up (no behavior change)
    on Jul 27, 2026
  2. 1jehuang commented on Jul 27, 2026

    @1jehuang
    OwnerAuthor

    Labeled tech-debt / triage: reproducible and cross-linked with #595, which covers the same parallel-isolation problem and already has measurements: full serialization costs about 14 seconds, and the mechanical "blanket the lock" approach self-deadlocks because render_state_test_lock is non-reentrant and several shared helpers already acquire it.

    No automated fix attempted: the suggested order here (scope the catalog/ambient tests, make the ambient cache capture JCODE_HOME at queue time, abstract the clipboard, then drop --test-threads=1) is a test-architecture change, and step 3 in particular needs a decision on the clipboard trait boundary.

    --- — Jcode agent (automated triage), on behalf of @1jehuang

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: mediumP2 - normal prioritytech-debtCode should probably be refactored / cleaned up (no behavior change)triage: reproducibleClear repro + clear fix path

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions