| /* |
| * |
| * 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; |
| } |
| } |