This commit is contained in:
2025-05-24 11:34:05 +00:00
parent 9958c036a0
commit 35712b18bc
9 changed files with 391 additions and 570 deletions

View File

@@ -7,6 +7,34 @@ const TEST_PORT = 2525;
let testServer;
// Helper function to wait for SMTP response
const waitForResponse = (socket: net.Socket, expectedCode: string, timeout = 5000): Promise<string> => {
return new Promise((resolve, reject) => {
let buffer = '';
const timer = setTimeout(() => {
socket.removeListener('data', handler);
reject(new Error(`Timeout waiting for ${expectedCode} response`));
}, timeout);
const handler = (data: Buffer) => {
buffer += data.toString();
const lines = buffer.split('\r\n');
// Check if we have a complete response
for (const line of lines) {
if (line.startsWith(expectedCode + ' ')) {
clearTimeout(timer);
socket.removeListener('data', handler);
resolve(buffer);
return;
}
}
};
socket.on('data', handler);
});
};
tap.test('prepare server', async () => {
testServer = await startTestServer({ port: TEST_PORT });
await new Promise(resolve => setTimeout(resolve, 100));
@@ -14,7 +42,7 @@ tap.test('prepare server', async () => {
tap.test('PERF-04: Memory usage - Connection memory test', async (tools) => {
const done = tools.defer();
const connectionCount = 20;
const connectionCount = 10; // Reduced from 20 to make test faster
const connections: net.Socket[] = [];
try {
@@ -45,55 +73,21 @@ tap.test('PERF-04: Memory usage - Connection memory test', async (tools) => {
});
// Read greeting
await new Promise<void>((resolve) => {
socket.once('data', () => resolve());
});
await waitForResponse(socket, '220');
// Send EHLO
socket.write(`EHLO testhost-mem-${i}\r\n`);
await new Promise<void>((resolve) => {
let data = '';
const handleData = (chunk: Buffer) => {
data += chunk.toString();
if (data.includes('250 ') && !data.includes('250-')) {
socket.removeListener('data', handleData);
resolve();
}
};
socket.on('data', handleData);
});
await waitForResponse(socket, '250');
// Send email transaction
socket.write(`MAIL FROM:<sender${i}@example.com>\r\n`);
await new Promise<void>((resolve) => {
socket.once('data', (chunk) => {
const response = chunk.toString();
expect(response).toInclude('250');
resolve();
});
});
await waitForResponse(socket, '250');
socket.write(`RCPT TO:<recipient${i}@example.com>\r\n`);
await new Promise<void>((resolve) => {
socket.once('data', (chunk) => {
const response = chunk.toString();
expect(response).toInclude('250');
resolve();
});
});
await waitForResponse(socket, '250');
socket.write('DATA\r\n');
await new Promise<void>((resolve) => {
socket.once('data', (chunk) => {
const response = chunk.toString();
expect(response).toInclude('354');
resolve();
});
});
await waitForResponse(socket, '354');
// Send large email content
const largeContent = 'This is a large email content for memory testing. '.repeat(100);
@@ -108,14 +102,7 @@ tap.test('PERF-04: Memory usage - Connection memory test', async (tools) => {
].join('\r\n');
socket.write(emailContent);
await new Promise<void>((resolve) => {
socket.once('data', (chunk) => {
const response = chunk.toString();
expect(response).toInclude('250');
resolve();
});
});
await waitForResponse(socket, '250');
// Pause every 5 connections
if (i > 0 && i % 5 === 0) {
@@ -148,8 +135,8 @@ tap.test('PERF-04: Memory usage - Connection memory test', async (tools) => {
}
}
// Test passes if memory increase is reasonable (less than 50MB for 20 connections)
expect(memoryIncreaseMB).toBeLessThan(50);
// Test passes if memory increase is reasonable (less than 30MB for 10 connections)
expect(memoryIncreaseMB).toBeLessThan(30);
done.resolve();
} catch (error) {
// Clean up on error
@@ -160,8 +147,8 @@ tap.test('PERF-04: Memory usage - Connection memory test', async (tools) => {
tap.test('PERF-04: Memory usage - Memory leak detection', async (tools) => {
const done = tools.defer();
const iterations = 5;
const connectionsPerIteration = 5;
const iterations = 3; // Reduced from 5
const connectionsPerIteration = 3; // Reduced from 5
try {
// Force GC if available
@@ -191,28 +178,13 @@ tap.test('PERF-04: Memory usage - Memory leak detection', async (tools) => {
});
// Quick transaction
await new Promise<void>((resolve) => {
socket.once('data', () => resolve());
});
await waitForResponse(socket, '220');
socket.write('EHLO leaktest\r\n');
await new Promise<void>((resolve) => {
let data = '';
const handleData = (chunk: Buffer) => {
data += chunk.toString();
if (data.includes('250 ') && !data.includes('250-')) {
socket.removeListener('data', handleData);
resolve();
}
};
socket.on('data', handleData);
});
await waitForResponse(socket, '250');
socket.write('QUIT\r\n');
await new Promise<void>((resolve) => {
socket.once('data', () => resolve());
});
await waitForResponse(socket, '221');
socket.end();
sockets.push(socket);