From dc47aa6f7f5d9737b593d9d8cfd532879cffad1b Mon Sep 17 00:00:00 2001 From: Oleksii Lisikh Date: Fri, 24 May 2019 19:52:07 +0200 Subject: [PATCH] Fixed bug: ConcurrentModificationException during project evaluation --- ...aMultiModuleWithMultipleTestTasksTest.java | 328 ++++++++++++++++++ .../a/build.gradle | 3 + .../scala/org/hello/a/WorldAIntSuite.scala | 13 + .../a/src/main/scala/org/hello/a/WorldA.scala | 16 + .../scala/org/hello/a/TestNothingASuite.scala | 12 + .../test/scala/org/hello/a/WorldASuite.scala | 13 + .../b/build.gradle | 3 + .../scala/org/hello/b/WorldBIntSuite.scala | 13 + .../b/src/main/scala/org/hello/b/WorldB.scala | 16 + .../scala/org/hello/b/TestNothingBSuite.scala | 12 + .../test/scala/org/hello/b/WorldBSuite.scala | 13 + .../build.gradle | 61 ++++ .../scala/org/hello/common/WorldCommon.scala | 9 + .../hello/common/TestNothingCommonSuite.scala | 12 + .../org/hello/common/WorldCommonSuite.scala | 13 + .../settings.gradle | 1 + .../scala/org/hello/TestNothingSuite.scala | 12 + .../scala/org/hello/WorldIntSuite.scala | 13 + .../src/main/scala/org/hello/World.scala | 11 + .../scala/org/hello/TestNothingSuite.scala | 12 + .../src/test/scala/org/hello/WorldSuite.scala | 13 + .../org/scoverage/ScoveragePlugin.groovy | 8 +- 22 files changed, 604 insertions(+), 3 deletions(-) create mode 100644 src/functionalTest/java/org.scoverage/ScalaMultiModuleWithMultipleTestTasksTest.java create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/build.gradle create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/intTest/scala/org/hello/a/WorldAIntSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/main/scala/org/hello/a/WorldA.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/TestNothingASuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/WorldASuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/build.gradle create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/intTest/scala/org/hello/b/WorldBIntSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/main/scala/org/hello/b/WorldB.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/TestNothingBSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/WorldBSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/build.gradle create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/main/scala/org/hello/common/WorldCommon.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/WorldCommonSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/settings.gradle create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/TestNothingSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/WorldIntSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/main/scala/org/hello/World.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/TestNothingSuite.scala create mode 100644 src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/WorldSuite.scala diff --git a/src/functionalTest/java/org.scoverage/ScalaMultiModuleWithMultipleTestTasksTest.java b/src/functionalTest/java/org.scoverage/ScalaMultiModuleWithMultipleTestTasksTest.java new file mode 100644 index 0000000..1905a1c --- /dev/null +++ b/src/functionalTest/java/org.scoverage/ScalaMultiModuleWithMultipleTestTasksTest.java @@ -0,0 +1,328 @@ +package org.scoverage; + +import org.junit.Assert; +import org.junit.Test; + + +import java.io.File; + + +public class ScalaMultiModuleWithMultipleTestTasksTest extends ScoverageFunctionalTest { + + + public ScalaMultiModuleWithMultipleTestTasksTest() { + super("scala-multi-module-multiple-test-tasks"); + } + + @Test + public void reportScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("intTest"); + result.assertTaskExists("reportIntTestScoverage"); + result.assertTaskExists("a:intTest"); + result.assertTaskExists("b:intTest"); + result.assertTaskExists("common:intTest"); + result.assertTaskExists("a:reportIntTestScoverage"); + result.assertTaskExists("b:reportIntTestScoverage"); + result.assertTaskExists("common:reportIntTestScoverage"); + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void reportScoverageOnlyRoot() { + + AssertableBuildResult result = dryRun("clean", ":" + ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void reportScoverageOnlyA() { + + AssertableBuildResult result = dryRun("clean", ":a:" + ScoveragePlugin.getREPORT_NAME()); + + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void aggregateScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + } + + @Test + public void checkScoverage() { + + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkScoverageOnlyRoot() { + + AssertableBuildResult result = dryRun("clean", ":" + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkScoverageOnlyA() { + + AssertableBuildResult result = dryRun("clean", ":a:" + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskDoesntExist(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskDoesntExist(ScoveragePlugin.getAGGREGATE_NAME()); + } + + @Test + public void checkScoverageWithoutIntTests() { + AssertableBuildResult result = dryRun("clean", ScoveragePlugin.getCHECK_NAME(), + "-x", "intTest"); + + result.assertTaskExists(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskExists("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskDoesntExist("intTest"); + result.assertTaskExists("reportIntTestScoverage"); + result.assertTaskDoesntExist("a:intTest"); + result.assertTaskDoesntExist("b:intTest"); + result.assertTaskDoesntExist("common:intTest"); + result.assertTaskExists("a:reportIntTestScoverage"); + result.assertTaskExists("b:reportIntTestScoverage"); + result.assertTaskExists("common:reportIntTestScoverage"); + } + + @Test + public void checkAndAggregateScoverage() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME()); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + } + + @Test + public void checkScoverageWithoutCoverageInRoot() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.WorldASuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite", + "-x", "intTest"); + + result.assertTaskFailed(ScoveragePlugin.getCHECK_NAME()); + + assertRootReportFilesExist(); + assertCoverage(0.0); + } + + @Test + public void checkScoverageWithoutCoverageInA() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + "test", + "--tests", "org.hello.a.TestNothingASuite", + "--tests", "org.hello.WorldSuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite", + "-x", ":a:intTest"); + + result.assertTaskFailed("a:" + ScoveragePlugin.getCHECK_NAME()); + + assertAReportFilesExist(); + assertCoverage(0.0, reportDir(projectDir().toPath().resolve("a").toFile())); + } + + @Test + public void checkScoverageWithoutNormalCompilationAndWithoutCoverageInCommon() throws Exception { + + AssertableBuildResult result = runAndFail("clean", + ":a:test", + ":common:test", "--tests", "org.hello.common.TestNothingCommonSuite", + "-x", "compileScala", + ScoveragePlugin.getCHECK_NAME()); + + result.assertTaskFailed("common:" + ScoveragePlugin.getCHECK_NAME()); + + assertCommonReportFilesExist(); + assertCoverage(0.0, reportDir(projectDir().toPath().resolve("common").toFile())); + } + + @Test + public void checkAndAggregateScoverageWithoutCoverageInRoot() throws Exception { + + // should pass as the check on the root is for the aggregation (which covers > 50%) + + AssertableBuildResult result = run("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME(), "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.WorldASuite", + "--tests", "org.hello.b.WorldBSuite", + "--tests", "org.hello.common.WorldCommonSuite"); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCHECK_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(93.33); + } + + @Test + public void checkAndAggregateScoverageWithoutCoverageInAll() throws Exception { + + AssertableBuildResult result = runAndFail("clean", ScoveragePlugin.getCHECK_NAME(), + ScoveragePlugin.getAGGREGATE_NAME(), "test", + "--tests", "org.hello.TestNothingSuite", + "--tests", "org.hello.a.TestNothingASuite", + "--tests", "org.hello.b.TestNothingBSuite", + "--tests", "org.hello.common.TestNothingCommonSuite", + "-x", "intTest"); + + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + result.assertTaskFailed(ScoveragePlugin.getCHECK_NAME()); + + assertAllReportFilesExist(); + assertCoverage(0.0); + } + + @Test + public void aggregateScoverageWithoutNormalCompilation() throws Exception { + + AssertableBuildResult result = run("clean", ScoveragePlugin.getAGGREGATE_NAME(), + "-x", "compileScala"); + + result.assertTaskSkipped("compileScala"); + result.assertTaskSkipped("a:compileScala"); + result.assertTaskSkipped("b:compileScala"); + result.assertTaskSkipped("common:compileScala"); + result.assertTaskSucceeded(ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getCOMPILE_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("a:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("b:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded("common:" + ScoveragePlugin.getREPORT_NAME()); + result.assertTaskSucceeded(ScoveragePlugin.getAGGREGATE_NAME()); + + assertAllReportFilesExist(); + assertCoverage(100.0); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "a")), "classes/scala/main/org/hello/a/WorldA.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "a")), "classes/scala/scoverage/org/hello/a/WorldA.class").exists()); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "b")), "classes/scala/main/org/hello/b/WorldB.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "b")), "classes/scala/scoverage/org/hello/b/WorldB.class").exists()); + + Assert.assertTrue(resolve(buildDir(resolve(projectDir(), "common")), "classes/scala/main/org/hello/common/WorldCommon.class").exists()); + Assert.assertFalse(resolve(buildDir(resolve(projectDir(), "common")), "classes/scala/scoverage/org/hello/common/WorldCommon.class").exists()); + } + + private void assertAllReportFilesExist() { + + assertRootReportFilesExist(); + assertAReportFilesExist(); + assertBReportFilesExist(); + assertCommonReportFilesExist(); + assertAggregationFilesExist(); + } + + private void assertAggregationFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "a/src/main/scala/org/hello/a/WorldA.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "b/src/main/scala/org/hello/b/WorldB.scala.html").exists()); + Assert.assertTrue(resolve(reportDir(), "common/src/main/scala/org/hello/common/WorldCommon.scala.html").exists()); + } + + private void assertRootReportFilesExist() { + + Assert.assertTrue(resolve(reportDir(), "index.html").exists()); + Assert.assertTrue(resolve(reportDir(), "src/main/scala/org/hello/World.scala.html").exists()); + } + + private void assertAReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("a").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/a/WorldA.scala.html").exists()); + } + + private void assertBReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("b").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/b/WorldB.scala.html").exists()); + } + + private void assertCommonReportFilesExist() { + + File reportDir = reportDir(projectDir().toPath().resolve("common").toFile()); + Assert.assertTrue(resolve(reportDir, "index.html").exists()); + Assert.assertTrue(resolve(reportDir, "src/main/scala/org/hello/common/WorldCommon.scala.html").exists()); + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/build.gradle new file mode 100644 index 0000000..368d0bc --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile project(":common") +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/intTest/scala/org/hello/a/WorldAIntSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/intTest/scala/org/hello/a/WorldAIntSuite.scala new file mode 100644 index 0000000..2abf597 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/intTest/scala/org/hello/a/WorldAIntSuite.scala @@ -0,0 +1,13 @@ +package org.hello.a + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldAIntSuite extends FunSuite { + + test("barA") { + new WorldA().barA() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/main/scala/org/hello/a/WorldA.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/main/scala/org/hello/a/WorldA.scala new file mode 100644 index 0000000..a564416 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/main/scala/org/hello/a/WorldA.scala @@ -0,0 +1,16 @@ +package org.hello.a + +import org.hello.common.WorldCommon + +class WorldA { + + def fooA(): String = { + val s = "a" + new WorldCommon().fooCommon() + s + } + + def barA(): String = { + val s = "a" + new WorldCommon().fooCommon() + s + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/TestNothingASuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/TestNothingASuite.scala new file mode 100644 index 0000000..ad764b7 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/TestNothingASuite.scala @@ -0,0 +1,12 @@ +package org.hello.a + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingASuite extends FunSuite { + + test("nothing") { + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/WorldASuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/WorldASuite.scala new file mode 100644 index 0000000..727de09 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/a/src/test/scala/org/hello/a/WorldASuite.scala @@ -0,0 +1,13 @@ +package org.hello.a + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldASuite extends FunSuite { + + test("fooA") { + new WorldA().fooA() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/build.gradle new file mode 100644 index 0000000..368d0bc --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/build.gradle @@ -0,0 +1,3 @@ +dependencies { + compile project(":common") +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/intTest/scala/org/hello/b/WorldBIntSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/intTest/scala/org/hello/b/WorldBIntSuite.scala new file mode 100644 index 0000000..a4c8ddf --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/intTest/scala/org/hello/b/WorldBIntSuite.scala @@ -0,0 +1,13 @@ +package org.hello.b + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldBIntSuite extends FunSuite { + + test("barB") { + new WorldB().barB() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/main/scala/org/hello/b/WorldB.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/main/scala/org/hello/b/WorldB.scala new file mode 100644 index 0000000..67f27cd --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/main/scala/org/hello/b/WorldB.scala @@ -0,0 +1,16 @@ +package org.hello.b + +import org.hello.common.WorldCommon + +class WorldB { + + def fooB(): String = { + val s = "b" + new WorldCommon().fooCommon() + s + } + + def barB(): String = { + val s = "b" + new WorldCommon().fooCommon() + s + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/TestNothingBSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/TestNothingBSuite.scala new file mode 100644 index 0000000..502fc77 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/TestNothingBSuite.scala @@ -0,0 +1,12 @@ +package org.hello.b + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingBSuite extends FunSuite { + + test("nothing") { + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/WorldBSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/WorldBSuite.scala new file mode 100644 index 0000000..f32f22f --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/b/src/test/scala/org/hello/b/WorldBSuite.scala @@ -0,0 +1,13 @@ +package org.hello.b + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldBSuite extends FunSuite { + + test("fooB") { + new WorldB().fooB() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/build.gradle b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/build.gradle new file mode 100644 index 0000000..af0a9b3 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/build.gradle @@ -0,0 +1,61 @@ +plugins { + id 'org.scoverage' +} + +allprojects { + repositories { + jcenter() + } +} + +description = 'a multi-module Scala project that builds successfully with 100% coverage' + +allprojects { + + apply plugin: 'java' + apply plugin: 'scala' + + dependencies { + compile group: 'org.scala-lang', name: 'scala-library', version: "${scalaVersionMajor}.${scalaVersionMinor}.${scalaVersionBuild}" + + testRuntime group: 'org.junit.vintage', name: 'junit-vintage-engine', version: junitVersion + testCompile group: 'org.junit.platform', name: 'junit-platform-runner', version: junitPlatformVersion + + testCompile group: 'org.scalatest', name: "scalatest_${scalaVersionMajor}.${scalaVersionMinor}", version: scalatestVersion + } + + test { + useJUnitPlatform() + maxParallelForks = 1 + } + + configurations { + intTestCompile.extendsFrom testCompile + intTestRuntime.extendsFrom testRuntime + } + sourceSets { + intTest { + resources.srcDir file('src/intTest/resources') + scala { + compileClasspath += main.output + test.output + runtimeClasspath += main.output + test.output + srcDir file("${projectDir}/src/intTest/scala") + } + } + } + + + task intTest(type: Test) { + testClassesDirs = sourceSets.intTest.output.classesDirs + classpath = sourceSets.intTest.runtimeClasspath + outputs.upToDateWhen { false } + + maxParallelForks = 1 + } + check.dependsOn(intTest) + intTest.mustRunAfter(test) + + scoverage { + minimumRate = 0.5 + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/main/scala/org/hello/common/WorldCommon.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/main/scala/org/hello/common/WorldCommon.scala new file mode 100644 index 0000000..5fe6c6e --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/main/scala/org/hello/common/WorldCommon.scala @@ -0,0 +1,9 @@ +package org.hello.common + +class WorldCommon { + + def fooCommon(): String = { + val s = "common" + "a" + s + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala new file mode 100644 index 0000000..9e74f75 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/TestNothingCommonSuite.scala @@ -0,0 +1,12 @@ +package org.hello.common + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingCommonSuite extends FunSuite { + + test("nothing") { + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/WorldCommonSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/WorldCommonSuite.scala new file mode 100644 index 0000000..d906699 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/common/src/test/scala/org/hello/common/WorldCommonSuite.scala @@ -0,0 +1,13 @@ +package org.hello.common + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldCommonSuite extends FunSuite { + + test("fooCommon") { + new WorldCommon().fooCommon() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/settings.gradle b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/settings.gradle new file mode 100644 index 0000000..46ba372 --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/settings.gradle @@ -0,0 +1 @@ +include 'a', 'b', 'common' diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/TestNothingSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/TestNothingSuite.scala new file mode 100644 index 0000000..b8599be --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/TestNothingSuite.scala @@ -0,0 +1,12 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingSuite extends FunSuite { + + test("nothing") { + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/WorldIntSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/WorldIntSuite.scala new file mode 100644 index 0000000..f884b8b --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/intTest/scala/org/hello/WorldIntSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldIntSuite extends FunSuite { + + test("bar") { + new World().bar() + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/main/scala/org/hello/World.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/main/scala/org/hello/World.scala new file mode 100644 index 0000000..f07b25e --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/main/scala/org/hello/World.scala @@ -0,0 +1,11 @@ +package org.hello + +class World { + + def foo(): String = { + val s = "a" + "b" + s + } + + def bar(): String = "bar" +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/TestNothingSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/TestNothingSuite.scala new file mode 100644 index 0000000..b8599be --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/TestNothingSuite.scala @@ -0,0 +1,12 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class TestNothingSuite extends FunSuite { + + test("nothing") { + } +} diff --git a/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/WorldSuite.scala b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/WorldSuite.scala new file mode 100644 index 0000000..1aa434c --- /dev/null +++ b/src/functionalTest/resources/projects/scala-multi-module-multiple-test-tasks/src/test/scala/org/hello/WorldSuite.scala @@ -0,0 +1,13 @@ +package org.hello + +import org.junit.runner.RunWith +import org.scalatest.FunSuite +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class WorldSuite extends FunSuite { + + test("foo") { + new World().foo() + } +} diff --git a/src/main/groovy/org/scoverage/ScoveragePlugin.groovy b/src/main/groovy/org/scoverage/ScoveragePlugin.groovy index c0492a9..1a4e6c4 100644 --- a/src/main/groovy/org/scoverage/ScoveragePlugin.groovy +++ b/src/main/groovy/org/scoverage/ScoveragePlugin.groovy @@ -123,7 +123,9 @@ class ScoveragePlugin implements Plugin { def globalCheckTask = project.tasks.register(CHECK_NAME, OverallCheckTask) project.afterEvaluate { - def testTasks = project.tasks.withType(Test) + // calling toList() on TaskCollection is required + // to avoid potential ConcurrentModificationException in multi-project builds + def testTasks = project.tasks.withType(Test).toList() List reportTasks = testTasks.collect { testTask -> testTask.mustRunAfter(compileTask) @@ -319,7 +321,7 @@ class ScoveragePlugin implements Plugin { private Set recursiveDependenciesOf(Task task) { if (!taskDependencies.containsKey(task)) { def directDependencies = task.getTaskDependencies().getDependencies(task) - def nestedDependencies = directDependencies.collect {recursiveDependenciesOf(it) }.flatten() + def nestedDependencies = directDependencies.collect { recursiveDependenciesOf(it) }.flatten() def dependencies = directDependencies + nestedDependencies taskDependencies.put(task, dependencies) @@ -328,4 +330,4 @@ class ScoveragePlugin implements Plugin { return taskDependencies.get(task) } } -} \ No newline at end of file +}