com.carrotsearch.junitbenchmarks.BenchmarkRule Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of junit-benchmarks Show documentation
Show all versions of junit-benchmarks Show documentation
A framework for writing performance micro-benchmarks using JUnit4 annotations, forked from https://github.com/carrotsearch/junit-benchmarks.
package com.carrotsearch.junitbenchmarks;
import java.lang.reflect.Field;
import org.junit.Rule;
import org.junit.internal.runners.statements.ExpectException;
import org.junit.internal.runners.statements.FailOnTimeout;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
/**
* A benchmark rule (causes tests to be repeated and measured). Benchmark rule should be
* placed in the test class as a field, with annotation. Example:
*
*
* {@link Rule}
* public {@link TestRule} runBenchmarks = new BenchmarkRule();
*
*/
public final class BenchmarkRule implements TestRule
{
private final IResultsConsumer [] consumers;
/**
* Creates a benchmark rule with the default sink for benchmark results (the default
* sink is taken from global properties).
*/
public BenchmarkRule()
{
this(BenchmarkOptionsSystemProperties.getDefaultConsumers());
}
/**
* Creates a benchmark rule with a given sink for benchmark results.
*/
public BenchmarkRule(IResultsConsumer... consumers)
{
if (consumers == null || consumers.length == 0)
throw new IllegalArgumentException("There needs to be at least one consumer.");
this.consumers = consumers;
}
/**
* Apply benchmarking to the given test description.
*/
@Override
public Statement apply(Statement base, Description description) {
try {
if (workAroundWrappedStatements(base, description)) {
return base;
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
return new BenchmarkStatement(base, description, consumers);
}
/**
* Works around a JUnit limitation regarding @Before and @After.
*
* When JUnit hands a {@link Statement} to the {@link BenchmarkRule}, it might
* not be the original statement, but rather a statement that is wrapped in
* statements ensuring that the methods annotated with @Before and/or
* @After are run. This method works around that by unwrapping the
* original statement, via reflection.
*
*
* @param statement the statement to benchmark, possibly wrapped
* @param description the description
* @return whether a workaround was necessary
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
private boolean workAroundWrappedStatements(Statement statement,
Description description) throws SecurityException, NoSuchFieldException,
IllegalArgumentException, IllegalAccessException
{
Field field = null;
Object object = null;
if (statement instanceof RunAfters) {
object = statement;
field = object.getClass().getDeclaredField("fNext");
field.setAccessible(true);
statement = (Statement) field.get(object);
}
if (statement instanceof RunBefores) {
object = statement;
field = object.getClass().getDeclaredField("fNext");
field.setAccessible(true);
statement = (Statement) field.get(object);
}
if (statement instanceof FailOnTimeout) {
object = statement;
field = object.getClass().getDeclaredField("fOriginalStatement");
field.setAccessible(true);
statement = (Statement) field.get(object);
}
if (statement instanceof ExpectException) {
object = statement;
field = object.getClass().getDeclaredField("fNext");
field.setAccessible(true);
statement = (Statement) field.get(object);
}
if (field == null) return false;
field.set(object, new BenchmarkStatement(statement, description, consumers));
return true;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy