1
+ import * as events from 'node:events' ;
2
+
1
3
import { expect } from 'chai' ;
2
4
3
5
import { getCSFLEKMSProviders } from '../../csfle-kms-providers' ;
4
6
import { type Collection , type FindCursor , type MongoClient } from '../../mongodb' ;
5
- import { type TestConfiguration } from '../../tools/runner/config' ;
6
7
import { runScriptAndGetProcessInfo } from './resource_tracking_script_builder' ;
7
8
8
9
describe ( 'MongoClient.close() Integration' , ( ) => {
9
10
// note: these tests are set-up in accordance of the resource ownership tree
10
11
11
- let config : TestConfiguration ;
12
-
13
- beforeEach ( function ( ) {
14
- config = this . configuration ;
15
- } ) ;
16
-
17
12
describe ( 'Node.js resource: TLS File read' , ( ) => {
18
13
describe ( 'when client is connecting and reads an infinite TLS file' , ( ) => {
19
14
it . skip ( 'the file read is interrupted by client.close()' , async function ( ) {
20
15
await runScriptAndGetProcessInfo (
21
16
'tls-file-read' ,
22
- config ,
17
+ this . configuration ,
23
18
async function run ( { MongoClient, uri, expect } ) {
24
19
const infiniteFile = '/dev/zero' ;
25
20
const client = new MongoClient ( uri , { tls : true , tlsCertificateKeyFile : infiniteFile } ) ;
@@ -52,10 +47,10 @@ describe('MongoClient.close() Integration', () => {
52
47
} ) ;
53
48
54
49
describe ( 'when MongoClientAuthProviders is instantiated and token file read hangs' , ( ) => {
55
- it . skip ( 'the file read is interrupted by client.close()' , async ( ) => {
50
+ it . skip ( 'the file read is interrupted by client.close()' , async function ( ) {
56
51
await runScriptAndGetProcessInfo (
57
52
'token-file-read' ,
58
- config ,
53
+ this . configuration ,
59
54
async function run ( { MongoClient, uri, expect } ) {
60
55
const infiniteFile = '/dev/zero' ;
61
56
process . env . OIDC_TOKEN_FILE = infiniteFile ;
@@ -81,30 +76,41 @@ describe('MongoClient.close() Integration', () => {
81
76
describe ( 'after a Topology is created through client.connect()' , ( ) => {
82
77
const metadata : MongoDBMetadataUI = { requires : { topology : 'replicaset' } } ;
83
78
84
- it . skip ( 'server selection timers are cleaned up by client.close()' , metadata , async ( ) => {
85
- const run = async function ( { MongoClient, uri, expect, sleep, mongodb, getTimerCount } ) {
86
- const serverSelectionTimeoutMS = 2222 ;
87
- const client = new MongoClient ( uri , {
88
- minPoolSize : 1 ,
89
- serverSelectionTimeoutMS,
90
- readPreference : new mongodb . ReadPreference ( 'secondary' , [
91
- { something : 'that does not exist' }
92
- ] )
93
- } ) ;
94
- const insertPromise = client . db ( 'db' ) . collection ( 'collection' ) . insertOne ( { x : 1 } ) ;
79
+ it . skip (
80
+ 'server selection timers are cleaned up by client.close()' ,
81
+ metadata ,
82
+ async function ( ) {
83
+ const run = async function ( {
84
+ MongoClient,
85
+ uri,
86
+ expect,
87
+ sleep,
88
+ mongodb,
89
+ getTimerCount
90
+ } ) {
91
+ const serverSelectionTimeoutMS = 2222 ;
92
+ const client = new MongoClient ( uri , {
93
+ minPoolSize : 1 ,
94
+ serverSelectionTimeoutMS,
95
+ readPreference : new mongodb . ReadPreference ( 'secondary' , [
96
+ { something : 'that does not exist' }
97
+ ] )
98
+ } ) ;
99
+ const insertPromise = client . db ( 'db' ) . collection ( 'collection' ) . insertOne ( { x : 1 } ) ;
95
100
96
- // don't allow entire server selection timer to elapse to ensure close is called mid-timeout
97
- await sleep ( serverSelectionTimeoutMS / 2 ) ;
101
+ // don't allow entire server selection timer to elapse to ensure close is called mid-timeout
102
+ await sleep ( serverSelectionTimeoutMS / 2 ) ;
98
103
99
- expect ( getTimerCount ( ) ) . to . not . equal ( 0 ) ;
100
- await client . close ( ) ;
101
- expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
104
+ expect ( getTimerCount ( ) ) . to . not . equal ( 0 ) ;
105
+ await client . close ( ) ;
106
+ expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
102
107
103
- const err = await insertPromise . catch ( e => e ) ;
104
- expect ( err ) . to . be . instanceOf ( mongodb . MongoTopologyClosedError ) ;
105
- } ;
106
- await runScriptAndGetProcessInfo ( 'timer-server-selection' , config , run ) ;
107
- } ) ;
108
+ const err = await insertPromise . catch ( e => e ) ;
109
+ expect ( err ) . to . be . instanceOf ( mongodb . MongoTopologyClosedError ) ;
110
+ } ;
111
+ await runScriptAndGetProcessInfo ( 'timer-server-selection' , this . configuration , run ) ;
112
+ }
113
+ ) ;
108
114
} ) ;
109
115
} ) ;
110
116
@@ -147,7 +153,11 @@ describe('MongoClient.close() Integration', () => {
147
153
148
154
expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
149
155
} ;
150
- await runScriptAndGetProcessInfo ( 'timer-monitor-interval' , config , run ) ;
156
+ await runScriptAndGetProcessInfo (
157
+ 'timer-monitor-interval' ,
158
+ this . configuration ,
159
+ run
160
+ ) ;
151
161
}
152
162
) ;
153
163
} ) ;
@@ -156,7 +166,7 @@ describe('MongoClient.close() Integration', () => {
156
166
it . skip (
157
167
'the new monitor interval timer is cleaned up by client.close()' ,
158
168
metadata ,
159
- async ( ) => {
169
+ async function ( ) {
160
170
const run = async function ( { MongoClient, expect, getTimerCount, once } ) {
161
171
const heartbeatFrequencyMS = 2000 ;
162
172
const client = new MongoClient ( 'mongodb://fakeUri' , { heartbeatFrequencyMS } ) ;
@@ -178,7 +188,11 @@ describe('MongoClient.close() Integration', () => {
178
188
179
189
await connectPromise ;
180
190
} ;
181
- await runScriptAndGetProcessInfo ( 'timer-heartbeat-failed-monitor' , config , run ) ;
191
+ await runScriptAndGetProcessInfo (
192
+ 'timer-heartbeat-failed-monitor' ,
193
+ this . configuration ,
194
+ run
195
+ ) ;
182
196
}
183
197
) ;
184
198
} ) ;
@@ -207,7 +221,11 @@ describe('MongoClient.close() Integration', () => {
207
221
expect ( getSocketEndpoints ( ) ) . to . not . deep . include ( { host, port } ) ;
208
222
}
209
223
} ;
210
- await runScriptAndGetProcessInfo ( 'socket-connection-monitoring' , config , run ) ;
224
+ await runScriptAndGetProcessInfo (
225
+ 'socket-connection-monitoring' ,
226
+ this . configuration ,
227
+ run
228
+ ) ;
211
229
} ) ;
212
230
} ) ;
213
231
} ) ;
@@ -242,7 +260,7 @@ describe('MongoClient.close() Integration', () => {
242
260
243
261
expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
244
262
} ;
245
- await runScriptAndGetProcessInfo ( 'timer-rtt-monitor' , config , run ) ;
263
+ await runScriptAndGetProcessInfo ( 'timer-rtt-monitor' , this . configuration , run ) ;
246
264
}
247
265
) ;
248
266
} ) ;
@@ -251,7 +269,7 @@ describe('MongoClient.close() Integration', () => {
251
269
describe ( 'Connection' , ( ) => {
252
270
describe ( 'Node.js resource: Socket' , ( ) => {
253
271
describe ( 'when rtt monitoring is turned on' , ( ) => {
254
- it . skip ( 'no sockets remain after client.close()' , metadata , async ( ) => {
272
+ it . skip ( 'no sockets remain after client.close()' , metadata , async function ( ) {
255
273
const run = async ( { MongoClient, uri, expect, getSockets, once } ) => {
256
274
const heartbeatFrequencyMS = 500 ;
257
275
const client = new MongoClient ( uri , {
@@ -289,7 +307,11 @@ describe('MongoClient.close() Integration', () => {
289
307
expect ( activeSocketsAfterClose ) . to . have . lengthOf ( 0 ) ;
290
308
} ;
291
309
292
- await runScriptAndGetProcessInfo ( 'socket-connection-rtt-monitoring' , config , run ) ;
310
+ await runScriptAndGetProcessInfo (
311
+ 'socket-connection-rtt-monitoring' ,
312
+ this . configuration ,
313
+ run
314
+ ) ;
293
315
} ) ;
294
316
} ) ;
295
317
} ) ;
@@ -323,7 +345,7 @@ describe('MongoClient.close() Integration', () => {
323
345
expect ( getMinPoolSizeTimer ( servers ) ) . to . not . exist ;
324
346
expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
325
347
} ;
326
- await runScriptAndGetProcessInfo ( 'timer-min-pool-size' , config , run ) ;
348
+ await runScriptAndGetProcessInfo ( 'timer-min-pool-size' , this . configuration , run ) ;
327
349
} ) ;
328
350
} ) ;
329
351
} ) ;
@@ -334,8 +356,8 @@ describe('MongoClient.close() Integration', () => {
334
356
const waitQueueTimeoutMS = 1515 ;
335
357
336
358
beforeEach ( async function ( ) {
337
- // configure failPoint
338
- utilClient = this . configuration . newClient ( ) ;
359
+ // this.configurationure failPoint
360
+ utilClient = this . this . configurationuration . newClient ( ) ;
339
361
await utilClient . connect ( ) ;
340
362
const failPoint = {
341
363
configureFailPoint : 'failCommand' ,
@@ -392,7 +414,7 @@ describe('MongoClient.close() Integration', () => {
392
414
'Timed out while checking out a connection from connection pool'
393
415
) ;
394
416
} ;
395
- await runScriptAndGetProcessInfo ( 'timer-check-out' , config , run ) ;
417
+ await runScriptAndGetProcessInfo ( 'timer-check-out' , this . configuration , run ) ;
396
418
} ) ;
397
419
} ) ;
398
420
} ) ;
@@ -418,7 +440,7 @@ describe('MongoClient.close() Integration', () => {
418
440
expect ( getSockets ( ) ) . to . have . lengthOf ( 0 ) ;
419
441
} ;
420
442
421
- await runScriptAndGetProcessInfo ( 'socket-minPoolSize' , config , run ) ;
443
+ await runScriptAndGetProcessInfo ( 'socket-minPoolSize' , this . configuration , run ) ;
422
444
} ) ;
423
445
} ) ;
424
446
} ) ;
@@ -432,7 +454,7 @@ describe('MongoClient.close() Integration', () => {
432
454
const metadata : MongoDBMetadataUI = { requires : { topology : 'sharded' } } ;
433
455
434
456
describe ( 'after SRVPoller is created' , ( ) => {
435
- it . skip ( 'timers are cleaned up by client.close()' , metadata , async ( ) => {
457
+ it . skip ( 'timers are cleaned up by client.close()' , metadata , async function ( ) {
436
458
const run = async function ( { MongoClient, expect, getTimerCount } ) {
437
459
const SRV_CONNECTION_STRING = `mongodb+srv://test1.test.build.10gen.cc` ;
438
460
@@ -450,13 +472,43 @@ describe('MongoClient.close() Integration', () => {
450
472
await client . close ( ) ;
451
473
expect ( getTimerCount ( ) ) . to . equal ( 0 ) ;
452
474
} ;
453
- await runScriptAndGetProcessInfo ( 'timer-srv-poller' , config , run ) ;
475
+ await runScriptAndGetProcessInfo ( 'timer-srv-poller' , this . configuration , run ) ;
454
476
} ) ;
455
477
} ) ;
456
478
} ) ;
457
479
} ) ;
458
480
} ) ;
459
481
482
+ describe ( 'ClientSession (Implicit)' , ( ) => {
483
+ let client : MongoClient ;
484
+
485
+ beforeEach ( async function ( ) {
486
+ client = this . configuration . newClient ( { } , { monitorCommands : true } ) ;
487
+ } ) ;
488
+
489
+ afterEach ( async function ( ) {
490
+ await client . close ( ) ;
491
+ } ) ;
492
+
493
+ describe ( 'when MongoClient.close is called' , function ( ) {
494
+ it ( 'sends an endSessions command' , async function ( ) {
495
+ await client . db ( 'a' ) . collection ( 'a' ) . insertOne ( { a : 1 } ) ;
496
+ await client . db ( 'a' ) . collection ( 'a' ) . insertOne ( { a : 1 } ) ;
497
+ await client . db ( 'a' ) . collection ( 'a' ) . insertOne ( { a : 1 } ) ;
498
+ const endSessionsStarted = events . once ( client , 'commandStarted' ) ;
499
+ const willEndSessions = events . once ( client , 'commandSucceeded' ) ;
500
+
501
+ await client . close ( ) ;
502
+
503
+ const [ startedEv ] = await endSessionsStarted ;
504
+ expect ( startedEv ) . to . have . nested . property ( 'command.endSessions' ) . that . has . lengthOf ( 1 ) ;
505
+
506
+ const [ commandEv ] = await willEndSessions ;
507
+ expect ( commandEv ) . to . have . property ( 'commandName' , 'endSessions' ) ;
508
+ } ) ;
509
+ } ) ;
510
+ } ) ;
511
+
460
512
describe ( 'ClientSession (Explicit)' , ( ) => {
461
513
let idleSessionsBeforeClose ;
462
514
let idleSessionsAfterClose ;
@@ -538,10 +590,10 @@ describe('MongoClient.close() Integration', () => {
538
590
describe ( 'KMS Request' , ( ) => {
539
591
describe ( 'Node.js resource: TLS file read' , ( ) => {
540
592
describe ( 'when KMSRequest reads an infinite TLS file' , ( ) => {
541
- it . skip ( 'the file read is interrupted by client.close()' , metadata , async ( ) => {
593
+ it . skip ( 'the file read is interrupted by client.close()' , metadata , async function ( ) {
542
594
await runScriptAndGetProcessInfo (
543
595
'tls-file-read-auto-encryption' ,
544
- config ,
596
+ this . configuration ,
545
597
async function run ( { MongoClient, uri, expect, mongodb } ) {
546
598
const infiniteFile = '/dev/zero' ;
547
599
@@ -666,7 +718,7 @@ describe('MongoClient.close() Integration', () => {
666
718
'all active server-side cursors are closed by client.close()' ,
667
719
metadata ,
668
720
async function ( ) {
669
- const getCursors = async ( ) => {
721
+ const getCursors = async function ( ) {
670
722
const cursors = await utilClient
671
723
. db ( 'admin' )
672
724
. aggregate ( [ { $currentOp : { idleCursors : true } } ] )
0 commit comments