Package org.apache.sling.performance

Source Code of org.apache.sling.performance.PerformanceRunner

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



public class PerformanceRunner extends BlockJUnit4ClassRunner {
  protected LinkedList<FrameworkMethod> tests = new LinkedList<FrameworkMethod>();
  private List<PerformanceSuiteState> suitesState = new ArrayList<PerformanceSuiteState>();
  public ReportLevel reportLevel = ReportLevel.ClassLevel;
 
  public static enum ReportLevel{
    ClassLevel,
    MethodLevel
  }
 
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public @interface Parameters {
    public ReportLevel reportLevel() default ReportLevel.ClassLevel;
  }
 
  public PerformanceRunner(Class<?> clazz) throws InitializationError {
    super(clazz);
   
    // set the report level for the tests that are run with the PerformanceRunner
    // by default set to class level for legacy tests compatibility
    if (clazz.getAnnotation(Parameters.class) != null){
      reportLevel = clazz.getAnnotation(Parameters.class).reportLevel();
    }
   
    try {
      computeTests();
    } catch (Exception e) {
      throw new InitializationError(e);
    }
  }

  /**
   * Compute the tests that will be run
   *
   * @throws Exception
   */
  protected void computeTests() throws Exception {
    // add normal JUnit tests
    tests.addAll(super.computeTestMethods());

    // add 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<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
    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);
        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 @PerformanceTestSuite 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 PerformanceSuite
    if (!testObjects.isEmpty()) {
      for (Object testObject : testObjects) {

        // retrieve the test methods from the test classes
        Method[] testMethods = getSpecificMethods(testObject.getClass(), PerformanceTest.class);

        for (Method method : testMethods) {
          FrameworkPerformanceMethod performaceTestMethod =
                            new FrameworkPerformanceMethod(method, testObject, current, reportLevel);
          tests.add(performaceTestMethod);
        }

                if (!suiteAlreadyRegistered) {
          newSuite.incrementNumberOfTestMethodsInSuite();
        }
      }

      // 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 performanceTestMethod = new FrameworkPerformanceMethod(
          method.getMethod(), targetObject, current, reportLevel);
      tests.add(performanceTestMethod);
    }

    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);
  }

}
TOP

Related Classes of org.apache.sling.performance.PerformanceRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.