@@ -517,6 +517,65 @@ describe('class MongoClient', function () {
517517 ) ;
518518 } ) ;
519519
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+
520579 context ( '#close()' , ( ) => {
521580 let client : MongoClient ;
522581 let db : Db ;
0 commit comments