/*
* Copyright (c) 2009, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.sqlobject;
import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import junit.framework.TestCase;
import ca.sqlpower.sql.DataSourceCollection;
import ca.sqlpower.sql.JDBCDataSource;
import ca.sqlpower.sql.PlDotIni;
import ca.sqlpower.sql.SPDataSource;
/**
* This is the test class to extend if your test class needs a connection to the
* HSQLDB testing database. The setUp method creates a connection to the
* database, which will be fresh and empty for every test, and the tearDown
* method shuts it down (which wipes out that database).
*/
public abstract class DatabaseConnectedTestCase extends TestCase {
private DataSourceCollection<SPDataSource> plini = new PlDotIni();
protected SQLDatabase db;
/**
* If set to false the database will not be setup and left as null.
* This is for products that don't connect to databases. (Mainly our
* XBRL stuff.)
*/
protected final boolean setupDB;
public DatabaseConnectedTestCase() {
this("", true);
}
public DatabaseConnectedTestCase(String name, boolean setupDB) {
super(name);
this.setupDB = setupDB;
}
public DatabaseConnectedTestCase(String name) {
this(name, true);
}
/**
* Looks up and returns an SPDataSource that represents the testing
* database. Uses a PL.INI file located in the current working directory,
* called "pl.regression.ini" and creates a connection to the database called
* "regression_test".
* <p>
* You are welcome to override this method in order to provide your own pl.ini
* and/or your own data source to the {@link #setUp()} method.
*
* <p>FIXME: Need to parameterise this so that we can test each supported
* database platform!
* @throws IOException
* @throws SQLObjectException
*/
protected JDBCDataSource getJDBCDataSource() throws IOException {
plini.read(new File("pl.regression.ini"));
return plini.getDataSource("regression_test", JDBCDataSource.class);
}
/**
* Sets up the instance variable <code>db</code>, which will be a SQLDatabase
* connected to the data source returned by {@link #getJDBCDataSource()}.
*/
@Override
protected void setUp() throws Exception {
if (setupDB) {
db = new SQLDatabase(new JDBCDataSource(getJDBCDataSource()));
db.setParent(new StubSQLObject());
assertNotNull(db.getDataSource().getParentType());
} else {
db = null;
plini = null;
}
}
@Override
protected void tearDown() throws Exception {
if (setupDB) {
try {
sqlx("SHUTDOWN");
db.disconnect();
db = null;
} catch (Exception ex) {
System.err.println("Shutdown failed. Test case probably modified the database connection! Retrying...");
DataSourceCollection<SPDataSource> dscol = new PlDotIni();
dscol.read(new File("pl.regression.ini"));
db.setDataSource(dscol.getDataSource("regression_test", JDBCDataSource.class));
sqlx("SHUTDOWN");
db.disconnect();
db = null;
}
}
}
public SQLDatabase getDb() {
return new SQLDatabase(new JDBCDataSource(db.getDataSource()));
}
/**
* Returns the data source collection that the current connection was obtained
* from. If you have not overridden the {@link #getJDBCDataSource()} method, this
* will be the data source collection specified by the file pl.regression.ini
* in the current working directory. If you have overridden that method, this
* method will return whatever plini value you set up in your override (which will
* be null if you didn't set the {@link #plini} variable).
*/
public DataSourceCollection<SPDataSource> getPLIni() {
return plini;
}
/**
* Executes the given SQL statement in {@link #db}.
*
* @param sql
* The SQL statement to execute. It should be an "update" type
* statement (that is, one that does not return a result set).
* @return The "row count" returned by the database.
* @throws SQLException If the statement fails.
* @throws SQLObjectException If getting the connection from {@link #db} fails.
*/
protected int sqlx(String sql) throws SQLException, SQLObjectException {
Connection con = null;
Statement stmt = null;
try {
con = db.getConnection();
stmt = con.createStatement();
return stmt.executeUpdate(sql);
} catch (SQLException ex) {
System.err.println("Got SQL Exception when executing: " + sql);
throw ex;
} finally {
try {
if (stmt != null) stmt.close();
} catch (SQLException ex) {
System.err.println("Failed to close statement; squishing this exception:");
ex.printStackTrace();
}
try {
if (con != null) con.close();
} catch (SQLException ex) {
System.err.println("Failed to close connection; squishing this exception:");
ex.printStackTrace();
}
}
}
}