Package com.proofpoint.dbpool

Source Code of com.proofpoint.dbpool.ManagedDataSourceTest

/*
* Copyright 2010 Proofpoint, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.proofpoint.dbpool;

import com.proofpoint.dbpool.MockConnectionPoolDataSource.MockConnection;
import com.proofpoint.units.Duration;
import org.testng.annotations.Test;

import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

import static com.proofpoint.testing.Assertions.assertGreaterThan;
import static com.proofpoint.testing.Assertions.assertInstanceOf;
import static com.proofpoint.units.Duration.nanosSince;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

public class ManagedDataSourceTest
{
    @Test
    public void testBasic()
            throws Exception
    {
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        assertEquals(dataSource.getConnectionsActive(), 0);
        assertEquals(dataSource.getStats().getCheckout().getAllTime().getCount(), 0.0);
        assertEquals(dataSource.getStats().getCreate().getAllTime().getCount(), 0.0);
        assertEquals(dataSource.getStats().getHeld().getAllTime().getCount(), 0.0);
        assertEquals(dataSource.getStats().getConnectionErrorCount(), 0);

        Connection connection = dataSource.getConnection();
        assertNotNull(connection);
        assertTrue(connection instanceof MockConnection);
        assertEquals(dataSource.getConnectionsActive(), 1);
        assertEquals(dataSource.getStats().getCheckout().getAllTime().getCount(), 1.0);
        assertEquals(dataSource.getStats().getCreate().getAllTime().getCount(), 1.0);
        assertEquals(dataSource.getStats().getHeld().getAllTime().getCount(), 0.0);
        assertEquals(dataSource.getStats().getConnectionErrorCount(), 0);

        connection.close();
        assertEquals(dataSource.getConnectionsActive(), 0);
        assertEquals(dataSource.getStats().getCheckout().getAllTime().getCount(), 1.0);
        assertEquals(dataSource.getStats().getCreate().getAllTime().getCount(), 1.0);
        assertEquals(dataSource.getStats().getHeld().getAllTime().getCount(), 1.0);
        assertEquals(dataSource.getStats().getConnectionErrorCount(), 0);
    }

    @Test
    public void testMaxConnectionWaitMillis()
            throws Exception
    {
        // datasource server to 1 connection and only wait 1 ms for a connection
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        assertEquals(dataSource.getMaxConnectionWaitMillis(), 10);

        // checkout a connection
        Connection connection = dataSource.getConnection();
        assertEquals(dataSource.getConnectionsActive(), 1);

        // try to get another one which will timeout
        long start = System.nanoTime();
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        Duration duration = nanosSince(start);
        assertGreaterThan(duration, new Duration(10, MILLISECONDS));
        assertEquals(dataSource.getConnectionsActive(), 1);

        // try with a different timeout
        dataSource.setMaxConnectionWaitMillis(new Duration(50, MILLISECONDS));
        assertEquals(dataSource.getMaxConnectionWaitMillis(), 50);
        start = System.nanoTime();
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        duration = nanosSince(start);
        assertGreaterThan(duration, new Duration(50, MILLISECONDS));
        assertEquals(dataSource.getConnectionsActive(), 1);

        // verify proper handling of illegal values
        try {
            dataSource.setMaxConnectionWaitMillis(null);
            fail("NullPointerException IllegalArgumentException");
        }
        catch (NullPointerException e) {
        }
        assertEquals(dataSource.getMaxConnectionWaitMillis(), 50);
        // verify proper handling of illegal values
        try {
            dataSource.setMaxConnectionWaitMillis(new Duration(0, MILLISECONDS));
            fail("Expected IllegalArgumentException");
        }
        catch (IllegalArgumentException e) {
        }
        assertEquals(dataSource.getMaxConnectionWaitMillis(), 50);

        connection.close();
        assertEquals(dataSource.getConnectionsActive(), 0);
    }

    /**
     * Verify adjustment of connection count limits.
     * </p> 1) Test initial limit
     * </p> 2) Test limit increase
     * </p> 3) Test decrease below current checkout
     * </p> 4) Verify handling of illegal values
     */
    @Test
    public void testMaxConnections()
            throws Exception
    {
        // datasource server to 1 connection and only wait 1 ms for a connection
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(1, MILLISECONDS));
        assertEquals(dataSource.getMaxConnections(), 1);

        // checkout a connection
        Queue<Connection> connections = new LinkedList<Connection>();
        connections.add(dataSource.getConnection());
        assertEquals(dataSource.getConnectionsActive(), 1);

        // verify that we can't another connection
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        assertEquals(dataSource.getConnectionsActive(), 1);

        // increase the max connection count to 3 and acquire two extra ones
        dataSource.setMaxConnections(3);
        assertEquals(dataSource.getMaxConnections(), 3);
        connections.add(dataSource.getConnection());
        connections.add(dataSource.getConnection());

        // verify that we can't get another connection
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        assertEquals(dataSource.getConnectionsActive(), 3);


        // reduce the max connection count to 2
        dataSource.setMaxConnections(2);
        assertEquals(dataSource.getMaxConnections(), 2);
        assertEquals(dataSource.getConnectionsActive(), 3);

        // first verify that we still can't get more connections
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        assertEquals(dataSource.getConnectionsActive(), 3);

        // now release one and verify we still can't get another one
        connections.remove().close();
        assertEquals(dataSource.getConnectionsActive(), 2);
        try {
            dataSource.getConnection();
            fail("Expected SQLException from timeout");
        }
        catch (SQLException expected) {
        }
        assertEquals(dataSource.getConnectionsActive(), 2);

        // finally close another one and verify we can reopen it
        connections.remove().close();
        connections.add(dataSource.getConnection());
        assertEquals(dataSource.getConnectionsActive(), 2);


        // verify proper handling of illegal values
        try {
            dataSource.setMaxConnectionWaitMillis(null);
            fail("Expected NullPointerException");
        }
        catch (NullPointerException e) {
        }
        assertEquals(dataSource.getMaxConnections(), 2);
        try {
            dataSource.setMaxConnectionWaitMillis(new Duration(0, MILLISECONDS));
            fail("Expected IllegalArgumentException");
        }
        catch (IllegalArgumentException e) {
        }
        assertEquals(dataSource.getMaxConnections(), 2);

        // clean up
        for (Connection connection : connections) {
            connection.close();
        }
        assertEquals(dataSource.getConnectionsActive(), 0);

    }

    @Test
    public void testAcquirePermitInterrupted()
            throws Exception
    {
        // datasource server to 1 connection and only wait 1 ms for a connection
        final ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(5000, MILLISECONDS));
        assertEquals(dataSource.getMaxConnectionWaitMillis(), 5000);

        // checkout a connection
        Connection connection = dataSource.getConnection();
        assertEquals(dataSource.getConnectionsActive(), 1);

        // checkout in another thread which we are going to interrupt
        final CountDownLatch startLatch = new CountDownLatch(1);
        final CountDownLatch endLatch = new CountDownLatch(1);
        final AtomicBoolean wasInterrupted = new AtomicBoolean();
        final AtomicReference<SQLException> exception = new AtomicReference<SQLException>();
        Thread createThread = new Thread()
        {
            @Override
            public void run()
            {
                startLatch.countDown();
                try {
                    dataSource.getConnection();
                }
                catch (SQLException e) {
                    exception.set(e);
                }
                finally {
                    wasInterrupted.set(isInterrupted());
                    endLatch.countDown();
                }
            }
        };
        createThread.start();

        // wait for thread to actually start
        startLatch.await();
        // interrupt the createThread
        createThread.interrupt();
        // wait for the thread to end
        endLatch.await();

        // verify that the thread is still in the interrupted state
        assertTrue(wasInterrupted.get(), "createThread.isInterrupted()");
        SQLException sqlException = exception.get();
        assertNotNull(sqlException);
        assertInstanceOf(sqlException.getCause(), InterruptedException.class);

        connection.close();
        assertEquals(dataSource.getConnectionsActive(), 0);
    }

    @Test
    public void testIdempotentClose()
            throws Exception
    {
        ManagedDataSource dataSource = new MockManagedDataSource(10, new Duration(10, MILLISECONDS));
        List<MockConnection> connections = new ArrayList<MockConnection>();
        for (int i = 0; i < 10; i++) {
            MockConnection connection = (MockConnection) dataSource.getConnection();
            assertNotNull(connection);
            connections.add(connection);
        }

        assertEquals(dataSource.getConnectionsActive(), 10);

        // close connections in a random order
        Collections.shuffle(connections);

        int closedCount = 0;
        for (MockConnection connection : connections) {
            closedCount++;
            for (int j = 0; j < 7; j++) {
                connection.close();
                assertEquals(dataSource.getConnectionsActive(), 10 - closedCount);
            }
        }
    }

    @Test
    public void testConnectionException()
            throws Exception
    {
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        MockConnection connection = (MockConnection) dataSource.getConnection();
        assertNotNull(connection);
        assertEquals(dataSource.getConnectionsActive(), 1);
        connection.errorOccurred();
        assertEquals(dataSource.getConnectionsActive(), 0);
    }

    @Test
    public void testCreateException()
    {
        MockConnectionPoolDataSource mockConnectionPoolDataSource = new MockConnectionPoolDataSource();
        ManagedDataSource dataSource = new MockManagedDataSource(mockConnectionPoolDataSource, 1, new Duration(10, MILLISECONDS));
        mockConnectionPoolDataSource.createException = new SQLException();

        assertEquals(dataSource.getConnectionsActive(), 0);
        try {
            dataSource.getConnection();
            fail("expected SQLException");
        }
        catch (SQLException e) {
            assertSame(e, mockConnectionPoolDataSource.createException);
        }
        assertEquals(dataSource.getConnectionsActive(), 0);

    }

    @Test
    public void testCloseException()
            throws SQLException
    {
        MockConnectionPoolDataSource mockConnectionPoolDataSource = new MockConnectionPoolDataSource();
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        mockConnectionPoolDataSource.closeException = new SQLException();

        assertEquals(dataSource.getConnectionsActive(), 0);
        MockConnection connection = (MockConnection) dataSource.getConnection();
        assertNotNull(connection);
        assertEquals(dataSource.getConnectionsActive(), 1);
        connection.close();
        assertEquals(dataSource.getConnectionsActive(), 0);

        connection = (MockConnection) dataSource.getConnection();
        assertNotNull(connection);
        assertEquals(dataSource.getConnectionsActive(), 1);
        connection.close();
        assertEquals(dataSource.getConnectionsActive(), 0);
        connection.errorOccurred();
        assertEquals(dataSource.getConnectionsActive(), 0);
    }

    @Test
    public void testIdempotentCloseAndException()
            throws SQLException
    {
        MockConnectionPoolDataSource mockConnectionPoolDataSource = new MockConnectionPoolDataSource();
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        mockConnectionPoolDataSource.closeException = new SQLException();

        assertEquals(dataSource.getConnectionsActive(), 0);
        MockConnection connection = (MockConnection) dataSource.getConnection();
        assertNotNull(connection);
        assertEquals(dataSource.getConnectionsActive(), 1);

        for (int i = 0; i < 10; i++) {
            connection.close();
            assertEquals(dataSource.getConnectionsActive(), 0);
            connection.errorOccurred();
            assertEquals(dataSource.getConnectionsActive(), 0);
        }
    }

    @Test
    public void testLogWriterIsNeverSet()
            throws SQLException
    {
        MockConnectionPoolDataSource mockConnectionPoolDataSource = new MockConnectionPoolDataSource();
        PrintWriter expectedLogWriter = new PrintWriter(new StringWriter());
        mockConnectionPoolDataSource.logWriter = expectedLogWriter;
        ManagedDataSource dataSource = new MockManagedDataSource(mockConnectionPoolDataSource, 1, new Duration(10, MILLISECONDS));

        // data source log writer should start with null
        assertNull(dataSource.getLogWriter());

        // set the writer
        PrintWriter newWriter = new PrintWriter(new StringWriter());
        dataSource.setLogWriter(newWriter);

        // data source log writer should still be null
        assertNull(dataSource.getLogWriter());
        // core data source should remain unaffected
        assertSame(mockConnectionPoolDataSource.logWriter, expectedLogWriter);
    }

    @Test
    public void testLoginTimeoutIsNeverSet()
            throws SQLException
    {
        MockConnectionPoolDataSource mockConnectionPoolDataSource = new MockConnectionPoolDataSource();
        mockConnectionPoolDataSource.loginTimeout = 42;
        ManagedDataSource dataSource = new MockManagedDataSource(mockConnectionPoolDataSource, 1, new Duration(5, SECONDS));

        // login timeout should always be max connection wait
        assertEquals(dataSource.getLoginTimeout(), 5);

        // set to a new value
        int newTimeout = 12345;
        dataSource.setLoginTimeout(newTimeout);

        // data source timeout should still be max connection wait
        assertEquals(dataSource.getLoginTimeout(), 5);

        // core data source should remain unaffected
        assertEquals(mockConnectionPoolDataSource.loginTimeout, 42);
    }

    @Test
    public void testWrapper()
            throws SQLException
    {
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        assertTrue(dataSource.isWrapperFor(ManagedDataSource.class));
        assertTrue(dataSource.isWrapperFor(DataSource.class));
        assertTrue(dataSource.isWrapperFor(Object.class));
        assertFalse(dataSource.isWrapperFor(ConnectionPoolDataSource.class));
        assertFalse(dataSource.isWrapperFor(Integer.class));
        try {
            dataSource.isWrapperFor(null);
            fail("Expected SQLException");
        }
        catch (SQLException expected) {
        }
        try {
            dataSource.unwrap(null);
            fail("Expected SQLException");
        }
        catch (SQLException expected) {
        }

        assertSame(dataSource.unwrap(ManagedDataSource.class), dataSource);
        assertSame(dataSource.unwrap(DataSource.class), dataSource);
        assertSame(dataSource.unwrap(Object.class), dataSource);

        try {
            dataSource.unwrap(ConnectionPoolDataSource.class);
            fail("Expected SQLException");
        }
        catch (SQLException expected) {
        }

        try {
            dataSource.unwrap(Integer.class);
            fail("Expected SQLException");
        }
        catch (SQLException expected) {
        }
    }

    @Test
    public void testGetConnectionUsernamePassword()
            throws SQLException
    {
        ManagedDataSource dataSource = new MockManagedDataSource(1, new Duration(10, MILLISECONDS));
        try {
            dataSource.getConnection("username", "password");
            fail("Expected SQLException");
        }
        catch (UnsupportedOperationException expected) {
        }
    }
}
TOP

Related Classes of com.proofpoint.dbpool.ManagedDataSourceTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.