Example #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);
            }
        }