SLING-2727 - Allow PerformanceRunner to run tests provided by a factory method
* applied patch from Andrei Dulvac (thanks)
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1551535 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/base/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java b/base/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java
index 8010a3a..3532afa 100644
--- a/base/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java
+++ b/base/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java
@@ -38,6 +38,7 @@
private Object target;
private PerformanceSuiteState performanceSuiteState;
private PerformanceRunner.ReportLevel reportLevel = PerformanceRunner.ReportLevel.ClassLevel;
+ private String testCaseName = "";
public FrameworkPerformanceMethod(Method method, Object target,
PerformanceSuiteState performanceSuiteState, PerformanceRunner.ReportLevel reportLevel) {
@@ -45,7 +46,10 @@
this.target = target;
this.performanceSuiteState = performanceSuiteState;
this.reportLevel = reportLevel;
+ if (target instanceof IdentifiableTestCase) {
+ this.testCaseName = ((IdentifiableTestCase) target).testCaseName();
}
+ }
@Override
public Object invokeExplosively(Object target, Object... params)
@@ -173,11 +177,8 @@
}
if (statistics.getN() > 0) {
- ReportLogger
- .writeReport(this.target.getClass().getName(),
- this.performanceSuiteState.testSuiteName,
- getMethod().getName(), statistics,
- ReportLogger.ReportType.TXT, reportLevel);
+ ReportLogger.writeReport(this.performanceSuiteState.testSuiteName, testCaseName, this.target.getClass().getName(),
+ getMethod().getName(), statistics, ReportLogger.ReportType.TXT, reportLevel);
}
// In case of a PerformanceSuite we need to run the methods annotated
@@ -345,4 +346,12 @@
return methodListResult.toArray(new Method[] {});
}
+ @Override
+ public String getName() {
+ System.out.println(testCaseName);
+ if (testCaseName == null || "".equals(testCaseName.trim())) { return super.getName(); }
+ return String.format("%s [%s.%s]", testCaseName, target.getClass().getSimpleName(),
+ getMethod().getName());
+}
+
}
diff --git a/base/src/main/java/org/apache/sling/performance/IdentifiableTestCase.java b/base/src/main/java/org/apache/sling/performance/IdentifiableTestCase.java
new file mode 100644
index 0000000..cfae459
--- /dev/null
+++ b/base/src/main/java/org/apache/sling/performance/IdentifiableTestCase.java
@@ -0,0 +1,10 @@
+package org.apache.sling.performance;
+
+/**
+ * Interface to be implemented by a class with PerformanceTests.
+ * <p></p>The provided method @{link #testCaseName()} exposes the possibility to give a name to each instance of the
+ * implementing class</p>
+ */
+public interface IdentifiableTestCase {
+ public String testCaseName();
+}
diff --git a/base/src/main/java/org/apache/sling/performance/PerformanceRunner.java b/base/src/main/java/org/apache/sling/performance/PerformanceRunner.java
index 68e2926..a2ff109 100644
--- a/base/src/main/java/org/apache/sling/performance/PerformanceRunner.java
+++ b/base/src/main/java/org/apache/sling/performance/PerformanceRunner.java
@@ -16,26 +16,31 @@
*/
package org.apache.sling.performance;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-
import org.apache.sling.performance.annotation.AfterSuite;
import org.apache.sling.performance.annotation.BeforeSuite;
import org.apache.sling.performance.annotation.PerformanceTest;
+import org.apache.sling.performance.annotation.PerformanceTestFactory;
import org.apache.sling.performance.annotation.PerformanceTestSuite;
import org.junit.After;
import org.junit.Before;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.TestClass;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
/**
* The custom JUnit runner that collects the performance tests
@@ -82,9 +87,10 @@
* @throws Exception
*/
protected void computeTests() throws Exception {
+ // add normal JUnit tests
tests.addAll(super.computeTestMethods());
- // count the performance tests
+ // add the performance tests
tests.addAll(computePerformanceTests());
// This is called here to ensure the test class constructor is called at
@@ -101,9 +107,12 @@
*/
protected Collection<? extends FrameworkMethod> computePerformanceTests()
throws Exception {
- List<FrameworkPerformanceMethod> tests = new LinkedList<FrameworkPerformanceMethod>();
+ List<FrameworkMethod> tests = new LinkedList<FrameworkMethod>();
List<Object> testObjects = new ArrayList<Object>();
+ List<Object> testObjectsTmp = new ArrayList<Object>();
+
+
ParameterizedTestList testCenter = new ParameterizedTestList();
// Retrieve the test objects included in the Performance test suite
@@ -114,10 +123,42 @@
.equals(ParameterizedTestList.class)) {
testCenter = (ParameterizedTestList) method.getMethod().invoke(
targetObject);
- testObjects = testCenter.getTestObjectList();
+ testObjectsTmp = testCenter.getTestObjectList();
+
+ // Iterate through all the test cases and see if they have a factory
+ for (Object testObject : testObjectsTmp) {
+ Method[] factoryMethods = getSpecificMethods(
+ testObject.getClass(), PerformanceTestFactory.class);
+
+ // If we have a factory method, get all the instance objects returned by this factory
+ if (factoryMethods.length > 0) {
+ // Make sure there's only one factory method
+ if (factoryMethods.length > 1) {
+ throw new IllegalStateException(
+ "There should be at most one PerformanceTestFactory method");
+ }
+ Method factoryMethod = factoryMethods[0];
+
+ // Execute the method (statically)
+ Object instances = factoryMethod.invoke(testObject);
+
+ // If the factory returned an array, make a list
+ if (instances.getClass().isArray()) {
+ instances = Arrays.asList((Object[]) instances);
+ }
+
+ // If the factory returned a single element, put it in a list
+ if (!(instances instanceof Iterable<?>)) {
+ instances = Collections.singletonList(instances);
+ }
+ testObjects.addAll((List) instances);
+ } else {
+ testObjects.add(testObject);
+ }
+ }
} else {
throw new InitializationError(
- "Wrong signature for the @PerformanceSuite method");
+ "Wrong signature for the @PerformanceTestSuite method");
}
}
@@ -172,22 +213,25 @@
// In case there are any objects retrieved from the Performance Suite
// we should add them to the tests that will be run and increase the
// number of methods
- // contained in the PerformaceSuite
+ // contained in the PerformanceSuite
if (!testObjects.isEmpty()) {
for (Object testObject : testObjects) {
+
// retrieve the test methods from the test classes
Method[] testMethods = getSpecificMethods(
testObject.getClass(), PerformanceTest.class);
- if (!suiteAlreadyRegistered) {
- newSuite.incrementNumberOfTestMethodsInSuite();
- }
for (Method method : testMethods) {
- FrameworkPerformanceMethod performaceTestMethod = new FrameworkPerformanceMethod(
+ FrameworkPerformanceMethod performaceTestMethod = new
+ FrameworkPerformanceMethod(
method, testObject, current, reportLevel);
tests.add(performaceTestMethod);
}
+
+ if (!suiteAlreadyRegistered) {
+ newSuite.incrementNumberOfTestMethodsInSuite();
+ }
}
// add the new suite to the list of suites
@@ -199,15 +243,16 @@
for (FrameworkMethod method : getTestClass().getAnnotatedMethods(
PerformanceTest.class)) {
Object targetObject = getTestClass().getJavaClass().newInstance();
- FrameworkPerformanceMethod performaceTestMethod = new FrameworkPerformanceMethod(
+ FrameworkPerformanceMethod performanceTestMethod = new FrameworkPerformanceMethod(
method.getMethod(), targetObject, current, reportLevel);
- tests.add(performaceTestMethod);
+ tests.add(performanceTestMethod);
}
return tests;
}
- /**
+
+ /**
* Retrieve specific method from test class
*
* @param testClass
diff --git a/base/src/main/java/org/apache/sling/performance/annotation/PerformanceTestFactory.java b/base/src/main/java/org/apache/sling/performance/annotation/PerformanceTestFactory.java
new file mode 100644
index 0000000..b7341b3
--- /dev/null
+++ b/base/src/main/java/org/apache/sling/performance/annotation/PerformanceTestFactory.java
@@ -0,0 +1,11 @@
+package org.apache.sling.performance.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface PerformanceTestFactory {
+}