mirror of
https://bitbucket.org/siakitem/my-pi.git
synced 2026-08-28 08:35:57 +00:00
fix(pi-ssh): harden remote execution and search
This commit is contained in:
@@ -182,12 +182,15 @@ test("connects with password auth, pins the host key, and streams exec output",
|
||||
assert.equal(fake.connectConfig?.hostVerifier?.(fixtureKey("wrong")), false);
|
||||
|
||||
const output: Buffer[] = [];
|
||||
const stderr: Buffer[] = [];
|
||||
const result = await transport.exec("printf ok", "/srv/build", {
|
||||
onData: (data) => output.push(data),
|
||||
onStderr: (data) => stderr.push(data),
|
||||
timeout: 5,
|
||||
});
|
||||
assert.equal(result.exitCode, 7);
|
||||
assert.equal(Buffer.concat(output).toString("utf8"), "stdout\nstderr\n");
|
||||
assert.equal(Buffer.concat(output).toString("utf8"), "stdout\n");
|
||||
assert.equal(Buffer.concat(stderr).toString("utf8"), "stderr\n");
|
||||
assert.match(fake.command ?? "", /^cd -- '\/srv\/build' && bash -lc 'printf ok' <\/dev\/null$/);
|
||||
await transport.dispose();
|
||||
assert.equal(fake.ended, true);
|
||||
@@ -279,6 +282,64 @@ test("falls back to direct overwrite when SFTP v3 rename cannot replace", async
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test("aborts an in-progress SSH connection attempt", async () => {
|
||||
const fake = new FakeClient();
|
||||
fake.connectAction = () => {};
|
||||
const transport = new Ssh2Transport(passwordHost(), fake as unknown as Client);
|
||||
const controller = new AbortController();
|
||||
const connecting = transport.connect(controller.signal);
|
||||
await new Promise<void>((resolve) => setImmediate(resolve));
|
||||
controller.abort();
|
||||
await assert.rejects(connecting, /SSH connection aborted/);
|
||||
assert.equal(fake.destroyed, true);
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test("allows four independent exec channels and bounds additional commands", async () => {
|
||||
const fake = new FakeClient();
|
||||
const channels: FakeChannel[] = [];
|
||||
fake.execAction = (_command, callback) => {
|
||||
const channel = new FakeChannel();
|
||||
channels.push(channel);
|
||||
callback(undefined, channel as ClientChannel);
|
||||
};
|
||||
const transport = new Ssh2Transport(passwordHost(), fake as unknown as Client);
|
||||
await transport.connect();
|
||||
const commands = Array.from({ length: 5 }, (_, index) =>
|
||||
transport.exec(`command-${index}`, "/srv", { onData() {}, timeout: 0 }),
|
||||
);
|
||||
await new Promise<void>((resolve) => setImmediate(resolve));
|
||||
assert.equal(channels.length, 4);
|
||||
channels[0]?.emit("close", 0);
|
||||
await new Promise<void>((resolve) => setImmediate(resolve));
|
||||
assert.equal(channels.length, 5);
|
||||
for (const channel of channels.slice(1)) channel.emit("close", 0);
|
||||
await Promise.all(commands);
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test("cancels an exec while it is waiting for a concurrency slot", async () => {
|
||||
const fake = new FakeClient();
|
||||
const channels: FakeChannel[] = [];
|
||||
fake.execAction = (_command, callback) => {
|
||||
const channel = new FakeChannel();
|
||||
channels.push(channel);
|
||||
callback(undefined, channel as ClientChannel);
|
||||
};
|
||||
const transport = new Ssh2Transport(passwordHost(), fake as unknown as Client);
|
||||
await transport.connect();
|
||||
const active = Array.from({ length: 4 }, () => transport.exec("sleep", "/srv", { onData() {}, timeout: 0 }));
|
||||
await new Promise<void>((resolve) => setImmediate(resolve));
|
||||
const controller = new AbortController();
|
||||
const queued = transport.exec("queued", "/srv", { onData() {}, timeout: 0, signal: controller.signal });
|
||||
controller.abort();
|
||||
await assert.rejects(queued, /SSH command aborted/);
|
||||
assert.equal(channels.length, 4);
|
||||
for (const channel of channels) channel.emit("close", 0);
|
||||
await Promise.all(active);
|
||||
await transport.dispose();
|
||||
});
|
||||
|
||||
test("aborts and times out commands by closing the active channel", async () => {
|
||||
const abortClient = new FakeClient();
|
||||
const abortChannel = new FakeChannel();
|
||||
|
||||
Reference in New Issue
Block a user