示例#1
0
        public void Stop_should_trigger_immidiate_maintenace_call(
            [Values(false, true)] bool checkOutConnection,
            [Values(false, true)] bool closeInUseConnection)
        {
            var eventCapturer = new EventCapturer()
                                .Capture <ConnectionPoolAddedConnectionEvent>()
                                .Capture <ConnectionPoolRemovedConnectionEvent>();

            int connectionId = 0;

            using (var pool = CreatePool(
                       eventCapturer,
                       minPoolSize: 1,
                       connectionFactoryConfigurator: (factory) =>
            {
                factory
                .Setup(f => f.CreateConnection(__serverId, __endPoint))
                .Returns(() => new MockConnection(new ConnectionId(__serverId, ++connectionId), new ConnectionSettings(), eventCapturer));
            }))     // use to ensure that Maintenance attempt has been called
            {
                var subject = pool._maintenanceHelper();

                var maitenanceInPlayTimeout = TimeSpan.FromMilliseconds(50);
                eventCapturer.WaitForEventOrThrowIfTimeout <ConnectionPoolAddedConnectionEvent>(maitenanceInPlayTimeout);
                eventCapturer.Next().Should().BeOfType <ConnectionPoolAddedConnectionEvent>().Which.ConnectionId.LocalValue.Should().Be(1);  // minPoolSize has been enrolled
                eventCapturer.Any().Should().BeFalse();

                SpinWait.SpinUntil(() => pool.ConnectionHolder._connections().Count > 0, TimeSpan.FromSeconds(1)).Should().BeTrue(); // wait until connection 1 has been returned to the pool after minPoolSize logic

                IConnection acquiredConnection = null;
                if (checkOutConnection)
                {
                    acquiredConnection = pool.AcquireConnection(CancellationToken.None);
                    acquiredConnection.ConnectionId.LocalValue.Should().Be(1);
                }

                IncrementGeneration(pool);
                subject.Stop(maxGenerationToReap: closeInUseConnection ? pool.Generation : null);

                var requestInPlayTimeout = TimeSpan.FromMilliseconds(100);
                if (!closeInUseConnection && checkOutConnection)
                {
                    // connection in progress should be not touched
                    Thread.Sleep(requestInPlayTimeout);
                }
                else
                {
                    eventCapturer.WaitForOrThrowIfTimeout((events) => events.OfType <ConnectionPoolRemovedConnectionEvent>().Count() >= 1, requestInPlayTimeout);
                    eventCapturer.Next().Should().BeOfType <ConnectionPoolRemovedConnectionEvent>();
                }
                eventCapturer.Any().Should().BeFalse();

                pool.AvailableCount.Should().Be(checkOutConnection ? pool.Settings.MaxConnections - 1 : pool.Settings.MaxConnections);
                pool.CreatedCount.Should().Be(checkOutConnection ? 1 : 0);
                pool.DormantCount.Should().Be(0);
                pool.PendingCount.Should().Be(0);
                pool.UsedCount.Should().Be(checkOutConnection ? 1 : 0);
            }
        }
        private void Wait()
        {
            var eventCondition = MapEventNameToCondition(_event);
            Func <IEnumerable <object>, bool> eventsConditionWithFilterByCount = (events) => events.Count(eventCondition) >= _count;

            _eventCapturer.WaitForOrThrowIfTimeout(
                eventsConditionWithFilterByCount,
                TimeSpan.FromSeconds(10),
                (timeout) =>
            {
                var triggeredEventsCount = _eventCapturer.Events.Count(eventCondition);
                return($"Waiting for {_count} {_event} exceeded the timeout {timeout}. The number of triggered events is {triggeredEventsCount}.");
            });
        }
        public void Heartbeat_should_work_as_expected()
        {
            var heartbeatSuceededTimestamps = new ConcurrentQueue <DateTime>();
            var eventCapturer = new EventCapturer()
                                .Capture <ServerHeartbeatSucceededEvent>(
                (@event) =>
            {
                heartbeatSuceededTimestamps.Enqueue(DateTime.UtcNow);
                return(true);
            }
                );

            var heartbeatInterval = TimeSpan.FromMilliseconds(500);

            eventCapturer.Clear();
            using (var client = CreateClient(eventCapturer, heartbeatInterval))
            {
                eventCapturer.WaitForOrThrowIfTimeout(
                    events => events.Count() > 3, // wait for at least 3 events
                    TimeSpan.FromSeconds(10),
                    (timeout) =>
                {
                    return($"Waiting for the expected events exceeded the timeout {timeout}. The number of triggered events is {eventCapturer.Events.ToList().Count}.");
                });
            }

            var heartbeatSuceededTimestampsList = heartbeatSuceededTimestamps.ToList();

            // we have at least 3 items here
            // Skip the first event because we have nothing to compare it to
            for (int i = 1; i < heartbeatSuceededTimestampsList.Count; i++)
            {
                var attemptDuration = heartbeatSuceededTimestampsList[i] - heartbeatSuceededTimestampsList[i - 1];
                attemptDuration
                .Should()
                .BeLessThan(TimeSpan.FromSeconds(2));
                // Assert the client processes isMaster replies more frequently than 10 secs (approximately every 500ms)
            }
        }
示例#4
0
        public void Heartbeat_should_make_immediate_next_attempt_for_streaming_protocol(string exceptionType, bool?moreToCome)
        {
            var capturedEvents = new EventCapturer()
                                 .Capture <ServerHeartbeatSucceededEvent>()
                                 .Capture <ServerHeartbeatFailedEvent>()
                                 .Capture <ServerDescriptionChangedEvent>();
            var subject = CreateSubject(out var mockConnection, out _, out var mockRoundTimeTripMonitor, capturedEvents);

            subject.DescriptionChanged +=
                (o, e) =>
            {
                capturedEvents.TryGetEventHandler <ServerDescriptionChangedEvent>(out var eventHandler);
                eventHandler(new ServerDescriptionChangedEvent(e.OldServerDescription, e.NewServerDescription));
            };

            SetupHeartbeatConnection(mockConnection, isStreamable: true, autoFillStreamingResponses: false);

            Exception exception = null;

            switch (exceptionType)
            {
            case null:
                mockConnection.EnqueueCommandResponseMessage(CreateStreamableCommandResponseMessage(moreToCome.Value), null);
                break;

            case "MongoConnectionException":
                // previousDescription type is "Known" for this case
                mockConnection.EnqueueCommandResponseMessage(
                    exception = CoreExceptionHelper.CreateException(exceptionType));
                break;
            }

            // 10 seconds delay. Not expected to be processed
            mockConnection.EnqueueCommandResponseMessage(CreateStreamableCommandResponseMessage(), TimeSpan.FromSeconds(10));

            subject.Initialize();

            var expectedServerDescriptionChangedEventCount = exception != null
                ? 3 // +1 event because a connection initialized event doesn't have waiting
                : 2;

            capturedEvents.WaitForOrThrowIfTimeout(
                events =>
                events.Count(e => e is ServerDescriptionChangedEvent) >= expectedServerDescriptionChangedEventCount,      // the connection has been initialized and the first heatbeat event has been fired
                TimeSpan.FromSeconds(10));

            capturedEvents.Next().Should().BeOfType <ServerDescriptionChangedEvent>(); // connection initialized
            AssertHeartbeatAttempt();
            capturedEvents.Any().Should().BeFalse();                                   // the next attempt will be in 10 seconds because the second stremable respone has 10 seconds delay

            void AssertHeartbeatAttempt()
            {
                if (exception != null)
                {
                    mockRoundTimeTripMonitor.Verify(c => c.Reset(), Times.Once);

                    var serverHeartbeatFailedEvent = capturedEvents.Next().Should().BeOfType <ServerHeartbeatFailedEvent>().Subject; // updating the server based on the heartbeat
                    serverHeartbeatFailedEvent.Exception.Should().Be(exception);

                    var serverDescriptionChangedEvent = capturedEvents.Next().Should().BeOfType <ServerDescriptionChangedEvent>().Subject;
                    serverDescriptionChangedEvent.NewDescription.HeartbeatException.Should().Be(exception);

                    serverDescriptionChangedEvent = capturedEvents.Next().Should().BeOfType <ServerDescriptionChangedEvent>().Subject;  // when we catch exceptions, we close the current connection, so opening connection will trigger one more ServerDescriptionChangedEvent
                    serverDescriptionChangedEvent.OldDescription.HeartbeatException.Should().Be(exception);
                    serverDescriptionChangedEvent.NewDescription.HeartbeatException.Should().BeNull();
                }
                else
                {
                    mockRoundTimeTripMonitor.Verify(c => c.Reset(), Times.Never);
                    capturedEvents.Next().Should().BeOfType <ServerHeartbeatSucceededEvent>();
                    var serverDescriptionChangedEvent = capturedEvents.Next().Should().BeOfType <ServerDescriptionChangedEvent>().Subject; // updating the server based on the heartbeat
                    serverDescriptionChangedEvent.NewDescription.HeartbeatException.Should().BeNull();
                }
            }
        }
        public async Task PoolClearedError_write_retryablity_test([Values(false, true)] bool async)
        {
            RequireServer.Check()
            .Supports(Feature.FailPointsBlockConnection)
            .ClusterTypes(ClusterType.ReplicaSet, ClusterType.Sharded);

            var heartbeatInterval = TimeSpan.FromMilliseconds(50);
            var eventsWaitTimeout = TimeSpan.FromMilliseconds(5000);

            var failPointCommand = BsonDocument.Parse(
                $@"{{
                    configureFailPoint : 'failCommand',
                    mode : {{ 'times' : 1 }},
                    data :
                    {{
                        failCommands : [ 'insert' ],
                        errorCode : 91,
                        blockConnection: true,
                        blockTimeMS: 1000,
                        errorLabels: [""RetryableWriteError""]
                    }}
                }}");

            IServerSelector failPointSelector = WritableServerSelector.Instance;
            var             settings          = DriverTestConfiguration.GetClientSettings();

            if (CoreTestConfiguration.Cluster.Description.Type == ClusterType.Sharded)
            {
                var serverAddress = settings.Servers.First();
                settings.Servers = new[] { serverAddress };

                // set settings.DirectConnection = true after removing obsolete ConnectionMode
#pragma warning disable CS0618 // Type or member is obsolete
                settings.ConnectionMode = ConnectionMode.Direct;
#pragma warning restore CS0618 // Type or member is obsolete

                failPointSelector = new EndPointServerSelector(new DnsEndPoint(serverAddress.Host, serverAddress.Port));
            }

            settings.MaxConnectionPoolSize = 1;
            settings.RetryWrites           = true;

            var eventCapturer = new EventCapturer()
                                .Capture <ConnectionPoolClearedEvent>()
                                .Capture <ConnectionPoolCheckedOutConnectionEvent>()
                                .Capture <ConnectionPoolCheckingOutConnectionFailedEvent>()
                                .CaptureCommandEvents("insert");

            var failpointServer = DriverTestConfiguration.Client.Cluster.SelectServer(failPointSelector, default);
            using var failPoint = FailPoint.Configure(failpointServer, NoCoreSession.NewHandle(), failPointCommand);

            using var client = CreateClient(settings, eventCapturer, heartbeatInterval);
            var database   = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
            var collection = database.GetCollection <BsonDocument>(DriverTestConfiguration.CollectionNamespace.CollectionName);

            eventCapturer.Clear();

            if (async)
            {
                await ThreadingUtilities.ExecuteTasksOnNewThreads(2, async _ =>
                {
                    await collection.InsertOneAsync(new BsonDocument("x", 1));
                });
            }
            else
            {
                ThreadingUtilities.ExecuteOnNewThreads(2, _ =>
                {
                    collection.InsertOne(new BsonDocument("x", 1));
                });
            }

            // wait for 2 CommandSucceededEvent events, meaning that all other events should be received
            eventCapturer.WaitForOrThrowIfTimeout(
                events => events.OfType <CommandSucceededEvent>().Count() == 2,
                eventsWaitTimeout);

            eventCapturer.Events.OfType <CommandStartedEvent>().Count().Should().Be(3);
            eventCapturer.Events.OfType <CommandFailedEvent>().Count().Should().Be(1);
            eventCapturer.Events.OfType <CommandSucceededEvent>().Count().Should().Be(2);
            eventCapturer.Events.OfType <ConnectionPoolClearedEvent>().Count().Should().Be(1);
            eventCapturer.Events.OfType <ConnectionPoolCheckedOutConnectionEvent>().Count().Should().Be(3);
            eventCapturer.Events.OfType <ConnectionPoolCheckingOutConnectionFailedEvent>().Count().Should().Be(1);
        }
        public async Task Ensure_server_session_are_allocated_only_on_connection_checkout([Values(true, false)] bool async)
        {
            var eventCapturer = new EventCapturer()
                                .Capture <CommandStartedEvent>();

            using var client = DriverTestConfiguration.CreateDisposableClient(
                      (MongoClientSettings settings) =>
            {
                settings.RetryWrites           = true;
                settings.MaxConnectionPoolSize = 1;
                settings.ClusterConfigurator   = c => c.Subscribe(eventCapturer);
            },
                      logger: null);

            var database = client.GetDatabase("test");

            database.DropCollection("inventory");
            var collection = database.GetCollection <BsonDocument>("inventory");

            const int operationsCount   = 8;
            var       singleSessionUsed = false;

            for (int i = 0; i < 5; i++)
            {
                eventCapturer.Clear();
                await ThreadingUtilities.ExecuteTasksOnNewThreads(operationsCount, async i =>
                {
                    switch (i)
                    {
                    case 0:
                        if (async)
                        {
                            await collection.InsertOneAsync(new BsonDocument("x", 0));
                        }
                        else
                        {
                            collection.InsertOne(new BsonDocument("x", 0));
                        }
                        break;

                    case 1:
                        if (async)
                        {
                            await collection.DeleteOneAsync(Builders <BsonDocument> .Filter.Eq("_id", 1));
                        }
                        else
                        {
                            collection.DeleteOne(Builders <BsonDocument> .Filter.Eq("_id", 1));
                        }
                        break;

                    case 2:
                        if (async)
                        {
                            await collection.UpdateOneAsync(Builders <BsonDocument> .Filter.Empty, Builders <BsonDocument> .Update.Set("a", 1));
                        }
                        else
                        {
                            collection.UpdateOne(Builders <BsonDocument> .Filter.Empty, Builders <BsonDocument> .Update.Set("a", 1));
                        }
                        break;

                    case 3:
                        var bulkWriteRequests = new WriteModel <BsonDocument>[]
                        {
                            new UpdateOneModel <BsonDocument>(Builders <BsonDocument> .Filter.Empty, new BsonDocument("$set", new BsonDocument("1", 1)))
                        };

                        if (async)
                        {
                            await collection.BulkWriteAsync(bulkWriteRequests);
                        }
                        else
                        {
                            collection.BulkWrite(bulkWriteRequests);
                        }
                        break;

                    case 4:
                        if (async)
                        {
                            await collection.FindOneAndDeleteAsync(Builders <BsonDocument> .Filter.Empty);
                        }
                        else
                        {
                            collection.FindOneAndDelete(Builders <BsonDocument> .Filter.Empty);
                        }
                        break;

                    case 5:
                        if (async)
                        {
                            await collection.FindOneAndUpdateAsync(Builders <BsonDocument> .Filter.Empty, Builders <BsonDocument> .Update.Set("a", 1));
                        }
                        else
                        {
                            collection.FindOneAndUpdate(Builders <BsonDocument> .Filter.Empty, Builders <BsonDocument> .Update.Set("a", 1));
                        }

                        break;

                    case 6:
                        if (async)
                        {
                            await collection.FindOneAndReplaceAsync(Builders <BsonDocument> .Filter.Empty, new BsonDocument("x", 0));
                        }
                        else
                        {
                            collection.FindOneAndReplace(Builders <BsonDocument> .Filter.Empty, new BsonDocument("x", 0));
                        }
                        break;

                    case 7:
                        if (async)
                        {
                            var cursor = await collection.FindAsync(Builders <BsonDocument> .Filter.Empty);
                            _          = await cursor.ToListAsync();
                        }
                        else
                        {
                            _ = collection.Find(Builders <BsonDocument> .Filter.Empty).ToList();
                        }
                        break;
                    }
                });

                eventCapturer.WaitForOrThrowIfTimeout(e => e.OfType <CommandStartedEvent>().Count() >= operationsCount, TimeSpan.FromSeconds(10));
                var lsids = eventCapturer.Events.OfType <CommandStartedEvent>().Select(c => c.Command["lsid"]).ToArray();
                var distinctLsidsCount = lsids.Distinct().Count();

                distinctLsidsCount.Should().BeLessThan(operationsCount);
                if (distinctLsidsCount == 1)
                {
                    singleSessionUsed = true;
                    break;
                }
            }

            singleSessionUsed.Should().BeTrue("At least one iteration should use single session");
        }
示例#7
0
        public void Ensure_command_network_error_before_hadnshake_is_correctly_handled([Values(false, true)] bool async, [Values(false, true)] bool streamable)
        {
            var eventCapturer = new EventCapturer().Capture <ServerDescriptionChangedEvent>();

            // ensure that hello or legacy hello check response is finished only after network error
            var hasNetworkErrorBeenTriggered = new TaskCompletionSource <bool>();
            // ensure that there are no unexpected events between test ending and cluster disposing
            var hasClusterBeenDisposed = new TaskCompletionSource <bool>();

            EndPoint initialSelectedEndpoint = null;

            using (var cluster = CreateAndSetupCluster(hasNetworkErrorBeenTriggered, hasClusterBeenDisposed, eventCapturer, streamable))
            {
                ForceClusterId(cluster, __clusterId);

                // 0. Initial heartbeat via `connection.Open`
                // The next hello or legacy hello response will be delayed because the Task.WaitAny in the mock.Returns
                cluster.Initialize();

                var selectedServer = cluster.SelectServer(CreateWritableServerAndEndPointSelector(__endPoint1), CancellationToken.None);
                initialSelectedEndpoint = selectedServer.EndPoint;
                initialSelectedEndpoint.Should().Be(__endPoint1);

                // make sure the next hello or legacy hello check has been called
                Thread.Sleep(__heartbeatInterval + TimeSpan.FromMilliseconds(50));

                // 1. Trigger the command network error BEFORE handshake. At this time hello or legacy hello response is already delayed until `hasNetworkErrorBeenTriggered.SetResult`
                Exception exception;
                if (async)
                {
                    exception = Record.Exception(() => selectedServer.GetChannelAsync(CancellationToken.None).GetAwaiter().GetResult());
                }
                else
                {
                    exception = Record.Exception(() => selectedServer.GetChannel(CancellationToken.None));
                }

                var e = exception.Should().BeOfType <MongoConnectionException>().Subject;
                e.Message.Should().Be("DnsException");

                // 2. Waiting for the hello or legacy hello check
                hasNetworkErrorBeenTriggered.SetResult(true); // unlock the in-progress hello or legacy hello response

                Thread.Sleep(100);                            // make sure the delayed hello or legacy hello check had time to change description if there is a bug
                var knownServers = cluster.Description.Servers.Where(s => s.Type != ServerType.Unknown);
                if (knownServers.Select(s => s.EndPoint).Contains(initialSelectedEndpoint))
                {
                    throw new Exception($"The type of failed server {initialSelectedEndpoint} has not been changed to Unknown.");
                }

                // ensure that a new server can be selected
                selectedServer = cluster.SelectServer(WritableServerSelector.Instance, CancellationToken.None);

                // ensure that the selected server is not the same as the initial
                selectedServer.EndPoint.Should().Be(__endPoint2);

                // the 4th event is MongoConnectionException which will trigger the next hello or legacy hello check immediately
                eventCapturer.WaitForOrThrowIfTimeout(events => events.Count() >= 4, TimeSpan.FromSeconds(5));
            }
            hasClusterBeenDisposed.SetCanceled(); // Cut off not related events. Stop waiting in the latest mock.Returns for OpenAsync

            // Events asserting
            var initialHeartbeatEvents = new[]
            {
                // endpoints can be in random order
                eventCapturer.Next().Should().BeOfType <ServerDescriptionChangedEvent>().Subject,
                eventCapturer.Next().Should().BeOfType <ServerDescriptionChangedEvent>().Subject
            }
            .OrderBy(c => GetPort(c.NewDescription.EndPoint))
            .ToList();

            AssertEvent(initialHeartbeatEvents[0], __endPoint1, ServerType.ShardRouter, "Heartbeat");
            AssertEvent(initialHeartbeatEvents[1], __endPoint2, ServerType.ShardRouter, "Heartbeat"); // the next 27018 events will be suppressed

            AssertNextEvent(eventCapturer, initialSelectedEndpoint, ServerType.Unknown, "InvalidatedBecause:ChannelException during handshake: MongoDB.Driver.MongoConnectionException: DnsException");
            AssertNextEvent(eventCapturer, initialSelectedEndpoint, ServerType.Unknown, "Heartbeat", typeof(MongoConnectionException));
            eventCapturer.Any().Should().BeFalse();

            int GetPort(EndPoint endpoint) => ((DnsEndPoint)endpoint).Port;
        }
        private (IConnectionPool, FailPoint, ICluster, Func <object, bool>) SetupConnectionData(BsonDocument test, EventCapturer eventCapturer, bool isUnit)
        {
            ParseSettings(test, out var connectionPoolSettings, out var connectionSettings);

            IConnectionPool     connectionPool;
            ICluster            cluster      = null;
            FailPoint           failPoint    = null;
            Func <object, bool> eventsFilter = _ => true;

            if (isUnit)
            {
                var endPoint = new DnsEndPoint("localhost", 27017);
                var serverId = new ServerId(new ClusterId(), endPoint);

                var connectionFactory          = new Mock <IConnectionFactory>();
                var connectionExceptionHandler = new Mock <IConnectionExceptionHandler>();

                connectionFactory
                .Setup(c => c.CreateConnection(serverId, endPoint))
                .Returns(() =>
                {
                    var connection = new MockConnection(serverId, connectionSettings, eventCapturer);
                    return(connection);
                });

                connectionPool = new ExclusiveConnectionPool(
                    serverId,
                    endPoint,
                    connectionPoolSettings,
                    connectionFactory.Object,
                    eventCapturer,
                    connectionExceptionHandler.Object);

                connectionPool.Initialize();
            }
            else
            {
                var async = test.GetValue(Schema.async).ToBoolean();
                cluster = CoreTestConfiguration.CreateCluster(b => b
                                                              .ConfigureServer(s => s.With(
                                                                                   heartbeatInterval: TimeSpan.FromMinutes(10)))
                                                              .ConfigureConnectionPool(c => c.With(
                                                                                           maxConnecting: connectionPoolSettings.MaxConnecting,
                                                                                           maxConnections: connectionPoolSettings.MaxConnections,
                                                                                           minConnections: connectionPoolSettings.MinConnections,
                                                                                           maintenanceInterval: connectionPoolSettings.MaintenanceInterval,
                                                                                           waitQueueTimeout: connectionPoolSettings.WaitQueueTimeout))
                                                              .ConfigureConnection(s => s.With(applicationName: $"{connectionSettings.ApplicationName}_async_{async}"))
                                                              .Subscribe(eventCapturer));

                var server = cluster.SelectServer(WritableServerSelector.Instance, CancellationToken.None);
                connectionPool = server._connectionPool();

                if (test.TryGetValue(Schema.Intergration.failPoint, out var failPointDocument))
                {
                    if (failPointDocument.AsBsonDocument.Contains("data"))
                    {
                        var data = failPointDocument["data"].AsBsonDocument;
                        if (data.TryGetValue("appName", out var appNameValue))
                        {
                            data["appName"] = $"{appNameValue}_async_{async}";
                        }
                    }

                    var resetPool = connectionPoolSettings.MinConnections > 0;

                    if (resetPool)
                    {
                        eventCapturer.WaitForOrThrowIfTimeout(events => events.Any(e => e is ConnectionCreatedEvent), TimeSpan.FromMilliseconds(500));

                        var connectionIdsToIgnore = new HashSet <int>(eventCapturer.Events
                                                                      .OfType <ConnectionCreatedEvent>()
                                                                      .Select(c => c.ConnectionId.LocalValue)
                                                                      .ToList());

                        eventsFilter = o =>
                        {
                            if (o is ConnectionOpenedEvent
                                or ConnectionClosedEvent
                                or ConnectionCreatedEvent
                                or ConnectionFailedEvent)
                            {
                                var connectionId = o.ConnectionId();
                                return(!connectionIdsToIgnore.Contains(connectionId.LocalValue) &&
                                       EndPointHelper.Equals(connectionId.ServerId.EndPoint, server.EndPoint));
                            }

                            if (o is ConnectionPoolReadyEvent
                                or ConnectionPoolClearedEvent)
                            {
                                var serverId = o.ServerId();
                                return(EndPointHelper.Equals(serverId.EndPoint, server.EndPoint));
                            }

                            return(true);
                        };

                        connectionPool.Clear(closeInUseConnections: false);
                        eventCapturer.WaitForOrThrowIfTimeout(events => events.Any(e => e is ConnectionPoolClearedEvent), TimeSpan.FromMilliseconds(500));
                    }

                    var failPointServer = CoreTestConfiguration.Cluster.SelectServer(new EndPointServerSelector(server.EndPoint), default);
                    failPoint = FailPoint.Configure(failPointServer, NoCoreSession.NewHandle(), failPointDocument.AsBsonDocument);

                    if (resetPool)
                    {
                        eventCapturer.Clear();
                        connectionPool.SetReady();
                    }
                }
            }

            return(connectionPool, failPoint, cluster, eventsFilter);
        }