test(launcher): stabilize SSH resolver coverage

This commit is contained in:
2026-07-09 22:39:26 -07:00
parent cbb19864c4
commit 3d715c8b89
2 changed files with 22 additions and 28 deletions
+16 -26
View File
@@ -1,8 +1,5 @@
import test from 'node:test'; import test from 'node:test';
import assert from 'node:assert/strict'; import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { assertSafeSshHost, resolveRemoteSubminerCommand, runScp, shellQuote } from './ssh.js'; import { assertSafeSshHost, resolveRemoteSubminerCommand, runScp, shellQuote } from './ssh.js';
test('assertSafeSshHost rejects option-like hosts', () => { test('assertSafeSshHost rejects option-like hosts', () => {
@@ -34,28 +31,21 @@ test('runScp rejects option-like remote host components', () => {
}); });
test('resolveRemoteSubminerCommand verifies the launcher under the remote runtime PATH', () => { test('resolveRemoteSubminerCommand verifies the launcher under the remote runtime PATH', () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'subminer-ssh-test-')); const calls: Array<{ host: string; remoteCommand: string }> = [];
const sshPath = path.join(tempDir, 'ssh'); const command = resolveRemoteSubminerCommand('macbook', null, (host, remoteCommand) => {
const originalPath = process.env.PATH; calls.push({ host, remoteCommand });
fs.writeFileSync( return { status: 0, stdout: '', stderr: '' };
sshPath, });
`#!/bin/sh
case "$2" in
*'$HOME/.local/bin'*'$HOME/.bun/bin'*'/opt/homebrew/bin'*'/usr/local/bin'*'/usr/bin'*'/bin'*'subminer --help'*) exit 0 ;;
*) exit 1 ;;
esac
`,
{ mode: 0o755 },
);
try { assert.equal(
process.env.PATH = `${tempDir}:${originalPath ?? ''}`; command,
assert.equal( 'PATH="$HOME/.local/bin:$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH" subminer',
resolveRemoteSubminerCommand('macbook', null), );
'PATH="$HOME/.local/bin:$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH" subminer', assert.deepEqual(calls, [
); {
} finally { host: 'macbook',
process.env.PATH = originalPath; remoteCommand:
fs.rmSync(tempDir, { recursive: true, force: true }); 'PATH="$HOME/.local/bin:$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH" subminer --help >/dev/null 2>&1',
} },
]);
}); });
+6 -2
View File
@@ -78,7 +78,11 @@ const REMOTE_RUNTIME_PATH =
* Non-interactive SSH shells often miss user-installed launchers and Bun. * Non-interactive SSH shells often miss user-installed launchers and Bun.
* Probe the launcher under the same deterministic PATH used by sync itself. * Probe the launcher under the same deterministic PATH used by sync itself.
*/ */
export function resolveRemoteSubminerCommand(host: string, preferred: string | null): string { export function resolveRemoteSubminerCommand(
host: string,
preferred: string | null,
runRemote: typeof runSsh = runSsh,
): string {
// Trusted defaults stay unquoted so the remote shell expands `~`; a // Trusted defaults stay unquoted so the remote shell expands `~`; a
// user-supplied override is shell-quoted to prevent command injection. // user-supplied override is shell-quoted to prevent command injection.
const candidates: Array<{ value: string; invocation: string }> = preferred const candidates: Array<{ value: string; invocation: string }> = preferred
@@ -89,7 +93,7 @@ export function resolveRemoteSubminerCommand(host: string, preferred: string | n
]; ];
for (const candidate of candidates) { for (const candidate of candidates) {
const command = `${REMOTE_RUNTIME_PATH} ${candidate.invocation}`; const command = `${REMOTE_RUNTIME_PATH} ${candidate.invocation}`;
const probe = runSsh(host, `${command} --help >/dev/null 2>&1`); const probe = runRemote(host, `${command} --help >/dev/null 2>&1`);
if (probe.status === 0) { if (probe.status === 0) {
return command; return command;
} }