public void GetChannel_should_clear_connection_pool_when_opening_connection_throws_MongoAuthenticationException(
            [Values(false, true)] bool async)
        {
            var connectionId                   = new ConnectionId(new ServerId(_clusterId, _endPoint));
            var mockConnectionHandle           = new Mock <IConnectionHandle>();
            var mockConnectionExceptionHandler = new Mock <IConnectionExceptionHandler>();

            LoadBalancedServer server = null;

            var mockConnectionPool      = new Mock <IConnectionPool>();
            var authenticationException = new MongoAuthenticationException(connectionId, "Invalid login.")
            {
                ServiceId = ObjectId.GenerateNewId()
            };

            mockConnectionPool
            .Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>()))
            .Callback(() => server.HandleExceptionOnOpen(authenticationException))
            .Throws(authenticationException);
            mockConnectionPool
            .Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>()))
            .Callback(() => server.HandleExceptionOnOpen(authenticationException))
            .Throws(authenticationException);
            mockConnectionPool.Setup(p => p.Clear(It.IsAny <ObjectId>()));

            var mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>();

            mockConnectionPoolFactory
            .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint, It.IsAny <IConnectionExceptionHandler>()))
            .Returns(mockConnectionPool.Object);

            server = new LoadBalancedServer(
                _clusterId,
                _clusterClock,
                _settings,
                _endPoint,
                mockConnectionPoolFactory.Object,
                _capturedEvents,
                _serverApi);
            server.Initialize();

            var exception = Record.Exception(() =>
            {
                if (async)
                {
                    server.GetChannelAsync(CancellationToken.None).GetAwaiter().GetResult();
                }
                else
                {
                    server.GetChannel(CancellationToken.None);
                }
            });

            exception.Should().BeOfType <MongoAuthenticationException>();
            mockConnectionPool.Verify(p => p.Clear(It.IsAny <ObjectId>()), Times.Once());
        }
        public void GetChannel_should_not_update_topology_and_clear_connection_pool_on_MongoConnectionException(
            [Values("TimedOutSocketException", "NetworkUnreachableSocketException")] string errorType,
            [Values(false, true)] bool async)
        {
            var serverId                       = new ServerId(_clusterId, _endPoint);
            var connectionId                   = new ConnectionId(serverId);
            var innerMostException             = CoreExceptionHelper.CreateException(errorType);
            var mockConnectionExceptionHandler = new Mock <IConnectionExceptionHandler>();

            var openConnectionException = new MongoConnectionException(connectionId, "Oops", new IOException("Cry", innerMostException));
            var mockConnection          = new Mock <IConnectionHandle>();

            mockConnection.Setup(c => c.Open(It.IsAny <CancellationToken>())).Throws(openConnectionException);
            mockConnection.Setup(c => c.OpenAsync(It.IsAny <CancellationToken>())).ThrowsAsync(openConnectionException);

            var connectionFactory = new Mock <IConnectionFactory>();

            connectionFactory.Setup(cf => cf.CreateConnection(serverId, _endPoint)).Returns(mockConnection.Object);

            var connectionPoolSettings = new ConnectionPoolSettings();
            var connectionPool         = new ExclusiveConnectionPool(serverId, _endPoint, connectionPoolSettings, connectionFactory.Object, new EventAggregator(), mockConnectionExceptionHandler.Object);

            var mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>();

            mockConnectionPoolFactory
            .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint, It.IsAny <IConnectionExceptionHandler>()))
            .Returns(connectionPool);

            var subject = new LoadBalancedServer(_clusterId, _clusterClock, _settings, _endPoint, mockConnectionPoolFactory.Object, _capturedEvents, _serverApi);

            subject.Initialize();

            IChannelHandle channel = null;
            Exception      exception;

            if (async)
            {
                exception = Record.Exception(() => channel = subject.GetChannelAsync(CancellationToken.None).GetAwaiter().GetResult());
            }
            else
            {
                exception = Record.Exception(() => channel = subject.GetChannel(CancellationToken.None));
            }

            channel.Should().BeNull();
            exception.Should().Be(openConnectionException);
            subject.Description.Type.Should().Be(ServerType.LoadBalanced);
            subject.Description.ReasonChanged.Should().Be("Initialized");
            subject.Description.State.Should().Be(ServerState.Connected);

            _mockConnectionPool.Verify(c => c.Clear(It.IsAny <bool>()), Times.Never);
        }
        public LoadBalancedTests()
        {
            _clusterId = new ClusterId();
            _endPoint  = new DnsEndPoint("localhost", 27017);

            _clusterClock       = new Mock <IClusterClock>().Object;
            _mockConnectionPool = new Mock <IConnectionPool>();
            _mockConnectionPool.Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>())).Returns(new Mock <IConnectionHandle>().Object);
            _mockConnectionPool.Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>())).Returns(Task.FromResult(new Mock <IConnectionHandle>().Object));
            _mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>();
            _mockConnectionPoolFactory
            .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint))
            .Returns(_mockConnectionPool.Object);

            _capturedEvents = new EventCapturer();
            _serverApi      = new ServerApi(ServerApiVersion.V1, true, true);
            _settings       = new ServerSettings(heartbeatInterval: Timeout.InfiniteTimeSpan);

            _subject      = new LoadBalancedServer(_clusterId, _clusterClock, _settings, _endPoint, _mockConnectionPoolFactory.Object, _capturedEvents, _serverApi);
            _connectionId = new ConnectionId(_subject.ServerId);
        }
 public void Constructor_should_not_throw_when_serverApi_is_null()
 {
     _ = new LoadBalancedServer(_clusterId, _clusterClock, _settings, _endPoint, _mockConnectionPoolFactory.Object, _capturedEvents, serverApi: null);
 }
 public static void HandleChannelException(this LoadBalancedServer server, IConnection connection, Exception ex)
 {
     Reflector.Invoke(server, nameof(HandleChannelException), connection, ex, checkBaseClass: true);
 }
        // private methods
        private Server SetupServer(bool exceptionOnConnectionOpen, bool exceptionOnConnectionAcquire)
        {
            var connectionId                   = new ConnectionId(new ServerId(_clusterId, _endPoint));
            var mockConnectionHandle           = new Mock <IConnectionHandle>();
            var mockConnectionExceptionHandler = new Mock <IConnectionExceptionHandler>();

            mockConnectionHandle
            .Setup(c => c.Fork())
            .Returns(mockConnectionHandle.Object);

            var mockConnectionPool = new Mock <IConnectionPool>();

            if (exceptionOnConnectionAcquire)
            {
                mockConnectionPool
                .Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>()))
                .Throws(new TimeoutException("Timeout"));
                mockConnectionPool
                .Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>()))
                .Throws(new TimeoutException("Timeout"));
                mockConnectionPool.Setup(p => p.Clear(It.IsAny <bool>()));
            }
            else if (exceptionOnConnectionOpen)
            {
                mockConnectionPool
                .Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>()))
                .Throws(new MongoAuthenticationException(connectionId, "Invalid login."));
                mockConnectionPool
                .Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>()))
                .Throws(new MongoAuthenticationException(connectionId, "Invalid login."));
                mockConnectionPool.Setup(p => p.Clear(It.IsAny <bool>()));
            }
            else
            {
                mockConnectionPool
                .Setup(p => p.AcquireConnection(It.IsAny <CancellationToken>()))
                .Returns(mockConnectionHandle.Object);
                mockConnectionPool
                .Setup(p => p.AcquireConnectionAsync(It.IsAny <CancellationToken>()))
                .Returns(Task.FromResult(mockConnectionHandle.Object));
                mockConnectionPool.Setup(p => p.Clear(It.IsAny <bool>()));
            }

            var mockConnectionPoolFactory = new Mock <IConnectionPoolFactory>();

            mockConnectionPoolFactory
            .Setup(f => f.CreateConnectionPool(It.IsAny <ServerId>(), _endPoint, It.IsAny <IConnectionExceptionHandler>()))
            .Returns(mockConnectionPool.Object);

            var server = new LoadBalancedServer(
                _clusterId,
                _clusterClock,
                _settings,
                _endPoint,
                mockConnectionPoolFactory.Object,
                _capturedEvents,
                _serverApi);

            server.Initialize();

            return(server);
        }