import { tap, expect } from '@git.zone/tstest/tapbundle'; import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.js'; import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.js'; import { Email } from '../../../ts/mail/core/classes.email.js'; let testServer: ITestServer; tap.test('setup test SMTP server', async () => { testServer = await startTestServer({ port: 2576, tlsEnabled: false, authRequired: false, maxConnections: 20 // Allow more connections for concurrent testing }); expect(testServer).toBeTruthy(); expect(testServer.port).toEqual(2576); }); tap.test('CEDGE-07: Multiple simultaneous connections', async () => { console.log('Testing multiple simultaneous connections'); const connectionCount = 5; const clients = []; // Create multiple clients for (let i = 0; i < connectionCount; i++) { const client = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: false, // Reduce noise maxConnections: 2 }); clients.push(client); } // Test concurrent verification console.log(` Testing ${connectionCount} concurrent verifications...`); const verifyPromises = clients.map(async (client, index) => { try { const result = await client.verify(); console.log(` Client ${index + 1}: ${result ? 'Success' : 'Failed'}`); return result; } catch (error) { console.log(` Client ${index + 1}: Error - ${error.message}`); return false; } }); const verifyResults = await Promise.all(verifyPromises); const successCount = verifyResults.filter(r => r).length; console.log(` Verify results: ${successCount}/${connectionCount} successful`); // We expect at least some connections to succeed expect(successCount).toBeGreaterThan(0); // Clean up clients await Promise.all(clients.map(client => client.close().catch(() => {}))); }); tap.test('CEDGE-07: Concurrent email sending', async () => { console.log('Testing concurrent email sending'); const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: false, maxConnections: 5 }); const emailCount = 10; console.log(` Sending ${emailCount} emails concurrently...`); const sendPromises = []; for (let i = 0; i < emailCount; i++) { const email = new Email({ from: 'sender@example.com', to: [`recipient${i}@example.com`], subject: `Concurrent test email ${i + 1}`, text: `This is concurrent test email number ${i + 1}` }); sendPromises.push( smtpClient.sendMail(email).then( result => { console.log(` Email ${i + 1}: Success`); return { success: true, result }; }, error => { console.log(` Email ${i + 1}: Failed - ${error.message}`); return { success: false, error }; } ) ); } const results = await Promise.all(sendPromises); const successCount = results.filter(r => r.success).length; console.log(` Send results: ${successCount}/${emailCount} successful`); // We expect a high success rate expect(successCount).toBeGreaterThan(emailCount * 0.7); // At least 70% success await smtpClient.close(); }); tap.test('CEDGE-07: Rapid connection cycling', async () => { console.log('Testing rapid connection cycling'); const cycleCount = 8; console.log(` Performing ${cycleCount} rapid connect/disconnect cycles...`); const cyclePromises = []; for (let i = 0; i < cycleCount; i++) { cyclePromises.push( (async () => { const client = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 3000, debug: false }); try { const verified = await client.verify(); console.log(` Cycle ${i + 1}: ${verified ? 'Success' : 'Failed'}`); await client.close(); return verified; } catch (error) { console.log(` Cycle ${i + 1}: Error - ${error.message}`); await client.close().catch(() => {}); return false; } })() ); } const cycleResults = await Promise.all(cyclePromises); const successCount = cycleResults.filter(r => r).length; console.log(` Cycle results: ${successCount}/${cycleCount} successful`); // We expect most cycles to succeed expect(successCount).toBeGreaterThan(cycleCount * 0.6); // At least 60% success }); tap.test('CEDGE-07: Connection pool stress test', async () => { console.log('Testing connection pool under stress'); const smtpClient = createSmtpClient({ host: testServer.hostname, port: testServer.port, secure: false, connectionTimeout: 5000, debug: false, maxConnections: 3, maxMessages: 50 }); const stressCount = 15; console.log(` Sending ${stressCount} emails to stress connection pool...`); const startTime = Date.now(); const stressPromises = []; for (let i = 0; i < stressCount; i++) { const email = new Email({ from: 'stress@example.com', to: [`stress${i}@example.com`], subject: `Stress test ${i + 1}`, text: `Connection pool stress test email ${i + 1}` }); stressPromises.push( smtpClient.sendMail(email).then( result => ({ success: true, index: i }), error => ({ success: false, index: i, error: error.message }) ) ); } const stressResults = await Promise.all(stressPromises); const duration = Date.now() - startTime; const successCount = stressResults.filter(r => r.success).length; console.log(` Stress results: ${successCount}/${stressCount} successful in ${duration}ms`); console.log(` Average: ${Math.round(duration / stressCount)}ms per email`); // Under stress, we still expect reasonable success rate expect(successCount).toBeGreaterThan(stressCount * 0.5); // At least 50% success under stress await smtpClient.close(); }); tap.test('cleanup test SMTP server', async () => { if (testServer) { await stopTestServer(testServer); } }); export default tap.start();