@@ -517,6 +517,65 @@ describe('class MongoClient', function () {
517
517
) ;
518
518
} ) ;
519
519
520
+ context ( 'concurrent #connect()' , ( ) => {
521
+ let client : MongoClient ;
522
+ let topologyOpenEvents ;
523
+
524
+ /** Keep track number of call to client connect to close as many as connect (otherwise leak_checker hook will failed) */
525
+ let clientConnectCounter : number ;
526
+
527
+ /**
528
+ * Wrap the connect method of the client to keep track
529
+ * of number of times connect is called
530
+ */
531
+ async function clientConnect ( ) {
532
+ if ( ! client ) {
533
+ return ;
534
+ }
535
+ clientConnectCounter ++ ;
536
+ return client . connect ( ) ;
537
+ }
538
+
539
+ beforeEach ( async function ( ) {
540
+ client = this . configuration . newClient ( ) ;
541
+ topologyOpenEvents = [ ] ;
542
+ clientConnectCounter = 0 ;
543
+ client . on ( 'open' , event => topologyOpenEvents . push ( event ) ) ;
544
+ } ) ;
545
+
546
+ afterEach ( async function ( ) {
547
+ // close `clientConnectCounter` times
548
+ const clientClosePromises = Array . from ( { length : clientConnectCounter } , ( ) =>
549
+ client . close ( )
550
+ ) ;
551
+ await Promise . all ( clientClosePromises ) ;
552
+ } ) ;
553
+
554
+ it ( 'parallel client connect calls only create one topology' , async function ( ) {
555
+ await Promise . all ( [ clientConnect ( ) , clientConnect ( ) , clientConnect ( ) ] ) ;
556
+
557
+ expect ( topologyOpenEvents ) . to . have . lengthOf ( 1 ) ;
558
+ expect ( client . topology ?. isConnected ( ) ) . to . be . true ;
559
+ } ) ;
560
+
561
+ it ( 'when connect rejects lock is released regardless' , async function ( ) {
562
+ const internalConnectStub = sinon . stub ( client , '_connect' as keyof MongoClient ) ;
563
+ internalConnectStub . onFirstCall ( ) . rejects ( new Error ( 'cannot connect' ) ) ;
564
+
565
+ // first call rejected to simulate a connection failure
566
+ const error = await clientConnect ( ) . catch ( error => error ) ;
567
+ expect ( error ) . to . match ( / c a n n o t c o n n e c t / ) ;
568
+
569
+ internalConnectStub . restore ( ) ;
570
+
571
+ // second call should connect
572
+ await clientConnect ( ) ;
573
+
574
+ expect ( topologyOpenEvents ) . to . have . lengthOf ( 1 ) ;
575
+ expect ( client . topology ?. isConnected ( ) ) . to . be . true ;
576
+ } ) ;
577
+ } ) ;
578
+
520
579
context ( '#close()' , ( ) => {
521
580
let client : MongoClient ;
522
581
let db : Db ;
0 commit comments