/* * Copyright (c) 2004, PostgreSQL Global Development Group * See the LICENSE file in the project root for more information. */ package org.postgresql.test.jdbc2.optional; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.postgresql.PGConnection; import org.postgresql.ds.common.BaseDataSource; import org.postgresql.test.TestUtil; import org.postgresql.test.util.MiniJndiContextFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Hashtable; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; /** * Common tests for all the BaseDataSource implementations. This is a small variety to make sure * that a connection can be opened and some basic queries run. The different BaseDataSource * subclasses have different subclasses of this which add additional custom tests. * * @author Aaron Mulder (ammulder@chariotsolutions.com) */ public abstract class BaseDataSourceTest { public static String DATA_SOURCE_JNDI = "BaseDataSource"; protected Connection con; protected BaseDataSource bds; /** * Creates a test table using a standard connection (not from a DataSource). */ @Before public void setUp() throws Exception { con = TestUtil.openDB(); TestUtil.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)"); Statement stmt = con.createStatement(); stmt.executeUpdate("INSERT INTO poolingtest VALUES (1, 'Test Row 1')"); stmt.executeUpdate("INSERT INTO poolingtest VALUES (2, 'Test Row 2')"); TestUtil.closeDB(con); } /** * Removes the test table using a standard connection (not from a DataSource) */ @After public void tearDown() throws Exception { TestUtil.closeDB(con); con = TestUtil.openDB(); TestUtil.dropTable(con, "poolingtest"); TestUtil.closeDB(con); } /** * Gets a connection from the current BaseDataSource */ protected Connection getDataSourceConnection() throws SQLException { if (bds == null) { initializeDataSource(); } return bds.getConnection(); } /** * Creates an instance of the current BaseDataSource for testing. Must be customized by each * subclass. */ protected abstract void initializeDataSource(); public static void setupDataSource(BaseDataSource bds) { bds.setServerName(TestUtil.getServer()); bds.setPortNumber(TestUtil.getPort()); bds.setDatabaseName(TestUtil.getDatabase()); bds.setUser(TestUtil.getUser()); bds.setPassword(TestUtil.getPassword()); bds.setPrepareThreshold(TestUtil.getPrepareThreshold()); bds.setLoggerLevel(TestUtil.getLogLevel()); bds.setLoggerFile(TestUtil.getLogFile()); bds.setProtocolVersion(TestUtil.getProtocolVersion()); } /** * Test to make sure you can instantiate and configure the appropriate DataSource */ @Test public void testCreateDataSource() { initializeDataSource(); } /** * Test to make sure you can get a connection from the DataSource, which in turn means the * DataSource was able to open it. */ @Test public void testGetConnection() { try { con = getDataSourceConnection(); con.close(); } catch (SQLException e) { fail(e.getMessage()); } } /** * A simple test to make sure you can execute SQL using the Connection from the DataSource */ @Test public void testUseConnection() { try { con = getDataSourceConnection(); Statement st = con.createStatement(); ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM poolingtest"); if (rs.next()) { int count = rs.getInt(1); if (rs.next()) { fail("Should only have one row in SELECT COUNT result set"); } if (count != 2) { fail("Count returned " + count + " expecting 2"); } } else { fail("Should have one row in SELECT COUNT result set"); } rs.close(); st.close(); con.close(); } catch (SQLException e) { fail(e.getMessage()); } } /** * A test to make sure you can execute DDL SQL using the Connection from the DataSource. */ @Test public void testDdlOverConnection() { try { con = getDataSourceConnection(); TestUtil.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)"); con.close(); } catch (SQLException e) { fail(e.getMessage()); } } /** * A test to make sure the connections are not being pooled by the current DataSource. Obviously * need to be overridden in the case of a pooling Datasource. */ @Test public void testNotPooledConnection() throws SQLException { con = getDataSourceConnection(); String name = con.toString(); con.close(); con = getDataSourceConnection(); String name2 = con.toString(); con.close(); assertTrue(!name.equals(name2)); } /** * Test to make sure that PGConnection methods can be called on the pooled Connection. */ @Test public void testPGConnection() { try { con = getDataSourceConnection(); ((PGConnection) con).getNotifications(); con.close(); } catch (Exception e) { fail("Unable to call PGConnection method on pooled connection due to " + e.getClass().getName() + " (" + e.getMessage() + ")"); } } /** * Eventually, we must test stuffing the DataSource in JNDI and then getting it back out and make * sure it's still usable. This should ideally test both Serializable and Referenceable * mechanisms. Will probably be multiple tests when implemented. */ @Test public void testJndi() { initializeDataSource(); BaseDataSource oldbds = bds; InitialContext ic = getInitialContext(); try { ic.rebind(DATA_SOURCE_JNDI, bds); bds = (BaseDataSource) ic.lookup(DATA_SOURCE_JNDI); assertTrue("Got null looking up DataSource from JNDI!", bds != null); compareJndiDataSource(oldbds, bds); } catch (NamingException e) { fail(e.getMessage()); } oldbds = bds; testUseConnection(); assertTrue("Test should not have changed DataSource (" + bds + " != " + oldbds + ")!", bds == oldbds); } /** * Uses the mini-JNDI implementation for testing purposes */ protected InitialContext getInitialContext() { Hashtable<String, Object> env = new Hashtable<String, Object>(); env.put(Context.INITIAL_CONTEXT_FACTORY, MiniJndiContextFactory.class.getName()); try { return new InitialContext(env); } catch (NamingException e) { fail("Unable to create InitialContext: " + e.getMessage()); return null; } } /** * Check whether a DS was dereferenced from JNDI or recreated. */ protected void compareJndiDataSource(BaseDataSource oldbds, BaseDataSource bds) { assertTrue("DataSource was dereferenced, should have been serialized or recreated", bds != oldbds); } }