feat(storage): add comprehensive tests for StorageManager with memory, filesystem, and custom function backends
feat(email): implement EmailSendJob class for robust email delivery with retry logic and MX record resolution feat(mail): restructure mail module exports for simplified access to core and delivery functionalities
This commit is contained in:
299
test/suite/smtpclient_connection/test.ccm-11.keepalive.ts
Normal file
299
test/suite/smtpclient_connection/test.ccm-11.keepalive.ts
Normal file
@@ -0,0 +1,299 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import { startTestServer, stopTestServer, type ITestServer } from '../../helpers/server.loader.ts';
|
||||
import { createSmtpClient } from '../../../ts/mail/delivery/smtpclient/index.ts';
|
||||
import { Email } from '../../../ts/mail/core/classes.email.ts';
|
||||
|
||||
let testServer: ITestServer;
|
||||
|
||||
tap.test('setup test SMTP server', async () => {
|
||||
testServer = await startTestServer({
|
||||
port: 2537,
|
||||
tlsEnabled: false,
|
||||
authRequired: false,
|
||||
socketTimeout: 30000 // 30 second timeout for keep-alive tests
|
||||
});
|
||||
expect(testServer).toBeTruthy();
|
||||
expect(testServer.port).toEqual(2537);
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Basic keep-alive functionality', async () => {
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: true,
|
||||
keepAliveInterval: 5000, // 5 seconds
|
||||
connectionTimeout: 10000,
|
||||
debug: true
|
||||
});
|
||||
|
||||
// Verify connection works
|
||||
const verified = await smtpClient.verify();
|
||||
expect(verified).toBeTrue();
|
||||
|
||||
// Send an email to establish connection
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'Keep-alive test',
|
||||
text: 'Testing connection keep-alive'
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
expect(result.success).toBeTrue();
|
||||
|
||||
// Wait to simulate idle time
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
|
||||
// Send another email to verify connection is still working
|
||||
const result2 = await smtpClient.sendMail(email);
|
||||
expect(result2.success).toBeTrue();
|
||||
|
||||
console.log('✅ Keep-alive functionality verified');
|
||||
|
||||
await smtpClient.close();
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Connection reuse with keep-alive', async () => {
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: true,
|
||||
keepAliveInterval: 3000,
|
||||
connectionTimeout: 10000,
|
||||
poolSize: 1, // Use single connection to test keep-alive
|
||||
debug: true
|
||||
});
|
||||
|
||||
// Send multiple emails with delays to test keep-alive
|
||||
const emails = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: `Keep-alive test ${i + 1}`,
|
||||
text: `Testing connection keep-alive - email ${i + 1}`
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
expect(result.success).toBeTrue();
|
||||
emails.push(result);
|
||||
|
||||
// Wait between emails (less than keep-alive interval)
|
||||
if (i < 2) {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
}
|
||||
}
|
||||
|
||||
// All emails should have been sent successfully
|
||||
expect(emails.length).toEqual(3);
|
||||
expect(emails.every(r => r.success)).toBeTrue();
|
||||
|
||||
console.log('✅ Connection reused successfully with keep-alive');
|
||||
|
||||
await smtpClient.close();
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Connection without keep-alive', async () => {
|
||||
// Create a client without keep-alive
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: false, // Disabled
|
||||
connectionTimeout: 5000,
|
||||
socketTimeout: 5000, // 5 second socket timeout
|
||||
poolSize: 1,
|
||||
debug: true
|
||||
});
|
||||
|
||||
// Send first email
|
||||
const email1 = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'No keep-alive test 1',
|
||||
text: 'Testing without keep-alive'
|
||||
});
|
||||
|
||||
const result1 = await smtpClient.sendMail(email1);
|
||||
expect(result1.success).toBeTrue();
|
||||
|
||||
// Wait longer than socket timeout
|
||||
await new Promise(resolve => setTimeout(resolve, 7000));
|
||||
|
||||
// Send second email - connection might need to be re-established
|
||||
const email2 = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: 'No keep-alive test 2',
|
||||
text: 'Testing without keep-alive after timeout'
|
||||
});
|
||||
|
||||
const result2 = await smtpClient.sendMail(email2);
|
||||
expect(result2.success).toBeTrue();
|
||||
|
||||
console.log('✅ Client handles reconnection without keep-alive');
|
||||
|
||||
await smtpClient.close();
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Keep-alive with long operations', async () => {
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: true,
|
||||
keepAliveInterval: 2000,
|
||||
connectionTimeout: 10000,
|
||||
poolSize: 2, // Use small pool
|
||||
debug: true
|
||||
});
|
||||
|
||||
// Send multiple emails with varying delays
|
||||
const operations = [];
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
operations.push((async () => {
|
||||
// Simulate random processing delay
|
||||
await new Promise(resolve => setTimeout(resolve, Math.random() * 3000));
|
||||
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: `Long operation test ${i + 1}`,
|
||||
text: `Testing keep-alive during long operations - email ${i + 1}`
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
return { index: i, result };
|
||||
})());
|
||||
}
|
||||
|
||||
const results = await Promise.all(operations);
|
||||
|
||||
// All operations should succeed
|
||||
const successCount = results.filter(r => r.result.success).length;
|
||||
expect(successCount).toEqual(5);
|
||||
|
||||
console.log('✅ Keep-alive maintained during long operations');
|
||||
|
||||
await smtpClient.close();
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Keep-alive interval effect on connection pool', async () => {
|
||||
const intervals = [1000, 3000, 5000]; // Different intervals to test
|
||||
|
||||
for (const interval of intervals) {
|
||||
console.log(`\nTesting keep-alive with ${interval}ms interval`);
|
||||
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: true,
|
||||
keepAliveInterval: interval,
|
||||
connectionTimeout: 10000,
|
||||
poolSize: 2,
|
||||
debug: false // Less verbose for this test
|
||||
});
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
// Send multiple emails over time period longer than interval
|
||||
const emails = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: `Interval test ${i + 1}`,
|
||||
text: `Testing with ${interval}ms keep-alive interval`
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
expect(result.success).toBeTrue();
|
||||
emails.push(result);
|
||||
|
||||
// Wait approximately one interval
|
||||
if (i < 2) {
|
||||
await new Promise(resolve => setTimeout(resolve, interval));
|
||||
}
|
||||
}
|
||||
|
||||
const totalTime = Date.now() - startTime;
|
||||
console.log(`Sent ${emails.length} emails in ${totalTime}ms with ${interval}ms keep-alive`);
|
||||
|
||||
// Check pool status
|
||||
const poolStatus = smtpClient.getPoolStatus();
|
||||
console.log(`Pool status: ${JSON.stringify(poolStatus)}`);
|
||||
|
||||
await smtpClient.close();
|
||||
}
|
||||
});
|
||||
|
||||
tap.test('CCM-11: Event monitoring during keep-alive', async () => {
|
||||
const smtpClient = createSmtpClient({
|
||||
host: testServer.hostname,
|
||||
port: testServer.port,
|
||||
secure: false,
|
||||
keepAlive: true,
|
||||
keepAliveInterval: 2000,
|
||||
connectionTimeout: 10000,
|
||||
poolSize: 1,
|
||||
debug: true
|
||||
});
|
||||
|
||||
let connectionEvents = 0;
|
||||
let disconnectEvents = 0;
|
||||
let errorEvents = 0;
|
||||
|
||||
// Monitor events
|
||||
smtpClient.on('connection', () => {
|
||||
connectionEvents++;
|
||||
console.log('📡 Connection event');
|
||||
});
|
||||
|
||||
smtpClient.on('disconnect', () => {
|
||||
disconnectEvents++;
|
||||
console.log('🔌 Disconnect event');
|
||||
});
|
||||
|
||||
smtpClient.on('error', (error) => {
|
||||
errorEvents++;
|
||||
console.log('❌ Error event:', error.message);
|
||||
});
|
||||
|
||||
// Send emails with delays
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const email = new Email({
|
||||
from: 'sender@example.com',
|
||||
to: 'recipient@example.com',
|
||||
subject: `Event test ${i + 1}`,
|
||||
text: 'Testing events during keep-alive'
|
||||
});
|
||||
|
||||
const result = await smtpClient.sendMail(email);
|
||||
expect(result.success).toBeTrue();
|
||||
|
||||
if (i < 2) {
|
||||
await new Promise(resolve => setTimeout(resolve, 1500));
|
||||
}
|
||||
}
|
||||
|
||||
// Should have at least one connection event
|
||||
expect(connectionEvents).toBeGreaterThan(0);
|
||||
console.log(`✅ Captured ${connectionEvents} connection events`);
|
||||
|
||||
await smtpClient.close();
|
||||
|
||||
// Wait a bit for close event
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
});
|
||||
|
||||
tap.test('cleanup test SMTP server', async () => {
|
||||
if (testServer) {
|
||||
await stopTestServer(testServer);
|
||||
}
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user