/**
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.dbcp.managed;
import org.apache.commons.dbcp.DelegatingConnection;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import junit.framework.Test;
import junit.framework.TestSuite;
import javax.transaction.Transaction;
/**
* TestSuite for ManagedDataSource with an active transaction in progress.
*
* @author Dain Sundstrom
* @version $Revision$
*/
public class TestManagedDataSourceInTx extends TestManagedDataSource {
public TestManagedDataSourceInTx(String testName) {
super(testName);
}
public static Test suite() {
return new TestSuite(TestManagedDataSourceInTx.class);
}
public void setUp() throws Exception {
super.setUp();
transactionManager.begin();
}
public void tearDown() throws Exception {
if (transactionManager.getTransaction() != null) {
transactionManager.commit();
}
super.tearDown();
}
/**
* @see #testSharedConnection()
*/
public void testManagedConnectionEqualsFail() throws Exception {
// this test is invalid for managed conections since because
// two connections to the same datasource are supposed to share
// a single connection
}
public void testConnectionsAreDistinct() throws Exception {
Connection[] conn = new Connection[getMaxActive()];
for(int i=0;i<conn.length;i++) {
conn[i] = newConnection();
for(int j=0;j<i;j++) {
// two connections should be distinct instances
assertNotSame(conn[j], conn[i]);
// but they should be equivilant since they are sharing the same underlying connection
assertEquals(conn[j], conn[i]);
}
}
for(int i=0;i<conn.length;i++) {
conn[i].close();
}
}
public void testHashCode() throws Exception {
Connection conn1 = newConnection();
assertNotNull(conn1);
Connection conn2 = newConnection();
assertNotNull(conn2);
// shared connections should have the same hashcode
assertEquals(conn1.hashCode(), conn2.hashCode());
}
public void testMaxActive() throws Exception {
Transaction[] transactions = new Transaction[getMaxActive()];
Connection[] c = new Connection[getMaxActive()];
for (int i = 0; i < c.length; i++) {
// create a new connection in the current transaction
c[i] = newConnection();
assertNotNull(c[i]);
// suspend the current transaction and start a new one
transactions[i] = transactionManager.suspend();
assertNotNull(transactions[i]);
transactionManager.begin();
}
try {
newConnection();
fail("Allowed to open more than DefaultMaxActive connections.");
} catch (java.sql.SQLException e) {
// should only be able to open 10 connections, so this test should
// throw an exception
} finally {
transactionManager.commit();
for (int i = 0; i < c.length; i++) {
transactionManager.resume(transactions[i]);
c[i].close();
transactionManager.commit();
}
}
}
public void testClearWarnings() throws Exception {
// open a connection
Connection connection = newConnection();
assertNotNull(connection);
// generate SQLWarning on connection
connection.prepareCall("warning");
assertNotNull(connection.getWarnings());
// create a new shared connection
Connection sharedConnection = newConnection();
// shared connection should see warning
assertNotNull(sharedConnection.getWarnings());
// close and allocate a new (original) connection
connection.close();
connection = newConnection();
// warnings should not have been cleared by closing the connection
assertNotNull(connection.getWarnings());
assertNotNull(sharedConnection.getWarnings());
connection.close();
sharedConnection.close();
}
public void testSharedConnection() throws Exception {
DelegatingConnection connectionA = (DelegatingConnection) newConnection();
DelegatingConnection connectionB = (DelegatingConnection) newConnection();
assertTrue(connectionA.equals(connectionB));
assertTrue(connectionB.equals(connectionA));
assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
connectionA.close();
connectionB.close();
}
public void testSharedTransactionConversion() throws Exception {
DelegatingConnection connectionA = (DelegatingConnection) newConnection();
DelegatingConnection connectionB = (DelegatingConnection) newConnection();
// in a transaciton the connections should be equal
assertTrue(connectionA.equals(connectionB));
assertTrue(connectionB.equals(connectionA));
assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
transactionManager.commit();
// use the connection so it adjusts to the completed transaction
connectionA.getAutoCommit();
connectionB.getAutoCommit();
// no there is no transaction so connections should not be equal
assertFalse(connectionA.equals(connectionB));
assertFalse(connectionB.equals(connectionA));
assertFalse(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
assertFalse(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
transactionManager.begin();
// use the connection so it adjusts to the new transaction
connectionA.getAutoCommit();
connectionB.getAutoCommit();
// back in a transaction so should be equal again
assertTrue(connectionA.equals(connectionB));
assertTrue(connectionB.equals(connectionA));
assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
connectionA.close();
connectionB.close();
}
public void testCloseInTransaction() throws Exception {
DelegatingConnection connectionA = (DelegatingConnection) newConnection();
DelegatingConnection connectionB = (DelegatingConnection) newConnection();
assertTrue(connectionA.equals(connectionB));
assertTrue(connectionB.equals(connectionA));
assertTrue(connectionA.innermostDelegateEquals(connectionB.getInnermostDelegate()));
assertTrue(connectionB.innermostDelegateEquals(connectionA.getInnermostDelegate()));
connectionA.close();
connectionB.close();
Connection connection = newConnection();
// conection should be open
assertFalse("Connection should be open", connection.isClosed());
// close the connection
connection.close();
// conection should be open
assertTrue("Connection should be closed", connection.isClosed());
// conection should be open
assertTrue("Connection should be closed", connection.isClosed());
}
public void testAutoCommitBehavior() throws Exception {
Connection connection = newConnection();
// auto commit should be off
assertFalse("Auto-commit should be disabled", connection.getAutoCommit());
// attempt to set auto commit
try {
connection.setAutoCommit(true);
fail("setAutoCommit method should be disabled while enlisted in a transaction");
} catch (SQLException e) {
// expected
}
// make sure it is still disabled
assertFalse("Auto-commit should be disabled", connection.getAutoCommit());
// close connection
connection.close();
}
public void testCommit() throws Exception {
Connection connection = newConnection();
// conection should be open
assertFalse("Connection should be open", connection.isClosed());
// attempt commit directly
try {
connection.commit();
fail("commit method should be disabled while enlisted in a transaction");
} catch (SQLException e) {
// expected
}
// make sure it is still open
assertFalse("Connection should be open", connection.isClosed());
// close connection
connection.close();
}
public void testReadOnly() throws Exception {
Connection connection = newConnection();
// NOTE: This test class uses connections that are read-only by default
// conection should be read only
assertTrue("Connection be read-only", connection.isReadOnly());
// attempt to setReadOnly
try {
connection.setReadOnly(true);
fail("setReadOnly method should be disabled while enlisted in a transaction");
} catch (SQLException e) {
// expected
}
// make sure it is still read-only
assertTrue("Connection be read-only", connection.isReadOnly());
// attempt to setReadonly
try {
connection.setReadOnly(false);
fail("setReadOnly method should be disabled while enlisted in a transaction");
} catch (SQLException e) {
// expected
}
// make sure it is still read-only
assertTrue("Connection be read-only", connection.isReadOnly());
// close connection
connection.close();
}
// can't actually test close in a transaction
protected void assertBackPointers(Connection conn, Statement statement) throws SQLException {
assertFalse(conn.isClosed());
assertFalse(isClosed(statement));
assertSame("statement.getConnection() should return the exact same connection instance that was used to create the statement",
conn, statement.getConnection());
ResultSet resultSet = statement.getResultSet();
assertFalse(isClosed(resultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, resultSet.getStatement());
ResultSet executeResultSet = statement.executeQuery("select * from dual");
assertFalse(isClosed(executeResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, executeResultSet.getStatement());
ResultSet keysResultSet = statement.getGeneratedKeys();
assertFalse(isClosed(keysResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, keysResultSet.getStatement());
ResultSet preparedResultSet = null;
if (statement instanceof PreparedStatement) {
PreparedStatement preparedStatement = (PreparedStatement) statement;
preparedResultSet = preparedStatement.executeQuery();
assertFalse(isClosed(preparedResultSet));
assertSame("resultSet.getStatement() should return the exact same statement instance that was used to create the result set",
statement, preparedResultSet.getStatement());
}
resultSet.getStatement().getConnection().close();
}
}