diff --git a/sbt/src/sbt-test/tests/nested-subproc/build.sbt b/sbt/src/sbt-test/tests/nested-subproc/build.sbt new file mode 100644 index 000000000..f2336a77e --- /dev/null +++ b/sbt/src/sbt-test/tests/nested-subproc/build.sbt @@ -0,0 +1,7 @@ +scalaVersion := "2.10.1" + +libraryDependencies += "org.scalatest" %% "scalatest" % "2.0.M6-SNAP15" + +testOptions in Test += Tests.Argument("-r", "custom.CustomReporter") + +fork := true \ No newline at end of file diff --git a/sbt/src/sbt-test/tests/nested-subproc/src/main/scala/custom/CustomReporter.scala b/sbt/src/sbt-test/tests/nested-subproc/src/main/scala/custom/CustomReporter.scala new file mode 100644 index 000000000..f21595450 --- /dev/null +++ b/sbt/src/sbt-test/tests/nested-subproc/src/main/scala/custom/CustomReporter.scala @@ -0,0 +1,30 @@ +package custom + +import java.io._ +import org.scalatest._ +import events._ + +class CustomReporter extends Reporter { + + private def writeFile(filePath: String, content: String) { + val file = new File(filePath) + val writer = + if (!file.exists) + new FileWriter(new File(filePath)) + else + new FileWriter(new File(filePath + "-2")) + writer.write(content) + writer.flush() + writer.close() + } + + def apply(event: Event) { + event match { + case SuiteStarting(_, suiteName, _, _, _, _, _, _, _, _) => writeFile("target/SuiteStarting-" + suiteName, suiteName) + case SuiteCompleted(_, suiteName, _, _, _, _, _, _, _, _, _) => writeFile("target/SuiteCompleted-" + suiteName, suiteName) + case TestStarting(_, _, _, _, testName, _, _, _, _, _, _, _) => writeFile("target/TestStarting-" + testName, testName) + case TestSucceeded(_, _, _, _, testName, _, _, _, _, _, _, _, _, _) => writeFile("target/TestSucceeded-" + testName, testName) + case _ => + } + } +} \ No newline at end of file diff --git a/sbt/src/sbt-test/tests/nested-subproc/src/test/scala/com/test/NestedSpecs.scala b/sbt/src/sbt-test/tests/nested-subproc/src/test/scala/com/test/NestedSpecs.scala new file mode 100644 index 000000000..b9d5a838f --- /dev/null +++ b/sbt/src/sbt-test/tests/nested-subproc/src/test/scala/com/test/NestedSpecs.scala @@ -0,0 +1,17 @@ +package com.test + +import org.scalatest._ + +class NestedSpecs extends Suites ( + new TestSpec +) + +@DoNotDiscover +class TestSpec extends Spec { + + def `TestSpec-test-1 ` {} + + def `TestSpec-test-2 ` {} + + def `TestSpec-test-3 ` {} +} \ No newline at end of file diff --git a/sbt/src/sbt-test/tests/nested-subproc/test b/sbt/src/sbt-test/tests/nested-subproc/test new file mode 100644 index 000000000..faf8391a9 --- /dev/null +++ b/sbt/src/sbt-test/tests/nested-subproc/test @@ -0,0 +1,48 @@ +#This test that the framework will execute ScalaTest nested suites as sequential nested task (SubProcess) properly. +#A CustomReporter is used to report expected ScalaTest's events by writing out to files in target/, +#it is then used to check for their existence, and if the expected event is fired > 1 (which is unexpected), +#a xxxx-2 file will be written, thus here we also check for 'absent' of such file. + +> clean + +> test + +$ exists target/SuiteStarting-NestedSpecs + +$ absent target/SuiteStarting-NestedSpecs-2 + +$ exists target/SuiteCompleted-NestedSpecs + +$ absent target/SuiteCompleted-NestedSpecs-2 + +$ exists target/SuiteStarting-TestSpec + +$ absent target/SuiteStarting-TestSpec-2 + +$ exists target/SuiteCompleted-TestSpec + +$ absent target/SuiteCompleted-TestSpec-2 + +$ exists target/TestStarting-TestSpec-test-1 + +$ absent target/TestStarting-TestSpec-test-1-2 + +$ exists target/TestSucceeded-TestSpec-test-1 + +$ absent target/TestSucceeded-TestSpec-test-1-2 + +$ exists target/TestStarting-TestSpec-test-2 + +$ absent target/TestStarting-TestSpec-test-2-2 + +$ exists target/TestSucceeded-TestSpec-test-2 + +$ absent target/TestSucceeded-TestSpec-test-2-2 + +$ exists target/TestStarting-TestSpec-test-3 + +$ absent target/TestStarting-TestSpec-test-3-2 + +$ exists target/TestSucceeded-TestSpec-test-3 + +$ absent target/TestSucceeded-TestSpec-test-3-2 \ No newline at end of file diff --git a/testing/agent/src/main/java/sbt/ForkMain.java b/testing/agent/src/main/java/sbt/ForkMain.java index 43950dafd..8ec30b795 100755 --- a/testing/agent/src/main/java/sbt/ForkMain.java +++ b/testing/agent/src/main/java/sbt/ForkMain.java @@ -13,6 +13,7 @@ import java.net.Socket; import java.net.InetAddress; import java.util.ArrayList; import java.util.List; +import java.util.Arrays; public class ForkMain { static class SubclassFingerscan implements SubclassFingerprint, Serializable { @@ -225,21 +226,63 @@ public class ForkMain { write(os, ForkTags.Done); is.readObject(); } + class NestedTask { + private String parentName; + private Task task; + NestedTask(String parentName, Task task) { + this.parentName = parentName; + this.task = task; + } + public String getParentName() { + return parentName; + } + public Task getTask() { + return task; + } + } void runTestSafe(ForkTestDefinition test, Runner runner, Logger[] loggers, ObjectOutputStream os) { - ForkEvent[] events; try { - events = runTest(test, runner, loggers, os); + // TODO: To pass in correct explicitlySpecified and selectors + Task task = runner.task(test.name, test.fingerprint, false, new Selector[] { new SuiteSelector() }); + + List nestedTasks = new ArrayList(); + for (Task nt : runTest(test, task, loggers, os)) + nestedTasks.add(new NestedTask(test.name, nt)); + while (true) { + List newNestedTasks = new ArrayList(); + int nestedTasksLength = nestedTasks.size(); + for (int i = 0; i < nestedTasksLength; i++) { + NestedTask nestedTask = nestedTasks.get(i); + String nestedParentName = nestedTask.getParentName() + "-" + i; + for (Task nt : runTest(new ForkTestDefinition(nestedParentName, test.fingerprint), nestedTask.getTask(), loggers, os)) { + newNestedTasks.add(new NestedTask(nestedParentName, nt)); + } + } + if (newNestedTasks.size() == 0) + break; + else { + nestedTasks = newNestedTasks; + } + } } catch (Throwable t) { + writeEvents(os, test, new ForkEvent[] { testError(os, test, "Uncaught exception when running " + test.name + ": " + t.toString(), t) }); + } + } + Task[] runTest(ForkTestDefinition test, Task task, Logger[] loggers, ObjectOutputStream os) { + ForkEvent[] events; + Task[] nestedTasks; + try { + final List eventList = new ArrayList(); + EventHandler handler = new EventHandler() { public void handle(Event e){ eventList.add(new ForkEvent(e)); } }; + nestedTasks = task.execute(handler, loggers); + events = eventList.toArray(new ForkEvent[eventList.size()]); + } + catch (Throwable t) { + nestedTasks = new Task[0]; events = new ForkEvent[] { testError(os, test, "Uncaught exception when running " + test.name + ": " + t.toString(), t) }; } writeEvents(os, test, events); - } - ForkEvent[] runTest(ForkTestDefinition test, Runner runner, Logger[] loggers, ObjectOutputStream os) { - final List events = new ArrayList(); - EventHandler handler = new EventHandler() { public void handle(Event e){ events.add(new ForkEvent(e)); } }; - // TODO: To pass in correct explicitlySpecified and selectors - runner.task(test.name, test.fingerprint, false, new Selector[] { new SuiteSelector() }).execute(handler, loggers); - return events.toArray(new ForkEvent[events.size()]); + return nestedTasks; } void run(ObjectInputStream is, ObjectOutputStream os) throws Exception { try {