package com.squareup.burst;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.TestClass;
import static com.squareup.burst.Util.checkNotNull;
import static java.util.Collections.unmodifiableList;
/**
* A suite associated with a particular test class. Its children are {@link BurstRunner}s, each
* representing a particular variation of that class.
*/
public final class BurstJUnit4 extends Suite {
public BurstJUnit4(Class<?> cls) throws InitializationError {
super(cls, explode(cls));
}
/*
* ParentRunner's default filter implementation generates a hierarchy of test descriptions,
* applies the filter to those descriptions, and removes any test nodes whose descriptions were
* all filtered out.
* <p>
* This would be problematic for us since we generate non-standard test descriptions which include
* parameter information. This implementation lets each {@link BurstRunner} child filter itself
* via {@link BurstRunner#filter(Filter)}.
*/
@Override public void filter(Filter filter) throws NoTestsRemainException {
List<Runner> filteredChildren = ParentRunnerSpy.getFilteredChildren(this);
// Iterate over a clone so that we can safely mutate the original.
for (Runner child : new ArrayList<>(filteredChildren)) {
try {
filter.apply(child);
} catch (NoTestsRemainException e) {
filteredChildren.remove(child);
}
}
if (filteredChildren.isEmpty()) {
throw new NoTestsRemainException();
}
}
static List<Runner> explode(Class<?> cls) throws InitializationError {
checkNotNull(cls, "cls");
TestClass testClass = new TestClass(cls);
List<FrameworkMethod> testMethods = testClass.getAnnotatedMethods(Test.class);
List<FrameworkMethod> burstMethods = new ArrayList<>(testMethods.size());
for (FrameworkMethod testMethod : testMethods) {
Method method = testMethod.getMethod();
for (Enum<?>[] methodArgs : Burst.explodeArguments(method)) {
burstMethods.add(new BurstMethod(method, methodArgs));
}
}
TestConstructor constructor = BurstableConstructor.findSingle(cls);
Enum<?>[][] constructorArgsList = Burst.explodeArguments(constructor);
List<Runner> burstRunners = new ArrayList<>(constructorArgsList.length);
for (Enum<?>[] constructorArgs : constructorArgsList) {
burstRunners.add(new BurstRunner(cls, constructor, constructorArgs, burstMethods));
}
return unmodifiableList(burstRunners);
}
static String nameWithArguments(String name, Enum<?>[] arguments) {
if (arguments.length == 0) {
return name;
}
return name + '[' + Burst.friendlyName(arguments) + ']';
}
}