Skip to main content
Glama
queue-limit-unit-test.test.ts4.8 kB
import { SSHConnectionManager } from "../src/ssh-connection-manager"; import { SSHConnectionConfig, CommandSource, QUEUE_CONSTANTS, } from "../src/types"; // Mock the ssh2 module jest.mock('ssh2', () => { const mockClient = { on: jest.fn(), shell: jest.fn(), connect: jest.fn(), destroy: jest.fn() }; return { Client: jest.fn(() => mockClient) }; }); describe("Queue Limit Unit Test", () => { let connectionManager: SSHConnectionManager; const mockConfig: SSHConnectionConfig = { name: "limit-test-session", host: "localhost", username: "testuser", password: "testpass" }; beforeEach(() => { connectionManager = new SSHConnectionManager(); jest.clearAllMocks(); const mockClient = require('ssh2').Client(); const mockChannel = { on: jest.fn(), write: jest.fn(), end: jest.fn(), removeListener: jest.fn(), stderr: { on: jest.fn() }, setWindow: jest.fn() }; mockClient.on = jest.fn((event, callback) => { if (event === 'ready') { setTimeout(() => callback(), 0); } }); mockClient.shell = jest.fn((callback) => { callback(null, mockChannel); }); mockClient.connect = jest.fn(); let dataCallback: ((data: Buffer) => void) | undefined; mockChannel.on = jest.fn((event, callback) => { if (event === 'data') { dataCallback = callback; setTimeout(() => { if (dataCallback) { dataCallback(Buffer.from('user@localhost:~$ ')); } }, 10); } }); // Mock shell channel to never complete commands // This will cause them to stay in executing state mockChannel.write = jest.fn(); }); afterEach(() => { connectionManager.cleanup(); }); it("should enforce queue size limit by synchronously adding many commands", async () => { await connectionManager.createConnection(mockConfig); const promises: Promise<any>[] = []; // Add significantly more than MAX_QUEUE_SIZE commands for (let i = 0; i < QUEUE_CONSTANTS.MAX_QUEUE_SIZE + 10; i++) { const promise = connectionManager.executeCommand( mockConfig.name, `echo "command ${i}"`, { source: "claude" as CommandSource } ); promises.push(promise); } console.log(`Created ${promises.length} command promises`); // Wait for all promises to settle const results = await Promise.allSettled(promises); // Count rejections const rejectedCount = results.filter(result => result.status === 'rejected').length; const fulfilledCount = results.filter(result => result.status === 'fulfilled').length; console.log(`Rejected: ${rejectedCount}, Fulfilled: ${fulfilledCount}`); // Should have exactly 10 rejections (commands beyond MAX_QUEUE_SIZE) expect(rejectedCount).toBe(10); expect(fulfilledCount).toBeLessThanOrEqual(QUEUE_CONSTANTS.MAX_QUEUE_SIZE); // Verify rejection reasons const rejectedResults = results.filter(result => result.status === 'rejected') as PromiseRejectedResult[]; rejectedResults.forEach(result => { expect(result.reason.message).toMatch(/queue.*full/i); }); }, 30000); it("should reject the 101st command when queue is full", async () => { await connectionManager.createConnection(mockConfig); const promises: Promise<any>[] = []; // Add exactly MAX_QUEUE_SIZE + 1 commands for (let i = 0; i <= QUEUE_CONSTANTS.MAX_QUEUE_SIZE; i++) { const promise = connectionManager.executeCommand( mockConfig.name, `echo "command ${i}"`, { source: "claude" as CommandSource } ); promises.push(promise); } // Wait for all to settle const results = await Promise.allSettled(promises); const rejectedCount = results.filter(result => result.status === 'rejected').length; const fulfilledCount = results.filter(result => result.status === 'fulfilled').length; console.log(`Total commands: ${results.length}, Rejected: ${rejectedCount}, Fulfilled: ${fulfilledCount}`); // Should have exactly 1 rejection (the 101st command) expect(rejectedCount).toBe(1); expect(fulfilledCount).toBe(QUEUE_CONSTANTS.MAX_QUEUE_SIZE); // Check the rejection message const rejectedResult = results.find(result => result.status === 'rejected') as PromiseRejectedResult; expect(rejectedResult.reason.message).toMatch(/queue.*full/i); expect(rejectedResult.reason.message).toContain('100'); }, 30000); it("should validate constants are reasonable", () => { expect(QUEUE_CONSTANTS.MAX_QUEUE_SIZE).toBe(100); // MAX_COMMAND_AGE_MS has been removed as part of timeout system cleanup }); });

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