/*-------------------------------------------------------------------------
*
* Copyright (c) 2004-2014, PostgreSQL Global Development Group
*
*
*-------------------------------------------------------------------------
*/
package org.postgresql.test.jdbc2.optional;
import junit.framework.TestCase;
import org.postgresql.test.TestUtil;
import org.postgresql.test.util.MiniJndiContextFactory;
import org.postgresql.ds.common.BaseDataSource;
import org.postgresql.PGConnection;
import java.sql.*;
import java.util.*;
import javax.naming.*;
/**
* 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 extends TestCase
{
public static String DATA_SOURCE_JNDI = "BaseDataSource";
protected Connection con;
protected BaseDataSource bds;
/**
* Constructor required by JUnit
*/
public BaseDataSourceTest(String name)
{
super(name);
}
/**
* Creates a test table using a standard connection (not from a
* DataSource).
*/
protected 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)
*/
protected 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.setLogLevel(TestUtil.getLogLevel());
bds.setProtocolVersion(TestUtil.getProtocolVersion());
}
/**
* Test to make sure you can instantiate and configure the
* appropriate DataSource
*/
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.
*/
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
*/
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.
*/
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.
*/
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.
*/
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() + ")");
}
}
/**
* Uses the mini-JNDI implementation for testing purposes
*/
protected InitialContext getInitialContext()
{
Hashtable env = new Hashtable();
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;
}
}
/**
* 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.
*/
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);
}
/**
* 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);
}
}