Skip to content

test(ssh): state mux explicitly so the ControlMaster tests are platform-stable - #179

Merged
github-actions[bot] merged 1 commit into
mainfrom
claude/daily-repo-scan-v8fvqs
Aug 11, 2026
Merged

test(ssh): state mux explicitly so the ControlMaster tests are platform-stable#179
github-actions[bot] merged 1 commit into
mainfrom
claude/daily-repo-scan-v8fvqs

Conversation

@dizhaky

@dizhaky dizhaky commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Correcting myself first

Across #174#178 I recorded that "Windows' no-mux SSH path has no test coverage at all." That was false.

ssh-connection.test.ts has seven dedicated no-mux: tests, covering every one of the five mux-conditional branches in ssh-connection.ts:

  • argument construction carries no ControlMaster/ControlPath/ControlPersist
  • open() verifies with a one-shot exec, no -M
  • open() classifies auth failure
  • forward() spawns the persistent -N -L child; cancelForward + close kill it
  • fail-fast when the tunnel child dies
  • an unrelated listener can't mask a delayed bind failure
  • tunnel death after readiness makes the connection unhealthy

I inferred the gap from watching the suite fail on Windows and never opened the file to check. It was cheap to check.

What's actually wrong is close to the inverse

All eight Windows failures were in mux tests that never set mux, so they inherited:

this._mux = opts.mux ?? process.platform !== 'win32'

On Windows that resolves false — the tests silently became no-mux connections, and their ControlMaster assertions couldn't hold. The suite wasn't missing no-mux coverage; its mux coverage was quietly evaporating on the one platform it was never run on.

The change

mux: true stated on all sixteen ControlMaster constructions. controlDir is the exact marker — it's meaningless without a master — so the edit is mechanical and complete rather than judged case-by-case.

Provably a no-op on Linux. The only value changed is opts.mux, and both undefined ?? true and true ?? true resolve to true there. A regression on the platform CI runs today isn't possible from this change. Simulated across all three platforms:

  linux   mux tests: before=true  after=true    no-mux tests: false
  darwin  mux tests: before=true  after=true    no-mux tests: false
  win32   mux tests: before=false after=true    no-mux tests: false

A second Windows problem mux: true does not fix

The control-dir safety block in open() is itself wrapped in process.platform !== 'win32' — so open() rejects a control-dir that is a symlink has no rejection to assert on Windows. Added the same if (process.platform === 'win32') return guard that the 0700 test three lines below already uses. Worth knowing that explicit mux alone would not have been sufficient.

Two sub-claims from my earlier triage, also corrected

  • createSshProbeConnection already forces mux: false internally — that test needed nothing.
  • The close() test I listed as already mux-explicit was a false grep hit on the string 'mux: master gone' in a stderr fixture. All eight failures share one cause, which is simpler than I reported.

Not included

ssh-connection.test.ts is not added to the Windows lane. This makes the suite capable of running there, but it's 40+ tests I can't execute from here, and over-including unverified files caused rounds #174 and #175. Adding it is a separate, checkable step — and given the lane is a required check since #176, the cost of being wrong is now everyone's PRs, not just mine.


Generated by Claude Code

…rm-stable

Correcting my own claim first: I recorded across five PR bodies that Windows'
no-mux SSH path had no test coverage. That was false. ssh-connection.test.ts
has seven dedicated no-mux tests covering every one of the five
mux-conditional branches in the source. I inferred the gap from seeing the
suite fail on Windows and never checked.

What is actually wrong is close to the inverse. All eight Windows failures
were in *mux* tests that never set mux, so they inherited
`opts.mux ?? process.platform !== 'win32'`, silently became no-mux objects on
Windows, and their ControlMaster assertions could not hold.

So mux: true is now stated on all sixteen ControlMaster constructions.
controlDir is the exact marker — it is meaningless without a master — which
makes the edit mechanical and complete rather than judged case by case.

Provably a no-op on Linux: the only value changed is opts.mux, and both
`undefined ?? true` and `true ?? true` resolve to true there, so this cannot
regress the platform CI runs today. Simulated across linux/darwin/win32: the
mux tests go false → true on win32 only, and the seven no-mux tests stay false
everywhere.

Also found a second Windows problem that mux: true does not fix: the
control-dir safety block in open() is itself wrapped in
`process.platform !== 'win32'`, so the symlink-rejection test has no rejection
to assert there. Added the same platform guard the 0700 test three lines below
already uses.

Not added to the Windows lane. This makes the suite capable of running there,
but 40+ tests cannot be verified from this sandbox, and over-including
unverified files caused two earlier rounds on that lane.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012689txgT12g2hjRczcUZi8
@github-actions
github-actions Bot merged commit 3c15d2e into main Aug 11, 2026
12 of 13 checks passed
@github-actions
github-actions Bot deleted the claude/daily-repo-scan-v8fvqs branch August 11, 2026 02:24
github-actions Bot pushed a commit that referenced this pull request Aug 11, 2026
The last open item from the Windows-lane work. Seven files now.

Inspected before adding rather than adding and hoping: over-including
unverified files caused rounds #174 and #175, and since #176 the lane is a
required check, so being wrong now blocks everyone's PRs rather than just
mine. The sweep covered Windows-hostile syscalls, separator-dependent
assertions and shell assumptions.

It found a third instance of the defect class behind #177:
`assert.match(a, /\/[0-9a-f]{16}\.sock$/)` against controlSocketPath, which
builds with path.join — a leading-slash regex can only match on POSIX. Now
asserted on path.basename(a), which is separator-independent and is what the
sun_path limit is actually about. Checked under both path flavours.

Everything else in the file is safe for stated reasons rather than by
assumption: the /var/folders/ check is a negative assertion; ControlPath
passes through baseSshOptions verbatim, which does no path joining; the
`cd '/home/me/project'` assertion is a remote shell command and remotes are
always POSIX; and the path.join calls create directories inside the two tests
that already carry win32 guards.

Also corrects the workflow header, which #179 had made false — it still said
ssh-connection was POSIX-only and that making it cross-platform was tracked as
follow-up, which is precisely what #179 did.

Remaining exposure is unknown-unknowns across ~40 tests that cannot be
executed from this sandbox. If the lane goes red on this, the fix is to drop
ssh-connection back out of the list — one word, and the test repairs stand on
their own.


Claude-Session: https://claude.ai/code/session_012689txgT12g2hjRczcUZi8

Co-authored-by: Claude <noreply@anthropic.com>
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.

2 participants