update
This commit is contained in:
@ -0,0 +1,686 @@
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import * as plugins from './plugins.js';
|
||||
import { createTestServer } from '../../helpers/server.loader.js';
|
||||
import { createSmtpClient } from '../../helpers/smtp.client.js';
|
||||
|
||||
tap.test('CPERF-05: should optimize network efficiency', async (tools) => {
|
||||
const testId = 'CPERF-05-network-efficiency';
|
||||
console.log(`\n${testId}: Testing network efficiency optimization...`);
|
||||
|
||||
let scenarioCount = 0;
|
||||
|
||||
// Helper to track network activity
|
||||
class NetworkTracker {
|
||||
private startTime: number;
|
||||
private bytesSent: number = 0;
|
||||
private bytesReceived: number = 0;
|
||||
private connections: number = 0;
|
||||
private roundTrips: number = 0;
|
||||
|
||||
constructor() {
|
||||
this.startTime = Date.now();
|
||||
}
|
||||
|
||||
addConnection() {
|
||||
this.connections++;
|
||||
}
|
||||
|
||||
addBytesSent(bytes: number) {
|
||||
this.bytesSent += bytes;
|
||||
}
|
||||
|
||||
addBytesReceived(bytes: number) {
|
||||
this.bytesReceived += bytes;
|
||||
}
|
||||
|
||||
addRoundTrip() {
|
||||
this.roundTrips++;
|
||||
}
|
||||
|
||||
getStats() {
|
||||
const elapsed = Date.now() - this.startTime;
|
||||
return {
|
||||
elapsed,
|
||||
bytesSent: this.bytesSent,
|
||||
bytesReceived: this.bytesReceived,
|
||||
totalBytes: this.bytesSent + this.bytesReceived,
|
||||
connections: this.connections,
|
||||
roundTrips: this.roundTrips,
|
||||
bytesPerSecond: ((this.bytesSent + this.bytesReceived) / elapsed) * 1000,
|
||||
efficiency: this.bytesSent / (this.bytesSent + this.bytesReceived)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Scenario 1: Connection reuse efficiency
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing connection reuse efficiency`);
|
||||
|
||||
const tracker = new NetworkTracker();
|
||||
let connectionCount = 0;
|
||||
let totalCommandBytes = 0;
|
||||
let totalResponseBytes = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
connectionCount++;
|
||||
tracker.addConnection();
|
||||
console.log(` [Server] Connection ${connectionCount} established`);
|
||||
|
||||
const greeting = '220 reuse.example.com ESMTP\r\n';
|
||||
socket.write(greeting);
|
||||
tracker.addBytesSent(greeting.length);
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log(` [Server] Connection ${connectionCount} closed`);
|
||||
});
|
||||
|
||||
socket.on('data', (data) => {
|
||||
totalCommandBytes += data.length;
|
||||
tracker.addBytesReceived(data.length);
|
||||
tracker.addRoundTrip();
|
||||
|
||||
const command = data.toString().trim();
|
||||
let response = '';
|
||||
|
||||
if (command.startsWith('EHLO')) {
|
||||
response = '250-reuse.example.com\r\n250 OK\r\n';
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
response = '250 OK\r\n';
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
response = '250 OK\r\n';
|
||||
} else if (command === 'DATA') {
|
||||
response = '354 Start mail input\r\n';
|
||||
} else if (command === '.') {
|
||||
response = '250 OK\r\n';
|
||||
} else if (command === 'RSET') {
|
||||
response = '250 OK\r\n';
|
||||
} else if (command === 'QUIT') {
|
||||
response = '221 Bye\r\n';
|
||||
}
|
||||
|
||||
if (response) {
|
||||
socket.write(response);
|
||||
totalResponseBytes += response.length;
|
||||
tracker.addBytesSent(response.length);
|
||||
}
|
||||
|
||||
if (command === 'QUIT') {
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Test individual connections vs reused connection
|
||||
const messageCount = 10;
|
||||
|
||||
// Individual connections approach
|
||||
console.log(` Testing ${messageCount} individual connections...`);
|
||||
const individualStart = Date.now();
|
||||
connectionCount = 0;
|
||||
totalCommandBytes = 0;
|
||||
totalResponseBytes = 0;
|
||||
|
||||
for (let i = 0; i < messageCount; i++) {
|
||||
const client = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false
|
||||
});
|
||||
|
||||
const email = new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: [`individual${i + 1}@example.com`],
|
||||
subject: `Individual connection test ${i + 1}`,
|
||||
text: `Testing individual connections - message ${i + 1}`
|
||||
});
|
||||
|
||||
await client.sendMail(email);
|
||||
|
||||
if (client.close) {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
const individualTime = Date.now() - individualStart;
|
||||
const individualStats = {
|
||||
connections: connectionCount,
|
||||
commandBytes: totalCommandBytes,
|
||||
responseBytes: totalResponseBytes,
|
||||
totalBytes: totalCommandBytes + totalResponseBytes,
|
||||
time: individualTime
|
||||
};
|
||||
|
||||
console.log(` Individual connections: ${individualStats.connections} connections, ${individualStats.totalBytes} bytes`);
|
||||
|
||||
// Connection reuse approach
|
||||
console.log(` Testing connection reuse...`);
|
||||
const reuseStart = Date.now();
|
||||
connectionCount = 0;
|
||||
totalCommandBytes = 0;
|
||||
totalResponseBytes = 0;
|
||||
|
||||
const reuseClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
pool: true,
|
||||
maxConnections: 1,
|
||||
maxMessages: messageCount
|
||||
});
|
||||
|
||||
const reuseEmails = Array(messageCount).fill(null).map((_, i) =>
|
||||
new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: [`reuse${i + 1}@example.com`],
|
||||
subject: `Connection reuse test ${i + 1}`,
|
||||
text: `Testing connection reuse - message ${i + 1}`
|
||||
})
|
||||
);
|
||||
|
||||
for (const email of reuseEmails) {
|
||||
await reuseClient.sendMail(email);
|
||||
}
|
||||
|
||||
await reuseClient.close();
|
||||
|
||||
const reuseTime = Date.now() - reuseStart;
|
||||
const reuseStats = {
|
||||
connections: connectionCount,
|
||||
commandBytes: totalCommandBytes,
|
||||
responseBytes: totalResponseBytes,
|
||||
totalBytes: totalCommandBytes + totalResponseBytes,
|
||||
time: reuseTime
|
||||
};
|
||||
|
||||
console.log(` Connection reuse: ${reuseStats.connections} connections, ${reuseStats.totalBytes} bytes`);
|
||||
|
||||
// Calculate efficiency
|
||||
const connectionEfficiency = individualStats.connections / reuseStats.connections;
|
||||
const byteEfficiency = individualStats.totalBytes / reuseStats.totalBytes;
|
||||
const timeEfficiency = individualTime / reuseTime;
|
||||
|
||||
console.log(` Connection efficiency: ${connectionEfficiency.toFixed(1)}x`);
|
||||
console.log(` Byte efficiency: ${byteEfficiency.toFixed(1)}x`);
|
||||
console.log(` Time efficiency: ${timeEfficiency.toFixed(1)}x`);
|
||||
|
||||
// Connection reuse should be more efficient
|
||||
expect(reuseStats.connections).toBeLessThan(individualStats.connections);
|
||||
expect(reuseStats.totalBytes).toBeLessThan(individualStats.totalBytes);
|
||||
expect(connectionEfficiency).toBeGreaterThan(5); // At least 5x fewer connections
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
// Scenario 2: Command pipelining efficiency
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing command pipelining efficiency`);
|
||||
|
||||
let totalCommands = 0;
|
||||
let pipelinedCommands = 0;
|
||||
let maxPipelineDepth = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
console.log(' [Server] Client connected for pipelining test');
|
||||
socket.write('220 pipeline.example.com ESMTP\r\n');
|
||||
|
||||
socket.on('data', (data) => {
|
||||
const commands = data.toString().split('\r\n').filter(cmd => cmd.length > 0);
|
||||
totalCommands += commands.length;
|
||||
|
||||
if (commands.length > 1) {
|
||||
pipelinedCommands += commands.length;
|
||||
maxPipelineDepth = Math.max(maxPipelineDepth, commands.length);
|
||||
console.log(` [Server] Received ${commands.length} pipelined commands`);
|
||||
}
|
||||
|
||||
commands.forEach(command => {
|
||||
if (command.startsWith('EHLO')) {
|
||||
socket.write('250-pipeline.example.com\r\n250-PIPELINING\r\n250 OK\r\n');
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'DATA') {
|
||||
socket.write('354 Start mail input\r\n');
|
||||
} else if (command === '.') {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'QUIT') {
|
||||
socket.write('221 Bye\r\n');
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const pipelineClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
pipelining: true
|
||||
});
|
||||
|
||||
// Send emails with multiple recipients (triggers pipelining)
|
||||
const emails = [
|
||||
new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient1@example.com', 'recipient2@example.com', 'recipient3@example.com'],
|
||||
subject: 'Pipelining test 1',
|
||||
text: 'Testing command pipelining efficiency'
|
||||
}),
|
||||
new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient4@example.com', 'recipient5@example.com'],
|
||||
subject: 'Pipelining test 2',
|
||||
text: 'Testing command pipelining efficiency'
|
||||
})
|
||||
];
|
||||
|
||||
console.log(' Sending emails with pipelining support...');
|
||||
for (const email of emails) {
|
||||
await pipelineClient.sendMail(email);
|
||||
}
|
||||
|
||||
console.log(` Total commands sent: ${totalCommands}`);
|
||||
console.log(` Pipelined commands: ${pipelinedCommands}`);
|
||||
console.log(` Max pipeline depth: ${maxPipelineDepth}`);
|
||||
console.log(` Pipelining efficiency: ${(pipelinedCommands / totalCommands * 100).toFixed(1)}%`);
|
||||
|
||||
// Should use pipelining for efficiency
|
||||
expect(pipelinedCommands).toBeGreaterThan(0);
|
||||
expect(maxPipelineDepth).toBeGreaterThan(1);
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
// Scenario 3: Message size optimization
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing message size optimization`);
|
||||
|
||||
let totalMessageBytes = 0;
|
||||
let messageCount = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
console.log(' [Server] Client connected for size optimization test');
|
||||
socket.write('220 size.example.com ESMTP\r\n');
|
||||
|
||||
let inData = false;
|
||||
let messageBytes = 0;
|
||||
|
||||
socket.on('data', (data) => {
|
||||
if (inData) {
|
||||
messageBytes += data.length;
|
||||
if (data.toString().includes('\r\n.\r\n')) {
|
||||
inData = false;
|
||||
messageCount++;
|
||||
totalMessageBytes += messageBytes;
|
||||
console.log(` [Server] Message ${messageCount}: ${messageBytes} bytes`);
|
||||
socket.write('250 OK\r\n');
|
||||
messageBytes = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const command = data.toString().trim();
|
||||
|
||||
if (command.startsWith('EHLO')) {
|
||||
socket.write('250-size.example.com\r\n250-SIZE 52428800\r\n250 OK\r\n');
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'DATA') {
|
||||
socket.write('354 Start mail input\r\n');
|
||||
inData = true;
|
||||
messageBytes = 0;
|
||||
} else if (command === 'QUIT') {
|
||||
socket.write('221 Bye\r\n');
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const sizeClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false
|
||||
});
|
||||
|
||||
// Test different message sizes and encoding efficiency
|
||||
const sizeTests = [
|
||||
{
|
||||
name: 'Plain text',
|
||||
email: new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient@example.com'],
|
||||
subject: 'Plain text efficiency test',
|
||||
text: 'This is a plain text message for testing size efficiency.'
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'HTML message',
|
||||
email: new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient@example.com'],
|
||||
subject: 'HTML efficiency test',
|
||||
html: '<html><body><h1>HTML Message</h1><p>This is an HTML message.</p></body></html>'
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'Multipart message',
|
||||
email: new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient@example.com'],
|
||||
subject: 'Multipart efficiency test',
|
||||
text: 'Plain text version of the message.',
|
||||
html: '<p>HTML version of the message.</p>'
|
||||
})
|
||||
},
|
||||
{
|
||||
name: 'Message with small attachment',
|
||||
email: new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient@example.com'],
|
||||
subject: 'Attachment efficiency test',
|
||||
text: 'Message with attachment.',
|
||||
attachments: [{
|
||||
filename: 'test.txt',
|
||||
content: 'Small test attachment content for efficiency testing.'
|
||||
}]
|
||||
})
|
||||
}
|
||||
];
|
||||
|
||||
for (const test of sizeTests) {
|
||||
console.log(` Testing ${test.name}...`);
|
||||
|
||||
const beforeBytes = totalMessageBytes;
|
||||
const beforeCount = messageCount;
|
||||
|
||||
await sizeClient.sendMail(test.email);
|
||||
|
||||
const messageSize = totalMessageBytes - beforeBytes;
|
||||
const overhead = messageSize / (test.email.text?.length || test.email.html?.length || 100);
|
||||
|
||||
console.log(` ${test.name}: ${messageSize} bytes (overhead: ${overhead.toFixed(1)}x)`);
|
||||
|
||||
// Message overhead should be reasonable
|
||||
expect(overhead).toBeLessThan(10); // Less than 10x overhead
|
||||
}
|
||||
|
||||
const avgMessageSize = totalMessageBytes / messageCount;
|
||||
console.log(` Average message size: ${avgMessageSize.toFixed(0)} bytes`);
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
// Scenario 4: Bandwidth utilization
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing bandwidth utilization`);
|
||||
|
||||
let totalBytes = 0;
|
||||
let dataTransferTime = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
socket.write('220 bandwidth.example.com ESMTP\r\n');
|
||||
|
||||
let transferStart = 0;
|
||||
let inData = false;
|
||||
|
||||
socket.on('data', (data) => {
|
||||
totalBytes += data.length;
|
||||
|
||||
if (inData) {
|
||||
if (data.toString().includes('\r\n.\r\n')) {
|
||||
inData = false;
|
||||
dataTransferTime += Date.now() - transferStart;
|
||||
socket.write('250 OK\r\n');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const command = data.toString().trim();
|
||||
|
||||
if (command.startsWith('EHLO')) {
|
||||
socket.write('250-bandwidth.example.com\r\n250 OK\r\n');
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'DATA') {
|
||||
socket.write('354 Start mail input\r\n');
|
||||
inData = true;
|
||||
transferStart = Date.now();
|
||||
} else if (command === 'QUIT') {
|
||||
socket.write('221 Bye\r\n');
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const bandwidthClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false
|
||||
});
|
||||
|
||||
// Test bandwidth efficiency with varying message sizes
|
||||
const messageSizes = [1024, 10240, 102400]; // 1KB, 10KB, 100KB
|
||||
|
||||
console.log(' Testing bandwidth utilization with different message sizes...');
|
||||
const bandwidthStart = Date.now();
|
||||
|
||||
for (const size of messageSizes) {
|
||||
const content = 'x'.repeat(size);
|
||||
|
||||
const email = new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['recipient@example.com'],
|
||||
subject: `Bandwidth test ${size} bytes`,
|
||||
text: content
|
||||
});
|
||||
|
||||
await bandwidthClient.sendMail(email);
|
||||
}
|
||||
|
||||
const bandwidthElapsed = Date.now() - bandwidthStart;
|
||||
const throughput = (totalBytes / bandwidthElapsed) * 1000; // bytes per second
|
||||
const dataEfficiency = (messageSizes.reduce((a, b) => a + b, 0) / totalBytes) * 100;
|
||||
|
||||
console.log(` Total bytes transferred: ${totalBytes}`);
|
||||
console.log(` Data transfer time: ${dataTransferTime}ms`);
|
||||
console.log(` Overall throughput: ${(throughput / 1024).toFixed(1)} KB/s`);
|
||||
console.log(` Data efficiency: ${dataEfficiency.toFixed(1)}% (payload vs total)`);
|
||||
|
||||
// Bandwidth utilization should be efficient
|
||||
expect(throughput).toBeGreaterThan(1024); // At least 1KB/s
|
||||
expect(dataEfficiency).toBeGreaterThan(20); // At least 20% payload efficiency
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
// Scenario 5: Network round-trip optimization
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing network round-trip optimization`);
|
||||
|
||||
let roundTrips = 0;
|
||||
let commandCount = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
socket.write('220 roundtrip.example.com ESMTP\r\n');
|
||||
|
||||
socket.on('data', (data) => {
|
||||
const commands = data.toString().split('\r\n').filter(cmd => cmd.length > 0);
|
||||
roundTrips++;
|
||||
commandCount += commands.length;
|
||||
|
||||
console.log(` [Server] Round-trip ${roundTrips}: ${commands.length} commands`);
|
||||
|
||||
commands.forEach(command => {
|
||||
if (command.startsWith('EHLO')) {
|
||||
socket.write('250-roundtrip.example.com\r\n250-PIPELINING\r\n250 OK\r\n');
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'DATA') {
|
||||
socket.write('354 Start mail input\r\n');
|
||||
} else if (command === '.') {
|
||||
socket.write('250 OK\r\n');
|
||||
} else if (command === 'QUIT') {
|
||||
socket.write('221 Bye\r\n');
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const roundtripClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
pipelining: true
|
||||
});
|
||||
|
||||
// Send email with multiple recipients to test round-trip efficiency
|
||||
const email = new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: ['rcpt1@example.com', 'rcpt2@example.com', 'rcpt3@example.com', 'rcpt4@example.com'],
|
||||
subject: 'Round-trip optimization test',
|
||||
text: 'Testing network round-trip optimization with multiple recipients'
|
||||
});
|
||||
|
||||
console.log(' Sending email with multiple recipients...');
|
||||
await roundtripClient.sendMail(email);
|
||||
|
||||
const commandsPerRoundTrip = commandCount / roundTrips;
|
||||
const efficiency = commandsPerRoundTrip;
|
||||
|
||||
console.log(` Total round-trips: ${roundTrips}`);
|
||||
console.log(` Total commands: ${commandCount}`);
|
||||
console.log(` Commands per round-trip: ${commandsPerRoundTrip.toFixed(1)}`);
|
||||
console.log(` Round-trip efficiency: ${efficiency.toFixed(1)}`);
|
||||
|
||||
// Should minimize round-trips through pipelining
|
||||
expect(roundTrips).toBeLessThan(commandCount); // Fewer round-trips than commands
|
||||
expect(commandsPerRoundTrip).toBeGreaterThan(1.5); // At least 1.5 commands per round-trip
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
// Scenario 6: Connection pooling network efficiency
|
||||
await (async () => {
|
||||
scenarioCount++;
|
||||
console.log(`\nScenario ${scenarioCount}: Testing connection pooling network efficiency`);
|
||||
|
||||
let totalConnections = 0;
|
||||
let totalBytes = 0;
|
||||
let connectionSetupBytes = 0;
|
||||
|
||||
const testServer = await createTestServer({
|
||||
onConnection: async (socket) => {
|
||||
totalConnections++;
|
||||
const greeting = '220 pool.example.com ESMTP\r\n';
|
||||
socket.write(greeting);
|
||||
connectionSetupBytes += greeting.length;
|
||||
|
||||
console.log(` [Server] Pool connection ${totalConnections} established`);
|
||||
|
||||
socket.on('data', (data) => {
|
||||
totalBytes += data.length;
|
||||
const command = data.toString().trim();
|
||||
|
||||
if (command.startsWith('EHLO')) {
|
||||
const response = '250-pool.example.com\r\n250 OK\r\n';
|
||||
socket.write(response);
|
||||
connectionSetupBytes += response.length;
|
||||
totalBytes += response.length;
|
||||
} else if (command.startsWith('MAIL FROM:')) {
|
||||
const response = '250 OK\r\n';
|
||||
socket.write(response);
|
||||
totalBytes += response.length;
|
||||
} else if (command.startsWith('RCPT TO:')) {
|
||||
const response = '250 OK\r\n';
|
||||
socket.write(response);
|
||||
totalBytes += response.length;
|
||||
} else if (command === 'DATA') {
|
||||
const response = '354 Start mail input\r\n';
|
||||
socket.write(response);
|
||||
totalBytes += response.length;
|
||||
} else if (command === '.') {
|
||||
const response = '250 OK\r\n';
|
||||
socket.write(response);
|
||||
totalBytes += response.length;
|
||||
} else if (command === 'QUIT') {
|
||||
const response = '221 Bye\r\n';
|
||||
socket.write(response);
|
||||
totalBytes += response.length;
|
||||
socket.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const poolClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
pool: true,
|
||||
maxConnections: 3,
|
||||
maxMessages: 100
|
||||
});
|
||||
|
||||
// Send multiple emails through pool
|
||||
const emailCount = 15;
|
||||
const emails = Array(emailCount).fill(null).map((_, i) =>
|
||||
new plugins.smartmail.Email({
|
||||
from: 'sender@example.com',
|
||||
to: [`pooled${i + 1}@example.com`],
|
||||
subject: `Pool efficiency test ${i + 1}`,
|
||||
text: `Testing pooled connection network efficiency - message ${i + 1}`
|
||||
})
|
||||
);
|
||||
|
||||
console.log(` Sending ${emailCount} emails through connection pool...`);
|
||||
const poolStart = Date.now();
|
||||
|
||||
await Promise.all(emails.map(email => poolClient.sendMail(email)));
|
||||
await poolClient.close();
|
||||
|
||||
const poolTime = Date.now() - poolStart;
|
||||
const setupOverhead = (connectionSetupBytes / totalBytes) * 100;
|
||||
const messagesPerConnection = emailCount / totalConnections;
|
||||
const bytesPerMessage = totalBytes / emailCount;
|
||||
|
||||
console.log(` Emails sent: ${emailCount}`);
|
||||
console.log(` Connections used: ${totalConnections}`);
|
||||
console.log(` Messages per connection: ${messagesPerConnection.toFixed(1)}`);
|
||||
console.log(` Total bytes: ${totalBytes}`);
|
||||
console.log(` Setup overhead: ${setupOverhead.toFixed(1)}%`);
|
||||
console.log(` Bytes per message: ${bytesPerMessage.toFixed(0)}`);
|
||||
console.log(` Network efficiency: ${(emailCount / totalConnections).toFixed(1)} msg/conn`);
|
||||
|
||||
// Connection pooling should be network efficient
|
||||
expect(totalConnections).toBeLessThan(emailCount); // Fewer connections than messages
|
||||
expect(messagesPerConnection).toBeGreaterThan(3); // At least 3 messages per connection
|
||||
expect(setupOverhead).toBeLessThan(20); // Less than 20% setup overhead
|
||||
|
||||
await testServer.server.close();
|
||||
})();
|
||||
|
||||
console.log(`\n${testId}: All ${scenarioCount} network efficiency scenarios tested ✓`);
|
||||
});
|
Reference in New Issue
Block a user