Skip to main content
Glama
story3-queue-integration-real.test.ts9.1 kB
import { SSHConnectionManager } from "../src/ssh-connection-manager"; import { SSHConnectionConfig, CommandSource, } from "../src/types"; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; describe("Story 3: Command Queue Integration (Real SSH)", () => { let connectionManager: SSHConnectionManager; // Use real SSH connection to localhost const sshConfig: SSHConnectionConfig = { name: "queue-integration-test", host: "localhost", username: process.env.USER || "testuser", keyFilePath: path.join(os.homedir(), ".ssh/id_ed25519") }; beforeAll(() => { // Skip tests if SSH key doesn't exist if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("SSH key not found, skipping integration tests"); } }); beforeEach(() => { connectionManager = new SSHConnectionManager(); }); afterEach(() => { connectionManager.cleanup(); }); describe("Real Queue Behavior", () => { it("should execute commands sequentially in FIFO order", async () => { // Skip if SSH key doesn't exist if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); const startTime = Date.now(); // Execute multiple commands that should queue const promises = [ connectionManager.executeCommand(sshConfig.name, "echo 'first command' && sleep 0.1", { source: "user" as CommandSource }), connectionManager.executeCommand(sshConfig.name, "echo 'second command' && sleep 0.1", { source: "claude" as CommandSource }), connectionManager.executeCommand(sshConfig.name, "echo 'third command'", { source: "user" as CommandSource }) ]; const results = await Promise.all(promises); const totalTime = Date.now() - startTime; // Verify all commands completed successfully expect(results).toHaveLength(3); expect(results[0].stdout).toContain("first command"); expect(results[1].stdout).toContain("second command"); expect(results[2].stdout).toContain("third command"); // Since commands execute sequentially, total time should be at least the sum of sleep times expect(totalTime).toBeGreaterThan(200); // At least 200ms for the sleeps console.log(`Commands executed in ${totalTime}ms`); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 15000); it("should handle command errors without blocking the queue", async () => { if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); // First command will have non-zero exit code (invalid command) const failingCommand = connectionManager.executeCommand( sshConfig.name, "nonexistentcommandthatfails123", { source: "user" as CommandSource } ); // Second command should succeed despite first having error const succeedingCommand = connectionManager.executeCommand( sshConfig.name, "echo 'success after failure'", { source: "claude" as CommandSource } ); const [failedResult, successResult] = await Promise.all([failingCommand, succeedingCommand]); // First command should have error output but not throw (this is correct behavior) expect(failedResult.stdout).toContain("command not found"); expect(successResult.stdout).toContain("success after failure"); console.log("Error handling test completed successfully"); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 15000); it("should handle actual thrown errors without blocking the queue", async () => { if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); let errorOccurred = false; // This command should actually throw an error (exit is blocked) const failingCommand = connectionManager.executeCommand( sshConfig.name, "exit", { source: "user" as CommandSource } ).catch((error) => { errorOccurred = true; throw error; }); // This command should succeed despite first throwing const succeedingCommand = connectionManager.executeCommand( sshConfig.name, "echo 'success after thrown error'", { source: "claude" as CommandSource } ); // First should throw, second should succeed await expect(failingCommand).rejects.toThrow(/would terminate the shell session/); const successResult = await succeedingCommand; expect(errorOccurred).toBe(true); expect(successResult.stdout).toContain("success after thrown error"); console.log("Thrown error handling test completed successfully"); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 15000); it("should preserve command source information through queue", async () => { if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); // Execute commands with different sources const userCommand = connectionManager.executeCommand( sshConfig.name, "echo 'user-initiated command'", { source: "user" as CommandSource } ); const claudeCommand = connectionManager.executeCommand( sshConfig.name, "echo 'claude-initiated command'", { source: "claude" as CommandSource } ); const [userResult, claudeResult] = await Promise.all([userCommand, claudeCommand]); expect(userResult.stdout).toContain("user-initiated command"); expect(claudeResult.stdout).toContain("claude-initiated command"); console.log("Source preservation test completed successfully"); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 15000); }); describe("Backward Compatibility", () => { it("should execute single commands immediately", async () => { if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); const startTime = Date.now(); const result = await connectionManager.executeCommand( sshConfig.name, "echo 'single command test'", { source: "claude" as CommandSource } ); const executionTime = Date.now() - startTime; expect(result.stdout).toContain("single command test"); expect(executionTime).toBeLessThan(2000); // Should be fast for single command console.log(`Single command executed in ${executionTime}ms`); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 10000); }); describe("Queue State Management", () => { it("should properly start next command immediately after completion", async () => { if (!fs.existsSync(sshConfig.keyFilePath!)) { console.log("Skipping test - SSH key not available"); return; } try { await connectionManager.createConnection(sshConfig); const startTime = Date.now(); // First command has a known delay const firstCommand = connectionManager.executeCommand( sshConfig.name, "echo 'first' && sleep 0.2", { source: "user" as CommandSource } ); // Second command should start immediately after first completes const secondCommand = connectionManager.executeCommand( sshConfig.name, "echo 'second'", { source: "claude" as CommandSource } ); const [firstResult, secondResult] = await Promise.all([firstCommand, secondCommand]); const totalTime = Date.now() - startTime; expect(firstResult.stdout).toContain("first"); expect(secondResult.stdout).toContain("second"); // Total time should be close to sleep duration (0.2s = 200ms) plus overhead expect(totalTime).toBeGreaterThan(200); expect(totalTime).toBeLessThan(500); // Should not be much longer than necessary console.log(`Queue state management test completed in ${totalTime}ms`); } catch (error) { console.warn("SSH connection failed, skipping test:", error); } }, 15000); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LightspeedDMS/ssh-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server