From a9e06109a38d6b4683105b1e59adb2158d853378 Mon Sep 17 00:00:00 2001 From: Matthew Farwell Date: Mon, 13 Apr 2015 16:31:22 +0200 Subject: [PATCH 1/3] Added exclusions to testOnly and testQuick command line, indicated by a '-' prefix. --- main/src/main/scala/sbt/Defaults.scala | 17 ++++-- .../tests/test-exclude/project/Build.scala | 10 ++++ .../test-exclude/src/test/scala/Test.scala | 15 +++++ sbt/src/sbt-test/tests/test-exclude/test | 55 +++++++++++++++++++ 4 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 sbt/src/sbt-test/tests/test-exclude/project/Build.scala create mode 100644 sbt/src/sbt-test/tests/test-exclude/src/test/scala/Test.scala create mode 100644 sbt/src/sbt-test/tests/test-exclude/test diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 5dc348471..0c0e69821 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -566,11 +566,18 @@ object Defaults extends BuildCommon { def selectedFilter(args: Seq[String]): Seq[String => Boolean] = { - val filters = args map GlobFilter.apply - if (filters.isEmpty) + val (excludeArgs, includeArgs) = args.partition(s => s.startsWith("-")) + + val includeFilters = includeArgs map GlobFilter.apply + val excludeFilters = excludeArgs.map(_.substring(1)).map(GlobFilter.apply) + + if (includeFilters.isEmpty && excludeArgs.isEmpty) Seq(const(true)) - else - filters.map { f => (s: String) => f accept s } + else if (includeFilters.isEmpty) { + excludeFilters.map { f => (s: String) => !f.accept(s) } + } else { + includeFilters.map { f => (s: String) => (f.accept(s) && !excludeFilters.exists(x => x.accept(s))) } + } } def detectTests: Initialize[Task[Seq[TestDefinition]]] = (loadedTestFrameworks, compile, streams) map { (frameworkMap, analysis, s) => Tests.discover(frameworkMap.values.toList, analysis, s.log)._1 @@ -892,7 +899,7 @@ object Defaults extends BuildCommon { selectTests ~ options } - def distinctParser(exs: Set[String], raw: Boolean): Parser[Seq[String]] = + private def distinctParser(exs: Set[String], raw: Boolean): Parser[Seq[String]] = { import DefaultParsers._ val base = token(Space) ~> token(NotSpace - "--" examples exs) diff --git a/sbt/src/sbt-test/tests/test-exclude/project/Build.scala b/sbt/src/sbt-test/tests/test-exclude/project/Build.scala new file mode 100644 index 000000000..7f2f30f93 --- /dev/null +++ b/sbt/src/sbt-test/tests/test-exclude/project/Build.scala @@ -0,0 +1,10 @@ +import sbt._ +import Keys._ +import Defaults._ + +object B extends Build { + lazy val root = Project("root", file("."), settings = defaultSettings ++ Seq( + libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1" % "test", + parallelExecution in test := false + )) +} diff --git a/sbt/src/sbt-test/tests/test-exclude/src/test/scala/Test.scala b/sbt/src/sbt-test/tests/test-exclude/src/test/scala/Test.scala new file mode 100644 index 000000000..c7b0235e2 --- /dev/null +++ b/sbt/src/sbt-test/tests/test-exclude/src/test/scala/Test.scala @@ -0,0 +1,15 @@ +import java.io.File +import org.scalatest.FlatSpec +import org.scalatest.matchers.ShouldMatchers + +class Test1 extends FlatSpec with ShouldMatchers { + "a test" should "pass" in { + new File("target/Test1.run").createNewFile() + } +} + +class Test2 extends FlatSpec with ShouldMatchers { + "a test" should "pass" in { + new File("target/Test2.run").createNewFile() + } +} diff --git a/sbt/src/sbt-test/tests/test-exclude/test b/sbt/src/sbt-test/tests/test-exclude/test new file mode 100644 index 000000000..ec11c6a39 --- /dev/null +++ b/sbt/src/sbt-test/tests/test-exclude/test @@ -0,0 +1,55 @@ +# Test1 & Test2 create files Test1.run & Test2.run respectively + +# no parameters +> test-only +$ exists target/Test1.run +$ exists target/Test2.run + +$ delete target/Test1.run +$ delete target/Test2.run + + +# with explicit match +> test-only Test1* +$ exists target/Test1.run +-$ exists target/Test2.run + +$ delete target/Test1.run + + +# with explicit match and exclusion +> test-only Test* -Test1 +-$ exists target/Test1.run +$ exists target/Test2.run + +$ delete target/Test2.run + + +# with explicit match and exclusion +> test-only Test* -Test2 +$ exists target/Test1.run +-$ exists target/Test2.run + +$ delete target/Test1.run + + +# with only exclusion +> test-only -Test2 +$ exists target/Test1.run +-$ exists target/Test2.run + +$ delete target/Test1.run + + +# with only exclusion +> test-only -Test1 +-$ exists target/Test1.run +$ exists target/Test2.run + +$ delete target/Test2.run + + +# with only glob exclusion +> test-only -Test* +-$ exists target/Test1.run +-$ exists target/Test2.run From 0e568785340cad9abff087698d39ac7ce98d2272 Mon Sep 17 00:00:00 2001 From: Matthew Farwell Date: Tue, 14 Apr 2015 06:31:27 +0200 Subject: [PATCH 2/3] Added unit tests for Defaults.selectedFilter --- main/src/test/scala/DefaultsTest.scala | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 main/src/test/scala/DefaultsTest.scala diff --git a/main/src/test/scala/DefaultsTest.scala b/main/src/test/scala/DefaultsTest.scala new file mode 100644 index 000000000..43e8dd064 --- /dev/null +++ b/main/src/test/scala/DefaultsTest.scala @@ -0,0 +1,45 @@ +package sbt + +import java.io._ + +import org.specs2.mutable.Specification + +object DefaultsTest extends Specification { + "`selectedFilter`" should { + def assertFiltered(filter: List[String], expected: Map[String, Boolean]) = { + val actual = expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) + + actual must be equalTo (expected) + } + + "return all tests for an empty list" in { + assertFiltered(List(), Map("Test1" -> true, "Test2" -> true)) + } + + "work correctly with exact matches" in { + assertFiltered(List("Test1", "foo"), Map("Test1" -> true, "Test2" -> false, "Foo" -> false)) + } + + "work correctly with glob" in { + assertFiltered(List("Test*"), Map("Test1" -> true, "Test2" -> true, "Foo" -> false)) + } + + "work correctly with excludes" in { + assertFiltered(List("Test*", "-Test2"), Map("Test1" -> true, "Test2" -> false, "Foo" -> false)) + } + + "work correctly without includes" in { + assertFiltered(List("-Test2"), Map("Test1" -> true, "Test2" -> false, "Foo" -> true)) + } + + "work correctly with excluded globs" in { + assertFiltered(List("Test*", "-F*"), Map("Test1" -> true, "Test2" -> true, "Foo" -> false)) + } + + "cope with multiple filters" in { + assertFiltered(List("T*1", "T*2", "-F*"), Map("Test1" -> true, "Test2" -> true, "Foo" -> false)) + } + } + +} + From d4cffdddd99fb4bcb08b48f5a8899ba0e6806616 Mon Sep 17 00:00:00 2001 From: Matthew Farwell Date: Fri, 17 Apr 2015 09:28:58 +0200 Subject: [PATCH 3/3] corrected exclusion logic, added more unit tests & scripted tests --- main/src/main/scala/sbt/Defaults.scala | 12 ++++++----- main/src/test/scala/DefaultsTest.scala | 20 +++++++++++++------ .../mavenint/MavenRepositoryResolver.scala | 2 +- sbt/src/sbt-test/tests/test-exclude/test | 6 ++++++ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 0c0e69821..d0cf1145b 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -566,17 +566,19 @@ object Defaults extends BuildCommon { def selectedFilter(args: Seq[String]): Seq[String => Boolean] = { - val (excludeArgs, includeArgs) = args.partition(s => s.startsWith("-")) + def matches(nfs: Seq[NameFilter], s: String) = nfs.exists(_.accept(s)) + + val (excludeArgs, includeArgs) = args.partition(_.startsWith("-")) val includeFilters = includeArgs map GlobFilter.apply val excludeFilters = excludeArgs.map(_.substring(1)).map(GlobFilter.apply) - if (includeFilters.isEmpty && excludeArgs.isEmpty) + if (includeFilters.isEmpty && excludeArgs.isEmpty) { Seq(const(true)) - else if (includeFilters.isEmpty) { - excludeFilters.map { f => (s: String) => !f.accept(s) } + } else if (includeFilters.isEmpty) { + Seq({ (s: String) => !matches(excludeFilters, s) }) } else { - includeFilters.map { f => (s: String) => (f.accept(s) && !excludeFilters.exists(x => x.accept(s))) } + includeFilters.map { f => (s: String) => (f.accept(s) && !matches(excludeFilters, s)) } } } def detectTests: Initialize[Task[Seq[TestDefinition]]] = (loadedTestFrameworks, compile, streams) map { (frameworkMap, analysis, s) => diff --git a/main/src/test/scala/DefaultsTest.scala b/main/src/test/scala/DefaultsTest.scala index 43e8dd064..c09a806c0 100644 --- a/main/src/test/scala/DefaultsTest.scala +++ b/main/src/test/scala/DefaultsTest.scala @@ -5,13 +5,13 @@ import java.io._ import org.specs2.mutable.Specification object DefaultsTest extends Specification { + private def assertFiltered(filter: List[String], expected: Map[String, Boolean]) = { + val actual = expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) + + actual must be equalTo (expected) + } + "`selectedFilter`" should { - def assertFiltered(filter: List[String], expected: Map[String, Boolean]) = { - val actual = expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) - - actual must be equalTo (expected) - } - "return all tests for an empty list" in { assertFiltered(List(), Map("Test1" -> true, "Test2" -> true)) } @@ -39,6 +39,14 @@ object DefaultsTest extends Specification { "cope with multiple filters" in { assertFiltered(List("T*1", "T*2", "-F*"), Map("Test1" -> true, "Test2" -> true, "Foo" -> false)) } + + "cope with multiple exclusion filters, no includes" in { + assertFiltered(List("-A*", "-F*"), Map("Test1" -> true, "Test2" -> true, "AAA" -> false, "Foo" -> false)) + } + + "cope with multiple exclusion filters with includes" in { + assertFiltered(List("T*", "-T*1", "-T*2"), Map("Test1" -> false, "Test2" -> false, "Test3" -> true)) + } } } diff --git a/sbt-maven-resolver/src/main/scala/sbt/mavenint/MavenRepositoryResolver.scala b/sbt-maven-resolver/src/main/scala/sbt/mavenint/MavenRepositoryResolver.scala index 6796efcd7..6ee17cced 100644 --- a/sbt-maven-resolver/src/main/scala/sbt/mavenint/MavenRepositoryResolver.scala +++ b/sbt-maven-resolver/src/main/scala/sbt/mavenint/MavenRepositoryResolver.scala @@ -259,7 +259,7 @@ abstract class MavenRepositoryResolver(settings: IvySettings) extends AbstractRe // Here we add in additional artifact requests, which ALLWAYS have to be explicit since // Maven/Aether doesn't include all known artifacts in a pom.xml // TODO - This does not appear to be working correctly. - if (dd.getAllDependencyArtifacts.isEmpty) { + if (dd.getAllDependencyArtifacts.isEmpty) { val artifactId = s"${drid.getName}-${drid.getRevision}" // Add the artifacts we know about the module packaging match { diff --git a/sbt/src/sbt-test/tests/test-exclude/test b/sbt/src/sbt-test/tests/test-exclude/test index ec11c6a39..913c97312 100644 --- a/sbt/src/sbt-test/tests/test-exclude/test +++ b/sbt/src/sbt-test/tests/test-exclude/test @@ -53,3 +53,9 @@ $ delete target/Test2.run > test-only -Test* -$ exists target/Test1.run -$ exists target/Test2.run + + +# with only glob exclusion +> test-only -T*1 -T*2 +-$ exists target/Test1.run +-$ exists target/Test2.run