/* * Copyright 2011 James Moger. * * Licensed 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 com.iciql.test; import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.sql.SQLException; import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import org.junit.Assert; import org.junit.runner.JUnitCore; import org.junit.runner.Result; import org.junit.runner.RunWith; import org.junit.runner.notification.Failure; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; import com.iciql.Constants; import com.iciql.Db; import com.iciql.util.StatementLogger; import com.iciql.util.StatementLogger.StatementListener; import com.iciql.util.StatementLogger.StatementType; import com.iciql.util.StringUtils; /** * JUnit 4 iciql test suite. * * By default this test suite will run against the H2 database. You can change * this by switching the DEFAULT_TEST_DB value. *
* Alternatively, you can run this class an application which will run all tests
* for all tested databases.
*
*/
@RunWith(Suite.class)
@SuiteClasses({ AliasMapTest.class, AnnotationsTest.class, BooleanModelTest.class, ClobTest.class,
ConcurrencyTest.class, EnumsTest.class, ModelsTest.class, PrimitivesTest.class,
RuntimeQueryTest.class, SamplesTest.class, UpdateTest.class, UUIDTest.class })
public class IciqlSuite {
private static final TestDb[] TEST_DBS = {
new TestDb("H2", "jdbc:h2:mem:db{0,number,000}"),
new TestDb("HSQL", "jdbc:hsqldb:mem:db{0,number,000}"),
new TestDb("Derby", "jdbc:derby:memory:db{0,number,000};create=true") };
private static final TestDb DEFAULT_TEST_DB = TEST_DBS[0];
private static final PrintStream ERR = System.err;
private static AtomicInteger openCount = new AtomicInteger(0);
private static String username = "sa";
private static String password = "sa";
private static PrintStream out = System.out;
public static void assertStartsWith(String value, String startsWith) {
Assert.assertTrue(MessageFormat.format("Expected \"{0}\", got: \"{1}\"", startsWith, value),
value.startsWith(startsWith));
}
/**
* Increment the database counter, open and create a new database.
*
* @return a fresh database
*/
public static Db openNewDb() {
String testUrl = System.getProperty("iciql.url");
if (testUrl == null) {
testUrl = DEFAULT_TEST_DB.url;
}
testUrl = MessageFormat.format(testUrl, openCount.incrementAndGet());
return Db.open(testUrl, username, password);
}
/**
* Open the current database.
*
* @return the current database
*/
public static Db openCurrentDb() {
String testUrl = System.getProperty("iciql.url");
if (testUrl == null) {
testUrl = DEFAULT_TEST_DB.url;
}
testUrl = MessageFormat.format(testUrl, openCount.get());
return Db.open(testUrl, username, password);
}
/**
* Returns the name of the underlying database engine for the Db object.
*
* @param db
* @return the database engine name
*/
public static String getDatabaseEngineName(Db db) {
String database = "";
try {
database = db.getConnection().getMetaData().getDatabaseProductName();
} catch (SQLException s) {
}
return database;
}
/**
* Returns true if the underlying database engine is Derby.
*
* @param db
* @return true if underlying database engine is Derby
*/
public static boolean isDerby(Db db) {
return IciqlSuite.getDatabaseEngineName(db).equals("Apache Derby");
}
/**
* Returns true if the underlying database engine is H2.
*
* @param db
* @return true if underlying database engine is H2
*/
public static boolean isH2(Db db) {
return IciqlSuite.getDatabaseEngineName(db).equals("H2");
}
/**
* Gets the default schema of the underlying database engine.
*
* @param db
* @return the default schema
*/
public static String getDefaultSchema(Db db) {
if (isDerby(db)) {
// Derby sets default schema name to username
return username.toUpperCase();
}
return "PUBLIC";
}
/**
* Main entry point for the test suite. Executing this method will run the
* test suite on all registered databases.
*
* @param args
* @throws Exception
*/
public static void main(String... args) throws Exception {
Params params = new Params();
JCommander jc = new JCommander(params);
try {
jc.parse(args);
} catch (ParameterException t) {
usage(jc, t);
}
// Replace System.out with a file
if (!StringUtils.isNullOrEmpty(params.dbPerformanceFile)) {
out = new PrintStream(params.dbPerformanceFile);
System.setErr(out);
}
// Statement logging
final FileWriter statementWriter;
if (StringUtils.isNullOrEmpty(params.sqlStatementsFile)) {
statementWriter = null;
} else {
statementWriter = new FileWriter(params.sqlStatementsFile);
}
StatementListener statementListener = new StatementListener() {
@Override
public void logStatement(StatementType type, String statement) {
if (statementWriter == null) {
return;
}
try {
statementWriter.append(statement);
statementWriter.append('\n');
} catch (IOException e) {
e.printStackTrace();
}
}
};
StatementLogger.registerListener(statementListener);
SuiteClasses suiteClasses = IciqlSuite.class.getAnnotation(SuiteClasses.class);
long quickestDatabase = Long.MAX_VALUE;
String dividerMajor = buildDivider('*', 70);
String dividerMinor = buildDivider('-', 70);
// Header
out.println(dividerMajor);
out.println(MessageFormat.format("{0} {1} ({2}) testing {3} databases", Constants.NAME,
Constants.VERSION, Constants.VERSION_DATE, TEST_DBS.length));
out.println(dividerMajor);
out.println();
showProperty("java.vendor");
showProperty("java.runtime.version");
showProperty("java.vm.name");
showProperty("os.name");
showProperty("os.version");
showProperty("os.arch");
showProperty("available processors", "" + Runtime.getRuntime().availableProcessors());
showProperty("available memory", MessageFormat.format("{0,number,#.0} GB", ((double) Runtime.getRuntime().maxMemory())/(1024*1024)));
out.println();
// Test a database
for (TestDb testDb : TEST_DBS) {
out.println(dividerMinor);
out.println("Testing " + testDb.name + " " + testDb.getVersion());
out.println(dividerMinor);
// inject a database section delimiter in the statement log
if (statementWriter != null) {
statementWriter.append("\n\n");
statementWriter.append("# ").append(dividerMinor).append('\n');
statementWriter.append("# ").append("Testing " + testDb.name + " " + testDb.getVersion()).append('\n');
statementWriter.append("# ").append(dividerMinor).append('\n');
statementWriter.append("\n\n");
}
System.setProperty("iciql.url", testDb.url);
Result result = JUnitCore.runClasses(suiteClasses.value());
testDb.runtime = result.getRunTime();
if (testDb.runtime < quickestDatabase) {
quickestDatabase = testDb.runtime;
}
out.println(MessageFormat.format("{0} tests: {1} failures, {2} ignores in {3,number,0.000} secs",
result.getRunCount(), result.getFailureCount(), result.getIgnoreCount(),
result.getRunTime() / 1000f));
if (result.getFailureCount() == 0) {
out.println();
} else {
for (Failure failure : result.getFailures()) {
out.println(MessageFormat.format("\n + {0}\n {1}\n", failure.getTestHeader(),
failure.getMessage()));
}
}
}
// Display runtime results sorted by performance leader
out.println(dividerMajor);
out.println(MessageFormat.format("{0} {1} ({2}) test suite performance results", Constants.NAME,
Constants.VERSION, Constants.VERSION_DATE));
out.println(dividerMajor);
List