2025-05-26 14:50:55 +00:00
import { tap , expect } from '@git.zone/tstest/tapbundle' ;
import * as net from 'net' ;
import { createTestSmtpClient } from '../../helpers/smtp.client.js' ;
2025-05-24 18:12:08 +00:00
import { Email } from '../../../ts/mail/core/classes.email.js' ;
2025-05-26 14:50:55 +00:00
// Helper function to get memory usage
const getMemoryUsage = ( ) = > {
const usage = process . memoryUsage ( ) ;
return {
heapUsed : Math.round ( usage . heapUsed / 1024 / 1024 * 100 ) / 100 , // MB
heapTotal : Math.round ( usage . heapTotal / 1024 / 1024 * 100 ) / 100 , // MB
external : Math.round ( usage . external / 1024 / 1024 * 100 ) / 100 , // MB
rss : Math.round ( usage . rss / 1024 / 1024 * 100 ) / 100 // MB
2025-05-24 18:12:08 +00:00
} ;
2025-05-26 14:50:55 +00:00
} ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Force garbage collection if available
const forceGC = ( ) = > {
if ( global . gc ) {
global . gc ( ) ;
global . gc ( ) ; // Run twice for thoroughness
}
} ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
tap . test ( 'CREL-05: Connection Pool Memory Management' , async ( ) = > {
console . log ( '\n🧠 Testing SMTP Client Memory Leak Prevention' ) ;
console . log ( '=' . repeat ( 60 ) ) ;
console . log ( '\n🏊 Testing connection pool memory management...' ) ;
// Create test server
const server = net . createServer ( socket = > {
socket . write ( '220 localhost SMTP Test Server\r\n' ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
socket . on ( 'data' , ( data ) = > {
const lines = data . toString ( ) . split ( '\r\n' ) ;
lines . forEach ( line = > {
if ( line . startsWith ( 'EHLO' ) || line . startsWith ( 'HELO' ) ) {
socket . write ( '250-localhost\r\n' ) ;
socket . write ( '250 SIZE 10485760\r\n' ) ;
} else if ( line . startsWith ( 'MAIL FROM:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line . startsWith ( 'RCPT TO:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line === 'DATA' ) {
socket . write ( '354 Send data\r\n' ) ;
} else if ( line === '.' ) {
socket . write ( '250 OK Message accepted\r\n' ) ;
} else if ( line === 'QUIT' ) {
socket . write ( '221 Bye\r\n' ) ;
socket . end ( ) ;
}
} ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
await new Promise < void > ( ( resolve ) = > {
server . listen ( 0 , '127.0.0.1' , ( ) = > {
resolve ( ) ;
} ) ;
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const port = ( server . address ( ) as net . AddressInfo ) . port ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
const initialMemory = getMemoryUsage ( ) ;
console . log ( ` Initial memory: ${ initialMemory . heapUsed } MB heap, ${ initialMemory . rss } MB RSS ` ) ;
console . log ( ' Phase 1: Creating and using multiple connection pools...' ) ;
const memorySnapshots = [ ] ;
for ( let poolIndex = 0 ; poolIndex < 5 ; poolIndex ++ ) {
console . log ( ` Creating connection pool ${ poolIndex + 1 } ... ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const smtpClient = createTestSmtpClient ( {
host : '127.0.0.1' ,
port : port ,
secure : false ,
maxConnections : 3 ,
maxMessages : 20 ,
connectionTimeout : 1000
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Send emails through this pool
const emails = [ ] ;
for ( let i = 0 ; i < 6 ; i ++ ) {
emails . push ( new Email ( {
from : ` sender ${ poolIndex } @memoryleak.test ` ,
to : [ ` recipient ${ i } @memoryleak.test ` ] ,
subject : ` Memory Pool Test ${ poolIndex + 1 } - ${ i + 1 } ` ,
text : ` Testing memory management in pool ${ poolIndex + 1 } , email ${ i + 1 } `
} ) ) ;
}
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Send emails concurrently
const promises = emails . map ( ( email , index ) = > {
return smtpClient . sendMail ( email ) . then ( result = > {
return { success : true , result } ;
} ) . catch ( error = > {
return { success : false , error } ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const results = await Promise . all ( promises ) ;
const successful = results . filter ( r = > r . success ) . length ;
console . log ( ` Pool ${ poolIndex + 1 } : ${ successful } / ${ emails . length } emails sent ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Close the pool
smtpClient . close ( ) ;
console . log ( ` Pool ${ poolIndex + 1 } closed ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Force garbage collection and measure memory
forceGC ( ) ;
await new Promise ( resolve = > setTimeout ( resolve , 100 ) ) ;
const currentMemory = getMemoryUsage ( ) ;
memorySnapshots . push ( {
pool : poolIndex + 1 ,
heap : currentMemory.heapUsed ,
rss : currentMemory.rss ,
external : currentMemory.external
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
console . log ( ` Memory after pool ${ poolIndex + 1 } : ${ currentMemory . heapUsed } MB heap ` ) ;
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
console . log ( '\n Memory analysis:' ) ;
memorySnapshots . forEach ( ( snapshot , index ) = > {
const memoryIncrease = snapshot . heap - initialMemory . heapUsed ;
console . log ( ` Pool ${ snapshot . pool } : + ${ memoryIncrease . toFixed ( 2 ) } MB heap increase ` ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
// Check for memory leaks (memory should not continuously increase)
const firstIncrease = memorySnapshots [ 0 ] . heap - initialMemory . heapUsed ;
const lastIncrease = memorySnapshots [ memorySnapshots . length - 1 ] . heap - initialMemory . heapUsed ;
const leakGrowth = lastIncrease - firstIncrease ;
console . log ( ` Memory leak assessment: ` ) ;
console . log ( ` First pool increase: + ${ firstIncrease . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Final memory increase: + ${ lastIncrease . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Memory growth across pools: + ${ leakGrowth . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Memory management: ${ leakGrowth < 3.0 ? 'Good (< 3MB growth)' : 'Potential leak detected' } ` ) ;
expect ( leakGrowth ) . toBeLessThan ( 5.0 ) ; // Allow some memory growth but detect major leaks
} finally {
server . close ( ) ;
}
} ) ;
tap . test ( 'CREL-05: Email Object Memory Lifecycle' , async ( ) = > {
console . log ( '\n📧 Testing email object memory lifecycle...' ) ;
// Create test server
const server = net . createServer ( socket = > {
socket . write ( '220 localhost SMTP Test Server\r\n' ) ;
socket . on ( 'data' , ( data ) = > {
const lines = data . toString ( ) . split ( '\r\n' ) ;
lines . forEach ( line = > {
if ( line . startsWith ( 'EHLO' ) || line . startsWith ( 'HELO' ) ) {
socket . write ( '250-localhost\r\n' ) ;
socket . write ( '250 SIZE 10485760\r\n' ) ;
} else if ( line . startsWith ( 'MAIL FROM:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line . startsWith ( 'RCPT TO:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line === 'DATA' ) {
socket . write ( '354 Send data\r\n' ) ;
} else if ( line === '.' ) {
socket . write ( '250 OK Message accepted\r\n' ) ;
} else if ( line === 'QUIT' ) {
socket . write ( '221 Bye\r\n' ) ;
socket . end ( ) ;
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
} ) ;
} ) ;
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
await new Promise < void > ( ( resolve ) = > {
server . listen ( 0 , '127.0.0.1' , ( ) = > {
resolve ( ) ;
} ) ;
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const port = ( server . address ( ) as net . AddressInfo ) . port ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
const smtpClient = createTestSmtpClient ( {
host : '127.0.0.1' ,
port : port ,
secure : false ,
maxConnections : 2
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const initialMemory = getMemoryUsage ( ) ;
console . log ( ` Initial memory: ${ initialMemory . heapUsed } MB heap ` ) ;
console . log ( ' Phase 1: Creating large batches of email objects...' ) ;
const batchSizes = [ 50 , 100 , 150 , 100 , 50 ] ; // Varying batch sizes
const memorySnapshots = [ ] ;
for ( let batchIndex = 0 ; batchIndex < batchSizes . length ; batchIndex ++ ) {
const batchSize = batchSizes [ batchIndex ] ;
console . log ( ` Creating batch ${ batchIndex + 1 } with ${ batchSize } emails... ` ) ;
const emails = [ ] ;
for ( let i = 0 ; i < batchSize ; i ++ ) {
emails . push ( new Email ( {
from : 'sender@emailmemory.test' ,
to : [ ` recipient ${ i } @emailmemory.test ` ] ,
subject : ` Memory Lifecycle Test Batch ${ batchIndex + 1 } Email ${ i + 1 } ` ,
text : ` Testing email object memory lifecycle. This is a moderately long email body to test memory usage patterns. Email ${ i + 1 } in batch ${ batchIndex + 1 } of ${ batchSize } emails. ` ,
html : ` <h1>Email ${ i + 1 } </h1><p>Testing memory patterns with HTML content. Batch ${ batchIndex + 1 } .</p> `
} ) ) ;
}
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ` Sending batch ${ batchIndex + 1 } ... ` ) ;
const promises = emails . map ( ( email , index ) = > {
return smtpClient . sendMail ( email ) . then ( result = > {
return { success : true } ;
} ) . catch ( error = > {
return { success : false , error } ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const results = await Promise . all ( promises ) ;
const successful = results . filter ( r = > r . success ) . length ;
console . log ( ` Batch ${ batchIndex + 1 } : ${ successful } / ${ batchSize } emails sent ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Clear email references
emails . length = 0 ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Force garbage collection
forceGC ( ) ;
await new Promise ( resolve = > setTimeout ( resolve , 100 ) ) ;
const currentMemory = getMemoryUsage ( ) ;
memorySnapshots . push ( {
batch : batchIndex + 1 ,
size : batchSize ,
heap : currentMemory.heapUsed ,
external : currentMemory.external
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ` Memory after batch ${ batchIndex + 1 } : ${ currentMemory . heapUsed } MB heap ` ) ;
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
console . log ( '\n Email object memory analysis:' ) ;
memorySnapshots . forEach ( ( snapshot , index ) = > {
const memoryIncrease = snapshot . heap - initialMemory . heapUsed ;
console . log ( ` Batch ${ snapshot . batch } ( ${ snapshot . size } emails): + ${ memoryIncrease . toFixed ( 2 ) } MB ` ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
// Check if memory scales reasonably with email batch size
const maxMemoryIncrease = Math . max ( . . . memorySnapshots . map ( s = > s . heap - initialMemory . heapUsed ) ) ;
const avgBatchSize = batchSizes . reduce ( ( a , b ) = > a + b , 0 ) / batchSizes . length ;
console . log ( ` Maximum memory increase: + ${ maxMemoryIncrease . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Average batch size: ${ avgBatchSize } emails ` ) ;
console . log ( ` Memory per email: ~ ${ ( maxMemoryIncrease / avgBatchSize * 1024 ) . toFixed ( 1 ) } KB ` ) ;
console . log ( ` Email object lifecycle: ${ maxMemoryIncrease < 10 ? 'Efficient' : 'Needs optimization' } ` ) ;
expect ( maxMemoryIncrease ) . toBeLessThan ( 15 ) ; // Allow reasonable memory usage
smtpClient . close ( ) ;
} finally {
server . close ( ) ;
}
} ) ;
tap . test ( 'CREL-05: Long-Running Client Memory Stability' , async ( ) = > {
console . log ( '\n⏱️ Testing long-running client memory stability...' ) ;
// Create test server
const server = net . createServer ( socket = > {
socket . write ( '220 localhost SMTP Test Server\r\n' ) ;
socket . on ( 'data' , ( data ) = > {
const lines = data . toString ( ) . split ( '\r\n' ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
lines . forEach ( line = > {
if ( line . startsWith ( 'EHLO' ) || line . startsWith ( 'HELO' ) ) {
socket . write ( '250-localhost\r\n' ) ;
socket . write ( '250 SIZE 10485760\r\n' ) ;
} else if ( line . startsWith ( 'MAIL FROM:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line . startsWith ( 'RCPT TO:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line === 'DATA' ) {
socket . write ( '354 Send data\r\n' ) ;
} else if ( line === '.' ) {
socket . write ( '250 OK Message accepted\r\n' ) ;
} else if ( line === 'QUIT' ) {
socket . write ( '221 Bye\r\n' ) ;
socket . end ( ) ;
2025-05-24 18:12:08 +00:00
}
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
await new Promise < void > ( ( resolve ) = > {
server . listen ( 0 , '127.0.0.1' , ( ) = > {
resolve ( ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const port = ( server . address ( ) as net . AddressInfo ) . port ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
const smtpClient = createTestSmtpClient ( {
host : '127.0.0.1' ,
port : port ,
secure : false ,
maxConnections : 2 ,
maxMessages : 1000
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const initialMemory = getMemoryUsage ( ) ;
console . log ( ` Initial memory: ${ initialMemory . heapUsed } MB heap ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ' Starting sustained email sending operation...' ) ;
const memoryMeasurements = [ ] ;
const totalEmails = 100 ; // Reduced for test efficiency
const measurementInterval = 20 ; // Measure every 20 emails
let emailsSent = 0 ;
let emailsFailed = 0 ;
for ( let i = 0 ; i < totalEmails ; i ++ ) {
const email = new Email ( {
from : 'sender@longrunning.test' ,
to : [ ` recipient ${ i } @longrunning.test ` ] ,
subject : ` Long Running Test ${ i + 1 } ` ,
text : ` Sustained operation test email ${ i + 1 } `
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
await smtpClient . sendMail ( email ) ;
emailsSent ++ ;
} catch ( error ) {
emailsFailed ++ ;
}
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Measure memory at intervals
if ( ( i + 1 ) % measurementInterval === 0 ) {
2025-05-24 18:12:08 +00:00
forceGC ( ) ;
2025-05-26 14:50:55 +00:00
const currentMemory = getMemoryUsage ( ) ;
memoryMeasurements . push ( {
emailCount : i + 1 ,
heap : currentMemory.heapUsed ,
rss : currentMemory.rss ,
timestamp : Date.now ( )
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ` ${ i + 1 } / ${ totalEmails } emails: ${ currentMemory . heapUsed } MB heap ` ) ;
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
}
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( '\n Long-running memory analysis:' ) ;
console . log ( ` Emails sent: ${ emailsSent } , Failed: ${ emailsFailed } ` ) ;
memoryMeasurements . forEach ( ( measurement , index ) = > {
const memoryIncrease = measurement . heap - initialMemory . heapUsed ;
console . log ( ` After ${ measurement . emailCount } emails: + ${ memoryIncrease . toFixed ( 2 ) } MB heap ` ) ;
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
// Analyze memory growth trend
if ( memoryMeasurements . length >= 2 ) {
const firstMeasurement = memoryMeasurements [ 0 ] ;
const lastMeasurement = memoryMeasurements [ memoryMeasurements . length - 1 ] ;
const memoryGrowth = lastMeasurement . heap - firstMeasurement . heap ;
const emailsProcessed = lastMeasurement . emailCount - firstMeasurement . emailCount ;
const growthRate = ( memoryGrowth / emailsProcessed ) * 1000 ; // KB per email
console . log ( ` Memory growth over operation: + ${ memoryGrowth . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Growth rate: ~ ${ growthRate . toFixed ( 2 ) } KB per email ` ) ;
console . log ( ` Memory stability: ${ growthRate < 10 ? 'Excellent' : growthRate < 25 ? 'Good' : 'Concerning' } ` ) ;
expect ( growthRate ) . toBeLessThan ( 50 ) ; // Allow reasonable growth but detect major leaks
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
expect ( emailsSent ) . toBeGreaterThanOrEqual ( totalEmails - 5 ) ; // Most emails should succeed
smtpClient . close ( ) ;
} finally {
server . close ( ) ;
}
} ) ;
tap . test ( 'CREL-05: Large Content Memory Management' , async ( ) = > {
console . log ( '\n🌊 Testing large content memory management...' ) ;
// Create test server
const server = net . createServer ( socket = > {
socket . write ( '220 localhost SMTP Test Server\r\n' ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
socket . on ( 'data' , ( data ) = > {
const lines = data . toString ( ) . split ( '\r\n' ) ;
lines . forEach ( line = > {
if ( line . startsWith ( 'EHLO' ) || line . startsWith ( 'HELO' ) ) {
socket . write ( '250-localhost\r\n' ) ;
socket . write ( '250 SIZE 10485760\r\n' ) ;
} else if ( line . startsWith ( 'MAIL FROM:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line . startsWith ( 'RCPT TO:' ) ) {
socket . write ( '250 OK\r\n' ) ;
} else if ( line === 'DATA' ) {
socket . write ( '354 Send data\r\n' ) ;
} else if ( line === '.' ) {
socket . write ( '250 OK Message accepted\r\n' ) ;
} else if ( line === 'QUIT' ) {
socket . write ( '221 Bye\r\n' ) ;
socket . end ( ) ;
}
} ) ;
2025-05-24 18:12:08 +00:00
} ) ;
2025-05-26 14:50:55 +00:00
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
await new Promise < void > ( ( resolve ) = > {
server . listen ( 0 , '127.0.0.1' , ( ) = > {
resolve ( ) ;
} ) ;
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const port = ( server . address ( ) as net . AddressInfo ) . port ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
const smtpClient = createTestSmtpClient ( {
host : '127.0.0.1' ,
port : port ,
secure : false ,
maxConnections : 1
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const initialMemory = getMemoryUsage ( ) ;
console . log ( ` Initial memory: ${ initialMemory . heapUsed } MB heap ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ' Testing with various content sizes...' ) ;
const contentSizes = [
{ size : 1024 , name : '1KB' } ,
{ size : 10240 , name : '10KB' } ,
{ size : 102400 , name : '100KB' } ,
{ size : 256000 , name : '250KB' }
] ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
for ( const contentTest of contentSizes ) {
console . log ( ` Testing ${ contentTest . name } content size... ` ) ;
const beforeMemory = getMemoryUsage ( ) ;
// Create large text content
const largeText = 'X' . repeat ( contentTest . size ) ;
const email = new Email ( {
from : 'sender@largemem.test' ,
to : [ 'recipient@largemem.test' ] ,
subject : ` Large Content Test - ${ contentTest . name } ` ,
text : largeText
} ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
try {
await smtpClient . sendMail ( email ) ;
console . log ( ` ✓ ${ contentTest . name } email sent successfully ` ) ;
} catch ( error ) {
console . log ( ` ✗ ${ contentTest . name } email failed: ${ error . message } ` ) ;
2025-05-24 18:12:08 +00:00
}
2025-05-26 14:50:55 +00:00
// Force cleanup
2025-05-24 18:12:08 +00:00
forceGC ( ) ;
2025-05-26 14:50:55 +00:00
await new Promise ( resolve = > setTimeout ( resolve , 100 ) ) ;
const afterMemory = getMemoryUsage ( ) ;
const memoryDiff = afterMemory . heapUsed - beforeMemory . heapUsed ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
console . log ( ` Memory impact: ${ memoryDiff > 0 ? '+' : '' } ${ memoryDiff . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Efficiency: ${ Math . abs ( memoryDiff ) < ( contentTest . size / 1024 / 1024 ) * 2 ? 'Good' : 'High memory usage' } ` ) ;
}
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
const finalMemory = getMemoryUsage ( ) ;
const totalMemoryIncrease = finalMemory . heapUsed - initialMemory . heapUsed ;
console . log ( ` \ n Large content memory summary: ` ) ;
console . log ( ` Total memory increase: + ${ totalMemoryIncrease . toFixed ( 2 ) } MB ` ) ;
console . log ( ` Memory management efficiency: ${ totalMemoryIncrease < 5 ? 'Excellent' : 'Needs optimization' } ` ) ;
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
expect ( totalMemoryIncrease ) . toBeLessThan ( 20 ) ; // Allow reasonable memory usage for large content
2025-05-24 18:12:08 +00:00
2025-05-26 14:50:55 +00:00
smtpClient . close ( ) ;
} finally {
server . close ( ) ;
}
} ) ;
tap . test ( 'CREL-05: Test Summary' , async ( ) = > {
2025-05-24 18:12:08 +00:00
console . log ( '\n✅ CREL-05: Memory Leak Prevention Reliability Tests completed' ) ;
console . log ( '🧠 All memory management scenarios tested successfully' ) ;
2025-05-26 14:50:55 +00:00
} ) ;
tap . start ( ) ;