mirror of https://github.com/sbt/sbt.git
Fixes after review, take 2.
This commit is contained in:
parent
e3a7a331d5
commit
4d5effcb28
|
|
@ -286,26 +286,29 @@ object Defaults extends BuildCommon
|
||||||
testOptions in GlobalScope :== Nil,
|
testOptions in GlobalScope :== Nil,
|
||||||
testFilter in testOnly :== (selectedFilter _),
|
testFilter in testOnly :== (selectedFilter _),
|
||||||
testFilter in testQuick <<= testQuickFilter,
|
testFilter in testQuick <<= testQuickFilter,
|
||||||
executeTests <<= (streams in test, loadedTestFrameworks, testLoader, testGrouping in test, fullClasspath in test, javaOptions in test, javaHome in test, resolvedScoped, state) flatMap {
|
executeTests <<= (streams in test, loadedTestFrameworks, testLoader, testGrouping in test, fullClasspath in test, javaOptions in test, javaHome in test) flatMap {
|
||||||
(s, frameworkMap, loader, groups, cp, javaOpts, javaHome, scoped, st) =>
|
(s, frameworkMap, loader, groups, cp, javaOpts, javaHome) =>
|
||||||
implicit val display = Project.showContextKey(st)
|
|
||||||
val results = groups map {
|
val results = groups map {
|
||||||
case Tests.TestGroup(name, tests, config) =>
|
case Tests.Group(name, tests, config) =>
|
||||||
config.subproc match {
|
config.subproc match {
|
||||||
case Tests.Fork(extraJvm) =>
|
case Tests.Fork(extraJvm) =>
|
||||||
ForkTests(frameworkMap.keys.toSeq, tests.toList, config, cp.files, javaHome, javaOpts, s.log)
|
ForkTests(frameworkMap.keys.toSeq, tests.toList, config, cp.files, javaHome, javaOpts, s.log)
|
||||||
case Tests.InProcess =>
|
case Tests.InProcess =>
|
||||||
Tests(frameworkMap, loader, tests, config, noTestsMessage(scoped, name), s.log)
|
Tests(frameworkMap, loader, tests, config, s.log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tests.reduce(results)
|
Tests.flatten(results)
|
||||||
|
},
|
||||||
|
test <<= (executeTests, streams, resolvedScoped, state) map {
|
||||||
|
(results, s, scoped, st) =>
|
||||||
|
implicit val display = Project.showContextKey(st)
|
||||||
|
Tests.showResults(s.log, results, noTestsMessage(scoped))
|
||||||
},
|
},
|
||||||
test <<= (executeTests, streams) map { (results, s) => Tests.showResults(s.log, results) },
|
|
||||||
testOnly <<= inputTests(testOnly),
|
testOnly <<= inputTests(testOnly),
|
||||||
testQuick <<= inputTests(testQuick)
|
testQuick <<= inputTests(testQuick)
|
||||||
)
|
)
|
||||||
private[this] def noTestsMessage(scoped: ScopedKey[_], group: String)(implicit display: Show[ScopedKey[_]]): String =
|
private[this] def noTestsMessage(scoped: ScopedKey[_])(implicit display: Show[ScopedKey[_]]): String =
|
||||||
"No tests to run for group " + group + " in " + display(scoped)
|
"No tests to run for " + display(scoped)
|
||||||
|
|
||||||
lazy val TaskGlobal: Scope = ThisScope.copy(task = Global)
|
lazy val TaskGlobal: Scope = ThisScope.copy(task = Global)
|
||||||
lazy val ConfigGlobal: Scope = ThisScope.copy(config = Global)
|
lazy val ConfigGlobal: Scope = ThisScope.copy(config = Global)
|
||||||
|
|
@ -316,7 +319,7 @@ object Defaults extends BuildCommon
|
||||||
testOptions <<= (testOptions in TaskGlobal, testListeners) map { (options, ls) => Tests.Listeners(ls) +: options },
|
testOptions <<= (testOptions in TaskGlobal, testListeners) map { (options, ls) => Tests.Listeners(ls) +: options },
|
||||||
testExecution <<= testExecutionTask(key),
|
testExecution <<= testExecutionTask(key),
|
||||||
testGrouping <<= ((definedTests, testExecution) map {
|
testGrouping <<= ((definedTests, testExecution) map {
|
||||||
(tests, exec) => Seq(new Tests.TestGroup("<default>", tests, exec))
|
(tests, exec) => Seq(new Tests.Group("<default>", tests, exec))
|
||||||
})
|
})
|
||||||
) )
|
) )
|
||||||
def testLogger(manager: Streams, baseKey: Scoped)(tdef: TestDefinition): Logger =
|
def testLogger(manager: Streams, baseKey: Scoped)(tdef: TestDefinition): Logger =
|
||||||
|
|
@ -372,17 +375,17 @@ object Defaults extends BuildCommon
|
||||||
case (s, frameworks, filter, groups, loader, scoped, (selected, frameworkOptions), cp, javaOpts, javaHome, st) =>
|
case (s, frameworks, filter, groups, loader, scoped, (selected, frameworkOptions), cp, javaOpts, javaHome, st) =>
|
||||||
implicit val display = Project.showContextKey(st)
|
implicit val display = Project.showContextKey(st)
|
||||||
val results = groups map {
|
val results = groups map {
|
||||||
case Tests.TestGroup(name, tests, config) =>
|
case Tests.Group(name, tests, config) =>
|
||||||
val modifiedOpts = Tests.Filter(filter(selected)) +: Tests.Argument(frameworkOptions : _*) +: config.options
|
val modifiedOpts = Tests.Filter(filter(selected)) +: Tests.Argument(frameworkOptions : _*) +: config.options
|
||||||
val newConfig = config.copy(options = modifiedOpts)
|
val newConfig = config.copy(options = modifiedOpts)
|
||||||
newConfig.subproc match {
|
newConfig.subproc match {
|
||||||
case Tests.Fork(extraJvm) =>
|
case Tests.Fork(extraJvm) =>
|
||||||
ForkTests(frameworks.keys.toSeq, tests.toList, newConfig, cp.files, javaHome, javaOpts, s.log)
|
ForkTests(frameworks.keys.toSeq, tests.toList, newConfig, cp.files, javaHome, javaOpts, s.log)
|
||||||
case Tests.InProcess =>
|
case Tests.InProcess =>
|
||||||
Tests(frameworks, loader, tests, newConfig, noTestsMessage(scoped, name), s.log)
|
Tests(frameworks, loader, tests, newConfig, s.log)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tests.reduce(results) map (Tests.showResults(s.log, _))
|
Tests.flatten(results) map (Tests.showResults(s.log, _, noTestsMessage(scoped)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ object Keys
|
||||||
val testListeners = TaskKey[Seq[TestReportListener]]("test-listeners", "Defines test listeners.")
|
val testListeners = TaskKey[Seq[TestReportListener]]("test-listeners", "Defines test listeners.")
|
||||||
val testExecution = TaskKey[Tests.Execution]("test-execution", "Settings controlling test execution")
|
val testExecution = TaskKey[Tests.Execution]("test-execution", "Settings controlling test execution")
|
||||||
val testFilter = TaskKey[Seq[String] => String => Boolean]("test-filter", "Filter controlling whether the test is executed")
|
val testFilter = TaskKey[Seq[String] => String => Boolean]("test-filter", "Filter controlling whether the test is executed")
|
||||||
val testGrouping = TaskKey[Seq[Tests.TestGroup]]("test-grouping", "Groups discovered tests into groups. Groups are run sequentially.")
|
val testGrouping = TaskKey[Seq[Tests.Group]]("test-grouping", "Groups discovered tests into groups. Groups are run sequentially.")
|
||||||
val isModule = AttributeKey[Boolean]("is-module", "True if the target is a module.")
|
val isModule = AttributeKey[Boolean]("is-module", "True if the target is a module.")
|
||||||
|
|
||||||
// Classpath/Dependency Management Keys
|
// Classpath/Dependency Management Keys
|
||||||
|
|
|
||||||
|
|
@ -58,12 +58,13 @@ private[sbt] object ForkTests {
|
||||||
os.writeObject(args.toArray)
|
os.writeObject(args.toArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import Tags._
|
||||||
@annotation.tailrec def react: Unit = is.readObject match {
|
@annotation.tailrec def react: Unit = is.readObject match {
|
||||||
case `TestsDone` => os.writeObject(TestsDone);
|
case `Done` => os.writeObject(Done);
|
||||||
case Array(`ErrorTag`, s: String) => log.error(s); react
|
case Array(`Error`, s: String) => log.error(s); react
|
||||||
case Array(`WarnTag`, s: String) => log.warn(s); react
|
case Array(`Warn`, s: String) => log.warn(s); react
|
||||||
case Array(`InfoTag`, s: String) => log.info(s); react
|
case Array(`Info`, s: String) => log.info(s); react
|
||||||
case Array(`DebugTag`, s: String) => log.debug(s); react
|
case Array(`Debug`, s: String) => log.debug(s); react
|
||||||
case t: Throwable => log.trace(t); react
|
case t: Throwable => log.trace(t); react
|
||||||
case tEvents: Array[Event] =>
|
case tEvents: Array[Event] =>
|
||||||
for (first <- tEvents.headOption) listeners.foreach(_ startGroup first.testName)
|
for (first <- tEvents.headOption) listeners.foreach(_ startGroup first.testName)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ object Tests
|
||||||
|
|
||||||
final case class Execution(options: Seq[TestOption], parallel: Boolean, subproc: SubProcessPolicy, tags: Seq[(Tag, Int)])
|
final case class Execution(options: Seq[TestOption], parallel: Boolean, subproc: SubProcessPolicy, tags: Seq[(Tag, Int)])
|
||||||
|
|
||||||
def apply(frameworks: Map[TestFramework, Framework], testLoader: ClassLoader, discovered: Seq[TestDefinition], config: Execution, noTestsMessage: => String, log: Logger): Task[Output] =
|
def apply(frameworks: Map[TestFramework, Framework], testLoader: ClassLoader, discovered: Seq[TestDefinition], config: Execution, log: Logger): Task[Output] =
|
||||||
{
|
{
|
||||||
import collection.mutable.{HashSet, ListBuffer, Map, Set}
|
import collection.mutable.{HashSet, ListBuffer, Map, Set}
|
||||||
val testFilters = new ListBuffer[String => Boolean]
|
val testFilters = new ListBuffer[String => Boolean]
|
||||||
|
|
@ -93,10 +93,10 @@ object Tests
|
||||||
def includeTest(test: TestDefinition) = !excludeTestsSet.contains(test.name) && testFilters.forall(filter => filter(test.name))
|
def includeTest(test: TestDefinition) = !excludeTestsSet.contains(test.name) && testFilters.forall(filter => filter(test.name))
|
||||||
val tests = discovered.filter(includeTest).toSet.toSeq
|
val tests = discovered.filter(includeTest).toSet.toSeq
|
||||||
val arguments = testArgsByFramework.map { case (k,v) => (k, v.toList) } toMap;
|
val arguments = testArgsByFramework.map { case (k,v) => (k, v.toList) } toMap;
|
||||||
testTask(frameworks.values.toSeq, testLoader, tests, noTestsMessage, setup.readOnly, cleanup.readOnly, log, testListeners.readOnly, arguments, config)
|
testTask(frameworks.values.toSeq, testLoader, tests, setup.readOnly, cleanup.readOnly, log, testListeners.readOnly, arguments, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
def testTask(frameworks: Seq[Framework], loader: ClassLoader, tests: Seq[TestDefinition], noTestsMessage: => String,
|
def testTask(frameworks: Seq[Framework], loader: ClassLoader, tests: Seq[TestDefinition],
|
||||||
userSetup: Iterable[ClassLoader => Unit], userCleanup: Iterable[ClassLoader => Unit],
|
userSetup: Iterable[ClassLoader => Unit], userCleanup: Iterable[ClassLoader => Unit],
|
||||||
log: Logger, testListeners: Seq[TestReportListener], arguments: Map[Framework, Seq[String]], config: Execution): Task[Output] =
|
log: Logger, testListeners: Seq[TestReportListener], arguments: Map[Framework, Seq[String]], config: Execution): Task[Output] =
|
||||||
{
|
{
|
||||||
|
|
@ -104,7 +104,7 @@ object Tests
|
||||||
def partApp(actions: Iterable[ClassLoader => Unit]) = actions.toSeq map {a => () => a(loader) }
|
def partApp(actions: Iterable[ClassLoader => Unit]) = actions.toSeq map {a => () => a(loader) }
|
||||||
|
|
||||||
val (frameworkSetup, runnables, frameworkCleanup) =
|
val (frameworkSetup, runnables, frameworkCleanup) =
|
||||||
TestFramework.testTasks(frameworks, loader, tests, noTestsMessage, log, testListeners, arguments)
|
TestFramework.testTasks(frameworks, loader, tests, log, testListeners, arguments)
|
||||||
|
|
||||||
val setupTasks = fj(partApp(userSetup) :+ frameworkSetup)
|
val setupTasks = fj(partApp(userSetup) :+ frameworkSetup)
|
||||||
val mainTasks =
|
val mainTasks =
|
||||||
|
|
@ -126,7 +126,7 @@ object Tests
|
||||||
|
|
||||||
def processResults(results: Iterable[(String, TestResult.Value)]): (TestResult.Value, Map[String, TestResult.Value]) =
|
def processResults(results: Iterable[(String, TestResult.Value)]): (TestResult.Value, Map[String, TestResult.Value]) =
|
||||||
(overall(results.map(_._2)), results.toMap)
|
(overall(results.map(_._2)), results.toMap)
|
||||||
def reduce(results: Seq[Task[Output]]): Task[Output] =
|
def flatten(results: Seq[Task[Output]]): Task[Output] =
|
||||||
reduced(results.toIndexedSeq, {
|
reduced(results.toIndexedSeq, {
|
||||||
case ((v1, m1), (v2, m2)) => (if (v1.id < v2.id) v2 else v1, m1 ++ m2)
|
case ((v1, m1), (v2, m2)) => (if (v1.id < v2.id) v2 else v1, m1 ++ m2)
|
||||||
})
|
})
|
||||||
|
|
@ -157,8 +157,11 @@ object Tests
|
||||||
(tests, mains.toSet)
|
(tests, mains.toSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
def showResults(log: Logger, results: (TestResult.Value, Map[String, TestResult.Value])): Unit =
|
def showResults(log: Logger, results: (TestResult.Value, Map[String, TestResult.Value]), noTestsMessage: =>String): Unit =
|
||||||
{
|
{
|
||||||
|
if (results._2.isEmpty)
|
||||||
|
log.info(noTestsMessage)
|
||||||
|
else {
|
||||||
import TestResult.{Error, Failed, Passed}
|
import TestResult.{Error, Failed, Passed}
|
||||||
|
|
||||||
def select(Tpe: TestResult.Value) = results._2 collect { case (name, Tpe) => name }
|
def select(Tpe: TestResult.Value) = results._2 collect { case (name, Tpe) => name }
|
||||||
|
|
@ -181,7 +184,8 @@ object Tests
|
||||||
if(!failures.isEmpty || !errors.isEmpty)
|
if(!failures.isEmpty || !errors.isEmpty)
|
||||||
error("Tests unsuccessful")
|
error("Tests unsuccessful")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
final case class TestGroup(name: String, tests: Seq[TestDefinition], config: Execution)
|
|
||||||
|
final case class Group(name: String, tests: Seq[TestDefinition], config: Execution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,6 @@ object TestFramework
|
||||||
def testTasks(frameworks: Seq[Framework],
|
def testTasks(frameworks: Seq[Framework],
|
||||||
testLoader: ClassLoader,
|
testLoader: ClassLoader,
|
||||||
tests: Seq[TestDefinition],
|
tests: Seq[TestDefinition],
|
||||||
noTestsMessage: => String,
|
|
||||||
log: Logger,
|
log: Logger,
|
||||||
listeners: Seq[TestReportListener],
|
listeners: Seq[TestReportListener],
|
||||||
testArgsByFramework: Map[Framework, Seq[String]]):
|
testArgsByFramework: Map[Framework, Seq[String]]):
|
||||||
|
|
@ -138,7 +137,7 @@ object TestFramework
|
||||||
val arguments = testArgsByFramework withDefaultValue Nil
|
val arguments = testArgsByFramework withDefaultValue Nil
|
||||||
val mappedTests = testMap(frameworks, tests, arguments)
|
val mappedTests = testMap(frameworks, tests, arguments)
|
||||||
if(mappedTests.isEmpty)
|
if(mappedTests.isEmpty)
|
||||||
(() => (), Nil, _ => () => log.info(noTestsMessage) )
|
(() => (), Nil, _ => () => () )
|
||||||
else
|
else
|
||||||
createTestTasks(testLoader, mappedTests, log, listeners)
|
createTestTasks(testLoader, mappedTests, log, listeners)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,9 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ForkMain {
|
public class ForkMain {
|
||||||
public static final String TestsDone = "TestsDone";
|
public static enum Tags {
|
||||||
public static final String ErrorTag = "[error]";
|
Error, Warn, Info, Debug, Done;
|
||||||
public static final String WarnTag = "[warn]";
|
}
|
||||||
public static final String InfoTag = "[info]";
|
|
||||||
public static final String DebugTag = "[debug]";
|
|
||||||
|
|
||||||
static class SubclassFingerscan implements TestFingerprint, Serializable {
|
static class SubclassFingerscan implements TestFingerprint, Serializable {
|
||||||
private boolean isModule;
|
private boolean isModule;
|
||||||
|
|
@ -95,18 +93,18 @@ public class ForkMain {
|
||||||
Logger[] loggers = {
|
Logger[] loggers = {
|
||||||
new Logger() {
|
new Logger() {
|
||||||
public boolean ansiCodesSupported() { return false; }
|
public boolean ansiCodesSupported() { return false; }
|
||||||
void print(Object obj) {
|
void write(Object obj) {
|
||||||
try {
|
try {
|
||||||
os.writeObject(obj);
|
os.writeObject(obj);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Cannot write to socket");
|
System.err.println("Cannot write to socket");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void error(String s) { print(new String[]{ErrorTag, s}); }
|
public void error(String s) { write(new Object[]{Tags.Error, s}); }
|
||||||
public void warn(String s) { print(new String[]{WarnTag, s}); }
|
public void warn(String s) { write(new Object[]{Tags.Warn, s}); }
|
||||||
public void info(String s) { print(new String[]{InfoTag, s}); }
|
public void info(String s) { write(new Object[]{Tags.Info, s}); }
|
||||||
public void debug(String s) { print(new String[]{DebugTag, s}); }
|
public void debug(String s) { write(new Object[]{Tags.Debug, s}); }
|
||||||
public void trace(Throwable t) { print(t); }
|
public void trace(Throwable t) { write(t); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -144,7 +142,7 @@ public class ForkMain {
|
||||||
os.writeObject(events.toArray(new ForkEvent[events.size()]));
|
os.writeObject(events.toArray(new ForkEvent[events.size()]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os.writeObject(TestsDone);
|
os.writeObject(Tags.Done);
|
||||||
is.readObject();
|
is.readObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue