Skip to content

tests: move package-only suites out of the app-host bundle - #13790

Merged
teamleaderleo merged 2 commits into
manaflow-ai:mainfrom
teamleaderleo:chore/move-class-a-package-tests
Sep 23, 2026
Merged

teamleaderleo merged 2 commits into
manaflow-ai:mainfrom
teamleaderleo:chore/move-class-a-package-tests

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 22, 2026 •

Copy link
Copy Markdown
Collaborator

Moves the first batch of app-host test files that reference only package types + Foundation out of cmuxTests/ and into the owning SwiftPM package's test target. The code under test already lives in a package; these suites were sitting in the app-host bundle for no reason, paying its compile and host-launch cost on every run.

This is item 1 of the placement plan in the cmuxTests audit for RFC #13519 ("move focused tests out of the giant app-host bundle with their code"), and follows the package-extraction pattern of #13107 / #13119 / RFC #13108.

What moved

Whole files only — no mega-file surgery, no half-split files.

tests file → package test target
26 SidebarTabDropIndicatorPredicateTests.swift (4 suites) CmuxFoundationTests
11 SSHPTYAttachExitCodeClassifierTests.swift CmuxFoundationTests
6 SidebarWorkspaceSelectionAnchorPolicyTests.swift CmuxFoundationTests
10 CloudImagePasteCoordinatorTests.swift (+ its CloudImagePasteTestPeer.swift helper) CmuxCloudImagePasteTests
7 RemoteTmuxNativeMirrorLayoutFuzzTests.swift CmuxRemoteSessionTests
1 RemoteTmuxLayoutNodePatchingTests.swift CmuxRemoteSessionTests
5 TerminalSurfaceResizePolicyTests.swift CmuxTerminalTests
1 TerminalPathEnvironmentTests.swift CmuxTerminalTests
3 GlobalSearchShortcutSettingsModelTests.swift CmuxSettingsUITests
1 ShortcutHintDebugSettingsBindingTests.swift CmuxSettingsTests

71 tests in 13 suites, 11 files, off the app-host bundle.

Supporting changes

  • SSHPTYAttachExitCode gains Sendable. It is a bare Int32-backed enum with no associated values; the app-host target never needed the conformance spelled out, but CmuxFoundationTests builds in Swift 6 language mode and @Test(arguments:) requires it. No behavior change.
  • CmuxRemoteSessionTests gains the Bonsplit product — the native-mirror layout fuzz test asserts the bonsplit plan against tmux geometry. Test target only; the CmuxRemoteSession library target is untouched.
  • The #if canImport(cmux_DEV) / @testable import cmux blocks are dropped from every moved file. None of these suites referenced an app symbol; that is what put them in the "movable now" class.
  • cmux.xcodeproj/project.pbxproj: the 11 files are removed from the cmuxTests target via ./scripts/sync-test-wiring, then python3 scripts/normalize-pbxproj.py. The files are deleted from cmuxTests/, not merely unwired, so lint-pbxproj-test-wiring.sh stays green.

tests/test-execution.toml needs no change: it registers Python lanes only, and python3 scripts/ci/validate_test_execution_registry.py passes unchanged (226 tests).

Verification

swift test per touched package, locally:

package result
CmuxCloudImagePaste 12 tests in 2 suites passed
CmuxRemoteSession 189 tests in 31 suites passed
CmuxSettings 359 tests in 56 suites passed
CmuxSettingsUI 177 tests in 33 suites passed
CmuxTerminal 303 tests in 39 suites passed
CmuxFoundation the 4 moved suites (43 tests) pass under --filter

Two caveats about the local box, both reproduced on unmodified upstream/main in the same worktree:

  • CmuxFoundation's full swift test does not build here: the pre-existing SSHPTYReplayOutputFilterTests.swift hits "the compiler is unable to type-check this expression in reasonable time" on two long string concatenations. Unrelated to this change — it fails identically with the changes stashed. With that expression temporarily annotated, the full run is 412 tests in 66 suites with 5 failures, all in CommandRunnerDescriptorLifecycleTests and SSHPTYAttachRetryScriptBuilderTests (process-spawning tests that do not like this sandbox), and none in a moved suite.
  • CommandRunner/SSHPTYAttachRetryScriptBuilder failures above are environmental for the same reason.

Fast static checks run locally and green: tests/test_normalize_pbxproj.py, scripts/check-pbxproj.sh, scripts/check-workspace-package-groups.py --check, tests/test_sync_test_wiring.py, scripts/lint-pbxproj-test-wiring.sh (1040 files checked).

What deliberately did not move

The audit counts 326 class-(a) tests across 72 suites. This PR ships the subset that is a clean whole-file move and actually compiles and passes under swift test. Everything below is a follow-up, not an oversight:

  • 5 files whose suite name already exists in the destination package — ShortcutWhenClauseTests, SocketControlPasswordStoreTests, RovoDevHookConfigTests, CommandPaletteEmojiTitleSearchTests, GhosttyCopyActionResolverAppTests (23 tests). These are the audit's "same behavior at two layers" cases: the coverage is complementary rather than duplicated, so they need a merge-and-dedupe into the existing package suite, not a move. GhosttyCopyActionResolverAppTests asserts that the app target resolves through the package resolver — that one should probably stay where it is.
  • ~186 class-(a) tests inside mixed mega-files (GhosttyConfigTests.swift, SidebarOrderingTests.swift, ShortcutAndCommandPaletteTests.swift, …). Lifting a suite out of a 6k-line grab-bag is mechanical, but the remainder of the file can only be proven by an app-host build, so it belongs in its own PR.
  • Suites the static classifier called movable that are not. Each was read, and two were moved and moved back once the compiler disagreed:
    • KeyboardShortcutSavedLayoutTemplateTests asserts CmuxSettings.ShortcutAction stays aligned with the app target's KeyboardShortcutSettings.Action.
    • DebugEventLogSerializedAppendTests calls bonsplit's dlog, and CMUXDebugLog is pinned to macOS 13 while Bonsplit needs 14 — a 2-test move is not worth raising a package's deployment target.
    • CloudSidebarAcceptanceTests drives other app-host suites as fixtures — host-required.
    • SidebarWorkspaceRowStatusGlyphRemovalTests scans Sources/*.swift through a #filePath walk anchored at cmuxTests/ — a repo-source guard, not a package test.
    • AutoNaming*Tests, SSHPTYAttachReconnectInputFilterTests, RemoteTmuxInputCommandCaptureTests cover code in CLI/ or helpers in cmuxTests/, not in any package.
    • BrowserPDFPreviewActionRegressionTests imports WebKit.

No file with an in-flight PR (#13759, #13752, #13736, #13744) is touched, and no CLI/product-subprocess suite is moved.

🤖 Generated with Claude Code


Summary by cubic

Moves 71 tests in 13 suites across 11 files out of the app-host bundle (cmuxTests/) into the test targets of the SwiftPM packages that own the code under test, so these package-only suites no longer pay the app-host compile and host-launch cost on every run.

What moved

  • SidebarTabDropIndicatorPredicateTests, SSHPTYAttachExitCodeClassifierTests, and SidebarWorkspaceSelectionAnchorPolicyTests move to CmuxFoundationTests.
  • CloudImagePasteCoordinatorTests and its CloudImagePasteTestPeer helper move to CmuxCloudImagePasteTests.
  • RemoteTmuxNativeMirrorLayoutFuzzTests and RemoteTmuxLayoutNodePatchingTests move to CmuxRemoteSessionTests.
  • TerminalSurfaceResizePolicyTests and TerminalPathEnvironmentTests move to CmuxTerminalTests.
  • GlobalSearchShortcutSettingsModelTests and ShortcutHintDebugSettingsBindingTests move to CmuxSettingsUITests and CmuxSettingsTests.
  • The @testable import cmux blocks are dropped from every moved file; none of these suites referenced an app symbol.
  • The files are deleted from cmuxTests/ and unwired from the cmuxTests target via scripts/sync-test-wiring, then normalized with scripts/normalize-pbxproj.py, so lint-pbxproj-test-wiring.sh stays green.

Supporting changes

  • SSHPTYAttachExitCode now conforms to Sendable; it's a bare Int32-backed enum, and CmuxFoundationTests builds in Swift 6 mode where @Test(arguments:) requires the conformance. No behavior change.
  • CmuxRemoteSessionTests gains the Bonsplit product dependency for the native-mirror layout fuzz assertion; the CmuxRemoteSession library target is untouched.

Written for commit 269d3ab. Summary will update on new commits.

Review in cubic

Eleven files under cmuxTests/ reference only package types and Foundation,
so the code they cover already lives in a SwiftPM package. They were paying
the app-host bundle's compile and host-launch cost for nothing. Move them
whole into the owning package's test target, where `swift test` runs them
on a plain, parallel lane.

71 tests in 13 suites move to CmuxFoundationTests, CmuxCloudImagePasteTests,
CmuxRemoteSessionTests, CmuxTerminalTests, CmuxSettingsTests and
CmuxSettingsUITests. The `@testable import cmux`
blocks go with them: none of these suites named an app symbol, which is
what made them movable in the first place.

Two supporting changes the package build needs:

- `SSHPTYAttachExitCode` gains `Sendable`. It is a bare Int32-backed enum
  with no associated values; the app-host target never needed the
  conformance spelled out, but CmuxFoundationTests builds in Swift 6
  language mode and `@Test(arguments:)` requires it.
- `CmuxRemoteSessionTests` gains the Bonsplit product, which the native
  mirror layout fuzz test asserts against. Test target only; the
  CmuxRemoteSession library target is unchanged.

The files are deleted from cmuxTests/ and unwired from the cmuxTests target
via scripts/sync-test-wiring, then normalized with
scripts/normalize-pbxproj.py, so lint-pbxproj-test-wiring.sh stays green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 22 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5a1c9342-0977-4662-b056-ca336f23d134

📥 Commits

Reviewing files that changed from the base of the PR and between d7f6648 and 269d3ab.

📒 Files selected for processing (14)
  • Packages/macOS/CmuxCloudImagePaste/Tests/CmuxCloudImagePasteTests/CloudImagePasteCoordinatorTests.swift
  • Packages/macOS/CmuxCloudImagePaste/Tests/CmuxCloudImagePasteTests/CloudImagePasteTestPeer.swift
  • Packages/macOS/CmuxFoundation/Sources/CmuxFoundation/SSHPTYAttachExitCode.swift
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/SSHPTYAttachExitCodeClassifierTests.swift
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/SidebarTabDropIndicatorPredicateTests.swift
  • Packages/macOS/CmuxFoundation/Tests/CmuxFoundationTests/SidebarWorkspaceSelectionAnchorPolicyTests.swift
  • Packages/macOS/CmuxRemoteSession/Package.swift
  • Packages/macOS/CmuxRemoteSession/Tests/CmuxRemoteSessionTests/RemoteTmuxLayoutNodePatchingTests.swift
  • Packages/macOS/CmuxRemoteSession/Tests/CmuxRemoteSessionTests/RemoteTmuxNativeMirrorLayoutFuzzTests.swift
  • Packages/macOS/CmuxSettings/Tests/CmuxSettingsTests/ShortcutHintDebugSettingsBindingTests.swift
  • Packages/macOS/CmuxSettingsUI/Tests/CmuxSettingsUITests/GlobalSearchShortcutSettingsModelTests.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalPathEnvironmentTests.swift
  • Packages/macOS/CmuxTerminal/Tests/CmuxTerminalTests/TerminalSurfaceResizePolicyTests.swift
  • cmux.xcodeproj/project.pbxproj

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 22, 2026 23:59
@teamleaderleo
teamleaderleo merged commit f47f4a7 into manaflow-ai:main Sep 23, 2026
48 of 49 checks passed
teamleaderleo added a commit that referenced this pull request Sep 23, 2026
* ci: run package tests on the pull requests that change packages

`macos / swift-package-tests` is gated on `inputs.full_suite == 'true'`,
and `full_suite` is false for every pull request under
`CI_PULL_REQUEST_SUITE=compile-only`. The job is therefore skipped on
every PR. The only macOS signal a PR gets is `macOS compile admission`,
which builds package *library* targets and never their test targets, so
a change to a package's tests currently lands with zero CI execution of
those assertions. #13786 and #13790 move ~150 of them into package test
targets.

Route the lane from changed paths, the way the `cli` lane selects itself
(#13760). A new `swift_packages` change area asks
`scripts/ci/select_package_tests.py` — the same selector the job already
uses to narrow its package list — whether a diff can affect any package
the job runs. Only paths that feed a package are offered to it:

  * The selector fails open, so the lane's own workflow and scripts
    select all 33 packages. On main that is right; on a pull request it
    is the 30-minute sweep under another name. Over the last 200 merged
    PRs, routing those would have queued 34 full runs.
  * A package outside the job's list selects nothing, so the lane would
    start, check out submodules and test zero packages.

Measured over the last 200 merged pull requests: 28 would run the lane
(0 do today), testing a median of 2 packages and never more than 15,
never all 33 and never zero.

The full suite is untouched: `app-host-unit-tests`, `tests-build-and-lag`
and the Release jobs stay gated on `full_suite` alone, and a test in this
change pins that set so a new lane cannot silently join it. The Release
Ghostty CLI helper steps inside the job now also require `full_suite`,
since only the `full_suite`-gated Release jobs consume that artifact.

Also collect the operating system's crash report when a package test
runner dies on a signal. `main` is currently red from a SIGBUS in
CmuxSettingsUI, and all the job records is SwiftPM's one-line
"Exited with unexpected signal code 10" — no faulting address, no
frames. Replaying the retry guard against that job's captured output
shows widening its signal list would not have retried it anyway: the
runner had already emitted 401 lines of test output, which the guard's
third clause correctly refuses to retry. The signal list is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* test: catch full package sweeps on mixed routed changes

* ci: keep targeted package selection aligned with routing

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo deleted the chore/move-class-a-package-tests branch September 23, 2026 11:22
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