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