/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.test.jdbcx; import java.io.PrintWriter; import java.io.StringWriter; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; import javax.sql.DataSource; import org.h2.jdbcx.JdbcConnectionPool; import org.h2.jdbcx.JdbcDataSource; import org.h2.test.TestBase; import org.h2.util.Task; /** * This class tests the JdbcConnectionPool. */ public class TestConnectionPool extends TestBase { /** * Run just this test. * * @param a ignored */ public static void main(String... a) throws Exception { TestBase.createCaller().init().test(); } public void test() throws Exception { deleteDb("connectionPool"); testShutdown(); testWrongUrl(); testTimeout(); testUncommittedTransaction(); testPerformance(); testKeepOpen(); testConnect(); testThreads(); deleteDb("connectionPool"); deleteDb("connectionPool2"); } private void testShutdown() throws SQLException { String url = getURL("connectionPool2", true), user = getUser(), password = getPassword(); JdbcConnectionPool cp = JdbcConnectionPool.create(url, user, password); StringWriter w = new StringWriter(); cp.setLogWriter(new PrintWriter(w)); Connection conn1 = cp.getConnection(); Connection conn2 = cp.getConnection(); conn1.close(); conn2.createStatement().execute("shutdown immediately"); cp.dispose(); assertTrue(w.toString().length() > 0); cp.dispose(); } private void testWrongUrl() { JdbcConnectionPool cp = JdbcConnectionPool.create("jdbc:wrong:url", "", ""); try { cp.getConnection(); } catch (SQLException e) { assertEquals(8001, e.getErrorCode()); } cp.dispose(); } private void testTimeout() throws Exception { String url = getURL("connectionPool", true), user = getUser(), password = getPassword(); final JdbcConnectionPool man = JdbcConnectionPool.create(url, user, password); man.setLoginTimeout(1); createClassProxy(man.getClass()); assertThrows(IllegalArgumentException.class, man). setMaxConnections(-1); man.setMaxConnections(2); // connection 1 (of 2) Connection conn = man.getConnection(); Task t = new Task() { public void call() { while (!stop) { // this calls notifyAll man.setMaxConnections(1); man.setMaxConnections(2); } } }; t.execute(); long time = System.currentTimeMillis(); try { // connection 2 (of 1 or 2) may fail man.getConnection(); // connection 3 (of 1 or 2) must fail man.getConnection(); fail(); } catch (SQLException e) { assertTrue(e.toString().toLowerCase().indexOf("timeout") >= 0); time = System.currentTimeMillis() - time; assertTrue("timeout after " + time + " ms", time > 1000); } finally { conn.close(); t.get(); } man.dispose(); } private void testUncommittedTransaction() throws SQLException { String url = getURL("connectionPool", true), user = getUser(), password = getPassword(); JdbcConnectionPool man = JdbcConnectionPool.create(url, user, password); assertEquals(30, man.getLoginTimeout()); man.setLoginTimeout(1); assertEquals(1, man.getLoginTimeout()); man.setLoginTimeout(0); assertEquals(30, man.getLoginTimeout()); assertEquals(10, man.getMaxConnections()); PrintWriter old = man.getLogWriter(); PrintWriter pw = new PrintWriter(new StringWriter()); man.setLogWriter(pw); assertTrue(pw == man.getLogWriter()); man.setLogWriter(old); Connection conn1 = man.getConnection(); assertTrue(conn1.getAutoCommit()); conn1.setAutoCommit(false); conn1.close(); assertTrue(conn1.isClosed()); Connection conn2 = man.getConnection(); assertTrue(conn2.getAutoCommit()); conn2.close(); man.dispose(); } private void testPerformance() throws SQLException { String url = getURL("connectionPool", true), user = getUser(), password = getPassword(); JdbcConnectionPool man = JdbcConnectionPool.create(url, user, password); Connection conn = man.getConnection(); int len = 1000; long time = System.currentTimeMillis(); for (int i = 0; i < len; i++) { man.getConnection().close(); } man.dispose(); trace((int) (System.currentTimeMillis() - time)); time = System.currentTimeMillis(); for (int i = 0; i < len; i++) { DriverManager.getConnection(url, user, password).close(); } trace((int) (System.currentTimeMillis() - time)); conn.close(); } private void testKeepOpen() throws Exception { JdbcConnectionPool man = getConnectionPool(1); Connection conn = man.getConnection(); Statement stat = conn.createStatement(); stat.execute("create local temporary table test(id int)"); conn.close(); conn = man.getConnection(); stat = conn.createStatement(); stat.execute("select * from test"); conn.close(); man.dispose(); } private void testThreads() throws Exception { final int len = getSize(4, 20); final JdbcConnectionPool man = getConnectionPool(len - 2); final boolean[] stop = { false }; /** * This class gets and returns connections from the pool. */ class TestRunner implements Runnable { public void run() { try { while (!stop[0]) { Connection conn = man.getConnection(); if (man.getActiveConnections() >= len + 1) { throw new Exception("a: " + man.getActiveConnections() + " is not smaller than b: " + len + 1); } Statement stat = conn.createStatement(); stat.execute("SELECT 1 FROM DUAL"); conn.close(); Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } } } Thread[] threads = new Thread[len]; for (int i = 0; i < len; i++) { threads[i] = new Thread(new TestRunner()); threads[i].start(); } Thread.sleep(1000); stop[0] = true; for (int i = 0; i < len; i++) { threads[i].join(); } assertEquals(0, man.getActiveConnections()); man.dispose(); } private JdbcConnectionPool getConnectionPool(int poolSize) { JdbcDataSource ds = new JdbcDataSource(); ds.setURL(getURL("connectionPool", true)); ds.setUser(getUser()); ds.setPassword(getPassword()); JdbcConnectionPool pool = JdbcConnectionPool.create(ds); pool.setMaxConnections(poolSize); return pool; } private void testConnect() throws SQLException { JdbcConnectionPool pool = getConnectionPool(3); for (int i = 0; i < 100; i++) { Connection conn = pool.getConnection(); conn.close(); } pool.dispose(); DataSource ds = pool; assertThrows(IllegalStateException.class, ds). getConnection(); assertThrows(UnsupportedOperationException.class, ds). getConnection(null, null); } }