Added >1 framework class per framework support, this enables sbt to support both old and new framework API at the same time.

This commit is contained in:
cheeseng 2013-04-03 21:07:31 +08:00
parent f38a244d0f
commit a76523a5f6
4 changed files with 46 additions and 29 deletions

View File

@ -53,7 +53,7 @@ private[sbt] object ForkTests {
os.writeInt(runners.size) os.writeInt(runners.size)
for ((testFramework, mainRunner) <- runners) { for ((testFramework, mainRunner) <- runners) {
val remoteArgs = mainRunner.remoteArgs() val remoteArgs = mainRunner.remoteArgs()
os.writeObject(testFramework.implClassName) os.writeObject(testFramework.implClassNames.toArray)
os.writeObject(mainRunner.args) os.writeObject(mainRunner.args)
os.writeObject(remoteArgs) os.writeObject(remoteArgs)
} }

View File

@ -58,7 +58,7 @@ object Tests
def frameworkArguments(framework: TestFramework, args: Seq[String]): Unit = def frameworkArguments(framework: TestFramework, args: Seq[String]): Unit =
(frameworks get framework) match { (frameworks get framework) match {
case Some(f) => frameworkArgs(f, args) case Some(f) => frameworkArgs(f, args)
case None => undefinedFrameworks += framework.implClassName case None => undefinedFrameworks ++= framework.implClassNames
} }
for(option <- config.options) for(option <- config.options)

View File

@ -168,6 +168,9 @@ public class ForkMain {
void logError(ObjectOutputStream os, String message) { void logError(ObjectOutputStream os, String message) {
write(os, new Object[]{ForkTags.Error, message}); write(os, new Object[]{ForkTags.Error, message});
} }
void logDebug(ObjectOutputStream os, String message) {
write(os, new Object[]{ForkTags.Debug, message});
}
void writeEvents(ObjectOutputStream os, ForkTestDefinition test, ForkEvent[] events) { void writeEvents(ObjectOutputStream os, ForkTestDefinition test, ForkEvent[] events) {
write(os, new Object[]{test.name, events}); write(os, new Object[]{test.name, events});
} }
@ -187,21 +190,26 @@ public class ForkMain {
}; };
for (int i = 0; i < nFrameworks; i++) { for (int i = 0; i < nFrameworks; i++) {
final String implClassName = (String) is.readObject(); final String[] implClassNames = (String[]) is.readObject();
final String[] frameworkArgs = (String[]) is.readObject(); final String[] frameworkArgs = (String[]) is.readObject();
final String[] remoteFrameworkArgs = (String[]) is.readObject(); final String[] remoteFrameworkArgs = (String[]) is.readObject();
final Framework framework; Framework framework = null;
for (String implClassName : implClassNames) {
try { try {
Object rawFramework = Class.forName(implClassName).newInstance(); Object rawFramework = Class.forName(implClassName).newInstance();
if (rawFramework instanceof Framework) if (rawFramework instanceof Framework)
framework = (Framework) rawFramework; framework = (Framework) rawFramework;
else else
framework = new FrameworkWrapper((org.scalatools.testing.Framework) rawFramework); framework = new FrameworkWrapper((org.scalatools.testing.Framework) rawFramework);
break;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
logError(os, "Framework implementation '" + implClassName + "' not present."); logDebug(os, "Framework implementation '" + implClassName + "' not present.");
continue;
} }
}
if (framework == null)
continue;
ArrayList<ForkTestDefinition> filteredTests = new ArrayList<ForkTestDefinition>(); ArrayList<ForkTestDefinition> filteredTests = new ArrayList<ForkTestDefinition>();
for (Fingerprint testFingerprint : framework.fingerprints()) { for (Fingerprint testFingerprint : framework.fingerprints()) {

View File

@ -8,6 +8,7 @@ package sbt
import testing.{Logger=>TLogger, _} import testing.{Logger=>TLogger, _}
import org.scalatools.testing.{Framework => OldFramework} import org.scalatools.testing.{Framework => OldFramework}
import classpath.{ClasspathUtilities, DualLoader, FilteredLoader} import classpath.{ClasspathUtilities, DualLoader, FilteredLoader}
import scala.annotation.tailrec
object TestResult extends Enumeration object TestResult extends Enumeration
{ {
@ -17,30 +18,38 @@ object TestResult extends Enumeration
object TestFrameworks object TestFrameworks
{ {
val ScalaCheck = new TestFramework("org.scalacheck.ScalaCheckFramework") val ScalaCheck = new TestFramework("org.scalacheck.ScalaCheckFramework")
val ScalaTest = new TestFramework("org.scalatest.tools.Framework") val ScalaTest = new TestFramework("org.scalatest.tools.Framework", "org.scalatest.tools.ScalaTestFramework")
val Specs = new TestFramework("org.specs.runner.SpecsFramework") val Specs = new TestFramework("org.specs.runner.SpecsFramework")
val Specs2 = new TestFramework("org.specs2.runner.SpecsFramework") val Specs2 = new TestFramework("org.specs2.runner.SpecsFramework")
val JUnit = new TestFramework("com.novocode.junit.JUnitFramework") val JUnit = new TestFramework("com.novocode.junit.JUnitFramework")
} }
case class TestFramework(val implClassName: String) case class TestFramework(val implClassNames: String*)
{
def create(loader: ClassLoader, log: Logger): Option[Framework] =
{ {
@tailrec
private def createFramework(loader: ClassLoader, log: Logger, frameworkClassNames: List[String]): Option[Framework] = {
frameworkClassNames match {
case head :: tail =>
try try
{ {
Some( Some(Class.forName(head, true, loader).newInstance match {
Class.forName(implClassName, true, loader).newInstance match {
case newFramework: Framework => newFramework case newFramework: Framework => newFramework
case oldFramework: OldFramework => new FrameworkWrapper(oldFramework) case oldFramework: OldFramework => new FrameworkWrapper(oldFramework)
} })
)
} }
catch catch
{ {
case e: ClassNotFoundException => log.debug("Framework implementation '" + implClassName + "' not present."); None case e: ClassNotFoundException =>
log.debug("Framework implementation '" + head + "' not present.");
createFramework(loader, log, tail)
}
case Nil =>
None
} }
} }
def create(loader: ClassLoader, log: Logger): Option[Framework] =
createFramework(loader, log, implClassNames.toList)
} }
final class TestDefinition(val name: String, val fingerprint: Fingerprint) final class TestDefinition(val name: String, val fingerprint: Fingerprint)
{ {