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