diff --git a/.travis.yml b/.travis.yml index 52fcfe5dc..1602d81c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ env: # WHITESOURCE_PASSWORD= - secure: d3bu2KNwsVHwfhbGgO+gmRfDKBJhfICdCJFGWKf2w3Gv86AJZX9nuTYRxz0KtdvEHO5Xw8WTBZLPb2thSJqhw9OCm4J8TBAVqCP0ruUj4+aqBUFy4bVexQ6WKE6nWHs4JPzPk8c6uC1LG3hMuzlC8RGETXtL/n81Ef1u7NjyXjs= matrix: - - SBT_CMD="mimaReportBinaryIssues ;scalafmtCheckAll ; scalafmtSbtCheck; headerCheck ;test:headerCheck ;whitesourceOnPush ;test:compile; publishLocal ;mainSettingsProj/test ;safeUnitTests ;otherUnitTests; doc; $UTIL_TESTS; ++$SCALA_213; $UTIL_TESTS" + - SBT_CMD="mimaReportBinaryIssues ; javafmtCheck ; Test / javafmtCheck; scalafmtCheckAll ; scalafmtSbtCheck; headerCheck ;test:headerCheck ;whitesourceOnPush ;test:compile; publishLocal ;mainSettingsProj/test ;safeUnitTests ;otherUnitTests; doc; $UTIL_TESTS; ++$SCALA_213; $UTIL_TESTS" - SBT_CMD="scripted actions/* apiinfo/* compiler-project/* ivy-deps-management/* reporter/* tests/* watch/* classloader-cache/* package/*" - SBT_CMD="scripted dependency-management/* plugins/* project-load/* java/* run/* nio/*" - SBT_CMD="repoOverrideTest:scripted dependency-management/*; scripted source-dependencies/* project/*" diff --git a/build.sbt b/build.sbt index 1d236719c..eadab0a66 100644 --- a/build.sbt +++ b/build.sbt @@ -87,6 +87,16 @@ def commonBaseSettings: Seq[Setting[_]] = Def.settings( s"https://github.com/sbt/sbt/tree/$tagOrSha€{FILE_PATH}.scala" ) }, + Compile / javafmtOnCompile := Def + .taskDyn(if ((scalafmtOnCompile).value) Compile / javafmt else Def.task(())) + .value, + Test / javafmtOnCompile := Def + .taskDyn(if ((Test / scalafmtOnCompile).value) Test / javafmt else Def.task(())) + .value, + Compile / unmanagedSources / inputFileStamps := + (Compile / unmanagedSources / inputFileStamps).dependsOn(Compile / javafmtOnCompile).value, + Test / unmanagedSources / inputFileStamps := + (Test / unmanagedSources / inputFileStamps).dependsOn(Test / javafmtOnCompile).value, crossScalaVersions := Seq(baseScalaVersion), bintrayPackage := (bintrayPackage in ThisBuild).value, bintrayRepository := (bintrayRepository in ThisBuild).value, @@ -1257,6 +1267,7 @@ lazy val otherProjects: ScopeFilter = ScopeFilter( ), inConfigurations(Test) ) +lazy val javafmtOnCompile = taskKey[Unit]("Formats java sources before compile") def customCommands: Seq[Setting[_]] = Seq( commands += Command.command("setupBuildScala212") { state => diff --git a/internal/util-interface/src/main/java/xsbti/Logger.java b/internal/util-interface/src/main/java/xsbti/Logger.java index a8b83951f..54023b52e 100644 --- a/internal/util-interface/src/main/java/xsbti/Logger.java +++ b/internal/util-interface/src/main/java/xsbti/Logger.java @@ -10,9 +10,13 @@ package xsbti; import java.util.function.Supplier; public interface Logger { - void error(Supplier msg); - void warn(Supplier msg); - void info(Supplier msg); - void debug(Supplier msg); - void trace(Supplier exception); + void error(Supplier msg); + + void warn(Supplier msg); + + void info(Supplier msg); + + void debug(Supplier msg); + + void trace(Supplier exception); } diff --git a/internal/util-interface/src/main/java/xsbti/Position.java b/internal/util-interface/src/main/java/xsbti/Position.java index 3dd516334..da4f139d6 100644 --- a/internal/util-interface/src/main/java/xsbti/Position.java +++ b/internal/util-interface/src/main/java/xsbti/Position.java @@ -10,24 +10,44 @@ package xsbti; import java.io.File; import java.util.Optional; -public interface Position -{ - Optional line(); - String lineContent(); - Optional offset(); +public interface Position { + Optional line(); - // pointer to the column position of the error/warning - Optional pointer(); - Optional pointerSpace(); + String lineContent(); - Optional sourcePath(); - Optional sourceFile(); + Optional offset(); - // Default values to avoid breaking binary compatibility - default Optional startOffset() { return Optional.empty(); } - default Optional endOffset() { return Optional.empty(); } - default Optional startLine() { return Optional.empty(); } - default Optional startColumn() { return Optional.empty(); } - default Optional endLine() { return Optional.empty(); } - default Optional endColumn() { return Optional.empty(); } + // pointer to the column position of the error/warning + Optional pointer(); + + Optional pointerSpace(); + + Optional sourcePath(); + + Optional sourceFile(); + + // Default values to avoid breaking binary compatibility + default Optional startOffset() { + return Optional.empty(); + } + + default Optional endOffset() { + return Optional.empty(); + } + + default Optional startLine() { + return Optional.empty(); + } + + default Optional startColumn() { + return Optional.empty(); + } + + default Optional endLine() { + return Optional.empty(); + } + + default Optional endColumn() { + return Optional.empty(); + } } diff --git a/internal/util-interface/src/main/java/xsbti/Problem.java b/internal/util-interface/src/main/java/xsbti/Problem.java index dde79f8fd..78c9145a3 100644 --- a/internal/util-interface/src/main/java/xsbti/Problem.java +++ b/internal/util-interface/src/main/java/xsbti/Problem.java @@ -9,18 +9,21 @@ package xsbti; import java.util.Optional; -public interface Problem -{ - String category(); - Severity severity(); - String message(); - Position position(); +public interface Problem { + String category(); + + Severity severity(); + + String message(); + + Position position(); // Default value to avoid breaking binary compatibility /** - * If present, the string shown to the user when displaying this Problem. - * Otherwise, the Problem will be shown in an implementation-defined way - * based on the values of its other fields. + * If present, the string shown to the user when displaying this Problem. Otherwise, the Problem + * will be shown in an implementation-defined way based on the values of its other fields. */ - default Optional rendered() { return Optional.empty(); } + default Optional rendered() { + return Optional.empty(); + } } diff --git a/internal/util-interface/src/main/java/xsbti/Severity.java b/internal/util-interface/src/main/java/xsbti/Severity.java index 08bd90ed1..833d91093 100644 --- a/internal/util-interface/src/main/java/xsbti/Severity.java +++ b/internal/util-interface/src/main/java/xsbti/Severity.java @@ -7,7 +7,8 @@ package xsbti; -public enum Severity -{ - Info, Warn, Error -} \ No newline at end of file +public enum Severity { + Info, + Warn, + Error +} diff --git a/internal/util-interface/src/main/java/xsbti/T2.java b/internal/util-interface/src/main/java/xsbti/T2.java index dd04ac57c..2f51726d7 100644 --- a/internal/util-interface/src/main/java/xsbti/T2.java +++ b/internal/util-interface/src/main/java/xsbti/T2.java @@ -8,8 +8,8 @@ package xsbti; /** Used to pass a pair of values. */ -public interface T2 -{ +public interface T2 { public A1 get1(); + public A2 get2(); } diff --git a/internal/util-scripted/src/main/java/sbt/internal/scripted/ScriptConfig.java b/internal/util-scripted/src/main/java/sbt/internal/scripted/ScriptConfig.java index 570c60a19..39216d3ae 100644 --- a/internal/util-scripted/src/main/java/sbt/internal/scripted/ScriptConfig.java +++ b/internal/util-scripted/src/main/java/sbt/internal/scripted/ScriptConfig.java @@ -13,26 +13,25 @@ import xsbti.Logger; public class ScriptConfig { - private String label; - private File testDirectory; - private Logger logger; + private String label; + private File testDirectory; + private Logger logger; - public ScriptConfig(String label, File testDirectory, Logger logger) { - this.label = label; - this.testDirectory = testDirectory; - this.logger = logger; - } + public ScriptConfig(String label, File testDirectory, Logger logger) { + this.label = label; + this.testDirectory = testDirectory; + this.logger = logger; + } - public String label() { - return this.label; - } + public String label() { + return this.label; + } - public File testDirectory() { - return this.testDirectory; - } + public File testDirectory() { + return this.testDirectory; + } - public Logger logger() { - return this.logger; - } - -} \ No newline at end of file + public Logger logger() { + return this.logger; + } +} diff --git a/main-command/src/main/java/sbt/internal/classpath/WrappedLoader.java b/main-command/src/main/java/sbt/internal/classpath/WrappedLoader.java index 932187f65..76942d046 100644 --- a/main-command/src/main/java/sbt/internal/classpath/WrappedLoader.java +++ b/main-command/src/main/java/sbt/internal/classpath/WrappedLoader.java @@ -13,6 +13,7 @@ import java.util.concurrent.atomic.AtomicBoolean; public class WrappedLoader extends URLClassLoader { private final AtomicBoolean invalidated = new AtomicBoolean(false); + static { ClassLoader.registerAsParallelCapable(); } diff --git a/main-command/src/main/scala/sbt/MainControl.scala b/main-command/src/main/scala/sbt/MainControl.scala index 69d0d2fdb..96a4857e4 100644 --- a/main-command/src/main/scala/sbt/MainControl.scala +++ b/main-command/src/main/scala/sbt/MainControl.scala @@ -18,6 +18,7 @@ final case class Reboot( app: xsbti.ApplicationID, baseDirectory: File ) extends xsbti.Reboot { + System.err.println("AARGH " + app.classpathExtra.toSeq) def arguments = argsList.toArray } @@ -30,6 +31,7 @@ final case class ApplicationID( crossVersionedValue: xsbti.CrossValue, extra: Seq[File] ) extends xsbti.ApplicationID { + new Exception("make app id").printStackTrace(System.err) def mainComponents = components.toArray def classpathExtra = extra.toArray def crossVersioned = crossVersionedValue != xsbti.CrossValue.Disabled diff --git a/main/src/main/java/sbt/internal/ClassLoadingLock.java b/main/src/main/java/sbt/internal/ClassLoadingLock.java index 482ec07b7..1c5307430 100644 --- a/main/src/main/java/sbt/internal/ClassLoadingLock.java +++ b/main/src/main/java/sbt/internal/ClassLoadingLock.java @@ -16,7 +16,8 @@ final class ClassLoadingLock { private final ConcurrentHashMap locks = new ConcurrentHashMap<>(); - R withLock(final String name, final ThrowsClassNotFound supplier) throws ClassNotFoundException { + R withLock(final String name, final ThrowsClassNotFound supplier) + throws ClassNotFoundException { final Object newLock = new Object(); Object prevLock; synchronized (locks) { diff --git a/main/src/main/java/sbt/internal/LayeredClassLoader.java b/main/src/main/java/sbt/internal/LayeredClassLoader.java index 32641e828..457881816 100644 --- a/main/src/main/java/sbt/internal/LayeredClassLoader.java +++ b/main/src/main/java/sbt/internal/LayeredClassLoader.java @@ -12,8 +12,13 @@ import java.net.URL; import sbt.util.Logger; final class LayeredClassLoader extends ManagedClassLoader { - LayeredClassLoader(final URL[] classpath, final ClassLoader parent, final File tempDir, final boolean close, final - boolean allowZombies, final Logger logger) { + LayeredClassLoader( + final URL[] classpath, + final ClassLoader parent, + final File tempDir, + final boolean close, + final boolean allowZombies, + final Logger logger) { super(classpath, parent, close, allowZombies, logger); setTempDir(tempDir); } diff --git a/main/src/main/java/sbt/internal/ManagedClassLoader.java b/main/src/main/java/sbt/internal/ManagedClassLoader.java index 59dac40a4..048572fc0 100644 --- a/main/src/main/java/sbt/internal/ManagedClassLoader.java +++ b/main/src/main/java/sbt/internal/ManagedClassLoader.java @@ -30,7 +30,11 @@ abstract class ManagedClassLoader extends URLClassLoader implements NativeLoader } 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); this.close = close; this.allowZombies = allowZombies; diff --git a/main/src/main/java/sbt/internal/MetaBuildLoader.java b/main/src/main/java/sbt/internal/MetaBuildLoader.java index 8976f0808..12b911c11 100644 --- a/main/src/main/java/sbt/internal/MetaBuildLoader.java +++ b/main/src/main/java/sbt/internal/MetaBuildLoader.java @@ -20,6 +20,7 @@ public final class MetaBuildLoader extends URLClassLoader { private final URLClassLoader fullScalaLoader; private final URLClassLoader libraryLoader; private final URLClassLoader interfaceLoader; + MetaBuildLoader( final URL[] urls, 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 - * without using the scala standard library to minimize classloading. + * Rearrange the classloaders so that test-interface is above the scala library. Implemented + * without using the scala standard library to minimize classloading. * * @param appProvider the appProvider that needs to be modified - * @return a ClassLoader with a URLClassLoader for the test-interface-1.0.jar above the - * scala library. + * @return a ClassLoader with a URLClassLoader for the test-interface-1.0.jar above the scala + * library. */ public static MetaBuildLoader makeLoader(final AppProvider appProvider) throws IOException { final Pattern pattern = Pattern.compile("test-interface-[0-9.]+\\.jar"); diff --git a/main/src/main/java/sbt/internal/ScalaLibraryClassLoader.java b/main/src/main/java/sbt/internal/ScalaLibraryClassLoader.java index 7d9d4f679..6fe4403a6 100644 --- a/main/src/main/java/sbt/internal/ScalaLibraryClassLoader.java +++ b/main/src/main/java/sbt/internal/ScalaLibraryClassLoader.java @@ -25,7 +25,7 @@ final class ScalaLibraryClassLoader extends URLClassLoader { @Override public String toString() { 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()); if (i < jars.length - 2) builder.append(", "); } diff --git a/project/plugins.sbt b/project/plugins.sbt index 5fe1f6908..c1a2b30d6 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -10,3 +10,4 @@ addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.9.0") addSbtPlugin("com.lightbend" % "sbt-whitesource" % "0.1.14") addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9") addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.6.1") +addSbtPlugin("com.swoval" % "sbt-java-format" % "0.2.3") diff --git a/testing/agent/src/main/java/sbt/ForkConfiguration.java b/testing/agent/src/main/java/sbt/ForkConfiguration.java index 50e06df18..5a357ae24 100644 --- a/testing/agent/src/main/java/sbt/ForkConfiguration.java +++ b/testing/agent/src/main/java/sbt/ForkConfiguration.java @@ -10,19 +10,19 @@ package sbt; import java.io.Serializable; public final class ForkConfiguration implements Serializable { - private final boolean ansiCodesSupported; - private final boolean parallel; + private final boolean ansiCodesSupported; + private final boolean parallel; - public ForkConfiguration(final boolean ansiCodesSupported, final boolean parallel) { - this.ansiCodesSupported = ansiCodesSupported; - this.parallel = parallel; - } + public ForkConfiguration(final boolean ansiCodesSupported, final boolean parallel) { + this.ansiCodesSupported = ansiCodesSupported; + this.parallel = parallel; + } - public boolean isAnsiCodesSupported() { - return ansiCodesSupported; - } + public boolean isAnsiCodesSupported() { + return ansiCodesSupported; + } - public boolean isParallel() { - return parallel; - } + public boolean isParallel() { + return parallel; + } } diff --git a/testing/agent/src/main/java/sbt/ForkMain.java b/testing/agent/src/main/java/sbt/ForkMain.java index 07b35430b..e9b5a9bbe 100644 --- a/testing/agent/src/main/java/sbt/ForkMain.java +++ b/testing/agent/src/main/java/sbt/ForkMain.java @@ -21,334 +21,480 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.*; -final public class ForkMain { +public final class ForkMain { - // serializables - // ----------------------------------------------------------------------------- + // serializables + // ----------------------------------------------------------------------------- - final static class SubclassFingerscan implements SubclassFingerprint, Serializable { - private final boolean isModule; - private final String superclassName; - 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; } - } + static final class SubclassFingerscan implements SubclassFingerprint, Serializable { + private final boolean isModule; + private final String superclassName; + private final boolean requireNoArgConstructor; - final static class AnnotatedFingerscan implements AnnotatedFingerprint, Serializable { - private final boolean isModule; - private final String annotationName; - AnnotatedFingerscan(final AnnotatedFingerprint print) { - isModule = print.isModule(); - annotationName = print.annotationName(); - } - public boolean isModule() { return isModule; } - public String annotationName() { return annotationName; } - } + SubclassFingerscan(final SubclassFingerprint print) { + isModule = print.isModule(); + superclassName = print.superclassName(); + requireNoArgConstructor = print.requireNoArgConstructor(); + } - final static class ForkEvent implements Event, Serializable { - private final String fullyQualifiedName; - private final Fingerprint fingerprint; - private final Selector selector; - private final Status status; - private final OptionalThrowable throwable; - private final long duration; + public boolean isModule() { + return isModule; + } - ForkEvent(final Event e) { - fullyQualifiedName = e.fullyQualifiedName(); - final Fingerprint rawFingerprint = e.fingerprint(); + public String superclassName() { + return superclassName; + } - if (rawFingerprint instanceof SubclassFingerprint) - fingerprint = new SubclassFingerscan((SubclassFingerprint) rawFingerprint); - 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 boolean requireNoArgConstructor() { + return requireNoArgConstructor; + } } - public static void main(final String[] args, ClassLoader classLoader) throws Exception { - final Socket socket = new Socket(InetAddress.getByName(null), Integer.valueOf(args[0])); - final ObjectInputStream is = new ObjectInputStream(socket.getInputStream()); - 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(); - } - } + static final class AnnotatedFingerscan implements AnnotatedFingerprint, Serializable { + private final boolean isModule; + private final String annotationName; - // ---------------------------------------------------------------------------------------------------------------- + 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) { - try { - runTests(is, os, classLoader); - } 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); - } - } - } + static final class ForkEvent implements Event, Serializable { + private final String fullyQualifiedName; + private final Fingerprint fingerprint; + private final Selector selector; + private final Status status; + private final OptionalThrowable throwable; + private final long duration; - 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; - } + ForkEvent(final Event e) { + fullyQualifiedName = e.fullyQualifiedName(); + final Fingerprint rawFingerprint = e.fingerprint(); - class RunAborted extends RuntimeException { - RunAborted(final Exception e) { super(e); } - } + if (rawFingerprint instanceof SubclassFingerprint) + fingerprint = new SubclassFingerscan((SubclassFingerprint) rawFingerprint); + else fingerprint = new AnnotatedFingerscan((AnnotatedFingerprint) rawFingerprint); - private synchronized void write(final ObjectOutputStream os, final Object obj) { - try { - os.writeObject(obj); - os.flush(); - } catch (final IOException e) { - throw new RunAborted(e); - } - } + selector = e.selector(); + checkSerializableSelector(selector); + status = e.status(); + final OptionalThrowable originalThrowable = e.throwable(); - private void log(final ObjectOutputStream os, final String message, final ForkTags level) { - write(os, new Object[]{level, message}); - } + if (originalThrowable.isDefined()) + throwable = new OptionalThrowable(new ForkError(originalThrowable.get())); + else throwable = originalThrowable; - 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); } + duration = e.duration(); + } - 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)); } - }; - } + public String fullyQualifiedName() { + return fullyQualifiedName; + } - private void writeEvents(final ObjectOutputStream os, final TaskDef taskDef, final ForkEvent[] events) { - write(os, new Object[]{taskDef.fullyQualifiedName(), events}); - } + public Fingerprint fingerprint() { + return fingerprint; + } - 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(); - } - } + public Selector selector() { + return selector; + } - 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) }; + public Status status() { + return status; + } - 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(); + public OptionalThrowable throwable() { + return throwable; + } - 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."); - } - } + public long duration() { + return duration; + } - if (framework == null) - continue; + 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 ArrayList 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); + static final class ForkError extends Exception { + 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); - } - write(os, ForkTags.Done); - is.readObject(); - } + public Exception getCause() { + return cause; + } + } - private void runTestTasks(final ExecutorService executor, final Task[] tasks, final Logger[] loggers, final ObjectOutputStream os) { - if( tasks.length > 0 ) { - final List> futureNestedTasks = new ArrayList<>(); - for( final Task task : tasks ) { - futureNestedTasks.add(runTest(executor, task, loggers, os)); - } + // main + // ---------------------------------------------------------------------------------------------------------------- - // 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 nestedTasks = new ArrayList<>(); - for( final Future 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); - } - } + public static void main(final String[] args) throws Exception { + ClassLoader classLoader = new Run().getClass().getClassLoader(); + try { + main(args, classLoader); + } finally { + System.exit(0); + } + } - private Future 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 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; - }); - } + public static void main(final String[] args, ClassLoader classLoader) throws Exception { + final Socket socket = new Socket(InetAddress.getByName(null), Integer.valueOf(args[0])); + final ObjectInputStream is = new ObjectInputStream(socket.getInputStream()); + 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(); + } + } - 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 static final class Run { - 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); - } - } + private void run( + final ObjectInputStream is, final ObjectOutputStream os, ClassLoader classLoader) { + try { + runTests(is, os, classLoader); + } 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 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> 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 nestedTasks = new ArrayList<>(); + for (final Future 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 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 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); + } + } } diff --git a/testing/agent/src/main/java/sbt/ForkTags.java b/testing/agent/src/main/java/sbt/ForkTags.java index 83563fae0..5f8022fed 100644 --- a/testing/agent/src/main/java/sbt/ForkTags.java +++ b/testing/agent/src/main/java/sbt/ForkTags.java @@ -8,5 +8,9 @@ package sbt; public enum ForkTags { - Error, Warn, Info, Debug, Done + Error, + Warn, + Info, + Debug, + Done } diff --git a/testing/agent/src/main/java/sbt/FrameworkWrapper.java b/testing/agent/src/main/java/sbt/FrameworkWrapper.java index ea98761ef..22c94af0b 100644 --- a/testing/agent/src/main/java/sbt/FrameworkWrapper.java +++ b/testing/agent/src/main/java/sbt/FrameworkWrapper.java @@ -10,259 +10,318 @@ package sbt; import sbt.testing.*; /** - * Adapts the old {@link org.scalatools.testing.Framework} interface into the new - * {@link sbt.testing.Framework} + * Adapts the old {@link org.scalatools.testing.Framework} interface into the new {@link + * sbt.testing.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) { - this.oldFramework = oldFramework; - } + FrameworkWrapper(final org.scalatools.testing.Framework oldFramework) { + this.oldFramework = oldFramework; + } - public String name() { - return oldFramework.name(); - } + public String name() { + return oldFramework.name(); + } - public Fingerprint[] fingerprints() { - final org.scalatools.testing.Fingerprint[] oldFingerprints = oldFramework.tests(); - final int length = oldFingerprints.length; - final Fingerprint[] fingerprints = new Fingerprint[length]; - for (int i=0; i < length; i++) { - final org.scalatools.testing.Fingerprint oldFingerprint = oldFingerprints[i]; - if (oldFingerprint instanceof org.scalatools.testing.TestFingerprint) - fingerprints[i] = new SubclassFingerprintWrapper((org.scalatools.testing.TestFingerprint) oldFingerprint); - else if (oldFingerprint instanceof org.scalatools.testing.SubclassFingerprint) - fingerprints[i] = new SubclassFingerprintWrapper((org.scalatools.testing.SubclassFingerprint) oldFingerprint); - else - fingerprints[i] = new AnnotatedFingerprintWrapper((org.scalatools.testing.AnnotatedFingerprint) oldFingerprint); - } - return fingerprints; - } + public Fingerprint[] fingerprints() { + final org.scalatools.testing.Fingerprint[] oldFingerprints = oldFramework.tests(); + final int length = oldFingerprints.length; + final Fingerprint[] fingerprints = new Fingerprint[length]; + for (int i = 0; i < length; i++) { + final org.scalatools.testing.Fingerprint oldFingerprint = oldFingerprints[i]; + if (oldFingerprint instanceof org.scalatools.testing.TestFingerprint) + fingerprints[i] = + new SubclassFingerprintWrapper((org.scalatools.testing.TestFingerprint) oldFingerprint); + else if (oldFingerprint instanceof org.scalatools.testing.SubclassFingerprint) + fingerprints[i] = + new SubclassFingerprintWrapper( + (org.scalatools.testing.SubclassFingerprint) oldFingerprint); + else + fingerprints[i] = + new AnnotatedFingerprintWrapper( + (org.scalatools.testing.AnnotatedFingerprint) oldFingerprint); + } + return fingerprints; + } - public Runner runner(final String[] args, final String[] remoteArgs, final ClassLoader testClassLoader) { - return new RunnerWrapper(oldFramework, testClassLoader, args); - } + public Runner runner( + final String[] args, final String[] remoteArgs, final ClassLoader testClassLoader) { + return new RunnerWrapper(oldFramework, testClassLoader, args); + } } final class SubclassFingerprintWrapper implements SubclassFingerprint { - private final String superclassName; - private final boolean isModule; - private final boolean requireNoArgConstructor; + private final String superclassName; + private final boolean isModule; + private final boolean requireNoArgConstructor; - SubclassFingerprintWrapper(final org.scalatools.testing.SubclassFingerprint oldFingerprint) { - superclassName = oldFingerprint.superClassName(); - isModule = oldFingerprint.isModule(); - requireNoArgConstructor = false; // Old framework SubclassFingerprint does not require no arg constructor - } + SubclassFingerprintWrapper(final org.scalatools.testing.SubclassFingerprint oldFingerprint) { + superclassName = oldFingerprint.superClassName(); + isModule = oldFingerprint.isModule(); + requireNoArgConstructor = + false; // Old framework SubclassFingerprint does not require no arg constructor + } - public boolean isModule() { - return isModule; - } + public boolean isModule() { + return isModule; + } - public String superclassName() { - return superclassName; - } + public String superclassName() { + return superclassName; + } - public boolean requireNoArgConstructor() { - return requireNoArgConstructor; - } + public boolean requireNoArgConstructor() { + return requireNoArgConstructor; + } } final class AnnotatedFingerprintWrapper implements AnnotatedFingerprint { - private final String annotationName; - private final boolean isModule; + private final String annotationName; + private final boolean isModule; - AnnotatedFingerprintWrapper(final org.scalatools.testing.AnnotatedFingerprint oldFingerprint) { - annotationName = oldFingerprint.annotationName(); - isModule = oldFingerprint.isModule(); - } + AnnotatedFingerprintWrapper(final org.scalatools.testing.AnnotatedFingerprint oldFingerprint) { + annotationName = oldFingerprint.annotationName(); + isModule = oldFingerprint.isModule(); + } - public boolean isModule() { - return isModule; - } + public boolean isModule() { + return isModule; + } - public String annotationName() { - return annotationName; - } + public String annotationName() { + return annotationName; + } } final class EventHandlerWrapper implements org.scalatools.testing.EventHandler { - private final EventHandler newEventHandler; - private final String fullyQualifiedName; - private final Fingerprint fingerprint; + private final EventHandler newEventHandler; + private final String fullyQualifiedName; + private final Fingerprint fingerprint; - EventHandlerWrapper(final EventHandler newEventHandler, final String fullyQualifiedName, final Fingerprint fingerprint) { - this.newEventHandler = newEventHandler; - this.fullyQualifiedName = fullyQualifiedName; - this.fingerprint = fingerprint; - } + EventHandlerWrapper( + final EventHandler newEventHandler, + final String fullyQualifiedName, + final Fingerprint fingerprint) { + this.newEventHandler = newEventHandler; + this.fullyQualifiedName = fullyQualifiedName; + this.fingerprint = fingerprint; + } - public void handle(final org.scalatools.testing.Event oldEvent) { - newEventHandler.handle(new EventWrapper(oldEvent, fullyQualifiedName, fingerprint)); - } + public void handle(final org.scalatools.testing.Event oldEvent) { + newEventHandler.handle(new EventWrapper(oldEvent, fullyQualifiedName, fingerprint)); + } } final class EventWrapper implements Event { - private final org.scalatools.testing.Event oldEvent; - private final String className; - private final Fingerprint fingerprint; - private final OptionalThrowable throwable; + private final org.scalatools.testing.Event oldEvent; + private final String className; + private final Fingerprint fingerprint; + private final OptionalThrowable throwable; - EventWrapper(final org.scalatools.testing.Event oldEvent, final String className, final Fingerprint fingerprint) { - this.oldEvent = oldEvent; - this.className = className; - this.fingerprint = fingerprint; - final Throwable oldThrowable = oldEvent.error(); - if (oldThrowable == null) - throwable = new OptionalThrowable(); - else - throwable = new OptionalThrowable(oldThrowable); - } + EventWrapper( + final org.scalatools.testing.Event oldEvent, + final String className, + final Fingerprint fingerprint) { + this.oldEvent = oldEvent; + this.className = className; + this.fingerprint = fingerprint; + final Throwable oldThrowable = oldEvent.error(); + if (oldThrowable == null) throwable = new OptionalThrowable(); + else throwable = new OptionalThrowable(oldThrowable); + } - public String fullyQualifiedName() { - return className; - } + public String fullyQualifiedName() { + return className; + } - public Fingerprint fingerprint() { - return fingerprint; - } + public Fingerprint fingerprint() { + return fingerprint; + } - public Selector selector() { - return new TestSelector(oldEvent.testName()); - } + public Selector selector() { + return new TestSelector(oldEvent.testName()); + } - public Status status() { - switch (oldEvent.result()) { - case Success: - return Status.Success; - case Error: - return Status.Error; - case Failure: - return Status.Failure; - case Skipped: - return Status.Skipped; - default: - throw new IllegalStateException("Invalid status."); - } - } + public Status status() { + switch (oldEvent.result()) { + case Success: + return Status.Success; + case Error: + return Status.Error; + case Failure: + return Status.Failure; + case Skipped: + return Status.Skipped; + default: + throw new IllegalStateException("Invalid status."); + } + } - public OptionalThrowable throwable() { - return throwable; - } + public OptionalThrowable throwable() { + return throwable; + } - public long duration() { - return -1; // Just return -1 as old event does not have duration. - } + public long duration() { + return -1; // Just return -1 as old event does not have duration. + } } final class RunnerWrapper implements Runner { - private final org.scalatools.testing.Framework oldFramework; - private final ClassLoader testClassLoader; - private final String[] args; + private final org.scalatools.testing.Framework oldFramework; + private final ClassLoader testClassLoader; + private final String[] args; - RunnerWrapper(final org.scalatools.testing.Framework oldFramework, final ClassLoader testClassLoader, final String[] args) { - this.oldFramework = oldFramework; - this.testClassLoader = testClassLoader; - this.args = args; - } + RunnerWrapper( + final org.scalatools.testing.Framework oldFramework, + final ClassLoader testClassLoader, + final String[] args) { + this.oldFramework = oldFramework; + this.testClassLoader = testClassLoader; + this.args = args; + } - public Task[] tasks(final TaskDef[] taskDefs) { - final int length = taskDefs.length; - final Task[] tasks = new Task[length]; - for (int i = 0; i < length; i++) { - final TaskDef taskDef = taskDefs[i]; - tasks[i] = createTask(taskDef); - } - return tasks; - } + public Task[] tasks(final TaskDef[] taskDefs) { + final int length = taskDefs.length; + final Task[] tasks = new Task[length]; + for (int i = 0; i < length; i++) { + final TaskDef taskDef = taskDefs[i]; + tasks[i] = createTask(taskDef); + } + return tasks; + } - private Task createTask(final TaskDef taskDef) { - return new Task() { - public String[] tags() { - return new String[0]; // Old framework does not support tags - } + private Task createTask(final TaskDef taskDef) { + return new Task() { + public String[] tags() { + return new String[0]; // Old framework does not support tags + } - private org.scalatools.testing.Logger createOldLogger(final Logger logger) { - return new org.scalatools.testing.Logger() { - public boolean ansiCodesSupported() { return logger.ansiCodesSupported(); } - public void error(final String msg) { logger.error(msg); } - 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 org.scalatools.testing.Logger createOldLogger(final Logger logger) { + return new org.scalatools.testing.Logger() { + public boolean ansiCodesSupported() { + return logger.ansiCodesSupported(); + } - private void runRunner(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 superClassName() { return subclassFingerprint.superclassName(); } - }; - final String name = taskDef.fullyQualifiedName(); - runner.run(name, oldFingerprint, new EventHandlerWrapper(eventHandler, name, subclassFingerprint), args); - } + public void error(final String msg) { + logger.error(msg); + } - private void runRunner2(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 void warn(final String msg) { + logger.warn(msg); + } - 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 - * For those users interested in using Internet resolvers like Maven Central, you can - * instantiate them via {@link Resolver#mavenCentral()} et al. - * - * @return A local ivy resolver. - */ - public static Resolver getLocalResolver() { - return ZincComponentCompiler.LocalResolver(); - } + /** + * Returns an ivy resolver to resolve dependencies locally in the default `.ivy2/local`. + * + *

For those users interested in using Internet resolvers like Maven Central, you can + * instantiate them via {@link Resolver#mavenCentral()} et al. + * + * @return A local ivy resolver. + */ + public static Resolver getLocalResolver() { + return ZincComponentCompiler.LocalResolver(); + } - /** - * Returns a global lock that does nothing but calling the callable to synchronize - * across threads. The lock file is used to resolve and download dependencies via ivy. - *

- * This operation is necessary to invoke {@link ZincBridgeProvider#getProvider(File, GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. - * - * @return A default global lock. - */ - public static GlobalLock getDefaultLock() { - return ZincComponentCompiler.getDefaultLock(); - } + /** + * Returns a global lock that does nothing but calling the callable to synchronize across threads. + * The lock file is used to resolve and download dependencies via ivy. + * + *

This operation is necessary to invoke {@link ZincBridgeProvider#getProvider(File, + * GlobalLock, ComponentProvider, IvyConfiguration, Logger)}. + * + * @return A default global lock. + */ + public static GlobalLock getDefaultLock() { + return ZincComponentCompiler.getDefaultLock(); + } - /** - * Returns a default component provider that retrieves and installs component managers - * (like the compiled bridge sources) under a given target directory. - *

- * 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 - * other servers, you need to implement your own component provider. - * - * @param componentsRoot The directory in which components will be installed and retrieved. - * @return A default component provider. - */ - public static ComponentProvider getDefaultComponentProvider(File componentsRoot) { - return ZincComponentCompiler.getDefaultComponentProvider(componentsRoot); - } + /** + * Returns a default component provider that retrieves and installs component managers (like the + * compiled bridge sources) under a given target directory. + * + *

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 other + * servers, you need to implement your own component provider. + * + * @param componentsRoot The directory in which components will be installed and retrieved. + * @return A default component provider. + */ + public static ComponentProvider getDefaultComponentProvider(File componentsRoot) { + return ZincComponentCompiler.getDefaultComponentProvider(componentsRoot); + } - /** - * 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 lock The lock file used internally by Ivy to synchronize the dependency resolution. - * @param componentProvider A provider capable of retrieving existing components or installing - * new ones. The component provider manages compiled bridge sources. - * @param dependencyResolution The library management module to use to retrieve the bridge. - * @param logger The logger. - * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. - */ - public static CompilerBridgeProvider getProvider( - File scalaJarsTarget, - GlobalLock lock, - ComponentProvider componentProvider, - DependencyResolution dependencyResolution, - Logger logger - ) { - ZincComponentManager manager = new ZincComponentManager(lock, componentProvider, None$.empty(), logger); - return ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, scalaJarsTarget); - } + /** + * 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 lock The lock file used internally by Ivy to synchronize the dependency resolution. + * @param componentProvider A provider capable of retrieving existing components or installing new + * ones. The component provider manages compiled bridge sources. + * @param dependencyResolution The library management module to use to retrieve the bridge. + * @param logger The logger. + * @return A compiler bridge provider capable of fetching scala jars and the compiler bridge. + */ + public static CompilerBridgeProvider getProvider( + File scalaJarsTarget, + GlobalLock lock, + ComponentProvider componentProvider, + DependencyResolution dependencyResolution, + Logger logger) { + ZincComponentManager manager = + new ZincComponentManager(lock, componentProvider, None$.empty(), logger); + return ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, scalaJarsTarget); + } }