org.pentaho.di.core.database.PoolableDataSourceTest.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.core.database.PoolableDataSourceTest.java

Source

/*
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2014 by Pentaho : http://www.pentaho.com
 *
 * **************************************************************************
 *
 * 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 org.pentaho.di.core.database;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.DelegatingConnection;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.pentaho.di.core.KettleEnvironment;
import org.pentaho.di.core.database.util.DatabaseUtil;
import org.pentaho.di.core.logging.LogChannelInterface;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;

import static org.junit.Assert.*;
import static org.mockito.Mockito.RETURNS_MOCKS;
import static org.mockito.Mockito.mock;

public class PoolableDataSourceTest {

    private static long MAX_WAIT_TIME = 1000;
    private static int MAX_ACTIVE = 3;
    private static String VALIDATION_QUERY = "select 1 from INFORMATION_SCHEMA.SYSTEM_USERS";

    private LogChannelInterface logChannelInterface;
    DatabaseMeta dbMeta;

    @Before
    public void setUp() throws Exception {
        logChannelInterface = mock(LogChannelInterface.class, RETURNS_MOCKS);
        KettleEnvironment.init();
        dbMeta = new DatabaseMeta("CP3", "Hypersonic", "JDBC", null, "mem:test", null, null, null);
        Properties dsProps = new Properties();
        dsProps.setProperty(ConnectionPoolUtil.DEFAULT_AUTO_COMMIT, "true");
        dsProps.setProperty(ConnectionPoolUtil.DEFAULT_READ_ONLY, "true");
        dsProps.setProperty(ConnectionPoolUtil.DEFAULT_TRANSACTION_ISOLATION, "1");
        dsProps.setProperty(ConnectionPoolUtil.DEFAULT_CATALOG, "");
        dsProps.setProperty(ConnectionPoolUtil.MAX_IDLE, "30");
        dsProps.setProperty(ConnectionPoolUtil.MIN_IDLE, "3");
        dsProps.setProperty(ConnectionPoolUtil.MAX_WAIT, String.valueOf(MAX_WAIT_TIME)); // tested
        dsProps.setProperty(ConnectionPoolUtil.VALIDATION_QUERY, VALIDATION_QUERY);
        dsProps.setProperty(ConnectionPoolUtil.TEST_ON_BORROW, "true");
        dsProps.setProperty(ConnectionPoolUtil.TEST_ON_RETURN, "true");
        dsProps.setProperty(ConnectionPoolUtil.TEST_WHILE_IDLE, "true");
        dsProps.setProperty(ConnectionPoolUtil.TIME_BETWEEN_EVICTION_RUNS_MILLIS, "300000");
        dsProps.setProperty(ConnectionPoolUtil.POOL_PREPARED_STATEMENTS, "true"); // tested
        dsProps.setProperty(ConnectionPoolUtil.MAX_OPEN_PREPARED_STATEMENTS, "2"); // tested
        dsProps.setProperty(ConnectionPoolUtil.ACCESS_TO_UNDERLYING_CONNECTION_ALLOWED, "true"); // tested
        dsProps.setProperty(ConnectionPoolUtil.REMOVE_ABANDONED, "false");
        dsProps.setProperty(ConnectionPoolUtil.REMOVE_ABANDONED_TIMEOUT, "1000");
        dsProps.setProperty(ConnectionPoolUtil.LOG_ABANDONED, "false");
        dbMeta.setConnectionPoolingProperties(dsProps);
        dbMeta.setUsername("SA");
        dbMeta.setPassword("");
        dbMeta.setInitialPoolSize(1);
        dbMeta.setMaximumPoolSize(MAX_ACTIVE); // tested
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testPropertiesAreSet() throws Exception {
        Connection conn = null;
        try {
            conn = getConnection();
            Field field = ConnectionPoolUtil.class.getDeclaredField("dataSources");
            assertNotNull("Can't find field 'dataSources' in class ConnectionPoolUtil", field);
            field.setAccessible(true);
            Map<String, BasicDataSource> dataSources = (Map<String, BasicDataSource>) field
                    .get(ConnectionPoolUtil.class);
            BasicDataSource ds = dataSources.get(dbMeta.getName());

            assertEquals(true, ds.getDefaultAutoCommit());
            assertEquals(true, ds.getDefaultReadOnly());
            assertEquals(1, ds.getDefaultTransactionIsolation());
            assertEquals(null, ds.getDefaultCatalog());
            assertEquals(30, ds.getMaxIdle());
            assertEquals(3, ds.getMinIdle());
            assertEquals(MAX_WAIT_TIME, ds.getMaxWait());
            assertEquals(VALIDATION_QUERY, ds.getValidationQuery());
            assertEquals(true, ds.getTestOnBorrow());
            assertEquals(true, ds.getTestOnReturn());
            assertEquals(true, ds.getTestWhileIdle());
            assertEquals(300000, ds.getTimeBetweenEvictionRunsMillis());
            assertEquals(true, ds.isPoolPreparedStatements());
            assertEquals(2, ds.getMaxOpenPreparedStatements());
            assertEquals(true, ds.isAccessToUnderlyingConnectionAllowed());
            assertEquals(false, ds.getRemoveAbandoned());
            assertEquals(1000, ds.getRemoveAbandonedTimeout());
            assertEquals(false, ds.getLogAbandoned());
        } finally {
            DatabaseUtil.closeSilently(conn);
        }
    }

    @Test
    public void testPreparedStatementsProperty() throws Exception {
        Connection conn = null;
        PreparedStatement[] ps = new PreparedStatement[3];
        try {

            conn = getConnection();
            ps[0] = conn.prepareStatement(VALIDATION_QUERY);
            ps[1] = conn.prepareStatement(VALIDATION_QUERY);
            boolean failed = false;
            try {
                ps[2] = conn.prepareStatement(VALIDATION_QUERY);
            } catch (Exception e) {
                failed = true;
            }
            assertTrue("Properties 'poolPreparedStatements' or 'maxOpenPreparedStatements' don't work", failed);
        } finally {
            DatabaseUtil.closeSilently(ps);
            DatabaseUtil.closeSilently(conn);
        }
    }

    // maxPoolSize is set to "3", maxWait = MAX_WAIT_TIME
    // so after getting the next connection the thread should block for 3 seconds and then
    // throw "Cannot get connection exception"
    @Test(timeout = 6000)
    public void testMaxActiveProperty() throws Exception {
        Connection[] c = new Connection[4];
        try {
            c[0] = getConnection();
            c[1] = getConnection();
            c[2] = getConnection();
            long startTime = System.currentTimeMillis();
            try {
                // this must wait a bit and throw an exception
                c[3] = getConnection();
            } catch (SQLException e) {
                long waitedTime = System.currentTimeMillis() - startTime;
                assertFalse("Waited < maxWait", waitedTime < MAX_WAIT_TIME);
            }
        } finally {
            DatabaseUtil.closeSilently(c);
        }
    }

    @Test
    public void testAccessToUnderlyingConnectionAllowedProperty() throws Exception {
        Connection conn = null;
        try {
            conn = getConnection();
            Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();
            assertNotNull("Property 'accessToUnderlyingConnectionAllowed' doesn't work", dconn);
        } catch (Exception e) {
            fail();
        }
    }

    private Connection getConnection() throws Exception {
        return ConnectionPoolUtil.getConnection(logChannelInterface, dbMeta, "");
    }

}