Apply javafmt in sbt project

This commit is contained in:
Ethan Atkins 2020-01-14 14:19:42 -08:00
parent 813864ec0f
commit cf745255e8
18 changed files with 884 additions and 633 deletions

View File

@ -10,9 +10,13 @@ package xsbti;
import java.util.function.Supplier; import java.util.function.Supplier;
public interface Logger { public interface Logger {
void error(Supplier<String> msg); void error(Supplier<String> msg);
void warn(Supplier<String> msg);
void info(Supplier<String> msg); void warn(Supplier<String> msg);
void debug(Supplier<String> msg);
void trace(Supplier<Throwable> exception); void info(Supplier<String> msg);
void debug(Supplier<String> msg);
void trace(Supplier<Throwable> exception);
} }

View File

@ -10,24 +10,44 @@ package xsbti;
import java.io.File; import java.io.File;
import java.util.Optional; import java.util.Optional;
public interface Position public interface Position {
{ Optional<Integer> line();
Optional<Integer> line();
String lineContent();
Optional<Integer> offset();
// pointer to the column position of the error/warning String lineContent();
Optional<Integer> pointer();
Optional<String> pointerSpace();
Optional<String> sourcePath(); Optional<Integer> offset();
Optional<File> sourceFile();
// Default values to avoid breaking binary compatibility // pointer to the column position of the error/warning
default Optional<Integer> startOffset() { return Optional.empty(); } Optional<Integer> pointer();
default Optional<Integer> endOffset() { return Optional.empty(); }
default Optional<Integer> startLine() { return Optional.empty(); } Optional<String> pointerSpace();
default Optional<Integer> startColumn() { return Optional.empty(); }
default Optional<Integer> endLine() { return Optional.empty(); } Optional<String> sourcePath();
default Optional<Integer> endColumn() { return Optional.empty(); }
Optional<File> sourceFile();
// Default values to avoid breaking binary compatibility
default Optional<Integer> startOffset() {
return Optional.empty();
}
default Optional<Integer> endOffset() {
return Optional.empty();
}
default Optional<Integer> startLine() {
return Optional.empty();
}
default Optional<Integer> startColumn() {
return Optional.empty();
}
default Optional<Integer> endLine() {
return Optional.empty();
}
default Optional<Integer> endColumn() {
return Optional.empty();
}
} }

View File

@ -9,18 +9,21 @@ package xsbti;
import java.util.Optional; import java.util.Optional;
public interface Problem public interface Problem {
{ String category();
String category();
Severity severity(); Severity severity();
String message();
Position position(); String message();
Position position();
// Default value to avoid breaking binary compatibility // Default value to avoid breaking binary compatibility
/** /**
* If present, the string shown to the user when displaying this Problem. * If present, the string shown to the user when displaying this Problem. Otherwise, the Problem
* Otherwise, the Problem will be shown in an implementation-defined way * will be shown in an implementation-defined way based on the values of its other fields.
* based on the values of its other fields.
*/ */
default Optional<String> rendered() { return Optional.empty(); } default Optional<String> rendered() {
return Optional.empty();
}
} }

View File

@ -7,7 +7,8 @@
package xsbti; package xsbti;
public enum Severity public enum Severity {
{ Info,
Info, Warn, Error Warn,
} Error
}

View File

@ -8,8 +8,8 @@
package xsbti; package xsbti;
/** Used to pass a pair of values. */ /** Used to pass a pair of values. */
public interface T2<A1, A2> public interface T2<A1, A2> {
{
public A1 get1(); public A1 get1();
public A2 get2(); public A2 get2();
} }

View File

@ -13,26 +13,25 @@ import xsbti.Logger;
public class ScriptConfig { public class ScriptConfig {
private String label; private String label;
private File testDirectory; private File testDirectory;
private Logger logger; private Logger logger;
public ScriptConfig(String label, File testDirectory, Logger logger) { public ScriptConfig(String label, File testDirectory, Logger logger) {
this.label = label; this.label = label;
this.testDirectory = testDirectory; this.testDirectory = testDirectory;
this.logger = logger; this.logger = logger;
} }
public String label() { public String label() {
return this.label; return this.label;
} }
public File testDirectory() { public File testDirectory() {
return this.testDirectory; return this.testDirectory;
} }
public Logger logger() { public Logger logger() {
return this.logger; return this.logger;
} }
}
}

View File

@ -13,6 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class WrappedLoader extends URLClassLoader { public class WrappedLoader extends URLClassLoader {
private final AtomicBoolean invalidated = new AtomicBoolean(false); private final AtomicBoolean invalidated = new AtomicBoolean(false);
static { static {
ClassLoader.registerAsParallelCapable(); ClassLoader.registerAsParallelCapable();
} }

View File

@ -18,6 +18,7 @@ final case class Reboot(
app: xsbti.ApplicationID, app: xsbti.ApplicationID,
baseDirectory: File baseDirectory: File
) extends xsbti.Reboot { ) extends xsbti.Reboot {
System.err.println("AARGH " + app.classpathExtra.toSeq)
def arguments = argsList.toArray def arguments = argsList.toArray
} }
@ -30,6 +31,7 @@ final case class ApplicationID(
crossVersionedValue: xsbti.CrossValue, crossVersionedValue: xsbti.CrossValue,
extra: Seq[File] extra: Seq[File]
) extends xsbti.ApplicationID { ) extends xsbti.ApplicationID {
new Exception("make app id").printStackTrace(System.err)
def mainComponents = components.toArray def mainComponents = components.toArray
def classpathExtra = extra.toArray def classpathExtra = extra.toArray
def crossVersioned = crossVersionedValue != xsbti.CrossValue.Disabled def crossVersioned = crossVersionedValue != xsbti.CrossValue.Disabled

View File

@ -16,7 +16,8 @@ final class ClassLoadingLock {
private final ConcurrentHashMap<String, Object> locks = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String, Object> locks = new ConcurrentHashMap<>();
<R> R withLock(final String name, final ThrowsClassNotFound<R> supplier) throws ClassNotFoundException { <R> R withLock(final String name, final ThrowsClassNotFound<R> supplier)
throws ClassNotFoundException {
final Object newLock = new Object(); final Object newLock = new Object();
Object prevLock; Object prevLock;
synchronized (locks) { synchronized (locks) {

View File

@ -12,8 +12,13 @@ import java.net.URL;
import sbt.util.Logger; import sbt.util.Logger;
final class LayeredClassLoader extends ManagedClassLoader { final class LayeredClassLoader extends ManagedClassLoader {
LayeredClassLoader(final URL[] classpath, final ClassLoader parent, final File tempDir, final boolean close, final LayeredClassLoader(
boolean allowZombies, final Logger logger) { final URL[] classpath,
final ClassLoader parent,
final File tempDir,
final boolean close,
final boolean allowZombies,
final Logger logger) {
super(classpath, parent, close, allowZombies, logger); super(classpath, parent, close, allowZombies, logger);
setTempDir(tempDir); setTempDir(tempDir);
} }

View File

@ -30,7 +30,11 @@ abstract class ManagedClassLoader extends URLClassLoader implements NativeLoader
} }
ManagedClassLoader( ManagedClassLoader(
final URL[] urls, final ClassLoader parent, final boolean close, final boolean allowZombies, final Logger logger) { final URL[] urls,
final ClassLoader parent,
final boolean close,
final boolean allowZombies,
final Logger logger) {
super(urls, parent); super(urls, parent);
this.close = close; this.close = close;
this.allowZombies = allowZombies; this.allowZombies = allowZombies;

View File

@ -20,6 +20,7 @@ public final class MetaBuildLoader extends URLClassLoader {
private final URLClassLoader fullScalaLoader; private final URLClassLoader fullScalaLoader;
private final URLClassLoader libraryLoader; private final URLClassLoader libraryLoader;
private final URLClassLoader interfaceLoader; private final URLClassLoader interfaceLoader;
MetaBuildLoader( MetaBuildLoader(
final URL[] urls, final URL[] urls,
final URLClassLoader fullScalaLoader, final URLClassLoader fullScalaLoader,
@ -49,12 +50,12 @@ public final class MetaBuildLoader extends URLClassLoader {
} }
/** /**
* Rearrange the classloaders so that test-interface is above the scala library. Implemented * Rearrange the classloaders so that test-interface is above the scala library. Implemented
* without using the scala standard library to minimize classloading. * without using the scala standard library to minimize classloading.
* *
* @param appProvider the appProvider that needs to be modified * @param appProvider the appProvider that needs to be modified
* @return a ClassLoader with a URLClassLoader for the test-interface-1.0.jar above the * @return a ClassLoader with a URLClassLoader for the test-interface-1.0.jar above the scala
* scala library. * library.
*/ */
public static MetaBuildLoader makeLoader(final AppProvider appProvider) throws IOException { public static MetaBuildLoader makeLoader(final AppProvider appProvider) throws IOException {
final Pattern pattern = Pattern.compile("test-interface-[0-9.]+\\.jar"); final Pattern pattern = Pattern.compile("test-interface-[0-9.]+\\.jar");

View File

@ -25,7 +25,7 @@ final class ScalaLibraryClassLoader extends URLClassLoader {
@Override @Override
public String toString() { public String toString() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
for (int i = 0; i < jars.length; ++ i) { for (int i = 0; i < jars.length; ++i) {
builder.append(jars[i].toString()); builder.append(jars[i].toString());
if (i < jars.length - 2) builder.append(", "); if (i < jars.length - 2) builder.append(", ");
} }

View File

@ -10,19 +10,19 @@ package sbt;
import java.io.Serializable; import java.io.Serializable;
public final class ForkConfiguration implements Serializable { public final class ForkConfiguration implements Serializable {
private final boolean ansiCodesSupported; private final boolean ansiCodesSupported;
private final boolean parallel; private final boolean parallel;
public ForkConfiguration(final boolean ansiCodesSupported, final boolean parallel) { public ForkConfiguration(final boolean ansiCodesSupported, final boolean parallel) {
this.ansiCodesSupported = ansiCodesSupported; this.ansiCodesSupported = ansiCodesSupported;
this.parallel = parallel; this.parallel = parallel;
} }
public boolean isAnsiCodesSupported() { public boolean isAnsiCodesSupported() {
return ansiCodesSupported; return ansiCodesSupported;
} }
public boolean isParallel() { public boolean isParallel() {
return parallel; return parallel;
} }
} }

View File

@ -21,334 +21,480 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.*; import java.util.concurrent.*;
final public class ForkMain { public final class ForkMain {
// serializables // serializables
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
final static class SubclassFingerscan implements SubclassFingerprint, Serializable { static final class SubclassFingerscan implements SubclassFingerprint, Serializable {
private final boolean isModule; private final boolean isModule;
private final String superclassName; private final String superclassName;
private final boolean requireNoArgConstructor; private final boolean requireNoArgConstructor;
SubclassFingerscan(final SubclassFingerprint print) {
isModule = print.isModule();
superclassName = print.superclassName();
requireNoArgConstructor = print.requireNoArgConstructor();
}
public boolean isModule() { return isModule; }
public String superclassName() { return superclassName; }
public boolean requireNoArgConstructor() { return requireNoArgConstructor; }
}
final static class AnnotatedFingerscan implements AnnotatedFingerprint, Serializable { SubclassFingerscan(final SubclassFingerprint print) {
private final boolean isModule; isModule = print.isModule();
private final String annotationName; superclassName = print.superclassName();
AnnotatedFingerscan(final AnnotatedFingerprint print) { requireNoArgConstructor = print.requireNoArgConstructor();
isModule = print.isModule(); }
annotationName = print.annotationName();
}
public boolean isModule() { return isModule; }
public String annotationName() { return annotationName; }
}
final static class ForkEvent implements Event, Serializable { public boolean isModule() {
private final String fullyQualifiedName; return isModule;
private final Fingerprint fingerprint; }
private final Selector selector;
private final Status status;
private final OptionalThrowable throwable;
private final long duration;
ForkEvent(final Event e) { public String superclassName() {
fullyQualifiedName = e.fullyQualifiedName(); return superclassName;
final Fingerprint rawFingerprint = e.fingerprint(); }
if (rawFingerprint instanceof SubclassFingerprint) public boolean requireNoArgConstructor() {
fingerprint = new SubclassFingerscan((SubclassFingerprint) rawFingerprint); return requireNoArgConstructor;
else }
fingerprint = new AnnotatedFingerscan((AnnotatedFingerprint) rawFingerprint);
selector = e.selector();
checkSerializableSelector(selector);
status = e.status();
final OptionalThrowable originalThrowable = e.throwable();
if (originalThrowable.isDefined())
throwable = new OptionalThrowable(new ForkError(originalThrowable.get()));
else
throwable = originalThrowable;
duration = e.duration();
}
public String fullyQualifiedName() { return fullyQualifiedName; }
public Fingerprint fingerprint() { return fingerprint; }
public Selector selector() { return selector; }
public Status status() { return status; }
public OptionalThrowable throwable() { return throwable; }
public long duration() { return duration; }
private static void checkSerializableSelector(final Selector selector) {
if (! (selector instanceof Serializable)) {
throw new UnsupportedOperationException("Selector implementation must be Serializable, but " + selector.getClass().getName() + " is not.");
}
}
}
// -----------------------------------------------------------------------------
final static class ForkError extends Exception {
private final String originalMessage;
private final String originalName;
private ForkError cause;
ForkError(final Throwable t) {
originalMessage = t.getMessage();
originalName = t.getClass().getName();
setStackTrace(t.getStackTrace());
if (t.getCause() != null) cause = new ForkError(t.getCause());
}
public String getMessage() { return originalName + ": " + originalMessage; }
public Exception getCause() { return cause; }
}
// main
// ----------------------------------------------------------------------------------------------------------------
public static void main(final String[] args) throws Exception {
ClassLoader classLoader = new Run().getClass().getClassLoader();
try {
main(args, classLoader);
} finally {
System.exit(0);
}
} }
public static void main(final String[] args, ClassLoader classLoader) throws Exception { static final class AnnotatedFingerscan implements AnnotatedFingerprint, Serializable {
final Socket socket = new Socket(InetAddress.getByName(null), Integer.valueOf(args[0])); private final boolean isModule;
final ObjectInputStream is = new ObjectInputStream(socket.getInputStream()); private final String annotationName;
final ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
// Must flush the header that the constructor writes, otherwise the ObjectInputStream on the other end may block indefinitely
os.flush();
try {
new Run().run(is, os, classLoader);
} finally {
is.close();
os.close();
}
}
// ---------------------------------------------------------------------------------------------------------------- AnnotatedFingerscan(final AnnotatedFingerprint print) {
isModule = print.isModule();
annotationName = print.annotationName();
}
public boolean isModule() {
return isModule;
}
final private static class Run { public String annotationName() {
return annotationName;
}
}
private void run(final ObjectInputStream is, final ObjectOutputStream os, ClassLoader classLoader) { static final class ForkEvent implements Event, Serializable {
try { private final String fullyQualifiedName;
runTests(is, os, classLoader); private final Fingerprint fingerprint;
} catch (final RunAborted e) { private final Selector selector;
internalError(e); private final Status status;
} catch (final Throwable t) { private final OptionalThrowable throwable;
try { private final long duration;
logError(os, "Uncaught exception when running tests: " + t.toString());
write(os, new ForkError(t));
} catch (final Throwable t2) {
internalError(t2);
}
}
}
private boolean matches(final Fingerprint f1, final Fingerprint f2) { ForkEvent(final Event e) {
if (f1 instanceof SubclassFingerprint && f2 instanceof SubclassFingerprint) { fullyQualifiedName = e.fullyQualifiedName();
final SubclassFingerprint sf1 = (SubclassFingerprint) f1; final Fingerprint rawFingerprint = e.fingerprint();
final SubclassFingerprint sf2 = (SubclassFingerprint) f2;
return sf1.isModule() == sf2.isModule() && sf1.superclassName().equals(sf2.superclassName());
} else if (f1 instanceof AnnotatedFingerprint && f2 instanceof AnnotatedFingerprint) {
final AnnotatedFingerprint af1 = (AnnotatedFingerprint) f1;
final AnnotatedFingerprint af2 = (AnnotatedFingerprint) f2;
return af1.isModule() == af2.isModule() && af1.annotationName().equals(af2.annotationName());
}
return false;
}
class RunAborted extends RuntimeException { if (rawFingerprint instanceof SubclassFingerprint)
RunAborted(final Exception e) { super(e); } fingerprint = new SubclassFingerscan((SubclassFingerprint) rawFingerprint);
} else fingerprint = new AnnotatedFingerscan((AnnotatedFingerprint) rawFingerprint);
private synchronized void write(final ObjectOutputStream os, final Object obj) { selector = e.selector();
try { checkSerializableSelector(selector);
os.writeObject(obj); status = e.status();
os.flush(); final OptionalThrowable originalThrowable = e.throwable();
} catch (final IOException e) {
throw new RunAborted(e);
}
}
private void log(final ObjectOutputStream os, final String message, final ForkTags level) { if (originalThrowable.isDefined())
write(os, new Object[]{level, message}); throwable = new OptionalThrowable(new ForkError(originalThrowable.get()));
} else throwable = originalThrowable;
private void logDebug(final ObjectOutputStream os, final String message) { log(os, message, ForkTags.Debug); } duration = e.duration();
private void logInfo(final ObjectOutputStream os, final String message) { log(os, message, ForkTags.Info); } }
private void logWarn(final ObjectOutputStream os, final String message) { log(os, message, ForkTags.Warn); }
private void logError(final ObjectOutputStream os, final String message) { log(os, message, ForkTags.Error); }
private Logger remoteLogger(final boolean ansiCodesSupported, final ObjectOutputStream os) { public String fullyQualifiedName() {
return new Logger() { return fullyQualifiedName;
public boolean ansiCodesSupported() { return ansiCodesSupported; } }
public void error(final String s) { logError(os, s); }
public void warn(final String s) { logWarn(os, s); }
public void info(final String s) { logInfo(os, s); }
public void debug(final String s) { logDebug(os, s); }
public void trace(final Throwable t) { write(os, new ForkError(t)); }
};
}
private void writeEvents(final ObjectOutputStream os, final TaskDef taskDef, final ForkEvent[] events) { public Fingerprint fingerprint() {
write(os, new Object[]{taskDef.fullyQualifiedName(), events}); return fingerprint;
} }
private ExecutorService executorService(final ForkConfiguration config, final ObjectOutputStream os) { public Selector selector() {
if(config.isParallel()) { return selector;
final int nbThreads = Runtime.getRuntime().availableProcessors(); }
logDebug(os, "Create a test executor with a thread pool of " + nbThreads + " threads.");
// more options later...
// TODO we might want to configure the blocking queue with size #proc
return Executors.newFixedThreadPool(nbThreads);
} else {
logDebug(os, "Create a single-thread test executor");
return Executors.newSingleThreadExecutor();
}
}
private void runTests(final ObjectInputStream is, final ObjectOutputStream os, ClassLoader classLoader) throws Exception { public Status status() {
final ForkConfiguration config = (ForkConfiguration) is.readObject(); return status;
final ExecutorService executor = executorService(config, os); }
final TaskDef[] tests = (TaskDef[]) is.readObject();
final int nFrameworks = is.readInt();
final Logger[] loggers = { remoteLogger(config.isAnsiCodesSupported(), os) };
for (int i = 0; i < nFrameworks; i++) { public OptionalThrowable throwable() {
final String[] implClassNames = (String[]) is.readObject(); return throwable;
final String[] frameworkArgs = (String[]) is.readObject(); }
final String[] remoteFrameworkArgs = (String[]) is.readObject();
Framework framework = null; public long duration() {
for (final String implClassName : implClassNames) { return duration;
try { }
final Object rawFramework = Class.forName(implClassName).getDeclaredConstructor().newInstance();
if (rawFramework instanceof Framework)
framework = (Framework) rawFramework;
else
framework = new FrameworkWrapper((org.scalatools.testing.Framework) rawFramework);
break;
} catch (final ClassNotFoundException e) {
logDebug(os, "Framework implementation '" + implClassName + "' not present.");
}
}
if (framework == null) private static void checkSerializableSelector(final Selector selector) {
continue; if (!(selector instanceof Serializable)) {
throw new UnsupportedOperationException(
"Selector implementation must be Serializable, but "
+ selector.getClass().getName()
+ " is not.");
}
}
}
final ArrayList<TaskDef> filteredTests = new ArrayList<>(); // -----------------------------------------------------------------------------
for (final Fingerprint testFingerprint : framework.fingerprints()) {
for (final TaskDef test : tests) {
// TODO: To pass in correct explicitlySpecified and selectors
if (matches(testFingerprint, test.fingerprint()))
filteredTests.add(new TaskDef(test.fullyQualifiedName(), test.fingerprint(), test.explicitlySpecified(), test.selectors()));
}
}
final Runner runner = framework.runner(frameworkArgs, remoteFrameworkArgs, classLoader);
final Task[] tasks = runner.tasks(filteredTests.toArray(new TaskDef[filteredTests.size()]));
logDebug(os, "Runner for " + framework.getClass().getName() + " produced " + tasks.length + " initial tasks for " + filteredTests.size() + " tests.");
Thread callDoneOnShutdown = new Thread(() -> runner.done()); static final class ForkError extends Exception {
Runtime.getRuntime().addShutdownHook(callDoneOnShutdown); private final String originalMessage;
private final String originalName;
private ForkError cause;
runTestTasks(executor, tasks, loggers, os); ForkError(final Throwable t) {
originalMessage = t.getMessage();
originalName = t.getClass().getName();
setStackTrace(t.getStackTrace());
if (t.getCause() != null) cause = new ForkError(t.getCause());
}
runner.done(); public String getMessage() {
return originalName + ": " + originalMessage;
}
Runtime.getRuntime().removeShutdownHook(callDoneOnShutdown); public Exception getCause() {
} return cause;
write(os, ForkTags.Done); }
is.readObject(); }
}
private void runTestTasks(final ExecutorService executor, final Task[] tasks, final Logger[] loggers, final ObjectOutputStream os) { // main
if( tasks.length > 0 ) { // ----------------------------------------------------------------------------------------------------------------
final List<Future<Task[]>> futureNestedTasks = new ArrayList<>();
for( final Task task : tasks ) {
futureNestedTasks.add(runTest(executor, task, loggers, os));
}
// Note: this could be optimized further, we could have a callback once a test finishes that executes immediately the nested tasks public static void main(final String[] args) throws Exception {
// At the moment, I'm especially interested in JUnit, which doesn't have nested tasks. ClassLoader classLoader = new Run().getClass().getClassLoader();
final List<Task> nestedTasks = new ArrayList<>(); try {
for( final Future<Task[]> futureNestedTask : futureNestedTasks ) { main(args, classLoader);
try { } finally {
nestedTasks.addAll( Arrays.asList(futureNestedTask.get())); System.exit(0);
} catch (final Exception e) { }
logError(os, "Failed to execute task " + futureNestedTask); }
}
}
runTestTasks(executor, nestedTasks.toArray(new Task[nestedTasks.size()]), loggers, os);
}
}
private Future<Task[]> runTest(final ExecutorService executor, final Task task, final Logger[] loggers, final ObjectOutputStream os) { public static void main(final String[] args, ClassLoader classLoader) throws Exception {
return executor.submit(() -> { final Socket socket = new Socket(InetAddress.getByName(null), Integer.valueOf(args[0]));
ForkEvent[] events; final ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
Task[] nestedTasks; final ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream());
final TaskDef taskDef = task.taskDef(); // Must flush the header that the constructor writes, otherwise the ObjectInputStream on the
try { // other end may block indefinitely
final Collection<ForkEvent> eventList = new ConcurrentLinkedDeque<>(); os.flush();
final EventHandler handler = new EventHandler() { public void handle(final Event e){ eventList.add(new ForkEvent(e)); } }; try {
logDebug(os, " Running " + taskDef); new Run().run(is, os, classLoader);
nestedTasks = task.execute(handler, loggers); } finally {
if(nestedTasks.length > 0 || eventList.size() > 0) is.close();
logDebug(os, " Produced " + nestedTasks.length + " nested tasks and " + eventList.size() + " events."); os.close();
events = eventList.toArray(new ForkEvent[eventList.size()]); }
} }
catch (final Throwable t) {
nestedTasks = new Task[0];
events = new ForkEvent[] { testError(os, taskDef, "Uncaught exception when running " + taskDef.fullyQualifiedName() + ": " + t.toString(), t) };
}
writeEvents(os, taskDef, events);
return nestedTasks;
});
}
private void internalError(final Throwable t) { // ----------------------------------------------------------------------------------------------------------------
System.err.println("Internal error when running tests: " + t.toString());
}
private ForkEvent testEvent(final String fullyQualifiedName, final Fingerprint fingerprint, final Selector selector, final Status r, final ForkError err, final long duration) { private static final class Run {
final OptionalThrowable throwable;
if (err == null)
throwable = new OptionalThrowable();
else
throwable = new OptionalThrowable(err);
return new ForkEvent(new Event() {
public String fullyQualifiedName() { return fullyQualifiedName; }
public Fingerprint fingerprint() { return fingerprint; }
public Selector selector() { return selector; }
public Status status() { return r; }
public OptionalThrowable throwable() {
return throwable;
}
public long duration() {
return duration;
}
});
}
private ForkEvent testError(final ObjectOutputStream os, final TaskDef taskDef, final String message, final Throwable t) { private void run(
logError(os, message); final ObjectInputStream is, final ObjectOutputStream os, ClassLoader classLoader) {
final ForkError fe = new ForkError(t); try {
write(os, fe); runTests(is, os, classLoader);
return testEvent(taskDef.fullyQualifiedName(), taskDef.fingerprint(), new SuiteSelector(), Status.Error, fe, 0); } catch (final RunAborted e) {
} internalError(e);
} } catch (final Throwable t) {
try {
logError(os, "Uncaught exception when running tests: " + t.toString());
write(os, new ForkError(t));
} catch (final Throwable t2) {
internalError(t2);
}
}
}
private boolean matches(final Fingerprint f1, final Fingerprint f2) {
if (f1 instanceof SubclassFingerprint && f2 instanceof SubclassFingerprint) {
final SubclassFingerprint sf1 = (SubclassFingerprint) f1;
final SubclassFingerprint sf2 = (SubclassFingerprint) f2;
return sf1.isModule() == sf2.isModule()
&& sf1.superclassName().equals(sf2.superclassName());
} else if (f1 instanceof AnnotatedFingerprint && f2 instanceof AnnotatedFingerprint) {
final AnnotatedFingerprint af1 = (AnnotatedFingerprint) f1;
final AnnotatedFingerprint af2 = (AnnotatedFingerprint) f2;
return af1.isModule() == af2.isModule()
&& af1.annotationName().equals(af2.annotationName());
}
return false;
}
class RunAborted extends RuntimeException {
RunAborted(final Exception e) {
super(e);
}
}
private synchronized void write(final ObjectOutputStream os, final Object obj) {
try {
os.writeObject(obj);
os.flush();
} catch (final IOException e) {
throw new RunAborted(e);
}
}
private void log(final ObjectOutputStream os, final String message, final ForkTags level) {
write(os, new Object[] {level, message});
}
private void logDebug(final ObjectOutputStream os, final String message) {
log(os, message, ForkTags.Debug);
}
private void logInfo(final ObjectOutputStream os, final String message) {
log(os, message, ForkTags.Info);
}
private void logWarn(final ObjectOutputStream os, final String message) {
log(os, message, ForkTags.Warn);
}
private void logError(final ObjectOutputStream os, final String message) {
log(os, message, ForkTags.Error);
}
private Logger remoteLogger(final boolean ansiCodesSupported, final ObjectOutputStream os) {
return new Logger() {
public boolean ansiCodesSupported() {
return ansiCodesSupported;
}
public void error(final String s) {
logError(os, s);
}
public void warn(final String s) {
logWarn(os, s);
}
public void info(final String s) {
logInfo(os, s);
}
public void debug(final String s) {
logDebug(os, s);
}
public void trace(final Throwable t) {
write(os, new ForkError(t));
}
};
}
private void writeEvents(
final ObjectOutputStream os, final TaskDef taskDef, final ForkEvent[] events) {
write(os, new Object[] {taskDef.fullyQualifiedName(), events});
}
private ExecutorService executorService(
final ForkConfiguration config, final ObjectOutputStream os) {
if (config.isParallel()) {
final int nbThreads = Runtime.getRuntime().availableProcessors();
logDebug(os, "Create a test executor with a thread pool of " + nbThreads + " threads.");
// more options later...
// TODO we might want to configure the blocking queue with size #proc
return Executors.newFixedThreadPool(nbThreads);
} else {
logDebug(os, "Create a single-thread test executor");
return Executors.newSingleThreadExecutor();
}
}
private void runTests(
final ObjectInputStream is, final ObjectOutputStream os, ClassLoader classLoader)
throws Exception {
final ForkConfiguration config = (ForkConfiguration) is.readObject();
final ExecutorService executor = executorService(config, os);
final TaskDef[] tests = (TaskDef[]) is.readObject();
final int nFrameworks = is.readInt();
final Logger[] loggers = {remoteLogger(config.isAnsiCodesSupported(), os)};
for (int i = 0; i < nFrameworks; i++) {
final String[] implClassNames = (String[]) is.readObject();
final String[] frameworkArgs = (String[]) is.readObject();
final String[] remoteFrameworkArgs = (String[]) is.readObject();
Framework framework = null;
for (final String implClassName : implClassNames) {
try {
final Object rawFramework =
Class.forName(implClassName).getDeclaredConstructor().newInstance();
if (rawFramework instanceof Framework) framework = (Framework) rawFramework;
else framework = new FrameworkWrapper((org.scalatools.testing.Framework) rawFramework);
break;
} catch (final ClassNotFoundException e) {
logDebug(os, "Framework implementation '" + implClassName + "' not present.");
}
}
if (framework == null) continue;
final ArrayList<TaskDef> filteredTests = new ArrayList<>();
for (final Fingerprint testFingerprint : framework.fingerprints()) {
for (final TaskDef test : tests) {
// TODO: To pass in correct explicitlySpecified and selectors
if (matches(testFingerprint, test.fingerprint()))
filteredTests.add(
new TaskDef(
test.fullyQualifiedName(),
test.fingerprint(),
test.explicitlySpecified(),
test.selectors()));
}
}
final Runner runner = framework.runner(frameworkArgs, remoteFrameworkArgs, classLoader);
final Task[] tasks = runner.tasks(filteredTests.toArray(new TaskDef[filteredTests.size()]));
logDebug(
os,
"Runner for "
+ framework.getClass().getName()
+ " produced "
+ tasks.length
+ " initial tasks for "
+ filteredTests.size()
+ " tests.");
Thread callDoneOnShutdown = new Thread(() -> runner.done());
Runtime.getRuntime().addShutdownHook(callDoneOnShutdown);
runTestTasks(executor, tasks, loggers, os);
runner.done();
Runtime.getRuntime().removeShutdownHook(callDoneOnShutdown);
}
write(os, ForkTags.Done);
is.readObject();
}
private void runTestTasks(
final ExecutorService executor,
final Task[] tasks,
final Logger[] loggers,
final ObjectOutputStream os) {
if (tasks.length > 0) {
final List<Future<Task[]>> futureNestedTasks = new ArrayList<>();
for (final Task task : tasks) {
futureNestedTasks.add(runTest(executor, task, loggers, os));
}
// Note: this could be optimized further, we could have a callback once a test finishes that
// executes immediately the nested tasks
// At the moment, I'm especially interested in JUnit, which doesn't have nested tasks.
final List<Task> nestedTasks = new ArrayList<>();
for (final Future<Task[]> futureNestedTask : futureNestedTasks) {
try {
nestedTasks.addAll(Arrays.asList(futureNestedTask.get()));
} catch (final Exception e) {
logError(os, "Failed to execute task " + futureNestedTask);
}
}
runTestTasks(executor, nestedTasks.toArray(new Task[nestedTasks.size()]), loggers, os);
}
}
private Future<Task[]> runTest(
final ExecutorService executor,
final Task task,
final Logger[] loggers,
final ObjectOutputStream os) {
return executor.submit(
() -> {
ForkEvent[] events;
Task[] nestedTasks;
final TaskDef taskDef = task.taskDef();
try {
final Collection<ForkEvent> eventList = new ConcurrentLinkedDeque<>();
final EventHandler handler =
new EventHandler() {
public void handle(final Event e) {
eventList.add(new ForkEvent(e));
}
};
logDebug(os, " Running " + taskDef);
nestedTasks = task.execute(handler, loggers);
if (nestedTasks.length > 0 || eventList.size() > 0)
logDebug(
os,
" Produced "
+ nestedTasks.length
+ " nested tasks and "
+ eventList.size()
+ " events.");
events = eventList.toArray(new ForkEvent[eventList.size()]);
} catch (final Throwable t) {
nestedTasks = new Task[0];
events =
new ForkEvent[] {
testError(
os,
taskDef,
"Uncaught exception when running "
+ taskDef.fullyQualifiedName()
+ ": "
+ t.toString(),
t)
};
}
writeEvents(os, taskDef, events);
return nestedTasks;
});
}
private void internalError(final Throwable t) {
System.err.println("Internal error when running tests: " + t.toString());
}
private ForkEvent testEvent(
final String fullyQualifiedName,
final Fingerprint fingerprint,
final Selector selector,
final Status r,
final ForkError err,
final long duration) {
final OptionalThrowable throwable;
if (err == null) throwable = new OptionalThrowable();
else throwable = new OptionalThrowable(err);
return new ForkEvent(
new Event() {
public String fullyQualifiedName() {
return fullyQualifiedName;
}
public Fingerprint fingerprint() {
return fingerprint;
}
public Selector selector() {
return selector;
}
public Status status() {
return r;
}
public OptionalThrowable throwable() {
return throwable;
}
public long duration() {
return duration;
}
});
}
private ForkEvent testError(
final ObjectOutputStream os,
final TaskDef taskDef,
final String message,
final Throwable t) {
logError(os, message);
final ForkError fe = new ForkError(t);
write(os, fe);
return testEvent(
taskDef.fullyQualifiedName(),
taskDef.fingerprint(),
new SuiteSelector(),
Status.Error,
fe,
0);
}
}
} }

View File

@ -8,5 +8,9 @@
package sbt; package sbt;
public enum ForkTags { public enum ForkTags {
Error, Warn, Info, Debug, Done Error,
Warn,
Info,
Debug,
Done
} }

View File

@ -10,259 +10,318 @@ package sbt;
import sbt.testing.*; import sbt.testing.*;
/** /**
* Adapts the old {@link org.scalatools.testing.Framework} interface into the new * Adapts the old {@link org.scalatools.testing.Framework} interface into the new {@link
* {@link sbt.testing.Framework} * sbt.testing.Framework}
*/ */
final class FrameworkWrapper implements Framework { final class FrameworkWrapper implements Framework {
private final org.scalatools.testing.Framework oldFramework; private final org.scalatools.testing.Framework oldFramework;
FrameworkWrapper(final org.scalatools.testing.Framework oldFramework) { FrameworkWrapper(final org.scalatools.testing.Framework oldFramework) {
this.oldFramework = oldFramework; this.oldFramework = oldFramework;
} }
public String name() { public String name() {
return oldFramework.name(); return oldFramework.name();
} }
public Fingerprint[] fingerprints() { public Fingerprint[] fingerprints() {
final org.scalatools.testing.Fingerprint[] oldFingerprints = oldFramework.tests(); final org.scalatools.testing.Fingerprint[] oldFingerprints = oldFramework.tests();
final int length = oldFingerprints.length; final int length = oldFingerprints.length;
final Fingerprint[] fingerprints = new Fingerprint[length]; final Fingerprint[] fingerprints = new Fingerprint[length];
for (int i=0; i < length; i++) { for (int i = 0; i < length; i++) {
final org.scalatools.testing.Fingerprint oldFingerprint = oldFingerprints[i]; final org.scalatools.testing.Fingerprint oldFingerprint = oldFingerprints[i];
if (oldFingerprint instanceof org.scalatools.testing.TestFingerprint) if (oldFingerprint instanceof org.scalatools.testing.TestFingerprint)
fingerprints[i] = new SubclassFingerprintWrapper((org.scalatools.testing.TestFingerprint) oldFingerprint); fingerprints[i] =
else if (oldFingerprint instanceof org.scalatools.testing.SubclassFingerprint) new SubclassFingerprintWrapper((org.scalatools.testing.TestFingerprint) oldFingerprint);
fingerprints[i] = new SubclassFingerprintWrapper((org.scalatools.testing.SubclassFingerprint) oldFingerprint); else if (oldFingerprint instanceof org.scalatools.testing.SubclassFingerprint)
else fingerprints[i] =
fingerprints[i] = new AnnotatedFingerprintWrapper((org.scalatools.testing.AnnotatedFingerprint) oldFingerprint); new SubclassFingerprintWrapper(
} (org.scalatools.testing.SubclassFingerprint) oldFingerprint);
return fingerprints; else
} fingerprints[i] =
new AnnotatedFingerprintWrapper(
(org.scalatools.testing.AnnotatedFingerprint) oldFingerprint);
}
return fingerprints;
}
public Runner runner(final String[] args, final String[] remoteArgs, final ClassLoader testClassLoader) { public Runner runner(
return new RunnerWrapper(oldFramework, testClassLoader, args); final String[] args, final String[] remoteArgs, final ClassLoader testClassLoader) {
} return new RunnerWrapper(oldFramework, testClassLoader, args);
}
} }
final class SubclassFingerprintWrapper implements SubclassFingerprint { final class SubclassFingerprintWrapper implements SubclassFingerprint {
private final String superclassName; private final String superclassName;
private final boolean isModule; private final boolean isModule;
private final boolean requireNoArgConstructor; private final boolean requireNoArgConstructor;
SubclassFingerprintWrapper(final org.scalatools.testing.SubclassFingerprint oldFingerprint) { SubclassFingerprintWrapper(final org.scalatools.testing.SubclassFingerprint oldFingerprint) {
superclassName = oldFingerprint.superClassName(); superclassName = oldFingerprint.superClassName();
isModule = oldFingerprint.isModule(); isModule = oldFingerprint.isModule();
requireNoArgConstructor = false; // Old framework SubclassFingerprint does not require no arg constructor requireNoArgConstructor =
} false; // Old framework SubclassFingerprint does not require no arg constructor
}
public boolean isModule() { public boolean isModule() {
return isModule; return isModule;
} }
public String superclassName() { public String superclassName() {
return superclassName; return superclassName;
} }
public boolean requireNoArgConstructor() { public boolean requireNoArgConstructor() {
return requireNoArgConstructor; return requireNoArgConstructor;
} }
} }
final class AnnotatedFingerprintWrapper implements AnnotatedFingerprint { final class AnnotatedFingerprintWrapper implements AnnotatedFingerprint {
private final String annotationName; private final String annotationName;
private final boolean isModule; private final boolean isModule;
AnnotatedFingerprintWrapper(final org.scalatools.testing.AnnotatedFingerprint oldFingerprint) { AnnotatedFingerprintWrapper(final org.scalatools.testing.AnnotatedFingerprint oldFingerprint) {
annotationName = oldFingerprint.annotationName(); annotationName = oldFingerprint.annotationName();
isModule = oldFingerprint.isModule(); isModule = oldFingerprint.isModule();
} }
public boolean isModule() { public boolean isModule() {
return isModule; return isModule;
} }
public String annotationName() { public String annotationName() {
return annotationName; return annotationName;
} }
} }
final class EventHandlerWrapper implements org.scalatools.testing.EventHandler { final class EventHandlerWrapper implements org.scalatools.testing.EventHandler {
private final EventHandler newEventHandler; private final EventHandler newEventHandler;
private final String fullyQualifiedName; private final String fullyQualifiedName;
private final Fingerprint fingerprint; private final Fingerprint fingerprint;
EventHandlerWrapper(final EventHandler newEventHandler, final String fullyQualifiedName, final Fingerprint fingerprint) { EventHandlerWrapper(
this.newEventHandler = newEventHandler; final EventHandler newEventHandler,
this.fullyQualifiedName = fullyQualifiedName; final String fullyQualifiedName,
this.fingerprint = fingerprint; final Fingerprint fingerprint) {
} this.newEventHandler = newEventHandler;
this.fullyQualifiedName = fullyQualifiedName;
this.fingerprint = fingerprint;
}
public void handle(final org.scalatools.testing.Event oldEvent) { public void handle(final org.scalatools.testing.Event oldEvent) {
newEventHandler.handle(new EventWrapper(oldEvent, fullyQualifiedName, fingerprint)); newEventHandler.handle(new EventWrapper(oldEvent, fullyQualifiedName, fingerprint));
} }
} }
final class EventWrapper implements Event { final class EventWrapper implements Event {
private final org.scalatools.testing.Event oldEvent; private final org.scalatools.testing.Event oldEvent;
private final String className; private final String className;
private final Fingerprint fingerprint; private final Fingerprint fingerprint;
private final OptionalThrowable throwable; private final OptionalThrowable throwable;
EventWrapper(final org.scalatools.testing.Event oldEvent, final String className, final Fingerprint fingerprint) { EventWrapper(
this.oldEvent = oldEvent; final org.scalatools.testing.Event oldEvent,
this.className = className; final String className,
this.fingerprint = fingerprint; final Fingerprint fingerprint) {
final Throwable oldThrowable = oldEvent.error(); this.oldEvent = oldEvent;
if (oldThrowable == null) this.className = className;
throwable = new OptionalThrowable(); this.fingerprint = fingerprint;
else final Throwable oldThrowable = oldEvent.error();
throwable = new OptionalThrowable(oldThrowable); if (oldThrowable == null) throwable = new OptionalThrowable();
} else throwable = new OptionalThrowable(oldThrowable);
}
public String fullyQualifiedName() { public String fullyQualifiedName() {
return className; return className;
} }
public Fingerprint fingerprint() { public Fingerprint fingerprint() {
return fingerprint; return fingerprint;
} }
public Selector selector() { public Selector selector() {
return new TestSelector(oldEvent.testName()); return new TestSelector(oldEvent.testName());
} }
public Status status() { public Status status() {
switch (oldEvent.result()) { switch (oldEvent.result()) {
case Success: case Success:
return Status.Success; return Status.Success;
case Error: case Error:
return Status.Error; return Status.Error;
case Failure: case Failure:
return Status.Failure; return Status.Failure;
case Skipped: case Skipped:
return Status.Skipped; return Status.Skipped;
default: default:
throw new IllegalStateException("Invalid status."); throw new IllegalStateException("Invalid status.");
} }
} }
public OptionalThrowable throwable() { public OptionalThrowable throwable() {
return throwable; return throwable;
} }
public long duration() { public long duration() {
return -1; // Just return -1 as old event does not have duration. return -1; // Just return -1 as old event does not have duration.
} }
} }
final class RunnerWrapper implements Runner { final class RunnerWrapper implements Runner {
private final org.scalatools.testing.Framework oldFramework; private final org.scalatools.testing.Framework oldFramework;
private final ClassLoader testClassLoader; private final ClassLoader testClassLoader;
private final String[] args; private final String[] args;
RunnerWrapper(final org.scalatools.testing.Framework oldFramework, final ClassLoader testClassLoader, final String[] args) { RunnerWrapper(
this.oldFramework = oldFramework; final org.scalatools.testing.Framework oldFramework,
this.testClassLoader = testClassLoader; final ClassLoader testClassLoader,
this.args = args; final String[] args) {
} this.oldFramework = oldFramework;
this.testClassLoader = testClassLoader;
this.args = args;
}
public Task[] tasks(final TaskDef[] taskDefs) { public Task[] tasks(final TaskDef[] taskDefs) {
final int length = taskDefs.length; final int length = taskDefs.length;
final Task[] tasks = new Task[length]; final Task[] tasks = new Task[length];
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
final TaskDef taskDef = taskDefs[i]; final TaskDef taskDef = taskDefs[i];
tasks[i] = createTask(taskDef); tasks[i] = createTask(taskDef);
} }
return tasks; return tasks;
} }
private Task createTask(final TaskDef taskDef) { private Task createTask(final TaskDef taskDef) {
return new Task() { return new Task() {
public String[] tags() { public String[] tags() {
return new String[0]; // Old framework does not support tags return new String[0]; // Old framework does not support tags
} }
private org.scalatools.testing.Logger createOldLogger(final Logger logger) { private org.scalatools.testing.Logger createOldLogger(final Logger logger) {
return new org.scalatools.testing.Logger() { return new org.scalatools.testing.Logger() {
public boolean ansiCodesSupported() { return logger.ansiCodesSupported(); } public boolean ansiCodesSupported() {
public void error(final String msg) { logger.error(msg); } return logger.ansiCodesSupported();
public void warn(final String msg) { logger.warn(msg); } }
public void info(final String msg) { logger.info(msg); }
public void debug(final String msg) { logger.debug(msg); }
public void trace(final Throwable t) { logger.trace(t); }
};
}
private void runRunner(final org.scalatools.testing.Runner runner, final Fingerprint fingerprint, final EventHandler eventHandler) { public void error(final String msg) {
// Old runner only support subclass fingerprint. logger.error(msg);
final SubclassFingerprint subclassFingerprint = (SubclassFingerprint) fingerprint; }
final org.scalatools.testing.TestFingerprint oldFingerprint =
new org.scalatools.testing.TestFingerprint() {
public boolean isModule() { return subclassFingerprint.isModule(); }
public String superClassName() { return subclassFingerprint.superclassName(); }
};
final String name = taskDef.fullyQualifiedName();
runner.run(name, oldFingerprint, new EventHandlerWrapper(eventHandler, name, subclassFingerprint), args);
}
private void runRunner2(final org.scalatools.testing.Runner2 runner, final Fingerprint fingerprint, final EventHandler eventHandler) { public void warn(final String msg) {
final org.scalatools.testing.Fingerprint oldFingerprint; logger.warn(msg);
if (fingerprint instanceof SubclassFingerprint) { }
final SubclassFingerprint subclassFingerprint = (SubclassFingerprint) fingerprint;
oldFingerprint = new org.scalatools.testing.SubclassFingerprint() {
public boolean isModule() { return subclassFingerprint.isModule(); }
public String superClassName() { return subclassFingerprint.superclassName(); }
};
}
else {
final AnnotatedFingerprint annotatedFingerprint = (AnnotatedFingerprint) fingerprint;
oldFingerprint = new org.scalatools.testing.AnnotatedFingerprint() {
public boolean isModule() { return annotatedFingerprint.isModule(); }
public String annotationName() { return annotatedFingerprint.annotationName(); }
};
}
final String name = taskDef.fullyQualifiedName();
runner.run(name, oldFingerprint, new EventHandlerWrapper(eventHandler, name, fingerprint), args);
}
public Task[] execute(final EventHandler eventHandler, final Logger[] loggers) { public void info(final String msg) {
final int length = loggers.length; logger.info(msg);
final org.scalatools.testing.Logger[] oldLoggers = new org.scalatools.testing.Logger[length]; }
for (int i=0; i<length; i++) {
oldLoggers[i] = createOldLogger(loggers[i]);
}
final org.scalatools.testing.Runner runner = oldFramework.testRunner(testClassLoader, oldLoggers); public void debug(final String msg) {
final Fingerprint fingerprint = taskDef.fingerprint(); logger.debug(msg);
if (runner instanceof org.scalatools.testing.Runner2) { }
runRunner2((org.scalatools.testing.Runner2) runner, fingerprint, eventHandler);
}
else {
runRunner(runner, fingerprint, eventHandler);
}
return new Task[0];
}
public TaskDef taskDef() { public void trace(final Throwable t) {
return taskDef; logger.trace(t);
} }
}; };
} }
public String done() { private void runRunner(
return ""; final org.scalatools.testing.Runner runner,
} final Fingerprint fingerprint,
final EventHandler eventHandler) {
// Old runner only support subclass fingerprint.
final SubclassFingerprint subclassFingerprint = (SubclassFingerprint) fingerprint;
final org.scalatools.testing.TestFingerprint oldFingerprint =
new org.scalatools.testing.TestFingerprint() {
public boolean isModule() {
return subclassFingerprint.isModule();
}
public String[] args() { public String superClassName() {
return args; return subclassFingerprint.superclassName();
} }
};
final String name = taskDef.fullyQualifiedName();
runner.run(
name,
oldFingerprint,
new EventHandlerWrapper(eventHandler, name, subclassFingerprint),
args);
}
public String[] remoteArgs() { private void runRunner2(
return new String[0]; // Old framework does not support remoteArgs final org.scalatools.testing.Runner2 runner,
} final Fingerprint fingerprint,
final EventHandler eventHandler) {
final org.scalatools.testing.Fingerprint oldFingerprint;
if (fingerprint instanceof SubclassFingerprint) {
final SubclassFingerprint subclassFingerprint = (SubclassFingerprint) fingerprint;
oldFingerprint =
new org.scalatools.testing.SubclassFingerprint() {
public boolean isModule() {
return subclassFingerprint.isModule();
}
public String superClassName() {
return subclassFingerprint.superclassName();
}
};
} else {
final AnnotatedFingerprint annotatedFingerprint = (AnnotatedFingerprint) fingerprint;
oldFingerprint =
new org.scalatools.testing.AnnotatedFingerprint() {
public boolean isModule() {
return annotatedFingerprint.isModule();
}
public String annotationName() {
return annotatedFingerprint.annotationName();
}
};
}
final String name = taskDef.fullyQualifiedName();
runner.run(
name, oldFingerprint, new EventHandlerWrapper(eventHandler, name, fingerprint), args);
}
public Task[] execute(final EventHandler eventHandler, final Logger[] loggers) {
final int length = loggers.length;
final org.scalatools.testing.Logger[] oldLoggers =
new org.scalatools.testing.Logger[length];
for (int i = 0; i < length; i++) {
oldLoggers[i] = createOldLogger(loggers[i]);
}
final org.scalatools.testing.Runner runner =
oldFramework.testRunner(testClassLoader, oldLoggers);
final Fingerprint fingerprint = taskDef.fingerprint();
if (runner instanceof org.scalatools.testing.Runner2) {
runRunner2((org.scalatools.testing.Runner2) runner, fingerprint, eventHandler);
} else {
runRunner(runner, fingerprint, eventHandler);
}
return new Task[0];
}
public TaskDef taskDef() {
return taskDef;
}
};
}
public String done() {
return "";
}
public String[] args() {
return args;
}
public String[] remoteArgs() {
return new String[0]; // Old framework does not support remoteArgs
}
} }

View File

@ -19,64 +19,65 @@ import xsbti.Logger;
import java.io.File; import java.io.File;
public interface ZincBridgeProvider { public interface ZincBridgeProvider {
/** /**
* Returns an ivy resolver to resolve dependencies locally in the default `.ivy2/local`. * Returns an ivy resolver to resolve dependencies locally in the default `.ivy2/local`.
* <p> *
* For those users interested in using Internet resolvers like Maven Central, you can * <p>For those users interested in using Internet resolvers like Maven Central, you can
* instantiate them via {@link Resolver#mavenCentral()} et al. * instantiate them via {@link Resolver#mavenCentral()} et al.
* *
* @return A local ivy resolver. * @return A local ivy resolver.
*/ */
public static Resolver getLocalResolver() { public static Resolver getLocalResolver() {
return ZincComponentCompiler.LocalResolver(); return ZincComponentCompiler.LocalResolver();
} }
/** /**
* Returns a global lock that does nothing but calling the callable to synchronize * Returns a global lock that does nothing but calling the callable to synchronize across threads.
* across threads. The lock file is used to resolve and download dependencies via ivy. * The lock file is used to resolve and download dependencies via ivy.
* <p> *
* This operation is necessary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. * <p>This operation is necessary to invoke {@link ZincBridgeProvider#getProvider(File,
* * GlobalLock, ComponentProvider, IvyConfiguration, Logger)}.
* @return A default global lock. *
*/ * @return A default global lock.
public static GlobalLock getDefaultLock() { */
return ZincComponentCompiler.getDefaultLock(); public static GlobalLock getDefaultLock() {
} return ZincComponentCompiler.getDefaultLock();
}
/** /**
* Returns a default component provider that retrieves and installs component managers * Returns a default component provider that retrieves and installs component managers (like the
* (like the compiled bridge sources) under a given target directory. * compiled bridge sources) under a given target directory.
* <p> *
* This is the most simplistic implementation of a component provider. If you need more * <p>This is the most simplistic implementation of a component provider. If you need more
* advanced feature, like management of component via proxies (for companies) or access to * advanced feature, like management of component via proxies (for companies) or access to other
* other servers, you need to implement your own component provider. * servers, you need to implement your own component provider.
* *
* @param componentsRoot The directory in which components will be installed and retrieved. * @param componentsRoot The directory in which components will be installed and retrieved.
* @return A default component provider. * @return A default component provider.
*/ */
public static ComponentProvider getDefaultComponentProvider(File componentsRoot) { public static ComponentProvider getDefaultComponentProvider(File componentsRoot) {
return ZincComponentCompiler.getDefaultComponentProvider(componentsRoot); return ZincComponentCompiler.getDefaultComponentProvider(componentsRoot);
} }
/** /**
* Get a compiler bridge provider that allows the user to fetch Scala and a compiled bridge. * Get a compiler bridge provider that allows the user to fetch Scala and a compiled bridge.
* *
* @param scalaJarsTarget The place where the downloaded Scala jars should be placed. * @param scalaJarsTarget The place where the downloaded Scala jars should be placed.
* @param lock The lock file used internally by Ivy to synchronize the dependency resolution. * @param lock The lock file used internally by Ivy to synchronize the dependency resolution.
* @param componentProvider A provider capable of retrieving existing components or installing * @param componentProvider A provider capable of retrieving existing components or installing new
* new ones. The component provider manages compiled bridge sources. * ones. The component provider manages compiled bridge sources.
* @param dependencyResolution The library management module to use to retrieve the bridge. * @param dependencyResolution The library management module to use to retrieve the bridge.
* @param logger The logger. * @param logger The logger.
* @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge.
*/ */
public static CompilerBridgeProvider getProvider( public static CompilerBridgeProvider getProvider(
File scalaJarsTarget, File scalaJarsTarget,
GlobalLock lock, GlobalLock lock,
ComponentProvider componentProvider, ComponentProvider componentProvider,
DependencyResolution dependencyResolution, DependencyResolution dependencyResolution,
Logger logger Logger logger) {
) { ZincComponentManager manager =
ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); new ZincComponentManager(lock, componentProvider, None$.empty(), logger);
return ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, scalaJarsTarget); return ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, scalaJarsTarget);
} }
} }