org.opencms.test.OpenCmsThreadedTestCaseSuite Maven / Gradle / Ivy
Show all versions of opencms-test Show documentation
/*
* This library is part of OpenCms -
* the Open Source Content Management System
*
* Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This 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
* Lesser General Public License for more details.
*
* For further information about Alkacon Software, please see the
* company website: http://www.alkacon.com
*
* For further information about OpenCms, please see the
* project website: http://www.opencms.org
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.opencms.test;
import org.opencms.file.CmsObject;
import java.lang.reflect.Method;
/**
* Allows to run a specific method of an {@link org.opencms.test.OpenCmsTestCase} case concurrently.
*
* @since 6.5.0
*/
public class OpenCmsThreadedTestCaseSuite {
/** A not-initialized OpenCms user context. */
public static final CmsObject PARAM_CMSOBJECT = new CmsObject(null, null);
/** A not-initialized OpenCms user context. */
public static final Integer PARAM_COUNTER = new Integer(Integer.MIN_VALUE + 1);
/** The maximum allowed runtime for this test suite. */
private long m_allowedRuntime;
/** The number of concurrent test cases to execute. */
private int m_count;
/** The time the method executed. */
private long m_runtime;
/** The initialized threaded test cases. */
private OpenCmsThreadedTestCase[] m_threads;
/** Error that occurred when running the test suite. */
private Throwable m_throwable;
/**
* Generates a new threaded test case suite with the selected test case method.
*
* The parameters
array may contain the following placeholders:
* - {@link #PARAM_CMSOBJECT}: This will be replaced by a new {@link CmsObject} instance.
*
- {@link #PARAM_COUNTER}: This will be replaced by an integer counter with the number of the generated thread
*
*
* @param count the number of concurrent test cases to execute
* @param testCase the test case class to use
* @param method the method to execute on the test case
* @param parameters the parameter values for the method
*/
public OpenCmsThreadedTestCaseSuite(int count, OpenCmsTestCase testCase, String method, Object[] parameters) {
m_count = count;
m_runtime = -1;
m_allowedRuntime = m_count * 100;
try {
// generate class array - required for reflection
Class[] clazz = new Class[parameters.length];
for (int i = 0; i < parameters.length; i++) {
clazz[i] = parameters[i].getClass();
}
// get the method we want to use from the test case
Method m = testCase.getClass().getMethod(method, clazz);
// now initialize the threads
m_threads = initThreads(m_count, testCase, m, parameters);
} catch (Exception e) {
// exception may be becasue of bad method, or during initialization of threads
m_throwable = e;
}
}
/**
* Returns a list of {@link OpenCmsThreadedTestCase} instances that will be executed concurrently by this suite.
*
* @param count the number of concurrent executions
* @param testCase the base test case instance to execute a method from
* @param method the method name from the test case to execute
* @param parameters the parameters of the test case
*
* @return a list of {@link OpenCmsThreadedTestCase} instances that will be executed concurrently by this suite
*
* @throws Exception if something goes wrong
*/
private static OpenCmsThreadedTestCase[] initThreads(
int count,
OpenCmsTestCase testCase,
Method method,
Object[] parameters) throws Exception {
OpenCmsThreadedTestCase[] result = new OpenCmsThreadedTestCase[count];
for (int i = 0; i < count; i++) {
// create a copy of the parameters, initialize any placeholders
Object[] params = new Object[parameters.length];
for (int j = 0; j < parameters.length; j++) {
if (parameters[j] == PARAM_CMSOBJECT) {
// initialize a new CmsObject instance
params[j] = testCase.getCmsObject();
} else if (parameters[j] == PARAM_COUNTER) {
// add a new counter parameter
params[j] = new Integer(i);
} else {
// just use the given parameter
params[j] = parameters[j];
}
}
result[i] = new OpenCmsThreadedTestCase(testCase, method, params);
}
return result;
}
/**
* Returns the maximum allowed runtime of this test suite.
*
* If the given limit is exceeded, then this suite will stop waiting for
* the running test cases to finish and generate an internal exception.
*
* The default is the number of threads multiplied by 100 milliseconds.
*
* @return the maximum allowed runtime of this test suite
*/
public long getAllowedRuntime() {
return m_allowedRuntime;
}
/**
* Returns the runtime of this test suite.
*
* @return the runtime of this test suite
*/
public long getRuntime() {
return m_runtime;
}
/**
* Returns the error that that may have been caused while initializing or running this suite,
* or null
in case no error was thrown.
*
* @return the error that that may have been caused while initializing or running this suite,
* or null
in case no error was thrown
*/
public Throwable getThrowable() {
return m_throwable;
}
/**
* Runs the initialized test concurrent test cases.
*
* Returns the array of generated {@link OpenCmsThreadedTestCase} instances, which contain information
* about the individual test results.
*
*
* @return the array of generated {@link OpenCmsThreadedTestCase} instances
*/
public OpenCmsThreadedTestCase[] run() {
long startTime = System.currentTimeMillis();
if (m_throwable == null) {
// there may have been an exception acessing the selected method, so the test cases can not run at all
try {
for (int i = 0; i < m_count; i++) {
// start all the test cases
m_threads[i].start();
}
// give the tests some time to finish
long runTime;
int runCount;
long loopTime = System.currentTimeMillis();
do {
runCount = 0;
for (int i = 0; i < m_count; i++) {
// check each test if it is still alive
if (m_threads[i].isAlive()) {
// this thread is still running
runCount++;
}
}
if (runCount > 0) {
// give the running threads some time to finish
Thread.sleep(50);
}
// calculate the runtime
runTime = System.currentTimeMillis() - loopTime;
// limit the run time to avoid total hangup of test
} while ((runCount > 0) && (runTime < m_allowedRuntime));
if ((runCount > 0) && (runTime >= m_allowedRuntime)) {
// allowed runtime was exceeded, generate exception that is stored be the member later
throw new RuntimeException(
"There where "
+ runCount
+ " threads still running after "
+ (m_allowedRuntime / 1000.0)
+ " seconds");
}
} catch (Throwable e) {
// store the exception
m_throwable = e;
}
}
// calculate the final runtime
m_runtime = System.currentTimeMillis() - startTime;
return m_threads;
}
/**
* Sets the maximum allowed runtime of this test suite.
*
* @param allowedRuntime the maximum allowed runtime of this test suite to set
*/
public void setAllowedRuntime(long allowedRuntime) {
m_allowedRuntime = allowedRuntime;
}
}