This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.performance.base-0.0.2 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-performance.git
commit eb67a440c990e294c858ea91f2f84b36b7aa347d Author: Antonio Sanso <[email protected]> AuthorDate: Sat Sep 29 18:22:43 2012 +0000 SLING-2593 - Improvement for the Sling performance tools. Adding patch provided from Christian Vazzolla. Thanks Christian! git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/performance/base@1391855 13f79535-47bb-0310-9956-ffa450edef68 --- .../sling/performance/AbstractRepositoryTest.java | 12 +- .../performance/FrameworkPerformanceMethod.java | 282 +++++++++++++++++++++ .../sling/performance/ParameterizedTestList.java | 70 +++++ .../sling/performance/PerformanceRunner.java | 209 +++++++++++++++ .../sling/performance/PerformanceSuiteState.java | 91 +++++++ .../org/apache/sling/performance/ReportLogger.java | 96 +++++++ .../annotation/AfterMethodInvocation.java | 25 ++ .../performance/annotation/AfterSpecificTest.java | 25 ++ .../sling/performance/annotation/AfterSuite.java | 25 ++ .../annotation/BeforeMethodInvocation.java | 25 ++ .../performance/annotation/BeforeSpecificTest.java | 25 ++ .../sling/performance/annotation/BeforeSuite.java | 25 ++ .../performance/annotation/PerformanceTest.java | 47 ++++ .../annotation/PerformanceTestSuite.java | 10 + 14 files changed, 958 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/apache/sling/performance/AbstractRepositoryTest.java b/src/main/java/org/apache/sling/performance/AbstractRepositoryTest.java index f5f818d..ff542c5 100644 --- a/src/main/java/org/apache/sling/performance/AbstractRepositoryTest.java +++ b/src/main/java/org/apache/sling/performance/AbstractRepositoryTest.java @@ -26,7 +26,7 @@ import org.apache.sling.jcr.api.SlingRepository; -public abstract class AbstractRepositoryTest extends AbstractTest { +public abstract class AbstractRepositoryTest { private static class ShutdownThread extends Thread { @Override @@ -34,7 +34,7 @@ public abstract class AbstractRepositoryTest extends AbstractTest { try { RepositoryUtil.stopRepository(); } catch(Exception e) { - System.out.println("Exception in ShutdownThread:" + e); + //ignore for now } } @@ -81,10 +81,4 @@ public abstract class AbstractRepositoryTest extends AbstractTest { return testRoot; } - @Override - public void tearDown() throws Exception { - super.tearDown(); - if(session != null) { - session.logout(); - } - }} +} diff --git a/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java b/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java new file mode 100644 index 0000000..1f151cc --- /dev/null +++ b/src/main/java/org/apache/sling/performance/FrameworkPerformanceMethod.java @@ -0,0 +1,282 @@ +/* + * 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.sling.performance; + +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.naming.directory.InvalidAttributesException; + +import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; +import org.apache.sling.performance.annotation.AfterMethodInvocation; +import org.apache.sling.performance.annotation.BeforeMethodInvocation; +import org.apache.sling.performance.annotation.PerformanceTest; +import org.junit.After; +import org.junit.Before; +import org.junit.runners.model.FrameworkMethod; + +class FrameworkPerformanceMethod extends FrameworkMethod { + + private Object target; + private PerformanceSuiteState performanceSuiteState; + + public FrameworkPerformanceMethod(Method method, Object target, PerformanceSuiteState performanceSuiteState) { + super(method); + this.target = target; + this.performanceSuiteState = performanceSuiteState; + + } + + @Override + public Object invokeExplosively(Object target, Object... params) throws Throwable { + // Executes the test method on the supplied target + + // Check if this is the first test running from this specific PerformanceSuite + // and run the BeforeSuite methods + if ((performanceSuiteState != null) && (performanceSuiteState.getBeforeSuiteMethod() != null) + && (performanceSuiteState.getTargetObjectSuite() != null) + && (performanceSuiteState.getNumberOfExecutedMethods() == 0) + && !performanceSuiteState.testSuiteName.equals(ParameterizedTestList.TEST_CASE_ONLY)){ + performanceSuiteState.getBeforeSuiteMethod().invoke(performanceSuiteState.getTargetObjectSuite()); + } + + // In case of a PerformanceSuite we need to run the methods annotated with Before and After + // ourselves as JUnit can't find them (JUnit is looking for them in the test suite class); + // in case we don't have to deal with a PerformanceSuite just skip this as JUnit will run the methods itself + if ((performanceSuiteState != null) && !performanceSuiteState.testSuiteName.equals(ParameterizedTestList.TEST_CASE_ONLY)){ + + recursiveCallSpecificMethod(this.target.getClass(), this.target, Before.class); + } + + // Need to count the number of tests run from the PerformanceSuite + // so that we can call the AfterSuite method after the last test from the suite + // has run and the AfterSuite needs to run + performanceSuiteState.incrementNumberOfExecutedTestMethods(); + + Object response = null; + + Method testMethodToInvoke = this.getMethod(); + + PerformanceTest performanceAnnotation = testMethodToInvoke.getAnnotation(PerformanceTest.class); + + // retrieve the test configuration options + int warmuptime = performanceAnnotation.warmuptime(); + int runtime = performanceAnnotation.runtime(); + int warmupinvocations = performanceAnnotation.warmupinvocations(); + int runinvocations = performanceAnnotation.runinvocations(); + + DescriptiveStatistics statistics = new DescriptiveStatistics(); + + //System.out.println("Warmup started - test :" + testMethodToInvoke.getName()); + + if (warmupinvocations != 0){ + // Run the number of invocation specified in the annotation + // for warming up the system + for (int invocationIndex = 0; invocationIndex < warmupinvocations; invocationIndex++){ + + recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeMethodInvocation.class); + + //TODO: implement the method to run a before a specific test method + //recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeSpecificTest.class); + + response = super.invokeExplosively(this.target, params); + + //TODO: implement the method to run a after a specific test method + //recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterSpecificTest.class); + + recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterMethodInvocation.class); + } + } + else{ + // Run a few iterations to warm up the system + long warmupEnd = System.currentTimeMillis() + warmuptime * 1000; + while (System.currentTimeMillis() < warmupEnd) { + recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeMethodInvocation.class); + + //TODO: implement the method to run a before a specific test method + //recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeSpecificTest.class); + + response = super.invokeExplosively(this.target, params); + + //recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterSpecificTest.class); + //TODO: implement the method to run a after a specific test method + + recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterMethodInvocation.class); + } + } + + //System.out.println("Warmup ended - test :" + testMethodToInvoke.getName()); + if (runinvocations != 0){ + // Run the specified number of iterations and capture the execution times + for (int invocationIndex = 0; invocationIndex < runinvocations; invocationIndex++){ + + response = this.invokeTimedTestMethod(testMethodToInvoke, statistics, params); + } + } + else{ + // Run test iterations and capture the execution times + long runtimeEnd = System.currentTimeMillis() + runtime * 1000; + + while (System.currentTimeMillis() < runtimeEnd) { + + response = this.invokeTimedTestMethod(testMethodToInvoke, statistics, params); + + } + } + + if (statistics.getN() > 0) { + ReportLogger.writeReport(this.target.getClass().getName(), this.performanceSuiteState.testSuiteName, + getMethod().getName() , statistics, ReportLogger.ReportType.TXT); + } + + // In case of a PerformanceSuite we need to run the methods annotated with Before and After + // ourselves as JUnit can't find them; in case we don't have to deal with a PerformanceSuite + // just skip this as JUnit will run the methods itself + if ((performanceSuiteState != null) + && !performanceSuiteState.testSuiteName.equals(ParameterizedTestList.TEST_CASE_ONLY)){ + + recursiveCallSpecificMethod(this.target.getClass(), this.target, After.class); + } + + + // Check if this is the last test running from a PerformanceSuite + // and run the AfterSuite method + if ((performanceSuiteState != null) && (performanceSuiteState.getAfterSuiteMethod() != null) + && (performanceSuiteState.getTargetObjectSuite() != null) + && (performanceSuiteState.getNumberOfExecutedMethods() == performanceSuiteState.getNumberOfMethodsInSuite()) + && !performanceSuiteState.testSuiteName.equals(ParameterizedTestList.TEST_CASE_ONLY)){ + performanceSuiteState.getAfterSuiteMethod().invoke(performanceSuiteState.getTargetObjectSuite()); + + } + + return response; + } + + /** + * Method that runs 1 invocation of the timed test method + * @param testMethodToInvoke the test method to invoke + * @param statistics the statistics object that collects the results + * @param params the parameters for the invocation of the test method + * @return the response from the method invocation + * @throws Throwable + */ + private Object invokeTimedTestMethod(Method testMethodToInvoke, DescriptiveStatistics statistics, Object... params) + throws Throwable{ + + Object response = null; + + recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeMethodInvocation.class); + + //TODO: implement the method to run a before a specific test method + //recursiveCallSpecificMethod(this.target.getClass(), this.target, BeforeSpecificTest.class); + + // timing the test method execution + //System.out.println("Start test: " + testMethodToInvoke.getName()); + long start = System.nanoTime(); + response = super.invokeExplosively(this.target, params); + long timeMilliseconds =TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS); + statistics.addValue(timeMilliseconds); + + //System.out.println("End test: " + testMethodToInvoke.getName()); + + //System.out.println("Test execution time (ms): " + timeMilliseconds); + + //TODO: implement the method to run a after a specific test method + //recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterSpecificTest.class); + + recursiveCallSpecificMethod(this.target.getClass(), this.target, AfterMethodInvocation.class); + + return response; + } + + /** + * Recursively call a specific method annotated with a custom annotation + * @param test the test class that contains the method + * @param instance the instance on which will run the method + * @param methodAnnotation the method annotation to look for + * @throws InvocationTargetException + * @throws InvalidAttributesException + * @throws IllegalAccessException + * @throws InstantiationException + */ + @SuppressWarnings({"rawtypes"}) + private void recursiveCallSpecificMethod(Class test, Object instance, Class<? extends Annotation> methodAnnotation) throws InvocationTargetException, InvalidAttributesException, IllegalAccessException, InstantiationException{ + if (test.getSuperclass() != null){ + recursiveCallSpecificMethod(test.getSuperclass(), instance, methodAnnotation); + } + + Method testMethod = getSpecificTestMethod(test, methodAnnotation); + if (testMethod != null){ + if (!testMethod.isAccessible()){ + testMethod.setAccessible(true); + } + testMethod.invoke(instance); + } + } + + /** + * Get the method annotated with the custom annotation + * @param testClass the test class on which to look for the method + * @param methodAnnotation the method annotation to look for + * @return + * @throws InvalidAttributesException + * @throws IllegalAccessException + * @throws InstantiationException + */ + @SuppressWarnings({"rawtypes"}) + private Method getSpecificTestMethod(Class testClass, Class<? extends Annotation> methodAnnotation) throws InvalidAttributesException, IllegalAccessException, InstantiationException{ + + Method[] methodsToReturn = getSpecificMethods(testClass,methodAnnotation); + Method methodToReturn = null; + if (methodsToReturn.length == 1){ + methodToReturn = methodsToReturn[0]; + } + else if (methodsToReturn.length > 1){ + throw new InvalidAttributesException("Only 1 non parameterized before method accepted"); + } + + return methodToReturn; + } + + + /** + * Retrieve all the specific methods from test class + * @param testClass the test class that we need to search in + * @param annotation the annotation that we should look for + * @return the list with the methods that have the specified annotation + */ + @SuppressWarnings({"rawtypes"}) + private Method[] getSpecificMethods(Class testClass, Class<? extends Annotation> annotation){ + Method[] allMethods = testClass.getDeclaredMethods(); + + List<Method> methodListResult = new ArrayList<Method>(); + + for(Method testMethod : allMethods){ + if (testMethod.isAnnotationPresent(annotation)){ + methodListResult.add(testMethod); + } + } + return methodListResult.toArray(new Method[]{}); + } + +} + + diff --git a/src/main/java/org/apache/sling/performance/ParameterizedTestList.java b/src/main/java/org/apache/sling/performance/ParameterizedTestList.java new file mode 100644 index 0000000..bfd7cd0 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/ParameterizedTestList.java @@ -0,0 +1,70 @@ +/* + * 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.sling.performance; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Represents the object that will be returned by the method + * in which a new PerformanceTestSuite is created + * + */ +public class ParameterizedTestList { + + public static final String TEST_CASE_ONLY = "TESTCASEONLY"; + + private List<Object> testObjectList = new ArrayList<Object>(); + private String testSuiteTitle = TEST_CASE_ONLY; + private Map<String, String> parameters = new LinkedHashMap<String, String>(); + private Map<String, Object> parametersObjects = new LinkedHashMap<String, Object>(); + + public Map<String, Object> getParametersObjects() { + return parametersObjects; + } + + public void addParameterObject(String key, Object parameterObject) { + this.parametersObjects.put(key, parameterObject); + } + + public Map<String, String> getParameters() { + return parameters; + } + + public void addParameter(String key, String value) { + parameters.put(key, value); + } + + public List<Object> getTestObjectList() { + return testObjectList; + } + + public void addTestObject(Object testObject) { + testObjectList.add(testObject); + } + + public String getTestSuiteName() { + return testSuiteTitle; + } + + public void setTestSuiteTitle(String testSuiteTitle) { + this.testSuiteTitle = testSuiteTitle; + } + +} diff --git a/src/main/java/org/apache/sling/performance/PerformanceRunner.java b/src/main/java/org/apache/sling/performance/PerformanceRunner.java new file mode 100644 index 0000000..cc971da --- /dev/null +++ b/src/main/java/org/apache/sling/performance/PerformanceRunner.java @@ -0,0 +1,209 @@ +/* + * 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.sling.performance; + +import java.lang.annotation.Annotation; +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.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; + + +/** + * The custom JUnit runner that collects the performance tests + * + */ +public class PerformanceRunner extends BlockJUnit4ClassRunner { + protected LinkedList<FrameworkMethod> tests = new LinkedList<FrameworkMethod>(); + private List<PerformanceSuiteState> suitesState = new ArrayList<PerformanceSuiteState>(); + + + public PerformanceRunner(Class<?> clazz) throws InitializationError { + super(clazz); + try { + computeTests(); + } + catch (Exception e) { + throw new InitializationError(e); + } + } + + /** + * Compute the tests that will be run + * @throws Exception + */ + protected void computeTests() throws Exception { + tests.addAll(super.computeTestMethods()); + + // count the performance tests + tests.addAll(computePerformanceTests()); + + // This is called here to ensure the test class constructor is called at least + // once during testing. + createTest(); + } + + /** + * Compute performance tests + * @return the list containing the performance test methods + * @throws Exception + */ + protected Collection<? extends FrameworkMethod> computePerformanceTests() throws Exception { + List<FrameworkPerformanceMethod> tests = new LinkedList<FrameworkPerformanceMethod>(); + + List<Object> testObjects = new ArrayList<Object>(); + ParameterizedTestList testCenter = new ParameterizedTestList(); + + // Retrieve the test objects included in the Performance test suite + for (FrameworkMethod method: getTestClass().getAnnotatedMethods(PerformanceTestSuite.class)) { + Object targetObject = getTestClass().getJavaClass().newInstance(); + if (method.getMethod().getReturnType().equals(ParameterizedTestList.class)){ + testCenter = (ParameterizedTestList) method.getMethod().invoke(targetObject); + testObjects = testCenter.getTestObjectList(); + } + else{ + throw new InitializationError("Wrong signature for the @PerformanceSuite method"); + } + } + + // Retrieve the methods before running the methods from the test suite + List<FrameworkMethod> beforeSuiteMethods = getTestClass().getAnnotatedMethods(BeforeSuite.class); + if (beforeSuiteMethods.size() > 1){ + throw new InitializationError("Only one @BeforeSuite method is allowed for a @PerformanceSuite"); + } + + // Retrieve the methods before running the methods from the test suite + List<FrameworkMethod> afterSuiteMethods = getTestClass().getAnnotatedMethods(AfterSuite.class); + if (afterSuiteMethods.size() > 1){ + throw new InitializationError("Only one @AfterSuite method is allowed for a @PerformanceSuite"); + } + + PerformanceSuiteState current = null; + boolean suiteAlreadyRegistered = false; + + for(PerformanceSuiteState suiteState : suitesState){ + if (suiteState.testSuiteName.equals(testCenter.getTestSuiteName())){ + suiteAlreadyRegistered = true; + suiteState.incrementNumberOfTestMethodsInSuite(); + current = suiteState; + break; + } + } + + // Create a new PerformanceSuiteState object + PerformanceSuiteState newSuite = new PerformanceSuiteState(testCenter.getTestSuiteName()); + + if (!suiteAlreadyRegistered){ + if (beforeSuiteMethods.size() == 1){ + newSuite.setBeforeSuiteMethod(beforeSuiteMethods.get(0).getMethod()); + } + if (afterSuiteMethods.size() == 1){ + newSuite.setAfterSuiteMethod(afterSuiteMethods.get(0).getMethod()); + } + + current = newSuite; + newSuite.setTargetObjectSuite(getTestClass().getJavaClass().newInstance()); + + } + + + // 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 + 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(method, testObject, current); + tests.add(performaceTestMethod); + } + } + + // add the new suite to the list of suites + suitesState.add(newSuite); + } + + // Retrieve the performance tests in the case we don't have a performance test suite + for (FrameworkMethod method: getTestClass().getAnnotatedMethods(PerformanceTest.class)) { + Object targetObject = getTestClass().getJavaClass().newInstance(); + FrameworkPerformanceMethod performaceTestMethod = new FrameworkPerformanceMethod(method.getMethod(), targetObject, current); + tests.add(performaceTestMethod); + } + + return tests; + } + + + /** + * Retrieve specific method from test class + * @param testClass the test class that we need to search in + * @param annotation the annotation that we should look for + * @return the list with the methods that have the specified annotation + */ + @SuppressWarnings({"rawtypes"}) + private Method[] getSpecificMethods(Class testClass, Class<? extends Annotation> annotation){ + Method[] allMethods = testClass.getDeclaredMethods(); + + List<Method> methodListResult = new ArrayList<Method>(); + + for(Method testMethod : allMethods){ + if (testMethod.isAnnotationPresent(annotation)){ + methodListResult.add(testMethod); + } + } + return methodListResult.toArray(new Method[]{}); + } + + /** + * {@inheritDoc} + * @see org.junit.runners.BlockJUnit4ClassRunner#computeTestMethods() + */ + @Override + protected List<FrameworkMethod> computeTestMethods() { + return tests; + } + + /** + * Need to override method otherwise the validation will fail because of some + * hardcoded conditions in JUnit + */ + @Override + protected void validateInstanceMethods(List<Throwable> errors) { + validatePublicVoidNoArgMethods(After.class, false, errors); + validatePublicVoidNoArgMethods(Before.class, false, errors); + validateTestMethods(errors); + } + + +} diff --git a/src/main/java/org/apache/sling/performance/PerformanceSuiteState.java b/src/main/java/org/apache/sling/performance/PerformanceSuiteState.java new file mode 100644 index 0000000..337cad0 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/PerformanceSuiteState.java @@ -0,0 +1,91 @@ +/* + * 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.sling.performance; + +import java.lang.reflect.Method; + +public class PerformanceSuiteState { + + public String testSuiteName = ParameterizedTestList.TEST_CASE_ONLY; + + private Method beforeSuiteMethod; + private Method afterSuiteMethod; + private int numberOfMethodsInSuite = 0; + private int numberOfExecutedMethods = 0; + private Object targetObjectSuite; + + public PerformanceSuiteState(String testSuiteName){ + this.testSuiteName = testSuiteName; + } + + public void incrementNumberOfTestMethodsInSuite(){ + numberOfMethodsInSuite++; + } + + public void incrementNumberOfExecutedTestMethods(){ + numberOfExecutedMethods++; + } + + public String getTestSuiteName() { + return testSuiteName; + } + + public void setTestSuiteName(String testSuiteName) { + this.testSuiteName = testSuiteName; + } + + public Method getBeforeSuiteMethod() { + return beforeSuiteMethod; + } + + public void setBeforeSuiteMethod(Method beforeSuiteMethod) { + this.beforeSuiteMethod = beforeSuiteMethod; + } + + public Method getAfterSuiteMethod() { + return afterSuiteMethod; + } + + public void setAfterSuiteMethod(Method afterSuiteMethod) { + this.afterSuiteMethod = afterSuiteMethod; + } + + public int getNumberOfMethodsInSuite() { + return numberOfMethodsInSuite; + } + + public void setNumberOfMethodsInSuite(int numberOfMethodsInSuite) { + this.numberOfMethodsInSuite = numberOfMethodsInSuite; + } + + public int getNumberOfExecutedMethods() { + return numberOfExecutedMethods; + } + + public void setNumberOfExecutedMethods(int numberOfExecutedMethods) { + this.numberOfExecutedMethods = numberOfExecutedMethods; + } + + public Object getTargetObjectSuite() { + return targetObjectSuite; + } + + public void setTargetObjectSuite(Object targetObjectSuite) { + this.targetObjectSuite = targetObjectSuite; + } + +} diff --git a/src/main/java/org/apache/sling/performance/ReportLogger.java b/src/main/java/org/apache/sling/performance/ReportLogger.java new file mode 100644 index 0000000..e0f24d2 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/ReportLogger.java @@ -0,0 +1,96 @@ +package org.apache.sling.performance; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.io.output.FileWriterWithEncoding; +import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; + +public class ReportLogger { + + public enum ReportType{ + TXT, XML + } + + + public static void writeReport(String test, String testSuiteName, String name, DescriptiveStatistics statistics, ReportType reportType) throws Exception{ + switch(reportType){ + case TXT: + writeReportTxt(test, testSuiteName, name, statistics); + break; + case XML: + throw new Exception("The XML reporting format is not yet supported"); + default: + throw new Exception("The specified reporting format is not yet supported"); + } + } + + /** + * Method the writes the performance report after a test is run + * @param test the test name + * @param name the name that will be listed in the report + * @param statistics the statistics data to be written + * @throws IOException + */ + public static void writeReportTxt(String test, String testSuiteName, String name, DescriptiveStatistics statistics) + throws IOException { + + String className=test; + className=className.substring(className.lastIndexOf(".")+1); + + File reportDir = new File("target/performance-reports"); + if (!reportDir.exists()){ + boolean test1 = reportDir.mkdir(); + } + + File report = new File("target/performance-reports", className + ".txt"); + + // need this in the case a user wants to set the suite name from the command line + // useful if we run the test cases from the command line for example + // by using maven + if (testSuiteName.equals(ParameterizedTestList.TEST_CASE_ONLY)){ + if (System.getenv("testsuitename") != null){ + testSuiteName = System.getenv("testsuitename"); + } + } + + boolean needsPrefix = !report.exists(); + PrintWriter writer = new PrintWriter( + new FileWriterWithEncoding(report, "UTF-8", true)); + try { + if (needsPrefix) { + writer.format( + "# %-34.34s min 10%% 50%% 90%% max%n", + className); + } + + writer.format( + "%-36.36s %6.0f %6.0f %6.0f %6.0f %6.0f%n", + testSuiteName, + statistics.getMin(), + statistics.getPercentile(10.0), + statistics.getPercentile(50.0), + statistics.getPercentile(90.0), + statistics.getMax()); + } finally { + writer.close(); + } + } + + + /** + * Get the date that will be written into the result file + * @return + */ + private static String getDate(){ + DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + Date date = new Date(); + + return dateFormat.format(date); + } + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/AfterMethodInvocation.java b/src/main/java/org/apache/sling/performance/annotation/AfterMethodInvocation.java new file mode 100644 index 0000000..00da352 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/AfterMethodInvocation.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface AfterMethodInvocation { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/AfterSpecificTest.java b/src/main/java/org/apache/sling/performance/annotation/AfterSpecificTest.java new file mode 100644 index 0000000..2020f8f --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/AfterSpecificTest.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface AfterSpecificTest { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/AfterSuite.java b/src/main/java/org/apache/sling/performance/annotation/AfterSuite.java new file mode 100644 index 0000000..0acdaa3 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/AfterSuite.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface AfterSuite { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/BeforeMethodInvocation.java b/src/main/java/org/apache/sling/performance/annotation/BeforeMethodInvocation.java new file mode 100644 index 0000000..725bb51 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/BeforeMethodInvocation.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface BeforeMethodInvocation { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/BeforeSpecificTest.java b/src/main/java/org/apache/sling/performance/annotation/BeforeSpecificTest.java new file mode 100644 index 0000000..d89307e --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/BeforeSpecificTest.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface BeforeSpecificTest { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/BeforeSuite.java b/src/main/java/org/apache/sling/performance/annotation/BeforeSuite.java new file mode 100644 index 0000000..6bbb112 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/BeforeSuite.java @@ -0,0 +1,25 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface BeforeSuite { + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/PerformanceTest.java b/src/main/java/org/apache/sling/performance/annotation/PerformanceTest.java new file mode 100644 index 0000000..3810234 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/PerformanceTest.java @@ -0,0 +1,47 @@ +/* + * 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.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +/** + * Performance test annotation to use for the framework to be able to find + * all the tests in the test class + * + */ +@Retention(RetentionPolicy.RUNTIME) +public @interface PerformanceTest { + + + // set the warmup time for the test + int warmuptime() default 1; + + // set the run time of the test + int runtime() default 5; + + // set the number of invocations to time + // by default the run time is used instead + int runinvocations() default 0; + + // set the number of invocations to run + // in the warm up phase + int warmupinvocations() default 0; + + +} diff --git a/src/main/java/org/apache/sling/performance/annotation/PerformanceTestSuite.java b/src/main/java/org/apache/sling/performance/annotation/PerformanceTestSuite.java new file mode 100644 index 0000000..54a1837 --- /dev/null +++ b/src/main/java/org/apache/sling/performance/annotation/PerformanceTestSuite.java @@ -0,0 +1,10 @@ +package org.apache.sling.performance.annotation; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + + +@Retention(RetentionPolicy.RUNTIME) +public @interface PerformanceTestSuite { + +} -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
