public void ShouldThrowErrorDirectlyIfProtocolError(AccessMode mode)
            {
                // Given
                var uri = new Uri("bolt+routing://123:456");
                var routingTableMock = NewMockedRoutingTable(mode, uri);
                var mock             = new Mock <IRoutingTableManager>();

                mock.Setup(x => x.RoutingTable).Returns(routingTableMock.Object);

                var clusterConnPoolMock = new Mock <IClusterConnectionPool>();

                clusterConnPoolMock.Setup(x => x.Acquire(uri)).Returns(() => null)
                .Callback(() => throw new ProtocolException("do not understand struct 0x01"));

                var balancer = new LoadBalancer(clusterConnPoolMock.Object, mock.Object);

                // When
                var error = Record.Exception(() => balancer.Acquire(mode));

                // Then
                error.Should().BeOfType <ProtocolException>();
                error.Message.Should().Contain("do not understand struct 0x01");

                // while the server is not removed
                routingTableMock.Verify(m => m.Remove(uri), Times.Never);
                clusterConnPoolMock.Verify(m => m.Deactivate(uri), Times.Never);
            }
            public void ShouldForgetServerWhenFailedToEstablishConn(AccessMode mode)
            {
                // Given
                var uri = new Uri("bolt+routing://123:456");
                var routingTableMock = NewMockedRoutingTable(mode, uri);
                var mock             = new Mock <IRoutingTableManager>();

                mock.Setup(x => x.RoutingTable).Returns(routingTableMock.Object);

                var clusterConnPoolMock = new Mock <IClusterConnectionPool>();

                clusterConnPoolMock.Setup(x => x.Acquire(uri))
                .Callback(() => throw new ServiceUnavailableException("failed init"));

                var balancer = new LoadBalancer(clusterConnPoolMock.Object, mock.Object);

                // When
                var error = Record.Exception(() => balancer.Acquire(mode));

                // Then
                error.Should().BeOfType <SessionExpiredException>();
                error.Message.Should().Contain("Failed to connect to any");

                // should be removed
                routingTableMock.Verify(m => m.Remove(uri), Times.Once);
                clusterConnPoolMock.Verify(m => m.Deactivate(uri), Times.Once);
            }
                public void ShouldThrowErrorDirectlyIfProtocolError(AccessMode mode)
                {
                    // Given
                    var uri = new Uri("bolt+routing://123:456");
                    var routingTableMock = CreateRoutingTable(mode, uri);

                    var clusterConnPoolMock = new Mock <IClusterConnectionPool>();
                    IPooledConnection conn  = null;

                    clusterConnPoolMock.Setup(x => x.TryAcquire(uri, out conn)).Returns(false)
                    .Callback(() =>
                    {
                        throw new ProtocolException("do not understand struct 0x01");
                    });

                    var balancer = new LoadBalancer(clusterConnPoolMock.Object, routingTableMock.Object);

                    // When
                    var error = Record.Exception(() => balancer.Acquire(mode));

                    // Then
                    error.Should().BeOfType <ProtocolException>();
                    error.Message.Should().Contain("do not understand struct 0x01");

                    // while the server is not removed
                    routingTableMock.Verify(m => m.Remove(uri), Times.Never);
                    clusterConnPoolMock.Verify(m => m.Purge(uri), Times.Never);
                }
            public void ShouldReturnConnectionAccordingToLoadBalancingStrategy(AccessMode mode)
            {
                var routingTable = NewRoutingTable(
                    new List <Uri> {
                    new Uri("router:1"), new Uri("router:2")
                },
                    new List <Uri> {
                    new Uri("reader:1"), new Uri("reader:2"), new Uri("reader:3")
                },
                    new List <Uri> {
                    new Uri("writer:1"), new Uri("writer:2")
                });

                var routingTableManager = new Mock <IRoutingTableManager>();

                routingTableManager.Setup(x => x.RoutingTable).Returns(routingTable);

                var clusterPoolMock = new Mock <IClusterConnectionPool>();

                clusterPoolMock.Setup(x => x.Acquire(It.IsAny <Uri>()))
                .Returns((Uri uri) => NewConnectionMock(uri));

                var balancer = new LoadBalancer(clusterPoolMock.Object, routingTableManager.Object);

                if (mode == AccessMode.Read)
                {
                    balancer.Acquire(mode).Server.Address.Should().Be("reader:1");
                    balancer.Acquire(mode).Server.Address.Should().Be("reader:2");
                    balancer.Acquire(mode).Server.Address.Should().Be("reader:3");

                    balancer.Acquire(mode).Server.Address.Should().Be("reader:1");
                    balancer.Acquire(mode).Server.Address.Should().Be("reader:2");
                    balancer.Acquire(mode).Server.Address.Should().Be("reader:3");
                }
                else if (mode == AccessMode.Write)
                {
                    balancer.Acquire(mode).Server.Address.Should().Be("writer:1");
                    balancer.Acquire(mode).Server.Address.Should().Be("writer:2");

                    balancer.Acquire(mode).Server.Address.Should().Be("writer:1");
                    balancer.Acquire(mode).Server.Address.Should().Be("writer:2");
                }
                else
                {
                    throw new ArgumentException();
                }
            }
                public void ShouldThrowSessionExpiredExceptionIfNoServerAvailable(AccessMode mode)
                {
                    // Given
                    var mock     = CreateRoutingTable(mode, null, false);
                    var balancer = new LoadBalancer(null, mock.Object);

                    // When
                    var error = Record.Exception(() => balancer.Acquire(mode));

                    // Then
                    error.Should().BeOfType <SessionExpiredException>();
                    error.Message.Should().Contain("Failed to connect to any");
                }
            public void ShouldThrowSessionExpiredExceptionIfNoServerAvailable(AccessMode mode)
            {
                // Given
                var mock = new Mock <IRoutingTableManager>();

                mock.Setup(x => x.RoutingTable).Returns(NewMockedRoutingTable(mode, null).Object);
                var balancer = new LoadBalancer(null, mock.Object);

                // When
                var error = Record.Exception(() => balancer.Acquire(mode));

                // Then
                error.Should().BeOfType <SessionExpiredException>();
                error.Message.Should().Contain("Failed to connect to any");
            }
            public void ShouldReturnConnectionWithCorrectMode(AccessMode mode)
            {
                // Given
                var uri              = new Uri("bolt+routing://123:456");
                var mock             = new Mock <IRoutingTableManager>();
                var routingTableMock = NewMockedRoutingTable(mode, uri);

                mock.Setup(x => x.RoutingTable).Returns(routingTableMock.Object);

                var clusterPoolMock = new Mock <IClusterConnectionPool>();
                var mockedConn      = new Mock <IConnection>();

                mockedConn.Setup(x => x.Server.Address).Returns(uri.ToString);
                var conn = mockedConn.Object;

                clusterPoolMock.Setup(x => x.Acquire(uri)).Returns(conn);
                var balancer = new LoadBalancer(clusterPoolMock.Object, mock.Object);

                // When
                var acquiredConn = balancer.Acquire(mode);

                // Then
                acquiredConn.Server.Address.Should().Be(uri.ToString());
            }