package com.tesora.dve.common;
/*
* #%L
* Tesora Inc.
* Database Virtualization Engine
* %%
* Copyright (C) 2011 - 2014 Tesora Inc.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import com.tesora.dve.exceptions.PEException;
/**
* Base class for all Tesora DVE tests. Sets up things like logging and temporary
* work directories. Useful when no DVE specific infrastructure is required
*
*/
public abstract class PEBaseTest {
protected static class LargeTestResourceNotAvailableException extends PEException {
private static final long serialVersionUID = -1629221497003489808L;
public LargeTestResourceNotAvailableException(final String m) {
super(m);
}
}
private static final String BT_PROPERTIES_FILENAME = "local.properties";
protected static final String LARGE_RESOURCE_DIR_VAR = "parelastic.test.resourcedir";
protected static String applicationName = "Unknown";
protected static String workDir = null;
protected static boolean deleteWorkDirectoryAfterEachTest = false;
protected static Logger logger = Logger.getLogger(PEBaseTest.class);
private static Properties localProps = getPersonalProperties();
private static final Properties getPersonalProperties()
{
Properties props = new Properties();
try
{
props.load(new FileInputStream(BT_PROPERTIES_FILENAME));
}
catch (Exception e)
{
// ignore if we can't load the file
}
return props;
}
@org.testng.annotations.BeforeClass
public void beforeClassTestNG()
{
System.out.println("Running " + this.getClass().getName());
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
// do nothing
}
@AfterClass
public static void tearDownBaseAfterClass() throws Exception
{
// reset variables
applicationName = "Unknown";
workDir = null;
deleteWorkDirectoryAfterEachTest = false;
}
protected static File getFileFromLargeFileRepository(final String fileName) throws LargeTestResourceNotAvailableException {
final String largeFileRepositoryPath = System.getProperty(LARGE_RESOURCE_DIR_VAR);
if (largeFileRepositoryPath == null) {
throw new LargeTestResourceNotAvailableException("Environment variable '" + LARGE_RESOURCE_DIR_VAR + "' is undefined.");
}
final File returnFile = new File(new File(largeFileRepositoryPath), fileName);
if (!returnFile.canRead()) {
throw new LargeTestResourceNotAvailableException("The file '" + returnFile.getAbsolutePath() + "' is not accessible.");
}
return returnFile;
}
/**
* Creates a new randomly named directory in the default temporary-file directory.
* The directory gets deleted when the virtual machine terminates.
*/
protected static File getTemporaryDirectory() throws IOException {
final File temp = Files.createTempDirectory(null).toFile();
temp.deleteOnExit();
return temp;
}
/**
* This class provides an interface for testing expected exception thrown in tests.
* Make a new instance of this class overriding the test() method
* where you specify the tested code. You then call assertException() on this object giving it
* the exception class you expect to be thrown from the tested block.
*/
protected static abstract class ExpectedExceptionTester {
private static enum Event {
WRONG_TYPE, WRONG_MSG, OK;
}
public void assertException(final Class<? extends Throwable> expectedExceptionClass) {
assertException(expectedExceptionClass, null, false);
}
public void assertException(final Class<? extends Throwable> expectedExceptionClass, final String expectedExceptionMessage) {
assertException(expectedExceptionClass, expectedExceptionMessage, false);
}
/**
* Execute the test.
*
* @param expectedExceptionClass
* The Exception class you expect to catch from the tested
* code.
* @param expectedExceptionMessage
* The expected message of the given exception.
* @param traceCauseTree
* Look down the cause tree until you find the expected
* exception type or hit the end.
*/
public void assertException(final Class<? extends Throwable> expectedExceptionClass, final String expectedExceptionMessage, final boolean traceCauseTree) {
getAssertException(expectedExceptionClass, expectedExceptionMessage, traceCauseTree);
}
protected <T extends Throwable> T getAssertException(final Class<T> expectedExceptionClass, final String expectedExceptionMessage,
final boolean traceCauseTree) {
try {
test();
} catch (Throwable e) {
Event result = checkException(e, expectedExceptionClass, expectedExceptionMessage);
if (traceCauseTree) {
while ((e.getCause() != null) && (result == Event.WRONG_TYPE)) {
e = e.getCause();
result = checkException(e, expectedExceptionClass, expectedExceptionMessage);
}
}
switch (result) {
case WRONG_TYPE:
failWithStackTrace(e, "An unexpected exception '" + e.getClass() + "' was thrown.");
break;
case WRONG_MSG:
fail("An exception with wrong message ('" + e.getMessage() + "') was thrown.");
break;
case OK:
return (T) e;
default:
break;
}
}
fail("Expected exception '" + expectedExceptionClass + "' was not thrown.");
return null;
}
/**
* The code to be tested.
*/
public abstract void test() throws Throwable;
private Event checkException(final Throwable e, final Class<? extends Throwable> expectedExceptionClass, final String expectedExceptionMessage) {
if (expectedExceptionClass.isAssignableFrom(e.getClass())) {
String msg = e.getMessage();
if ((expectedExceptionMessage != null) && !expectedExceptionMessage.equals(msg)) {
return Event.WRONG_MSG;
} else {
return Event.OK;
}
} else {
return Event.WRONG_TYPE;
}
}
}
/**
* Assert a type for a given object.
*/
protected void assertType(final Object object, final Class<?> type) {
if (!object.getClass().isAssignableFrom(type)) {
final StringBuilder message = new StringBuilder();
message.append("Type <").append(type.getName()).append("> expected but was <").append(object.getClass().getName()).append(">.");
fail(message.toString());
}
}
/**
* Assert that two objects are equal. If the objects are arrays compare
* them element-wise, using equals(), handling multi-dimensional arrays
* correctly.
*/
protected static void assertEqualData(final Object expected, final Object actual) {
if ((expected != null) && expected.getClass().isArray()) {
assertTrue("expected: <" + ArrayUtils.toString(expected) + "> but was: <" + ArrayUtils.toString(actual) + ">",
ArrayUtils.isEquals(expected, actual));
} else {
assertEquals(expected, actual);
}
}
protected static void failWithStackTrace(Throwable e)
{
failWithStackTrace(e, null);
}
protected static void failWithStackTrace(Throwable e, String message)
{
fail((message != null && !message.isEmpty() ? message : "Should not throw exception") + ": "
+ e.getLocalizedMessage() + "\nTrace: " + PEStringUtils.toString(e));
}
/**
* Returns the value for the given label. Checks for properties first, then the environment
*
* @param label
* @return
*/
protected static String determineValue(String label)
{
return determineValue(label, null);
}
/**
* Returns the value for the given label. Checks for properties first, then the environment
*
* @param label
* @return
*/
protected static String determineValue(String label, String defaultValue)
{
String value = localProps.getProperty(label.replaceAll("_", ".").toLowerCase());
if (value == null || value.isEmpty())
{
value = localProps.getProperty(label);
}
if (value == null || value.isEmpty())
{
value = System.getProperty(label.replaceAll("_", ".").toLowerCase());
}
if (value == null || value.isEmpty())
{
value = System.getProperty(label);
}
if (value == null || value.isEmpty())
{
value = System.getenv(label);
}
if (value == null || value.isEmpty())
{
value = defaultValue;
}
return value;
}
/**
* Count rows in a given result set.
*/
protected int countResultSetRows(final ResultSet resultSet) throws SQLException {
if (resultSet == null) { throw new IllegalArgumentException(); }
int counter = 0;
while (resultSet.next()) {
++counter;
}
return counter;
}
}