refactor(ssh): import the system-ssh and ssh -G modules directly, not through re-export shims (#30255)

Deletes ssh-system-fallback.ts and the re-export lines in ssh-config-parser.ts, ssh-connection.ts,
system-ssh-file-binary-transfer.ts and ssh-remote-powershell.ts; importers name the real modules.
SshConnection tests mock each real module, keeping the parser stub that holds ~/.ssh/config out.
This commit is contained in:
Neil
2026-10-18 02:34:30 -07:00
committed by GitHub
parent 383513b8bb
commit 019417bd86
60 changed files with 454 additions and 179 deletions
+1 -1
View File
@@ -6349,7 +6349,7 @@
"pnpm exec vitest run --config config/vitest.config.ts src/shared/browser-client-host-protocol.test.ts src/main/browser/browser-client-host-attach-request.test.ts src/main/browser/browser-client-network-route-registry.test.ts src/main/browser/paired-runtime-browser-client-host-composition.test.ts src/main/browser/paired-runtime-browser-client-host.test.ts src/main/browser/paired-runtime-browser-client-host-reconnect.test.ts src/main/browser/paired-runtime-browser-host-lease.test.ts src/main/browser/paired-runtime-browser-host-lease-reconnect.test.ts src/main/browser/browser-host-lease-reconnect-delay.test.ts src/main/browser/paired-runtime-browser-network-route.test.ts src/main/runtime/browser-host/browser-host-command-ledger.test.ts src/main/runtime/browser-host/browser-host-command-ledger-capacity.test.ts src/main/runtime/browser-host/browser-host-lease-placement-retirement.test.ts src/main/runtime/browser-host/browser-host-lease-registry.test.ts src/main/runtime/runtime-rpc-browser-host-admission.test.ts src/main/runtime/rpc/methods/browser-client-host.test.ts",
"pnpm exec vitest run --config config/vitest.config.ts src/main/browser/browser-client-network-route-registry.test.ts src/main/browser/paired-runtime-browser-client-host-composition.test.ts src/main/browser/paired-runtime-browser-client-host-registry.test.ts src/main/browser/paired-runtime-browser-client-host-runtime.test.ts src/main/browser/browser-client-page-command-executor.test.ts src/main/browser/browser-session-startup.test.ts src/main/ipc/runtime-environments-subscription-teardown.test.ts",
"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/browser-host/browser-host-command-ledger.test.ts src/main/runtime/browser-host/browser-host-command-ledger-capacity.test.ts src/main/runtime/browser-host/browser-host-lease-registry.test.ts src/main/runtime/rpc/methods/browser-client-host.test.ts",
"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/browser-host/browser-host-lease-registry.test.ts src/main/browser/browser-network-deferred-socket.test.ts src/main/browser/browser-network-execution-route.test.ts src/main/browser/paired-runtime-browser-network-route.test.ts src/main/runtime/rpc/methods/browser-network-tunnel.test.ts src/main/browser/ssh-browser-network-execution-route.test.ts src/main/browser/system-ssh-socks-client-socket.test.ts src/main/ssh/system-ssh-dynamic-forward-process.test.ts src/shared/browser-client-host-protocol.test.ts src/main/ssh/system-ssh-forward-process.test.ts src/main/ssh/ssh-system-fallback.test.ts src/main/ssh/ssh-port-forward.test.ts",
"pnpm exec vitest run --config config/vitest.config.ts src/main/runtime/browser-host/browser-host-lease-registry.test.ts src/main/browser/browser-network-deferred-socket.test.ts src/main/browser/browser-network-execution-route.test.ts src/main/browser/paired-runtime-browser-network-route.test.ts src/main/runtime/rpc/methods/browser-network-tunnel.test.ts src/main/browser/ssh-browser-network-execution-route.test.ts src/main/browser/system-ssh-socks-client-socket.test.ts src/main/ssh/system-ssh-dynamic-forward-process.test.ts src/shared/browser-client-host-protocol.test.ts src/main/ssh/system-ssh-forward-process.test.ts src/main/ssh/system-ssh-operations.test.ts src/main/ssh/ssh-port-forward.test.ts",
"ORCA_RUN_DOCKER_SSH_BROWSER_E2E=1 pnpm exec vitest run --config config/vitest.config.ts tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts",
"ORCA_RUN_DOCKER_SSH_BROWSER_E2E=1 node_modules/.bin/vitest run --config config/vitest.config.ts tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts"
],
+1 -1
View File
@@ -5802,7 +5802,7 @@
"src/main/ssh/ssh-request-outcome-verdict.test.ts": 37,
"src/main/ssh/ssh-security-key-identity.test.ts": 147,
"src/main/ssh/ssh-session-limit-error.test.ts": 27,
"src/main/ssh/ssh-system-fallback.test.ts": 275,
"src/main/ssh/system-ssh-operations.test.ts": 275,
"src/main/ssh/ssh-system-transport.integration.test.ts": 277,
"src/main/ssh/ssh-target-id-migration.test.ts": 46,
"src/main/ssh/ssh-target-orcad-claims.test.ts": 306,
@@ -1,4 +1,4 @@
import type { SshConnectionCallbacks } from '../ssh/ssh-connection'
import type { SshConnectionCallbacks } from '../ssh/ssh-connection-utils'
import type { SshConnectionState } from '../../shared/ssh-types'
import { isSshHostCensusInFlight } from '../ssh/ssh-connection-attribution'
import { clearSshCredentialDeclined, isSshCredentialDeclined } from '../ssh/ssh-credential-decline'
@@ -21,7 +21,8 @@ import {
REMOTE_NODE_RUNTIME_SELFTEST_FAILED,
REMOTE_NODE_RUNTIME_VERIFIED_MARKER
} from './orcad-remote-node-runtime-report'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
function windowsPath(...segments: string[]): string {
return segments
+1 -1
View File
@@ -22,7 +22,7 @@ import type { OrcadHostTransport } from './orcad-host-transport'
import { execCommand, isUnconfirmedSshCommandTermination } from './ssh-relay-exec-command'
import { RELAY_REMOTE_DIR } from './relay-protocol'
import { joinRemotePath, remoteDirname, type RemoteHostPlatform } from './ssh-remote-platform'
import { powerShellLiteral } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import { ORCAD_WINDOWS_COMMAND_LINE_UNSAFE_CODE } from '../orcad/orcad-host-unavailable'
import {
ORCAD_WINDOWS_HOST_SCRIPT,
@@ -24,7 +24,8 @@ import {
} from './remote-node-runtime-store-inventory'
import { RELAY_REMOTE_DIR } from './relay-protocol'
import { isWindowsRemoteHost, joinRemotePath, type RemoteHostPlatform } from './ssh-remote-platform'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
const REPARSE = '[IO.FileAttributes]::ReparsePoint'
+1 -1
View File
@@ -1,7 +1,7 @@
import { existsSync, readFileSync } from 'node:fs'
import { utils, type BaseAgent, type ParsedKey } from 'ssh2'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import { createIdentityFilteredAgent } from './ssh-agent-identity-filter'
import { resolveSshConfigHomePath } from './ssh-config-path-expansion'
import { isOpenSshConfigBackedTarget } from './system-ssh-args'
+2 -1
View File
@@ -1,6 +1,7 @@
import { describe, expect, it, vi } from 'vitest'
import { join } from 'node:path'
import { parseSshConfig, sshConfigHostsToTargets, parseSshGOutput } from './ssh-config-parser'
import { parseSshConfig, sshConfigHostsToTargets } from './ssh-config-parser'
import { parseSshGOutput } from './ssh-g-config-resolution'
import { searchSshConfigHosts } from './ssh-config-host-picker'
const sshConfigHostsToSummaries = (
-1
View File
@@ -4,7 +4,6 @@ import { homedir } from 'node:os'
import type { SshTarget } from '../../shared/ssh-types'
import { expandSshConfigIncludes } from './ssh-config-include-expander'
import { resolveSshConfigHomePath } from './ssh-config-path-expansion'
export { parseSshGOutput, resolveWithSshG, type SshResolvedConfig } from './ssh-g-config-resolution'
export type SshConfigHost = {
host: string
+1 -1
View File
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import { runProcess } from '@orca/process-host'
vi.mock('os', () => ({
@@ -16,14 +16,27 @@ import {
walkInitialAuthLadder
} from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).createSsh2Module())
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -31,6 +44,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -9,8 +9,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -18,6 +31,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
beforeEach(resetSshConnectionMocks)
afterEach(() => {
@@ -14,8 +14,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -23,6 +36,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -4,14 +4,27 @@ import { resetSshConnectionMocks, spawnSystemSshCommandMock } from './ssh-connec
import { createCallbacks, createResolvedConfig, createTarget } from './ssh-connection-test-fixtures'
import type { createSystemCommandChannel } from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).createSsh2Module())
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -19,6 +32,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -2,22 +2,34 @@ import { describe, expect, it, vi, beforeEach } from 'vitest'
import { resetSshConnectionMocks } from './ssh-connection-test-harness'
import { createCallbacks, createResolvedConfig, createTarget } from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import {
downloadFileViaSystemSsh,
uploadDirectoryViaSystemSsh,
uploadFileViaSystemSsh,
writeBufferViaSystemSsh,
writeFileViaSystemSsh
} from './ssh-system-fallback'
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
import { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './system-ssh-file-transfer'
import { getRemoteHostPlatform } from './ssh-remote-platform'
vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).createSsh2Module())
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -25,6 +37,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -12,12 +12,11 @@ import {
import type { RemoteHostPlatform } from './ssh-remote-platform'
import {
downloadFileViaSystemSsh,
uploadDirectoryViaSystemSsh,
uploadFileViaSystemSsh,
writeBufferViaSystemSsh,
writeFileViaSystemSsh,
type SystemSshBuildArgsOptions
} from './ssh-system-fallback'
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
import { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './system-ssh-file-transfer'
import type { SystemSshBuildArgsOptions } from './system-ssh-args'
export type SshRemoteFileOptions = {
hostPlatform?: RemoteHostPlatform
@@ -7,14 +7,27 @@ import {
createTarget
} from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).createSsh2Module())
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -22,6 +35,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -17,14 +17,27 @@ import {
createTarget
} from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).createSsh2Module())
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -32,6 +45,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -15,7 +15,7 @@ import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:f
import { tmpdir } from 'node:os'
import { join } from 'node:path'
// Type-only, so it is erased before vi.mock's hoisted factory runs.
import type * as SshConfigParser from './ssh-config-parser'
import type * as SshGConfigResolution from './ssh-g-config-resolution'
import type * as Ssh2 from 'ssh2'
const VALID_ED25519_HOST_KEY = Buffer.from(
@@ -76,8 +76,8 @@ vi.mock('ssh2', async (importOriginal) => {
}
})
vi.mock('./ssh-config-parser', async (importOriginal) => ({
...(await importOriginal<typeof SshConfigParser>()),
vi.mock('./ssh-g-config-resolution', async (importOriginal) => ({
...(await importOriginal<typeof SshGConfigResolution>()),
resolveWithSshG: vi.fn(async () => null)
}))
@@ -10,8 +10,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -19,6 +32,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
const UNIDENTIFIABLE_HOST_KEY = Buffer.from('not-a-real-host-key-blob')
@@ -7,8 +7,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -16,6 +29,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnectionManager', () => {
beforeEach(() => {
@@ -17,8 +17,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -26,6 +39,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
const authFailure = (): Error => new Error('All configured authentication methods failed')
+2 -5
View File
@@ -1,9 +1,6 @@
import type { SshTarget, SshConnectionState } from '../../shared/ssh-types'
import {
SshConnection,
type SshCachedCredentials,
type SshConnectionCallbacks
} from './ssh-connection'
import { SshConnection, type SshCachedCredentials } from './ssh-connection'
import type { SshConnectionCallbacks } from './ssh-connection-utils'
import { recordSshConnectionOpened, recordSshConnectionReused } from './ssh-connection-attribution'
import { createSshCredentialDeclinedError, isSshCredentialDeclined } from './ssh-credential-decline'
import { createSshUserDisconnectedError, isSshUserDisconnected } from './ssh-user-disconnect'
@@ -15,8 +15,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -24,6 +37,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
// ssh2's exact shape when TCP connects but the socket closes before the server banner.
const preBannerLoss = (): Error =>
@@ -17,7 +17,7 @@ import {
createTarget
} from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import { CONNECT_TIMEOUT_MS, RECONNECT_BACKOFF_MS } from './ssh-connection-utils'
import { MIN_SSH_RELAY_GRACE_PERIOD_SECONDS } from '../../shared/ssh-types'
@@ -25,8 +25,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -34,6 +47,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
@@ -7,6 +7,10 @@ import { mkdtempSync, realpathSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type * as SystemSshArgs from './system-ssh-args'
import type * as SystemSshFileBinaryTransfer from './system-ssh-file-binary-transfer'
import type * as SystemSshFileTransfer from './system-ssh-file-transfer'
import type * as SshGConfigResolution from './ssh-g-config-resolution'
vi.mock('ssh2', () => ({
BaseAgent: class {},
@@ -15,25 +19,34 @@ vi.mock('ssh2', () => ({
utils: { parseKey: vi.fn() }
}))
vi.mock('./ssh-system-fallback', () => ({
getOrcaControlSocketPath: vi.fn().mockReturnValue(null),
spawnSystemSsh: vi.fn(),
spawnSystemSshCommand: vi.fn(),
vi.mock('./system-ssh-args', async (importOriginal) => ({
...(await importOriginal<typeof SystemSshArgs>()),
getOrcaControlSocketPath: vi.fn().mockReturnValue(null)
}))
vi.mock('./system-ssh-command', () => ({ spawnSystemSsh: vi.fn(), spawnSystemSshCommand: vi.fn() }))
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) => ({
...(await importOriginal<typeof SystemSshFileBinaryTransfer>()),
downloadFileViaSystemSsh: vi.fn().mockResolvedValue(undefined),
uploadDirectoryViaSystemSsh: vi.fn().mockResolvedValue(undefined),
uploadFileViaSystemSsh: vi.fn().mockResolvedValue(undefined),
writeBufferViaSystemSsh: vi.fn().mockResolvedValue(undefined),
writeBufferViaSystemSsh: vi.fn().mockResolvedValue(undefined)
}))
vi.mock('./system-ssh-file-transfer', async (importOriginal) => ({
...(await importOriginal<typeof SystemSshFileTransfer>()),
uploadDirectoryViaSystemSsh: vi.fn().mockResolvedValue(undefined),
writeFileViaSystemSsh: vi.fn().mockResolvedValue(undefined)
}))
vi.mock('./ssh-control-socket', () => ({ removeControlSocketPath: vi.fn() }))
vi.mock('./ssh-config-parser', () => ({ resolveWithSshG: vi.fn().mockResolvedValue(null) }))
vi.mock('./ssh-g-config-resolution', async (importOriginal) => ({
...(await importOriginal<typeof SshGConfigResolution>()),
resolveWithSshG: vi.fn().mockResolvedValue(null)
}))
import { SshConnection } from './ssh-connection'
import type { SftpNamespacePathMapping } from './sftp-namespace-resolution'
import { getRemoteHostPlatform } from './ssh-remote-platform'
import { isSshSessionLimitError } from './ssh-session-limit-error'
import { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './ssh-system-fallback'
import { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './system-ssh-file-transfer'
import type { SshTarget } from '../../shared/ssh-types'
const SHELL_HOME = '/var/services/homes/alice'
@@ -19,9 +19,10 @@ import {
createSystemCommandChannel,
createTarget
} from './ssh-connection-test-fixtures'
import { SshConnection, shouldUseSystemSshTransport } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { writeFileViaSystemSsh } from './ssh-system-fallback'
import { SshConnection } from './ssh-connection'
import { shouldUseSystemSshTransport } from './ssh-transport-selection'
import { resolveWithSshG } from './ssh-g-config-resolution'
import { writeFileViaSystemSsh } from './system-ssh-file-transfer'
import { CONNECT_TIMEOUT_MS } from './ssh-connection-utils'
import type { SshTarget } from '../../shared/ssh-types'
import {
@@ -33,8 +34,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -42,6 +56,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
+2 -2
View File
@@ -2,8 +2,8 @@ import { EventEmitter } from 'node:events'
import { vi } from 'vitest'
import type { Mock } from 'vitest'
import type { AnyAuthMethod, AuthenticationType } from 'ssh2'
import type { SshConnectionCallbacks } from './ssh-connection'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshConnectionCallbacks } from './ssh-connection-utils'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import type { SshTarget } from '../../shared/ssh-types'
export function createTarget(overrides?: Partial<SshTarget>): SshTarget {
+35 -21
View File
@@ -2,9 +2,14 @@ import { vi } from 'vitest'
import { createSystemCommandChannel, createSystemSshProcess } from './ssh-connection-test-fixtures'
import type { SshConnection } from './ssh-connection'
import type { MockSystemCommandChannel, MockSystemSshProcess } from './ssh-connection-test-fixtures'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import type { SystemSshBuildArgsOptions } from './system-ssh-args'
import type { SshTarget } from '../../shared/ssh-types'
import type * as SystemSshArgs from './system-ssh-args'
import type * as SystemSshCommand from './system-ssh-command'
import type * as SystemSshFileBinaryTransfer from './system-ssh-file-binary-transfer'
import type * as SystemSshFileTransfer from './system-ssh-file-transfer'
import type * as SshGConfigResolution from './ssh-g-config-resolution'
import { resetSsh2ClientState, ssh2Mock } from './__tests__/ssh-connection-test-client'
export {
clientInstances,
@@ -22,23 +27,10 @@ export type { MockSshClient, Ssh2ModuleMock } from './__tests__/ssh-connection-t
export type SystemSshBinaryModuleMock = { findSystemSsh: typeof findSystemSshMock }
export type SystemFallbackModuleMock = {
getOrcaControlSocketPath: typeof getOrcaControlSocketPathMock
spawnSystemSsh: typeof spawnSystemSshMock
spawnSystemSshCommand: typeof spawnSystemSshCommandMock
downloadFileViaSystemSsh: typeof downloadFileViaSystemSshMock
uploadDirectoryViaSystemSsh: typeof uploadDirectoryViaSystemSshMock
uploadFileViaSystemSsh: typeof uploadFileViaSystemSshMock
writeBufferViaSystemSsh: typeof writeBufferViaSystemSshMock
writeFileViaSystemSsh: typeof writeFileViaSystemSshMock
}
export type ControlSocketModuleMock = {
removeControlSocketPath: typeof removeControlSocketPathMock
}
export type SshConfigParserModuleMock = { resolveWithSshG: typeof resolveWithSshGMock }
export const findSystemSshMock = vi.fn<() => string | null>()
export const getOrcaControlSocketPathMock =
vi.fn<(target: SshTarget, options?: SystemSshBuildArgsOptions) => string | null>()
@@ -83,15 +75,32 @@ export function createSystemSshBinaryModule(): SystemSshBinaryModuleMock {
return { findSystemSsh: findSystemSshMock }
}
export function createSystemFallbackModule(): SystemFallbackModuleMock {
// The system-ssh seams SshConnection reaches, each layered over its module's real exports.
export function withSystemSshArgsMocks(actual: typeof SystemSshArgs) {
return { ...actual, getOrcaControlSocketPath: getOrcaControlSocketPathMock }
}
export function withSystemSshCommandMocks(actual: typeof SystemSshCommand) {
return {
getOrcaControlSocketPath: getOrcaControlSocketPathMock,
...actual,
spawnSystemSsh: spawnSystemSshMock,
spawnSystemSshCommand: spawnSystemSshCommandMock,
spawnSystemSshCommand: spawnSystemSshCommandMock
}
}
export function withSystemSshFileBinaryTransferMocks(actual: typeof SystemSshFileBinaryTransfer) {
return {
...actual,
downloadFileViaSystemSsh: downloadFileViaSystemSshMock,
uploadDirectoryViaSystemSsh: uploadDirectoryViaSystemSshMock,
uploadFileViaSystemSsh: uploadFileViaSystemSshMock,
writeBufferViaSystemSsh: writeBufferViaSystemSshMock,
writeBufferViaSystemSsh: writeBufferViaSystemSshMock
}
}
export function withSystemSshFileTransferMocks(actual: typeof SystemSshFileTransfer) {
return {
...actual,
uploadDirectoryViaSystemSsh: uploadDirectoryViaSystemSshMock,
writeFileViaSystemSsh: writeFileViaSystemSshMock
}
}
@@ -100,8 +109,13 @@ export function createControlSocketModule(): ControlSocketModuleMock {
return { removeControlSocketPath: removeControlSocketPathMock }
}
export function createSshConfigParserModule(): SshConfigParserModuleMock {
return { resolveWithSshG: resolveWithSshGMock }
// Why: an unreadable config keeps the developer's own ~/.ssh/config out of alias-claim verdicts.
export function createSshConfigParserModule(): Record<string, never> {
return {}
}
export function withSshGConfigResolutionMocks(actual: typeof SshGConfigResolution) {
return { ...actual, resolveWithSshG: resolveWithSshGMock }
}
export function resetSshConnectionMocks(): void {
+1 -1
View File
@@ -32,7 +32,7 @@ import { findDefaultKeyFile, resolveAgentSocket } from './ssh-auth-resolution'
import { resolveEffectiveProxy } from './ssh-proxy-command'
import { walkInitialAuthLadder } from './ssh-connection-test-fixtures'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
// ── isTransientError ─────────────────────────────────────────────────
+1 -1
View File
@@ -1,6 +1,6 @@
import type { ConnectConfig } from 'ssh2'
import type { SshTarget, SshConnectionState } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import {
findEncryptedPrivateKeyPath,
isUnencryptedPrivateKey,
+21 -3
View File
@@ -16,7 +16,7 @@ import {
createTarget
} from './ssh-connection-test-fixtures'
import { SshConnection } from './ssh-connection'
import { resolveWithSshG } from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import { SshConnectionManager } from './ssh-connection-manager'
import { RECONNECT_BACKOFF_MS } from './ssh-connection-utils'
import { recordSshUserDisconnected, resetSshUserDisconnectsForTests } from './ssh-user-disconnect'
@@ -25,8 +25,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -34,6 +47,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
function failHandshakes(): void {
ssh2Mock.connectBehavior = 'error'
+20 -2
View File
@@ -15,8 +15,21 @@ vi.mock('ssh2', async () => (await import('./ssh-connection-test-harness')).crea
vi.mock('./system-ssh-binary', async () =>
(await import('./ssh-connection-test-harness')).createSystemSshBinaryModule()
)
vi.mock('./ssh-system-fallback', async () =>
(await import('./ssh-connection-test-harness')).createSystemFallbackModule()
vi.mock('./system-ssh-args', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshArgsMocks(await importOriginal())
)
vi.mock('./system-ssh-command', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshCommandMocks(await importOriginal())
)
vi.mock('./system-ssh-file-binary-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileBinaryTransferMocks(
await importOriginal()
)
)
vi.mock('./system-ssh-file-transfer', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSystemSshFileTransferMocks(
await importOriginal()
)
)
vi.mock('./ssh-control-socket', async () =>
(await import('./ssh-connection-test-harness')).createControlSocketModule()
@@ -24,6 +37,11 @@ vi.mock('./ssh-control-socket', async () =>
vi.mock('./ssh-config-parser', async () =>
(await import('./ssh-connection-test-harness')).createSshConfigParserModule()
)
vi.mock('./ssh-g-config-resolution', async (importOriginal) =>
(await import('./ssh-connection-test-harness')).withSshGConfigResolutionMocks(
await importOriginal()
)
)
describe('SshConnection', () => {
beforeEach(() => {
+9 -8
View File
@@ -23,12 +23,11 @@ import type {
import type { SshTarget, SshConnectionState, SshConnectionStatus } from '../../shared/ssh-types'
import {
getOrcaControlSocketPath,
spawnSystemSshCommand,
isOpenSshConfigBackedTarget,
type SystemSshBuildArgsOptions
} from './ssh-system-fallback'
import { resolveWithSshG, type SshResolvedConfig } from './ssh-config-parser'
} from './system-ssh-args'
import { spawnSystemSshCommand } from './system-ssh-command'
import { removeControlSocketPath } from './ssh-control-socket'
import { isOpenSshConfigBackedTarget } from './system-ssh-args'
import {
INITIAL_RETRY_ATTEMPTS,
INITIAL_RETRY_DELAY_MS,
@@ -57,7 +56,12 @@ import {
orderServerHostKeyAlgorithms
} from './ssh-host-key-verifier'
import { HostKeyVerificationError, isHostKeyVerificationError } from './ssh-host-key-decision'
import { siteConfigMayRestrictHostKeys, sshGArgsForHost } from './ssh-g-config-resolution'
import {
resolveWithSshG,
siteConfigMayRestrictHostKeys,
sshGArgsForHost,
type SshResolvedConfig
} from './ssh-g-config-resolution'
import {
boundSshHostKeyStoreFile,
loadTrustedHostKeys,
@@ -95,7 +99,6 @@ import { tagSftpHandshakeCorruption } from './sftp-handshake-corruption'
import { withTimeout } from '../../shared/promise-timeout-fallback'
import { isEphemeralRuntimeSshOwner } from '../../shared/managed-orcad-ssh-owner'
import { isSshUserDisconnected } from './ssh-user-disconnect'
export type { SshConnectionCallbacks } from './ssh-connection-utils'
/** The sign-in a connection holds in memory, handed to the connection that replaces it. */
export type SshCachedCredentials = { password: string | null; passphrase: string | null }
@@ -1611,5 +1614,3 @@ export class SshConnection {
this.callbacks.onStateChange(this.target.id, { ...this.state })
}
}
export { shouldUseSystemSshTransport } from './ssh-transport-selection'
+1 -1
View File
@@ -3,7 +3,7 @@ import { lstatSync, mkdirSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { isAbsolute, join as pathJoin } from 'node:path'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
export type SystemSshResolvedConfig = Pick<
SshResolvedConfig,
@@ -7,11 +7,11 @@ import { SshConnection } from './ssh-connection'
import { INITIAL_RETRY_DELAY_MS } from './ssh-connection-utils'
import { createCallbacks, createResolvedConfig, createTarget } from './ssh-connection-test-fixtures'
import { initSshHostKeyStoreFile } from './ssh-host-key-store'
import { resolveWithSshG } from './ssh-config-parser'
import type * as SshConfigParser from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import type * as SshGConfigResolution from './ssh-g-config-resolution'
vi.mock('./ssh-config-parser', async (importOriginal) => ({
...(await importOriginal<typeof SshConfigParser>()),
vi.mock('./ssh-g-config-resolution', async (importOriginal) => ({
...(await importOriginal<typeof SshGConfigResolution>()),
resolveWithSshG: vi.fn()
}))
@@ -9,7 +9,10 @@
*/
import { RELAY_REMOTE_DIR } from './relay-protocol'
import { commandWithNodePath } from './ssh-remote-commands'
import { powerShellLiteral, powerShellNativeArg } from './ssh-remote-powershell'
import {
quotePowerShellLiteral as powerShellLiteral,
quotePowerShellNativeArgument as powerShellNativeArg
} from '../../shared/powershell-native-argument'
import { windowsRelayPipePathsForSocketName } from './ssh-relay-endpoints'
import { RELAY_INSTALL_MODEL, remoteInstallVersionDirRegex } from './remote-install-model'
import { joinRemotePath, type RemoteHostPlatform } from './ssh-remote-platform'
@@ -6,11 +6,11 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { SshConnection } from './ssh-connection'
import { createCallbacks, createResolvedConfig, createTarget } from './ssh-connection-test-fixtures'
import { initSshHostKeyStoreFile } from './ssh-host-key-store'
import { resolveWithSshG } from './ssh-config-parser'
import type * as SshConfigParser from './ssh-config-parser'
import { resolveWithSshG } from './ssh-g-config-resolution'
import type * as SshGConfigResolution from './ssh-g-config-resolution'
vi.mock('./ssh-config-parser', async (importOriginal) => ({
...(await importOriginal<typeof SshConfigParser>()),
vi.mock('./ssh-g-config-resolution', async (importOriginal) => ({
...(await importOriginal<typeof SshGConfigResolution>()),
resolveWithSshG: vi.fn()
}))
@@ -18,7 +18,7 @@ import {
} from 'ssh2'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import { buildConnectConfig, type BuildConnectConfigOptions } from './ssh-connection-utils'
vi.mock('node:os', async (importOriginal) => {
@@ -27,7 +27,7 @@ import { getPassphrasePrivateKeyPath } from './ssh-private-key-authentication'
import { buildSshArgs } from './system-ssh-args'
import { walkInitialAuthLadder } from './ssh-connection-test-fixtures'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
function makeTarget(overrides: Partial<SshTarget> = {}): SshTarget {
return {
+1 -1
View File
@@ -3,7 +3,7 @@ import { spawnProcess } from '@orca/process-host'
import { Duplex } from 'node:stream'
import type { Socket as NetSocket } from 'node:net'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import { shellEscape } from './ssh-connection-utils'
import { isOpenSshConfigBackedTarget } from './system-ssh-args'
+2 -1
View File
@@ -9,7 +9,8 @@ import {
tryStealInstallLockCommand
} from './ssh-relay-install-lock-commands'
import { removeRemoteTreeCommand } from './ssh-remote-commands'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import {
getRemoteHostPlatform,
isWindowsRemoteHost,
@@ -1,5 +1,6 @@
import { shellEscape } from './ssh-connection-utils'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import { isWindowsRemoteHost, type RemoteHostPlatform } from './ssh-remote-platform'
import * as exitedOwnerSteal from './ssh-relay-install-lock-exited-owner'
@@ -4,7 +4,7 @@
*/
import { shellEscape } from './ssh-connection-utils'
import type { InstallLockOwnerFile } from './ssh-relay-install-lock-commands'
import { powerShellLiteral } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import {
posixStateMutationGroupRecord,
posixStateMutationPidRecord
@@ -1,7 +1,7 @@
/** How the host census reaches a running Windows relay through its own bridge. */
import { commandWithNodePath } from './ssh-remote-commands'
import type { RemoteHostPlatform } from './ssh-remote-platform'
import { powerShellLiteral } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
export function windowsRelayConnectCommand(
hostPlatform: RemoteHostPlatform,
+2 -1
View File
@@ -1,7 +1,8 @@
import { remoteInstallListingRegexSource, type RemoteInstallModel } from './remote-install-model'
import type { RemoteHostPlatform } from './ssh-remote-platform'
import { isWindowsRemoteHost, joinRemotePath, remoteDirname } from './ssh-remote-platform'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import { shellEscape } from './ssh-connection-utils'
export function readRemoteHomeCommand(host: RemoteHostPlatform): string {
+2 -1
View File
@@ -1,6 +1,7 @@
import type { SshConnectionManager } from './ssh-connection-manager'
import type { SshExecOptions } from './ssh-connection-utils'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import type { FilesystemPathFlavor } from '../../shared/filesystem-entry-types'
import { sortDirEntries } from '../../shared/file-name-sort'
import { buildPosixStdoutFence } from '../../shared/posix-stdout-fence'
@@ -1,6 +1,6 @@
import { posix as posixPath } from 'node:path'
import { shellEscape } from './ssh-connection-utils'
import { powerShellLiteral } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
/** The host-Node floor for the npm path. */
export const MIN_HOST_NODE_MAJOR = 18
-4
View File
@@ -1,10 +1,6 @@
import { gunzipSync, gzipSync } from 'node:zlib'
import { encodePowerShellCommand } from '../../shared/powershell-command-encoding'
import { CMD_EXE_COMMAND_LINE_MAX_CHARS } from '../providers/windows-shell-args'
export {
quotePowerShellLiteral as powerShellLiteral,
quotePowerShellNativeArgument as powerShellNativeArg
} from '../../shared/powershell-native-argument'
// Why cmd.exe and not the 32767 CreateProcess cap: Windows OpenSSH runs every exec request
// through sshd's DefaultShell, cmd.exe on a stock install. Budget under cmd.exe's own ceiling
-13
View File
@@ -1,13 +0,0 @@
export { findSystemSsh } from './system-ssh-binary'
export {
buildSshArgs,
getOrcaControlSocketPath,
type SystemSshBuildArgsOptions
} from './system-ssh-args'
export { spawnSystemSsh, spawnSystemSshCommand, type SystemSshProcess } from './system-ssh-command'
export {
downloadFileViaSystemSsh,
uploadFileViaSystemSsh,
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
export { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './system-ssh-file-transfer'
@@ -7,7 +7,7 @@ vi.mock('electron', () => ({
}))
import { SshConnection } from './ssh-connection'
import { uploadDirectoryViaSystemSsh } from './ssh-system-fallback'
import { uploadDirectoryViaSystemSsh } from './system-ssh-file-transfer'
import type { SshTarget } from '../../shared/ssh-types'
import { relayArtifactFilenames } from './relay-install-artifacts'
+1 -1
View File
@@ -1,7 +1,7 @@
import { constants } from 'node:fs'
import { open, stat } from 'node:fs/promises'
import type { SshTarget } from '../../shared/ssh-types'
import type { SshResolvedConfig } from './ssh-config-parser'
import type { SshResolvedConfig } from './ssh-g-config-resolution'
import { listDefaultIdentityFilePaths, resolveIdentityFilePaths } from './ssh-auth-resolution'
import { resolveSshConfigHomePath } from './ssh-config-path-expansion'
import {
@@ -10,10 +10,7 @@ const { spawnMock, connectMock, createServerMock, waitForStopMock } = vi.hoisted
vi.mock('node:child_process', () => ({ spawn: spawnMock }))
vi.mock('node:net', () => ({ connect: connectMock, createServer: createServerMock }))
vi.mock('./ssh-system-fallback', async (importOriginal) => {
const actual = (await importOriginal()) as Record<string, unknown>
return { ...actual, findSystemSsh: () => '/usr/bin/ssh' }
})
vi.mock('./system-ssh-binary', () => ({ findSystemSsh: () => '/usr/bin/ssh' }))
vi.mock('./system-ssh-forward-process', () => ({
waitForSystemSshForwardStop: waitForStopMock
}))
@@ -1,7 +1,8 @@
import { spawn, type ChildProcess } from 'node:child_process'
import { connect, createServer, type AddressInfo, type Socket } from 'node:net'
import type { SshTarget } from '../../shared/ssh-types'
import { buildSshArgs, findSystemSsh, type SystemSshBuildArgsOptions } from './ssh-system-fallback'
import { buildSshArgs, type SystemSshBuildArgsOptions } from './system-ssh-args'
import { findSystemSsh } from './system-ssh-binary'
import { waitForSystemSshForwardStop } from './system-ssh-forward-process'
const STARTUP_TIMEOUT_MS = 10_000
@@ -12,7 +12,8 @@ import {
} from './system-ssh-args'
import { spawnSystemSshCommand } from './system-ssh-command'
import { isWindowsRemoteHost, type RemoteHostPlatform } from './ssh-remote-platform'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import {
awaitWithSystemSshAbort,
throwIfAborted,
@@ -23,12 +24,6 @@ import {
type WindowsWriteSource
} from './system-ssh-windows-write-strategy'
export {
WINDOWS_STDIN_WRITE_CHUNK_BYTES,
WINDOWS_STDIN_WRITE_TIMEOUT_MS
} from './system-ssh-windows-write-strategy'
export { WINDOWS_STAGED_WRITE_SUFFIX } from './system-ssh-windows-file-write'
type SystemSshOperationOptions = SystemSshBuildArgsOptions & {
signal?: AbortSignal
hostPlatform?: RemoteHostPlatform
+3 -4
View File
@@ -23,12 +23,11 @@ import {
isHostAnsweredSystemSshExit,
type ProcessResult
} from './system-ssh-operation-lifecycle'
import { uploadFileViaSystemSsh, writeBufferViaSystemSsh } from './system-ssh-file-binary-transfer'
import {
uploadFileViaSystemSsh,
WINDOWS_STDIN_WRITE_CHUNK_BYTES,
WINDOWS_STDIN_WRITE_TIMEOUT_MS,
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
WINDOWS_STDIN_WRITE_TIMEOUT_MS
} from './system-ssh-windows-write-strategy'
import {
isSftpPathUnsupportedError,
isSftpUnavailableError,
+2 -1
View File
@@ -1,6 +1,7 @@
import { spawn, type ChildProcess } from 'node:child_process'
import { connect, createServer } from 'node:net'
import { buildSshArgs, findSystemSsh, type SystemSshBuildArgsOptions } from './ssh-system-fallback'
import { buildSshArgs, type SystemSshBuildArgsOptions } from './system-ssh-args'
import { findSystemSsh } from './system-ssh-binary'
import { stopOrphanedOrcaSshForward } from './system-ssh-orphaned-forward'
import type { SshTarget } from '../../shared/ssh-types'
@@ -22,16 +22,14 @@ vi.mock('child_process', () => ({
spawn: spawnMock
}))
import { buildSshArgs } from './system-ssh-args'
import {
buildSshArgs,
downloadFileViaSystemSsh,
spawnSystemSsh,
spawnSystemSshCommand,
uploadDirectoryViaSystemSsh,
uploadFileViaSystemSsh,
writeBufferViaSystemSsh,
writeFileViaSystemSsh
} from './ssh-system-fallback'
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
import { spawnSystemSsh, spawnSystemSshCommand } from './system-ssh-command'
import { uploadDirectoryViaSystemSsh, writeFileViaSystemSsh } from './system-ssh-file-transfer'
import { getRemoteHostPlatform } from './ssh-remote-platform'
import type { SshTarget } from '../../shared/ssh-types'
import type { SystemSshResolvedConfig } from './ssh-control-socket'
@@ -1,5 +1,6 @@
import { randomBytes } from 'node:crypto'
import { powerShellCommand, powerShellLiteral } from './ssh-remote-powershell'
import { powerShellCommand } from './ssh-remote-powershell'
import { quotePowerShellLiteral as powerShellLiteral } from '../../shared/powershell-native-argument'
import { normalizeWindowsRemotePath } from './ssh-remote-platform'
/**
@@ -43,13 +43,8 @@ vi.mock('./system-ssh-operation-lifecycle', async (importActual) => {
})
import { uploadDirectoryViaSystemSsh } from './system-ssh-file-transfer'
import {
uploadFileViaSystemSsh,
WINDOWS_STAGED_WRITE_SUFFIX,
WINDOWS_STDIN_WRITE_CHUNK_BYTES,
WINDOWS_STDIN_WRITE_TIMEOUT_MS,
writeBufferViaSystemSsh
} from './system-ssh-file-binary-transfer'
import { uploadFileViaSystemSsh, writeBufferViaSystemSsh } from './system-ssh-file-binary-transfer'
import { WINDOWS_STAGED_WRITE_SUFFIX } from './system-ssh-windows-file-write'
import { waitForChannelClose } from './system-ssh-operation-lifecycle'
import * as windowsFileWrite from './system-ssh-windows-file-write'
import { getRemoteHostPlatform } from './ssh-remote-platform'
@@ -59,6 +54,8 @@ import {
} from './system-ssh-windows-write-capabilities'
import {
explainWindowsPowerShellStdinFailure,
WINDOWS_STDIN_WRITE_CHUNK_BYTES,
WINDOWS_STDIN_WRITE_TIMEOUT_MS,
writeWindowsRemoteFile
} from './system-ssh-windows-write-strategy'
import type { SshTarget } from '../../shared/ssh-types'