blob: 630dbe082bf067ccc8879a7c81701f0f256d2dce [file] [log] [blame]
/*
*
* 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.qpid.test.utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import ch.qos.logback.classic.ClassicConstants;
import ch.qos.logback.classic.LoggerContext;
import junit.framework.TestCase;
import junit.framework.TestResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class QpidTestCase extends TestCase
{
private static final String TEST_EXCLUDES = "test.excludes";
private static final String TEST_EXCLUDELIST = "test.excludelist";
private static final String TEST_EXCLUDEFILES = "test.excludefiles";
private static final String VIRTUAL_HOST_NODE_TYPE = "virtualhostnode.type";
private static final String VIRTUAL_HOST_NODE_CONTEXT_BLUEPRINT = "virtualhostnode.context.blueprint";
private static final String TEST_OVERRIDDEN_PROPERTIES = "test.overridden.properties";
public static final String QPID_HOME = System.getProperty("QPID_HOME");
public static final String TEST_PROFILES_DIR = QPID_HOME + File.separator + ".." + File.separator + "test-profiles" + File.separator;
public static final String TEST_RESOURCES_DIR = TEST_PROFILES_DIR + "test_resources/";
public static final String TMP_FOLDER = System.getProperty("java.io.tmpdir");
private static final Logger LOGGER = LoggerFactory.getLogger(QpidTestCase.class);
private static QpidTestCase _currentInstance;
private final Map<String, String> _propertiesSetForTest = new HashMap<>();
private final Set<Runnable> _tearDownRegistry = new HashSet<>();
/**
* Some tests are excluded when the property test.excludes is set to true.
* An exclusion list is either a file (prop test.excludesfile) which contains one test name
* to be excluded per line or a String (prop test.excludeslist) where tests to be excluded are
* separated by " ". Excluded tests are specified following the format:
* className#testName where className is the class of the test to be
* excluded and testName is the name of the test to be excluded.
* className#* excludes all the tests of the specified class.
*/
static
{
if (Boolean.getBoolean("test.exclude"))
{
LOGGER.info("Some tests should be excluded, building the exclude list");
String exclusionListURIs = System.getProperty(TEST_EXCLUDEFILES, "");
String exclusionListString = System.getProperty(TEST_EXCLUDELIST, "");
String testExcludes = System.getProperty(TEST_EXCLUDES);
//For the maven build, process the test.excludes property
if(testExcludes != null && "".equals(exclusionListURIs))
{
for (String exclude : testExcludes.split("\\s+"))
{
exclusionListURIs += TEST_PROFILES_DIR + File.separator + exclude + ";";
}
}
List<String> exclusionList = new ArrayList<>();
for (String uri : exclusionListURIs.split(";\\s*"))
{
File file = new File(uri);
if (file.exists())
{
LOGGER.info("Using exclude file: " + uri);
try(FileReader fileReader = new FileReader(file))
{
try(BufferedReader in = new BufferedReader(fileReader))
{
String excludedTest = in.readLine();
do
{
exclusionList.add(excludedTest);
excludedTest = in.readLine();
}
while (excludedTest != null);
}
}
catch (IOException e)
{
LOGGER.warn("Exception when reading exclusion list", e);
}
}
else
{
LOGGER.info("Specified exclude file does not exist: " + uri);
}
}
if (!exclusionListString.equals(""))
{
LOGGER.info("Using excludeslist: " + exclusionListString);
for (String test : exclusionListString.split("\\s+"))
{
exclusionList.add(test);
}
}
_exclusionList = Collections.unmodifiableList(exclusionList);
}
else
{
_exclusionList = Collections.emptyList();
}
}
private static final List<String> _exclusionList;
private static final Properties OVERRIDDEN_PROPERTIES = loadOverriddenTestSystemProperties();
@Override
public void run(TestResult testResult)
{
final LoggerContext loggerContext = ((ch.qos.logback.classic.Logger) LOGGER).getLoggerContext();
try
{
_currentInstance = this;
loggerContext.putProperty(LogbackPropertyValueDiscriminator.CLASS_QUALIFIED_TEST_NAME, getClassQualifiedTestName());
if (_exclusionList.contains(getClass().getPackage().getName() + ".*") ||
_exclusionList.contains(getClass().getName() + "#*") ||
_exclusionList.contains(getClass().getName() + "#" + getName()))
{
LOGGER.info("Test: " + getName() + " is excluded");
testResult.endTest(this);
}
else
{
overrideTestSystemProperties();
super.run(testResult);
}
}
finally
{
LOGGER.info(ClassicConstants.FINALIZE_SESSION_MARKER, "Shutting down sub-appender");
_currentInstance = null;
loggerContext.putProperty(LogbackPropertyValueDiscriminator.CLASS_QUALIFIED_TEST_NAME, null);
revertTestSystemProperties();
}
}
@Override
protected void runTest() throws Throwable
{
LOGGER.info("========== run " + getTestName() + " ==========");
super.runTest();
}
public String getTestProfileVirtualHostNodeType()
{
final String storeType = System.getProperty(VIRTUAL_HOST_NODE_TYPE);
if (LOGGER.isDebugEnabled())
{
LOGGER.debug(VIRTUAL_HOST_NODE_TYPE + "=" + storeType);
}
return storeType != null ? storeType : "TestMemory";
}
protected String getClassQualifiedTestName()
{
return getClass().getCanonicalName() + "." + getName();
}
protected String getTestName()
{
return getClass().getSimpleName() + "." + getName();
}
public String getTestProfileVirtualHostNodeBlueprint()
{
return System.getProperty(VIRTUAL_HOST_NODE_CONTEXT_BLUEPRINT);
}
public void registerTearDown(Runnable runnable)
{
_tearDownRegistry.add(runnable);
}
public static QpidTestCase getCurrentInstance()
{
return _currentInstance;
}
/**
* Gets the next available port starting at a port.
*
* @param fromPort the port to scan for availability
* @throws NoSuchElementException if there are no ports available
*/
public int getNextAvailable(int fromPort)
{
return new PortHelper().getNextAvailable(fromPort);
}
public int findFreePort()
{
return new PortHelper().getNextAvailable();
}
/**
* Set a System property for duration of this test only. The tearDown will
* guarantee to reset the property to its previous value after the test
* completes.
*
* @param property The property to set
* @param value the value to set it to, if null, the property will be cleared
*/
protected void setTestSystemProperty(final String property, final String value)
{
if (!_propertiesSetForTest.containsKey(property))
{
// Record the current value so we can revert it later.
_propertiesSetForTest.put(property, System.getProperty(property));
}
if (value == null)
{
System.clearProperty(property);
}
else
{
System.setProperty(property, value);
}
LOGGER.info("Set system property \"" + property + "\" to: \"" + value + "\"");
}
/**
* Restore the System property values that were set by this test run.
*/
protected void revertTestSystemProperties()
{
if(!_propertiesSetForTest.isEmpty())
{
LOGGER.debug("reverting " + _propertiesSetForTest.size() + " test properties");
for (String key : _propertiesSetForTest.keySet())
{
String value = _propertiesSetForTest.get(key);
if (value != null)
{
System.setProperty(key, value);
}
else
{
System.clearProperty(key);
}
}
_propertiesSetForTest.clear();
}
}
@Override
protected void setUp() throws Exception
{
LOGGER.info("========== start " + getTestName() + " ==========");
super.setUp();
}
@Override
protected void tearDown() throws Exception
{
LOGGER.info("========== tearDown " + getTestName() + " ==========");
for (Runnable runnable : _tearDownRegistry)
{
runnable.run();
}
_tearDownRegistry.clear();
}
protected void overrideTestSystemProperties()
{
setTestOverriddenProperties(OVERRIDDEN_PROPERTIES);
}
protected void setTestOverriddenProperties(Properties properties)
{
for (String propertyName : properties.stringPropertyNames())
{
setTestSystemProperty(propertyName, properties.getProperty(propertyName));
}
}
private static Properties loadOverriddenTestSystemProperties()
{
Properties properties = new Properties();
String pathToFileWithOverriddenClientAndBrokerProperties = System.getProperty(TEST_OVERRIDDEN_PROPERTIES);
if (pathToFileWithOverriddenClientAndBrokerProperties != null)
{
File file = new File(pathToFileWithOverriddenClientAndBrokerProperties);
if (file.exists())
{
LOGGER.info("Loading overridden system properties from {}", file.getAbsolutePath());
try (InputStream propertiesStream = new FileInputStream(file))
{
properties.load(propertiesStream);
}
catch (IOException e)
{
throw new RuntimeException(String.format(
"Cannot load overridden properties from '%s'. Verify value provided with system property '%s'",
file.getAbsolutePath(),
TEST_OVERRIDDEN_PROPERTIES), e);
}
}
else
{
throw new RuntimeException(String.format(
"File with overridden properties at '%s' does not exists. Verify value provided with system property '%s'",
file.getAbsolutePath(),
TEST_OVERRIDDEN_PROPERTIES));
}
}
return properties;
}
}