11'use strict'
22
3- const { test } = require ( 'node:test' )
3+ const { test, after } = require ( 'node:test' )
44const assert = require ( 'node:assert' )
55const { Pool } = require ( '..' )
66const { createServer } = require ( 'node:http' )
@@ -16,87 +16,84 @@ test('Pool client count does not grow on repeated connection errors', async (t)
1616 bodyTimeout : 100 ,
1717 headersTimeout : 100
1818 } )
19+ after ( ( ) => pool . close ( ) )
20+
21+ const clientCounts = [ ]
22+
23+ // Track initial client count
24+ clientCounts . push ( pool [ kClients ] . length )
25+
26+ // Make several requests that will fail with connection errors
27+ const requests = 5
28+ for ( let i = 0 ; i < requests ; i ++ ) {
29+ try {
30+ await pool . request ( {
31+ path : `/${ i } ` ,
32+ method : 'GET'
33+ } )
34+ assert . fail ( 'Request should have failed with a connection error' )
35+ } catch ( err ) {
36+ // We expect connection errors, but the error might be wrapped
37+ assert . ok (
38+ err . code === 'ECONNREFUSED' ||
39+ err . cause ?. code === 'ECONNREFUSED' ||
40+ err . code === 'UND_ERR_CONNECT' ,
41+ `Expected connection error but got: ${ err . message } (${ err . code } )`
42+ )
43+ }
1944
20- try {
21- const clientCounts = [ ]
22-
23- // Track initial client count
45+ // Track client count after each request
2446 clientCounts . push ( pool [ kClients ] . length )
2547
26- // Make several requests that will fail with connection errors
27- const requests = 5
28- for ( let i = 0 ; i < requests ; i ++ ) {
29- try {
30- await pool . request ( {
31- path : `/${ i } ` ,
32- method : 'GET'
33- } )
34- assert . fail ( 'Request should have failed with a connection error' )
35- } catch ( err ) {
36- // We expect connection errors, but the error might be wrapped
37- assert . ok (
38- err . code === 'ECONNREFUSED' ||
39- err . cause ?. code === 'ECONNREFUSED' ||
40- err . code === 'UND_ERR_CONNECT' ,
41- `Expected connection error but got: ${ err . message } (${ err . code } )`
42- )
43- }
44-
45- // Track client count after each request
46- clientCounts . push ( pool [ kClients ] . length )
47-
48- // Small delay to allow for client cleanup
49- await new Promise ( resolve => setTimeout ( resolve , 10 ) )
50- }
48+ // Small delay to allow for client cleanup
49+ await new Promise ( resolve => setTimeout ( resolve , 10 ) )
50+ }
5151
52- // The key test: verify that client count doesn't increase monotonically,
53- // which would indicate the memory leak that was fixed
54- const maxCount = Math . max ( ...clientCounts )
55- assert . ok (
56- clientCounts [ clientCounts . length - 1 ] <= maxCount ,
57- `Client count should not increase continuously. Counts: ${ clientCounts . join ( ', ' ) } `
58- )
59-
60- // Ensure the last two counts are similar (stabilized)
61- const lastCount = clientCounts [ clientCounts . length - 1 ]
62- const secondLastCount = clientCounts [ clientCounts . length - 2 ]
63-
64- assert . ok (
65- Math . abs ( lastCount - secondLastCount ) <= 1 ,
66- `Client count should stabilize. Last counts: ${ secondLastCount } , ${ lastCount } `
67- )
68-
69- // Additional verification: make many more requests to check for significant growth
70- const moreRequests = 10
71- const startCount = pool [ kClients ] . length
72-
73- for ( let i = 0 ; i < moreRequests ; i ++ ) {
74- try {
75- await pool . request ( {
76- path : `/more-${ i } ` ,
77- method : 'GET'
78- } )
79- } catch ( err ) {
80- // Expected error
81- }
82-
83- // Small delay to allow for client cleanup
84- await new Promise ( resolve => setTimeout ( resolve , 10 ) )
52+ // The key test: verify that client count doesn't increase monotonically,
53+ // which would indicate the memory leak that was fixed
54+ const maxCount = Math . max ( ...clientCounts )
55+ assert . ok (
56+ clientCounts [ clientCounts . length - 1 ] <= maxCount ,
57+ `Client count should not increase continuously. Counts: ${ clientCounts . join ( ', ' ) } `
58+ )
59+
60+ // Ensure the last two counts are similar (stabilized)
61+ const lastCount = clientCounts [ clientCounts . length - 1 ]
62+ const secondLastCount = clientCounts [ clientCounts . length - 2 ]
63+
64+ assert . ok (
65+ Math . abs ( lastCount - secondLastCount ) <= 1 ,
66+ `Client count should stabilize. Last counts: ${ secondLastCount } , ${ lastCount } `
67+ )
68+
69+ // Additional verification: make many more requests to check for significant growth
70+ const moreRequests = 10
71+ const startCount = pool [ kClients ] . length
72+
73+ for ( let i = 0 ; i < moreRequests ; i ++ ) {
74+ try {
75+ await pool . request ( {
76+ path : `/more-${ i } ` ,
77+ method : 'GET'
78+ } )
79+ } catch ( err ) {
80+ // Expected error
8581 }
8682
87- const endCount = pool [ kClients ] . length
83+ // Small delay to allow for client cleanup
84+ await new Promise ( resolve => setTimeout ( resolve , 10 ) )
85+ }
8886
89- // The maximum tolerable growth - some growth may occur due to timing issues,
90- // but it should be limited and not proportional to the number of requests
91- const maxGrowth = 3
87+ const endCount = pool [ kClients ] . length
9288
93- assert . ok (
94- endCount - startCount <= maxGrowth ,
95- `Client count should not grow significantly after many failed requests. Start: ${ startCount } , End: ${ endCount } `
96- )
97- } finally {
98- await pool . close ( )
99- }
89+ // The maximum tolerable growth - some growth may occur due to timing issues,
90+ // but it should be limited and not proportional to the number of requests
91+ const maxGrowth = 3
92+
93+ assert . ok (
94+ endCount - startCount <= maxGrowth ,
95+ `Client count should not grow significantly after many failed requests. Start: ${ startCount } , End: ${ endCount } `
96+ )
10097} )
10198
10299// This test specifically verifies the fix in pool-base.js for connectionError event
@@ -113,46 +110,43 @@ test('Pool clients are removed on connectionError event', async (t) => {
113110 const pool = new Pool ( `http://localhost:${ port } ` , {
114111 connections : 3 // Small pool to make testing easier
115112 } )
113+ after ( ( ) => pool . close ( ) )
114+ after ( ( ) => server . close ( ) )
116115
117- try {
118- // Make an initial successful request to create a client
119- await pool . request ( {
120- path : '/' ,
121- method : 'GET'
122- } )
123-
124- // Save the initial number of clients
125- const initialCount = pool [ kClients ] . length
126- assert . ok ( initialCount > 0 , 'Should have at least one client after a successful request' )
116+ // Make an initial successful request to create a client
117+ await pool . request ( {
118+ path : '/' ,
119+ method : 'GET'
120+ } )
127121
128- // Manually trigger a connectionError on all clients
129- for ( const client of [ ...pool [ kClients ] ] ) {
130- client . emit ( 'connectionError' , 'origin' , [ client ] , new Error ( 'Simulated connection error' ) )
131- }
122+ // Save the initial number of clients
123+ const initialCount = pool [ kClients ] . length
124+ assert . ok ( initialCount > 0 , 'Should have at least one client after a successful request' )
132125
133- // Allow some time for the event to be processed
134- await new Promise ( resolve => setTimeout ( resolve , 50 ) )
135-
136- // After the fix, all clients should be removed when they emit a connectionError
137- assert . strictEqual (
138- pool [ kClients ] . length ,
139- 0 ,
140- 'All clients should be removed from pool after connectionError events'
141- )
142-
143- // Make another request to verify the pool can create new clients
144- await pool . request ( {
145- path : '/after-error' ,
146- method : 'GET'
147- } )
148-
149- // Verify new clients were created
150- assert . ok (
151- pool [ kClients ] . length > 0 ,
152- 'Pool should create new clients after previous ones were removed'
153- )
154- } finally {
155- await pool . close ( )
156- await new Promise ( resolve => server . close ( resolve ) )
126+ // Manually trigger a connectionError on all clients
127+ for ( const client of [ ...pool [ kClients ] ] ) {
128+ client . emit ( 'connectionError' , 'origin' , [ client ] , new Error ( 'Simulated connection error' ) )
157129 }
130+
131+ // Allow some time for the event to be processed
132+ await new Promise ( resolve => setTimeout ( resolve , 50 ) )
133+
134+ // After the fix, all clients should be removed when they emit a connectionError
135+ assert . strictEqual (
136+ pool [ kClients ] . length ,
137+ 0 ,
138+ 'All clients should be removed from pool after connectionError events'
139+ )
140+
141+ // Make another request to verify the pool can create new clients
142+ await pool . request ( {
143+ path : '/after-error' ,
144+ method : 'GET'
145+ } )
146+
147+ // Verify new clients were created
148+ assert . ok (
149+ pool [ kClients ] . length > 0 ,
150+ 'Pool should create new clients after previous ones were removed'
151+ )
158152} )
0 commit comments