@@ -84,6 +84,11 @@ type WriteConcernErrorData struct {
8484 ErrInfo bson.Raw `bson:"errInfo,omitempty"`
8585}
8686
87+ type failPoint struct {
88+ name string
89+ client * mongo.Client
90+ }
91+
8792// T is a wrapper around testing.T.
8893type T struct {
8994 // connsCheckedOut is the net number of connections checked out during test execution.
@@ -103,7 +108,7 @@ type T struct {
103108 createdColls []* Collection // collections created in this test
104109 proxyDialer * proxyDialer
105110 dbName , collName string
106- failPointNames [] string
111+ failPoints [] failPoint
107112 minServerVersion string
108113 maxServerVersion string
109114 validTopologies []TopologyKind
@@ -128,15 +133,16 @@ type T struct {
128133 succeeded []* event.CommandSucceededEvent
129134 failed []* event.CommandFailedEvent
130135
131- Client * mongo.Client
132- fpClient * mongo.Client
133- DB * mongo.Database
134- Coll * mongo.Collection
136+ Client * mongo.Client
137+ fpClients map [ * mongo.Client ] bool
138+ DB * mongo.Database
139+ Coll * mongo.Collection
135140}
136141
137142func newT (wrapped * testing.T , opts ... * Options ) * T {
138143 t := & T {
139- T : wrapped ,
144+ T : wrapped ,
145+ fpClients : make (map [* mongo.Client ]bool ),
140146 }
141147 for _ , opt := range opts {
142148 for _ , optFn := range opt .optFuncs {
@@ -176,16 +182,10 @@ func New(wrapped *testing.T, opts ...*Options) *T {
176182
177183 t := newT (wrapped , opts ... )
178184
179- fpOpt := t .clientOpts
180- if fpOpt != nil {
181- fpOpt .AutoEncryptionOptions = nil
182- }
183- t .fpClient = t .createTestClient (fpOpt )
184-
185185 // only create a client if it needs to be shared in sub-tests
186186 // otherwise, a new client will be created for each subtest
187187 if t .shareClient != nil && * t .shareClient {
188- t .Client = t . createTestClient (t . clientOpts )
188+ t .createTestClient ()
189189 }
190190
191191 wrapped .Cleanup (t .cleanup )
@@ -209,6 +209,12 @@ func (t *T) cleanup() {
209209 // always disconnect the client regardless of clientType because Client.Disconnect will work against
210210 // all deployments
211211 _ = t .Client .Disconnect (context .Background ())
212+ for client , v := range t .fpClients {
213+ if v {
214+ client .Disconnect (context .Background ())
215+ }
216+ }
217+ t .fpClients = nil
212218}
213219
214220// Run creates a new T instance for a sub-test and runs the given callback. It also creates a new collection using the
@@ -231,21 +237,14 @@ func (t *T) RunOpts(name string, opts *Options, callback func(mt *T)) {
231237 sub .AddMockResponses (sub .mockResponses ... )
232238 }
233239
234- if sub .fpClient == nil {
235- clientOpts := sub .clientOpts
236- if clientOpts != nil {
237- clientOpts .AutoEncryptionOptions = nil
238- }
239- sub .fpClient = sub .createTestClient (clientOpts )
240- }
241240 // for shareClient, inherit the client from the parent
242241 if sub .shareClient != nil && * sub .shareClient && sub .clientType == t .clientType {
243242 sub .Client = t .Client
244243 }
245244 // only create a client if not already set
246245 if sub .Client == nil {
247246 if sub .createClient == nil || * sub .createClient {
248- sub .Client = sub . createTestClient (sub . clientOpts )
247+ sub .createTestClient ()
249248 }
250249 }
251250 // create a collection for this test
@@ -270,7 +269,9 @@ func (t *T) RunOpts(name string, opts *Options, callback func(mt *T)) {
270269 }
271270 // only disconnect client if it's not being shared
272271 if sub .shareClient == nil || ! * sub .shareClient {
273- _ = sub .Client .Disconnect (context .Background ())
272+ if _ , ok := sub .fpClients [sub .Client ]; ! ok {
273+ _ = sub .Client .Disconnect (context .Background ())
274+ }
274275 }
275276 assert .Equal (sub , 0 , sessions , "%v sessions checked out" , sessions )
276277 assert .Equal (sub , 0 , conns , "%v connections checked out" , conns )
@@ -419,8 +420,10 @@ func (t *T) ResetClient(opts *options.ClientOptions) {
419420 t .clientOpts = opts
420421 }
421422
422- _ = t .Client .Disconnect (context .Background ())
423- t .Client = t .createTestClient (t .clientOpts )
423+ if _ , ok := t .fpClients [t .Client ]; ! ok {
424+ _ = t .Client .Disconnect (context .Background ())
425+ }
426+ t .createTestClient ()
424427 t .DB = t .Client .Database (t .dbName )
425428 t .Coll = t .DB .Collection (t .collName , t .collOpts )
426429
@@ -576,7 +579,8 @@ func (t *T) SetFailPoint(fp FailPoint) {
576579 if err := SetFailPoint (fp , t .Client ); err != nil {
577580 t .Fatal (err )
578581 }
579- t .failPointNames = append (t .failPointNames , fp .ConfigureFailPoint )
582+ t .fpClients [t .Client ] = true
583+ t .failPoints = append (t .failPoints , failPoint {fp .ConfigureFailPoint , t .Client })
580584}
581585
582586// SetFailPointFromDocument sets the fail point represented by the given document for the client associated with T. This
@@ -588,30 +592,35 @@ func (t *T) SetFailPointFromDocument(fp bson.Raw) {
588592 t .Fatal (err )
589593 }
590594
595+ t .fpClients [t .Client ] = true
591596 name := fp .Index (0 ).Value ().StringValue ()
592- t .failPointNames = append (t .failPointNames , name )
597+ t .failPoints = append (t .failPoints , failPoint { name , t . Client } )
593598}
594599
595600// TrackFailPoint adds the given fail point to the list of fail points to be disabled when the current test finishes.
596601// This function does not create a fail point on the server.
597- func (t * T ) TrackFailPoint (fpName string ) {
598- t .failPointNames = append (t .failPointNames , fpName )
602+ func (t * T ) TrackFailPoint (fpName string , client * mongo.Client ) {
603+ t .fpClients [client ] = true
604+ t .failPoints = append (t .failPoints , failPoint {fpName , client })
599605}
600606
601607// ClearFailPoints disables all previously set failpoints for this test.
602608func (t * T ) ClearFailPoints () {
603- db := t .Client .Database ("admin" )
604- for _ , fp := range t .failPointNames {
609+ for _ , fp := range t .failPoints {
605610 cmd := bson.D {
606- {"configureFailPoint" , fp },
611+ {"configureFailPoint" , fp . name },
607612 {"mode" , "off" },
608613 }
609- err := db .RunCommand (context .Background (), cmd ).Err ()
614+ err := fp . client . Database ( "admin" ) .RunCommand (context .Background (), cmd ).Err ()
610615 if err != nil {
611- t .Fatalf ("error clearing fail point %s: %v" , fp , err )
616+ t .Fatalf ("error clearing fail point %s: %v" , fp .name , err )
617+ }
618+ if fp .client != t .Client {
619+ _ = fp .client .Disconnect (context .Background ())
620+ t .fpClients [fp .client ] = false
612621 }
613622 }
614- t .failPointNames = t .failPointNames [:0 ]
623+ t .failPoints = t .failPoints [:0 ]
615624}
616625
617626// CloneDatabase modifies the default database for this test to match the given options.
@@ -639,7 +648,8 @@ func sanitizeCollectionName(db string, coll string) string {
639648 return coll
640649}
641650
642- func (t * T ) createTestClient (clientOpts * options.ClientOptions ) * mongo.Client {
651+ func (t * T ) createTestClient () {
652+ clientOpts := t .clientOpts
643653 if clientOpts == nil {
644654 // default opts
645655 clientOpts = options .Client ().SetWriteConcern (MajorityWc ).SetReadPreference (PrimaryRp )
@@ -697,20 +707,17 @@ func (t *T) createTestClient(clientOpts *options.ClientOptions) *mongo.Client {
697707 })
698708 }
699709
700- var client * mongo.Client
701- var err error
710+ var uriOpts * options.ClientOptions
702711 switch t .clientType {
703712 case Pinned :
704713 // pin to first mongos
705714 pinnedHostList := []string {testContext .connString .Hosts [0 ]}
706- uriOpts := options .Client ().ApplyURI (testContext .connString .Original ).SetHosts (pinnedHostList )
707- client , err = mongo .NewClient (uriOpts , clientOpts )
715+ uriOpts = options .Client ().ApplyURI (testContext .connString .Original ).SetHosts (pinnedHostList )
708716 case Mock :
709717 // clear pool monitor to avoid configuration error
710718 clientOpts .PoolMonitor = nil
711719 t .mockDeployment = newMockDeployment ()
712720 clientOpts .Deployment = t .mockDeployment
713- client , err = mongo .NewClient (clientOpts )
714721 case Proxy :
715722 t .proxyDialer = newProxyDialer ()
716723 clientOpts .SetDialer (t .proxyDialer )
@@ -720,23 +727,23 @@ func (t *T) createTestClient(clientOpts *options.ClientOptions) *mongo.Client {
720727 case Default :
721728 // Use a different set of options to specify the URI because clientOpts may already have a URI or host seedlist
722729 // specified.
723- var uriOpts * options.ClientOptions
724730 if clientOpts .Deployment == nil {
725731 // Only specify URI if the deployment is not set to avoid setting topology/server options along with the
726732 // deployment.
727733 uriOpts = options .Client ().ApplyURI (testContext .connString .Original )
728734 }
729-
730- // Pass in uriOpts first so clientOpts wins if there are any conflicting settings.
731- client , err = mongo .NewClient (uriOpts , clientOpts )
732735 }
736+ t .clientOpts = options .MergeClientOptions (uriOpts , clientOpts )
737+
738+ var err error
739+ // Pass in uriOpts first so clientOpts wins if there are any conflicting settings.
740+ t .Client , err = mongo .NewClient (t .clientOpts )
733741 if err != nil {
734742 t .Fatalf ("error creating client: %v" , err )
735743 }
736- if err := client .Connect (context .Background ()); err != nil {
744+ if err := t . Client .Connect (context .Background ()); err != nil {
737745 t .Fatalf ("error connecting client: %v" , err )
738746 }
739- return client
740747}
741748
742749func (t * T ) createTestCollection () {
0 commit comments