コード例 #1
0
        public void ForgetConnection_ExceedPoolSize_GetConnectionShouldBlockAndReturnNewConnection()
        {
            // Arrange
            var pool = new SapConnectionPool(
                ConnectionParameters,
                poolSize: 1,
                connectionFactory: _ => Mock.Of <ISapConnection>());

            ISapConnection connection1 = pool.GetConnection();

            // Act
            Task.Run(async() =>
            {
                await Task.Delay(150);
                pool.ForgetConnection(connection1);
            });
            var sw = new Stopwatch();

            sw.Start();
            ISapConnection connection2 = pool.GetConnection();

            sw.Stop();

            // Assert
            sw.ElapsedMilliseconds.Should().BeGreaterThan(100);
            connection2.Should().NotBeNull();
            connection2.Should().NotBe(connection1);
        }
コード例 #2
0
        public void GetConnection_ShouldOpenConnection()
        {
            // Arrange
            var connectionMock = new Mock <ISapConnection>();
            var pool           = new SapConnectionPool(ConnectionParameters, connectionFactory: _ => connectionMock.Object);

            // Act
            ISapConnection connection = pool.GetConnection();

            // Assert
            connection.Should().Be(connectionMock.Object);
            connectionMock.Verify(x => x.Connect(), Times.Once);
        }
コード例 #3
0
        public void ForgetConnection_ShouldDisposeConnection()
        {
            // Arrange
            var            connectionMock = new Mock <ISapConnection>();
            var            pool           = new SapConnectionPool(ConnectionParameters, connectionFactory: _ => connectionMock.Object);
            ISapConnection connection     = pool.GetConnection();

            // Act
            pool.ForgetConnection(connection);

            // Assert
            connectionMock.Verify(x => x.Dispose(), Times.Once);
        }
コード例 #4
0
        /// <summary>
        /// Returns the underlying <see cref="SapConnection"/> to the connection pool and make it available for reuse.
        /// </summary>
        public void Dispose()
        {
            if (_disposed)
            {
                return;
            }

            if (_connection != null)
            {
                _pool.ReturnConnection(_connection);
                _connection = null;
            }

            _disposed = true;
        }
コード例 #5
0
        public void GetConnection_ShouldReturnDifferentConnectionsUpToPoolSize()
        {
            // Arrange
            var pool = new SapConnectionPool(
                ConnectionParameters,
                poolSize: 2,
                connectionFactory: _ => Mock.Of <ISapConnection>());

            // Act
            ISapConnection connection1 = pool.GetConnection();
            ISapConnection connection2 = pool.GetConnection();

            // Assert
            connection1.Should().NotBeNull();
            connection2.Should().NotBeNull();
            connection1.Should().NotBe(connection2);
        }
コード例 #6
0
        public void Dispose_ShouldDisposeIdleConnections()
        {
            // Arrange
            var            connectionMock = new Mock <ISapConnection>();
            var            pool           = new SapConnectionPool(ConnectionParameters, connectionFactory: _ => connectionMock.Object);
            ISapConnection connection1    = pool.GetConnection();
            ISapConnection connection2    = pool.GetConnection();

            pool.ReturnConnection(connection1);
            pool.ReturnConnection(connection2);

            // Act
            pool.Dispose();

            // Assert
            connectionMock.Verify(x => x.Dispose(), Times.Exactly(2));
        }
コード例 #7
0
        public void GetConnection_AfterReturnConnection_ShouldReturnSameConnection()
        {
            // Arrange
            var pool = new SapConnectionPool(
                ConnectionParameters,
                poolSize: 3,
                connectionFactory: _ => Mock.Of <ISapConnection>());

            // Act
            ISapConnection connection1 = pool.GetConnection();

            pool.ReturnConnection(connection1);
            ISapConnection connection2 = pool.GetConnection();

            // Assert
            connection1.Should().NotBeNull();
            connection2.Should().Be(connection1);
        }
コード例 #8
0
        /// <inheritdoc cref="ISapPooledConnection"/>
        public TOutput InvokeFunction <TOutput>(string name, CancellationToken cancellationToken = default)
        {
            try
            {
                _connection = _connection ?? _pool.GetConnection(cancellationToken);
                using (ISapFunction function = _connection.CreateFunction(name))
                    return(function.Invoke <TOutput>());
            }
            catch (SapCommunicationFailedException)
            {
                // Let the pool collect the dead connection
                _pool.ForgetConnection(_connection);

                // Retry invocation with new connection from the pool
                _connection = _pool.GetConnection(cancellationToken);
                using (ISapFunction function = _connection.CreateFunction(name))
                    return(function.Invoke <TOutput>());
            }
        }
コード例 #9
0
        /// <inheritdoc cref="ISapPooledConnection"/>
        public void InvokeFunction(string name, object input, CancellationToken cancellationToken = default)
        {
            try
            {
                _connection = _connection ?? _pool.GetConnection(cancellationToken);
                using (ISapFunction function = _connection.CreateFunction(name))
                    function.Invoke(input);
            }
            catch (SapCommunicationFailedException)
            {
                // Let the pool collect the dead connection
                _pool.ForgetConnection(_connection);

                // Retry invocation with new connection from the pool
                _connection = _pool.GetConnection(cancellationToken);
                using (ISapFunction function = _connection.CreateFunction(name))
                    function.Invoke(input);
            }
        }
コード例 #10
0
        public void GetConnection_ConnectionFactoryReturnsNullFirst_ShouldRetryUntilFactoryReturnsConnection()
        {
            // Arrange
            ISapConnection firstConnection       = null;
            ISapConnection secondConnection      = Mock.Of <ISapConnection>();
            var            connectionFactoryMock = new Mock <Func <SapConnectionParameters, ISapConnection> >();

            connectionFactoryMock.SetupSequence(x => x(It.IsAny <SapConnectionParameters>())).Returns(firstConnection);
            connectionFactoryMock.SetupSequence(x => x(It.IsAny <SapConnectionParameters>())).Returns(secondConnection);

            var pool = new SapConnectionPool(
                ConnectionParameters,
                poolSize: 1,
                connectionFactory: connectionFactoryMock.Object);

            // Act
            ISapConnection connection = pool.GetConnection();

            // Assert
            connection.Should().Be(secondConnection);
        }
コード例 #11
0
        public void ReturnConnection_ExceedPoolSize_GetConnectionShouldBlockAndReturnFirstReturnedConnection()
        {
            // Arrange
            var pool = new SapConnectionPool(
                ConnectionParameters,
                poolSize: 2,
                connectionFactory: _ => Mock.Of <ISapConnection>());

            ISapConnection connection1 = pool.GetConnection();
            ISapConnection connection2 = pool.GetConnection();

            // Act
            Task.Run(async() =>
            {
                await Task.Delay(150);
                pool.ReturnConnection(connection1);
                await Task.Delay(150);
                pool.ReturnConnection(connection2);
            });
            var sw = new Stopwatch();

            sw.Start();
            ISapConnection connection3 = pool.GetConnection();

            sw.Stop();

            // Assert
            sw.ElapsedMilliseconds.Should().BeGreaterThan(100).And.BeLessThan(250);
            connection3.Should().NotBeNull();
            connection3.Should().Be(connection1);

            connection1.Dispose();
            connection2.Dispose();
            connection3.Dispose();
            pool.Dispose();
        }