package com.oracle.mxtool.junit;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Description;
import org.junit.runner.Request;
import org.junit.runner.Runner;
import org.junit.runner.notification.Failure;
import org.junit.runners.Suite;
import org.junit.runners.model.InitializationError;
public final class MxJUnitRequest {
private final Request request;
final Set<Class<?>> classes;
final String methodName;
final List<Failure> missingClasses;
private MxJUnitRequest(Request request, Set<Class<?>> classes, String methodName, List<Failure> missingClasses) {
this.request = request;
this.classes = classes;
this.methodName = methodName;
this.missingClasses = missingClasses;
}
public Request getRequest() {
return request;
}
public List<Failure> getMissingClasses() {
return Collections.unmodifiableList(missingClasses);
}
public static final class BuilderException extends Exception {
private static final long serialVersionUID = 1L;
private BuilderException(String msg) {
super(msg);
}
}
public static class Builder extends AllDefaultPossibilitiesBuilder {
private final Set<Class<?>> classes = new LinkedHashSet<>();
private String methodName = null;
private final List<Failure> missingClasses = new ArrayList<>();
public Builder() {
super(true);
}
protected Class<?> resolveClass(String name) throws ClassNotFoundException {
return Class.forName(name, false, Builder.class.getClassLoader());
}
public void addTestSpec(String arg) throws BuilderException {
String className;
if (methodName != null) {
throw new BuilderException("Only a single class and method can be specified: " + arg);
} else if (arg.contains("#")) {
String[] pair = arg.split("#");
if (pair.length != 2) {
throw new BuilderException("Malformed class and method request: " + arg);
} else if (!classes.isEmpty()) {
throw new BuilderException("Only a single class and method can be specified: " + arg);
} else {
methodName = pair[1];
className = pair[0];
}
} else {
className = arg;
}
try {
Class<?> cls = resolveClass(className);
if ((cls.getModifiers() & Modifier.ABSTRACT) == 0) {
classes.add(cls);
}
} catch (ClassNotFoundException e) {
Description description = Description.createSuiteDescription(className);
Failure failure = new Failure(description, e);
missingClasses.add(failure);
}
}
private static List<Runner> filterRunners(List<Runner> runners) {
for (Runner runner : runners) {
if (runner instanceof ErrorReportingRunner) {
List<Runner> result = new ArrayList<>(runners);
result.removeIf((x) -> !(x instanceof ErrorReportingRunner));
List<Runner> tail = new ArrayList<>(runners);
tail.removeIf((x) -> x instanceof ErrorReportingRunner);
result.addAll(tail);
return result;
}
}
return runners;
}
@Override
public List<Runner> runners(Class<?> parent, List<Class<?>> children) throws InitializationError {
return filterRunners(super.runners(parent, children));
}
@Override
public List<Runner> runners(Class<?> parent, Class<?>[] children) throws InitializationError {
return filterRunners(super.runners(parent, children));
}
public MxJUnitRequest build() {
Request request;
if (methodName == null) {
try {
Runner suite = new Suite(this, classes.toArray(new Class<?>[0]));
request = Request.runner(suite);
} catch (InitializationError e) {
throw new RuntimeException(e);
}
} else {
request = Request.method(classes.iterator().next(), methodName);
}
return new MxJUnitRequest(request, classes, methodName, missingClasses);
}
}
}