You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:26:53 UTC

[sling-tooling-scm] 05/27: SLING-2593 - Improvement for the Sling performance tools. Adding patch provided from Christian Vazzolla. Thanks Christian!

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-tooling-scm.git

commit eb67a440c990e294c858ea91f2f84b36b7aa347d
Author: Antonio Sanso <as...@apache.org>
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
"commits@sling.apache.org" <co...@sling.apache.org>.