mirror of https://github.com/apache/cassandra
110 lines
3.6 KiB
Java
110 lines
3.6 KiB
Java
/*
|
|
* 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.cassandra;
|
|
|
|
import java.lang.annotation.ElementType;
|
|
import java.lang.annotation.Retention;
|
|
import java.lang.annotation.RetentionPolicy;
|
|
import java.lang.annotation.Target;
|
|
|
|
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
|
|
import org.junit.runner.Description;
|
|
import org.junit.runner.Runner;
|
|
import org.junit.runner.notification.RunNotifier;
|
|
import org.junit.runners.BlockJUnit4ClassRunner;
|
|
import org.junit.runners.model.RunnerBuilder;
|
|
|
|
/**
|
|
* This class comes useful when debugging flaky tests that will fail only when the full test suite is ran. It is
|
|
* intended for test failure investigation only.
|
|
* <p>
|
|
* Decorate your class with the runner and iterations you want. Defaults to 10.
|
|
* Beware of tests that change singleton status as those won't work.
|
|
* <pre>{@code
|
|
* @RunWith(RepeatableRunner.class)
|
|
* @RepeatableRunnerConfiguration(iterations = 2, runner = BlockJUnit4ClassRunner.class)
|
|
* public class MyTest
|
|
* {
|
|
* ...
|
|
* }
|
|
* }</pre>
|
|
*/
|
|
public class RepeatableRunner extends Runner
|
|
{
|
|
private static final int DEFAULT_REPETITIONS = 10;
|
|
private static final Class<? extends Runner> DEFAULT_RUNNER_CLASS = BlockJUnit4ClassRunner.class;
|
|
|
|
private final Runner runner;
|
|
private final int iterations;
|
|
|
|
public RepeatableRunner(Class<?> testClass) throws Throwable
|
|
{
|
|
Class<? extends Runner> runnerClass = DEFAULT_RUNNER_CLASS;
|
|
|
|
if (testClass.isAnnotationPresent(RepeatableRunnerConfiguration.class))
|
|
{
|
|
RepeatableRunnerConfiguration configuration = testClass.getAnnotation(RepeatableRunnerConfiguration.class);
|
|
iterations = configuration.iterations();
|
|
runnerClass = configuration.runner();
|
|
}
|
|
else
|
|
{
|
|
iterations = DEFAULT_REPETITIONS;
|
|
}
|
|
|
|
runner = buildRunner(runnerClass, testClass);
|
|
}
|
|
|
|
@Override
|
|
public Description getDescription()
|
|
{
|
|
return runner.getDescription();
|
|
}
|
|
|
|
@Override
|
|
public void run(RunNotifier notifier)
|
|
{
|
|
for (int i = 0; i < iterations; i++)
|
|
{
|
|
runner.run(notifier);
|
|
}
|
|
}
|
|
|
|
private static Runner buildRunner(Class<? extends Runner> runnerClass, Class<?> testClass) throws Throwable
|
|
{
|
|
try
|
|
{
|
|
return runnerClass.getConstructor(Class.class).newInstance(testClass);
|
|
}
|
|
catch (NoSuchMethodException e)
|
|
{
|
|
return runnerClass.getConstructor(Class.class, RunnerBuilder.class)
|
|
.newInstance(testClass, new AllDefaultPossibilitiesBuilder(true));
|
|
}
|
|
}
|
|
|
|
@Retention(RetentionPolicy.RUNTIME)
|
|
@Target(ElementType.TYPE)
|
|
public @interface RepeatableRunnerConfiguration
|
|
{
|
|
int iterations() default DEFAULT_REPETITIONS;
|
|
|
|
Class<? extends Runner> runner() default BlockJUnit4ClassRunner.class;
|
|
}
|
|
}
|