Port mutable.Specification to verify.BasicTestSuite

This commit is contained in:
Eugene Yokota 2021-01-16 00:47:53 -05:00
parent 508a4b4bb9
commit 1c6a5d21bb
18 changed files with 544 additions and 480 deletions

View File

@ -7,54 +7,43 @@
package sbt
import org.specs2.mutable.Specification
import BuildPaths.expandTildePrefix
object BuildPathsTest extends Specification {
object BuildPathsTest extends verify.BasicTestSuite {
private def assertExpandedPath(given: String, expected: String) = {
val actual = BuildPaths.expandTildePrefix(given)
actual must be equalTo (expected)
test("expandTildePrefix should expand empty path to itself") {
assertEquals("", expandTildePrefix(""))
}
"expandTildePrefix" should {
"expand empty path to itself" in {
assertExpandedPath("", "")
}
"expand /home/user/path to itself" in {
assertExpandedPath("/home/user/path", "/home/user/path")
}
"expand /~/foo/ to itself" in {
assertExpandedPath("/~/foo/", "/~/foo/")
}
"expand ~ to $HOME" in {
assertExpandedPath("~", sys.env.getOrElse("HOME", ""))
}
"expand ~/foo/bar to $HOME/foo/bar" in {
assertExpandedPath("~/foo/bar", sys.env.getOrElse("HOME", "") + "/foo/bar")
}
"expand ~+ to $PWD" in {
assertExpandedPath("~+", sys.env.getOrElse("PWD", ""))
}
"expand ~+/foo/bar to $PWD/foo/bar" in {
assertExpandedPath("~+/foo/bar", sys.env.getOrElse("PWD", "") + "/foo/bar")
}
"expand ~- to $OLDPWD" in {
assertExpandedPath("~-", sys.env.getOrElse("OLDPWD", ""))
}
"expand ~-/foo/bar to $OLDPWD/foo/bar" in {
assertExpandedPath("~-/foo/bar", sys.env.getOrElse("OLDPWD", "") + "/foo/bar")
}
test("it should expand /home/user/path to itself") {
assertEquals("/home/user/path", expandTildePrefix("/home/user/path"))
}
test("it should expand /~/foo/ to itself") {
assertEquals("/~/foo/", expandTildePrefix("/~/foo/"))
}
test("it should expand ~ to $HOME") {
assertEquals(sys.env.getOrElse("HOME", ""), expandTildePrefix("~"))
}
test("it should expand ~/foo/bar to $HOME/foo/bar") {
assertEquals(sys.env.getOrElse("HOME", "") + "/foo/bar", expandTildePrefix("~/foo/bar"))
}
test("it should expand ~+ to $PWD") {
assertEquals(sys.env.getOrElse("PWD", ""), expandTildePrefix("~+"))
}
test("it should expand ~+/foo/bar to $PWD/foo/bar") {
assertEquals(sys.env.getOrElse("PWD", "") + "/foo/bar", expandTildePrefix("~+/foo/bar"))
}
test("it should expand ~- to $OLDPWD") {
assertEquals(sys.env.getOrElse("OLDPWD", ""), expandTildePrefix("~-"))
}
test("it should expand ~-/foo/bar to $OLDPWD/foo/bar") {
assertEquals(sys.env.getOrElse("OLDPWD", "") + "/foo/bar", expandTildePrefix("~-/foo/bar"))
}
}

View File

@ -7,63 +7,77 @@
package sbt
import org.specs2.mutable.Specification
object DefaultsTest extends verify.BasicTestSuite {
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)
test("`selectedFilter` should return all tests for an empty list") {
val expected = Map("Test1" -> true, "Test2" -> true)
val filter = List.empty[String]
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
"`selectedFilter`" should {
"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)
)
}
"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)
)
}
test("it should work correctly with exact matches") {
val expected = Map("Test1" -> true, "Test2" -> false, "Foo" -> false)
val filter = List("Test1", "foo")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should work correctly with glob") {
val expected = Map("Test1" -> true, "Test2" -> true, "Foo" -> false)
val filter = List("Test*")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should work correctly with excludes") {
val expected = Map("Test1" -> true, "Test2" -> false, "Foo" -> false)
val filter = List("Test*", "-Test2")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should work correctly without includes") {
val expected = Map("Test1" -> true, "Test2" -> false, "Foo" -> true)
val filter = List("-Test2")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should work correctly with excluded globs") {
val expected = Map("Test1" -> true, "Test2" -> true, "Foo" -> false)
val filter = List("Test*", "-F*")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should cope with multiple filters") {
val expected = Map("Test1" -> true, "Test2" -> true, "Foo" -> false)
val filter = List("T*1", "T*2", "-F*")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should cope with multiple exclusion filters, no includes") {
val expected = Map("Test1" -> true, "Test2" -> true, "AAA" -> false, "Foo" -> false)
val filter = List("-A*", "-F*")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
test("it should cope with multiple exclusion filters with includes") {
val expected = Map("Test1" -> false, "Test2" -> false, "Test3" -> true)
val filter = List("T*", "-T*1", "-T*2")
assert(
expected.map(t => (t._1, Defaults.selectedFilter(filter).exists(fn => fn(t._1)))) == expected
)
}
}

View File

@ -9,7 +9,6 @@ package sbt
import java.io._
import org.specs2.mutable.Specification
import sbt.internal._
import sbt.internal.util.{
AttributeEntry,
@ -29,45 +28,41 @@ package subpackage {
}
object PluginCommandTest extends Specification {
sequential
object PluginCommandTest extends verify.BasicTestSuite {
import subpackage._
import FakeState._
"The `plugin` command" should {
"should work for plugins within nested in one package" in {
val output = processCommand(
"plugin sbt.PluginCommandTestPlugin0",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
output must contain("sbt.PluginCommandTestPlugin0 is activated.")
}
"should work for plugins nested more than one package" in {
val output = processCommand(
"plugin sbt.subpackage.PluginCommandTestPlugin1",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
output must contain("sbt.subpackage.PluginCommandTestPlugin1 is activated.")
}
"suggest a plugin when given an incorrect plugin with a similar name" in {
val output = processCommand(
"plugin PluginCommandTestPlugin0",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
output must contain(
"Not a valid plugin: PluginCommandTestPlugin0 (similar: sbt.PluginCommandTestPlugin0, sbt.subpackage.PluginCommandTestPlugin1)"
)
}
test("`plugin` command should work for plugins within nested in one package") {
val output = processCommand(
"plugin sbt.PluginCommandTestPlugin0",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
assert(output.contains("sbt.PluginCommandTestPlugin0 is activated."))
}
test("it should work for plugins nested more than one package") {
val output = processCommand(
"plugin sbt.subpackage.PluginCommandTestPlugin1",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
assert(output.contains("sbt.subpackage.PluginCommandTestPlugin1 is activated."))
}
test("it should suggest a plugin when given an incorrect plugin with a similar name") {
val output = processCommand(
"plugin PluginCommandTestPlugin0",
PluginCommandTestPlugin0,
PluginCommandTestPlugin1
)
assert(
output.contains(
"Not a valid plugin: PluginCommandTestPlugin0 (similar: sbt.PluginCommandTestPlugin0, sbt.subpackage.PluginCommandTestPlugin1)"
)
)
}
}
object FakeState {

View File

@ -7,20 +7,10 @@
package sbt
import org.specs2.Specification
class ProjectSpec extends Specification {
def is = s2"""
This is a specification to check utility methods on the Project object
Project should
normalize projectIDs if they are empty ${normalizeEmptyFileName}
"""
object ProjectSpec extends verify.BasicTestSuite {
test("Project should normalize projectIDs if they are empty") {
assert(Project.normalizeProjectID(emptyFilename) == Right("root"))
}
def emptyFilename = ""
def normalizeEmptyFileName =
Project.normalizeProjectID(emptyFilename) must equalTo(Right("root"))
}

View File

@ -7,23 +7,18 @@
package sbt.internal
import org.specs2.mutable.Specification
class AggregationSpec extends Specification {
object AggregationSpec extends verify.BasicTestSuite {
val timing = Aggregation.timing(Aggregation.defaultFormat, 0, _: Long)
"timing" should {
"format total time properly" in {
timing(101) must be startWith "Total time: 0 s,"
timing(1000) must be startWith "Total time: 1 s,"
timing(3000) must be startWith "Total time: 3 s,"
timing(30399) must be startWith "Total time: 30 s,"
timing(60399) must be startWith "Total time: 60 s,"
timing(60699) must be startWith "Total time: 61 s (01:01),"
timing(303099) must be startWith "Total time: 303 s (05:03),"
timing(6003099) must be startWith "Total time: 6003 s (01:40:03),"
timing(96003099) must be startWith "Total time: 96003 s (26:40:03),"
}
test("timing should format total time properly") {
assert(timing(101).startsWith("Total time: 0 s,"))
assert(timing(1000).startsWith("Total time: 1 s,"))
assert(timing(3000).startsWith("Total time: 3 s,"))
assert(timing(30399).startsWith("Total time: 30 s,"))
assert(timing(60399).startsWith("Total time: 60 s,"))
assert(timing(60699).startsWith("Total time: 61 s (01:01),"))
assert(timing(303099).startsWith("Total time: 303 s (05:03),"))
assert(timing(6003099).startsWith("Total time: 6003 s (01:40:03),"))
assert(timing(96003099).startsWith("Total time: 96003 s (26:40:03),"))
}
}

View File

@ -7,6 +7,4 @@
package sbt.internal.parser
import org.specs2.mutable._
trait AbstractSpec extends Specification with SplitExpression
trait AbstractSpec extends verify.BasicTestSuite with SplitExpression

View File

@ -14,30 +14,33 @@ abstract class CheckIfParsedSpec(
EvaluateConfigurations.splitExpressions
) extends AbstractSpec {
this.getClass.getName should {
"Parse sbt file " in {
foreach(files) {
case (content, description, nonEmptyImports, nonEmptyStatements) =>
println(s"""${getClass.getSimpleName}: "$description" """)
val (imports, statements) = split(content)
statements.nonEmpty must be_==(nonEmptyStatements).setMessage(s"""$description
|***${shouldContains(nonEmptyStatements)} statements***
|$content """.stripMargin)
imports.nonEmpty must be_==(nonEmptyImports).setMessage(s"""$description
|***${shouldContains(nonEmptyImports)} imports***
|$content """.stripMargin)
}
test(s"${this.getClass.getName} should parse sbt file") {
files foreach {
case (content, description, nonEmptyImports, nonEmptyStatements) =>
println(s"""${getClass.getSimpleName}: "$description" """)
val (imports, statements) = split(content)
assert(
nonEmptyStatements == statements.nonEmpty,
s"""$description
|***${shouldContains(nonEmptyStatements)} statements***
|$content """.stripMargin
)
assert(
nonEmptyImports == imports.nonEmpty,
s"""$description
|***${shouldContains(nonEmptyImports)} imports***
|$content """.stripMargin
)
}
}
private def shouldContains(b: Boolean) =
private def shouldContains(b: Boolean): String =
s"""Should ${if (b) {
"contain"
} else {
"not contain"
}}"""
protected val files: Seq[(String, String, Boolean, Boolean)]
protected def files: Seq[(String, String, Boolean, Boolean)]
}

View File

@ -7,7 +7,7 @@
package sbt.internal.parser
class CommentedXmlSpec extends CheckIfParsedSpec {
object CommentedXmlSpec extends CheckIfParsedSpec {
override protected val files = Seq(
(

View File

@ -9,44 +9,41 @@ package sbt.internal.parser
import sbt.internal.util.MessageOnlyException
class EmbeddedXmlSpec extends CheckIfParsedSpec {
object EmbeddedXmlSpec extends CheckIfParsedSpec {
"File with xml content " should {
"Handle last xml part" in {
val errorLine = """<version>4.0<version>"""
val buildSbt = s"""|
|
|name := "play-html-compressor"
|
|scalaVersion := "2.11.1"
|
|val pom = <xml:group><scm>
|<url>git@github.com:mhiva/play-html-compressor.git</url>
|<connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
| </scm>
|<developers>
| <developer>
| <id>akkie</id>
| <name>Christian Kaps</name>
| <url>http://mohiva.com</url>
| </developer>
| </developers></xml:group>
|$errorLine
|
|""".stripMargin
split(buildSbt) must throwA[MessageOnlyException].like {
case exception =>
val index = buildSbt.linesIterator.indexWhere(line => line.contains(errorLine)) + 1
val numberRegex = """(\d+)""".r
val message = exception.getMessage
val list = numberRegex.findAllIn(message).toList
list must contain(index.toString)
}
test("File with xml content should Handle last xml part") {
val errorLine = """<version>4.0<version>"""
val buildSbt = s"""|
|
|name := "play-html-compressor"
|
|scalaVersion := "2.11.1"
|
|val pom = <xml:group><scm>
|<url>git@github.com:mhiva/play-html-compressor.git</url>
|<connection>scm:git:git@github.com:mohiva/play-html-compressor.git</connection>
| </scm>
|<developers>
| <developer>
| <id>akkie</id>
| <name>Christian Kaps</name>
| <url>http://mohiva.com</url>
| </developer>
| </developers></xml:group>
|$errorLine
|
|""".stripMargin
try {
split(buildSbt)
} catch {
case exception: MessageOnlyException =>
val index = buildSbt.linesIterator.indexWhere(line => line.contains(errorLine)) + 1
val numberRegex = """(\d+)""".r
val message = exception.getMessage
val list = numberRegex.findAllIn(message).toList
assert(list.contains(index.toString))
}
}
protected val files = Seq(

View File

@ -13,29 +13,29 @@ import java.io.File
import sbt.internal.util.MessageOnlyException
import scala.io.Source
class ErrorSpec extends AbstractSpec {
object ErrorSpec extends AbstractSpec {
implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
"Parser " should {
"contains file name and line number" in {
val rootPath = getClass.getResource("/error-format/").getPath
println(s"Reading files from: $rootPath")
foreach(new File(rootPath).listFiles) { file =>
print(s"Processing ${file.getName}: ")
val buildSbt = Source.fromFile(file).getLines().mkString("\n")
SbtParser(file, buildSbt.linesIterator.toSeq) must throwA[MessageOnlyException]
.like {
case exp =>
val message = exp.getMessage
println(s"${exp.getMessage}")
message must contain(file.getName)
}
containsLineNumber(buildSbt)
test("Parser should contains file name and line number") {
val rootPath = getClass.getResource("/error-format/").getPath
println(s"Reading files from: $rootPath")
new File(rootPath).listFiles foreach { file =>
print(s"Processing ${file.getName}: ")
val buildSbt = Source.fromFile(file).getLines().mkString("\n")
try {
SbtParser(file, buildSbt.linesIterator.toSeq)
} catch {
case exp: MessageOnlyException =>
val message = exp.getMessage
println(s"${exp.getMessage}")
assert(message.contains(file.getName))
}
containsLineNumber(buildSbt)
}
}
"handle wrong parsing " in {
test("it should handle wrong parsing") {
intercept[MessageOnlyException] {
val buildSbt =
"""
|libraryDependencies ++= Seq("a" % "b" % "2") map {
@ -50,25 +50,25 @@ class ErrorSpec extends AbstractSpec {
2,
"fake.txt",
new MessageOnlyException("fake")
) must throwA[MessageOnlyException]
)
()
}
}
"handle xml error " in {
test("it should handle xml error") {
try {
val buildSbt =
"""
|val a = <a/><b/>
|val s = '
""".stripMargin
SbtParser(SbtParser.FAKE_FILE, buildSbt.linesIterator.toSeq) must throwA[
MessageOnlyException
].like {
case exp =>
val message = exp.getMessage
println(s"${exp.getMessage}")
message must contain(SbtParser.FAKE_FILE.getName)
}
SbtParser(SbtParser.FAKE_FILE, buildSbt.linesIterator.toSeq)
} catch {
case exp: MessageOnlyException =>
val message = exp.getMessage
println(s"${exp.getMessage}")
assert(message.contains(SbtParser.FAKE_FILE.getName))
}
}
private def containsLineNumber(buildSbt: String) = {

View File

@ -11,29 +11,22 @@ package parser
import java.io.File
import org.junit.runner.RunWith
import org.specs2.runner.JUnitRunner
import scala.io.Source
@RunWith(classOf[JUnitRunner])
class NewFormatSpec extends AbstractSpec {
object NewFormatSpec extends AbstractSpec {
implicit val splitter: SplitExpressions.SplitExpression = EvaluateConfigurations.splitExpressions
"New Format " should {
"Handle lines " in {
val rootPath = getClass.getResource("/new-format").getPath
println(s"Reading files from: $rootPath")
val allFiles = new File(rootPath).listFiles.toList
foreach(allFiles) { path =>
println(s"$path")
val lines = Source.fromFile(path).getLines().toList
val (_, statements) = splitter(path, lines)
statements.nonEmpty must be_==(true).setMessage(s"""
|***should contains statements***
|$lines """.stripMargin)
}
test("New Format should handle lines") {
val rootPath = getClass.getResource("/new-format").getPath
println(s"Reading files from: $rootPath")
val allFiles = new File(rootPath).listFiles.toList
allFiles foreach { path =>
println(s"$path")
val lines = Source.fromFile(path).getLines().toList
val (_, statements) = splitter(path, lines)
assert(statements.nonEmpty, s"""
|***should contains statements***
|$lines """.stripMargin)
}
}
}

View File

@ -11,9 +11,6 @@ package parser
import java.io.{ File, FilenameFilter }
import org.specs2.matcher.MatchResult
import scala.collection.GenTraversableOnce
import scala.io.Source
import SessionSettings.SessionSetting
@ -22,35 +19,32 @@ abstract class AbstractSessionSettingsSpec(folder: String) extends AbstractSpec
println(s"Reading files from: $rootPath")
protected val rootDir = new File(rootPath)
"SessionSettings " should {
"Be identical for empty map " in {
def unit(f: File) = Seq((Source.fromFile(f).getLines().toList, Seq()))
runTestOnFiles(unit)
}
test("SessionSettings should be identical for empty map") {
def unit(f: File) = Seq((Source.fromFile(f).getLines().toList, Seq()))
runTestOnFiles(unit)
}
"Replace statements " in {
runTestOnFiles(replace)
}
test("it should replace statements") {
runTestOnFiles(replace)
}
private def runTestOnFiles(
expectedResultAndMap: File => Seq[(List[String], Seq[SessionSetting])]
): MatchResult[GenTraversableOnce[File]] = {
): Unit = {
val allFiles = rootDir
.listFiles(new FilenameFilter() {
def accept(dir: File, name: String) = name.endsWith(".sbt.txt")
})
.toList
foreach(allFiles) { file =>
allFiles foreach { file =>
val originalLines = Source.fromFile(file).getLines().toList
foreach(expectedResultAndMap(file)) {
expectedResultAndMap(file) foreach {
case (expectedResultList, commands) =>
val resultList = SbtRefactorings.applySessionSettings((file, originalLines), commands)
val expected = SbtParser(file, expectedResultList)
val result = SbtParser(file, resultList._2)
result.settings must_== expected.settings
assert(result.settings == expected.settings)
}
}
}

View File

@ -11,44 +11,44 @@ package parser
import java.io.File
import org.specs2.mutable.SpecificationLike
import sbt.internal.util.LineRange
trait SplitExpression {
def split(s: String, file: File = new File("noFile"))(
implicit splitter: SplitExpressions.SplitExpression
) = splitter(file, s.split("\n").toSeq)
): (Seq[(String, Int)], Seq[(String, LineRange)]) = splitter(file, s.split("\n").toSeq)
}
trait SplitExpressionsBehavior extends SplitExpression { this: SpecificationLike =>
trait SplitExpressionsBehavior extends SplitExpression { this: verify.BasicTestSuite =>
def newExpressionsSplitter(implicit splitter: SplitExpressions.SplitExpression) = {
"parse a two settings without intervening blank line" in {
test("parse a two settings without intervening blank line") {
val (imports, settings) = split("""version := "1.0"
scalaVersion := "2.10.4"""")
imports.isEmpty should beTrue
settings.size === 2
assert(imports.isEmpty)
assert(settings.size == 2)
}
"parse a setting and val without intervening blank line" in {
test("parse a setting and val without intervening blank line") {
val (imports, settings) =
split("""version := "1.0"
lazy val root = (project in file(".")).enablePlugins­(PlayScala)""")
imports.isEmpty should beTrue
settings.size === 2
assert(imports.isEmpty)
assert(settings.size == 2)
}
"parse a config containing two imports and a setting with no blank line" in {
test("parse a config containing two imports and a setting with no blank line") {
val (imports, settingsAndDefs) = split(
"""import foo.Bar
import foo.Bar
version := "1.0"
""".stripMargin
)
imports.size === 2
settingsAndDefs.size === 1
assert(imports.size == 2)
assert(settingsAndDefs.size == 1)
}
}

View File

@ -9,10 +9,6 @@ package sbt
package internal
package parser
import org.specs2.mutable.Specification
class SplitExpressionsTest extends Specification with SplitExpressionsBehavior {
"EvaluateConfigurations" should newExpressionsSplitter(EvaluateConfigurations.splitExpressions)
object SplitExpressionsTest extends verify.BasicTestSuite with SplitExpressionsBehavior {
newExpressionsSplitter(EvaluateConfigurations.splitExpressions)
}

View File

@ -10,169 +10,233 @@ package internal
package server
import com.github.benmanes.caffeine.cache.Caffeine
import sbt.internal.inc.Analysis
class DefinitionTest extends org.specs2.mutable.Specification {
object DefinitionTest extends verify.BasicTestSuite {
import Definition.textProcessor
"text processor" should {
"find valid standard scala identifier when caret is set at the start of it" in {
textProcessor.identifier("val identifier = 0", 4) must beSome("identifier")
}
"not find valid standard scala identifier because it is '='" in {
textProcessor.identifier("val identifier = 0", 15) must beNone
}
"find valid standard scala identifier when caret is set in the middle of it" in {
textProcessor.identifier("val identifier = 0", 11) must beSome("identifier")
}
"find valid standard scala identifier with comma" in {
textProcessor.identifier("def foo(a: identifier, b: other) = ???", 13) must beSome(
"identifier"
)
}
"find valid standard short scala identifier when caret is set at the start of it" in {
textProcessor.identifier("val a = 0", 4) must beSome("a")
}
"find valid standard short scala identifier when caret is set at the end of it" in {
textProcessor.identifier("def foo(f: Int) = Foo(f)", 19) must beSome("Foo")
}
"find valid non-standard short scala identifier when caret is set at the start of it" in {
textProcessor.identifier("val == = 0", 4) must beSome("==")
}
"find valid non-standard short scala identifier when caret is set in the middle of it" in {
textProcessor.identifier("val == = 0", 5) must beSome("==")
}
"find valid non-standard short scala identifier when caret is set at the end of it" in {
textProcessor.identifier("val == = 0", 6) must beSome("==")
}
"choose longest valid standard scala identifier from scala keyword when caret is set at the start of it" in {
textProcessor.identifier("val k = 0", 0) must beSome("va") or beSome("al")
}
"choose longest valid standard scala identifier from scala keyword when caret is set in the middle of it" in {
textProcessor.identifier("val k = 0", 1) must beSome("va") or beSome("al")
}
"match symbol as class name" in {
textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A") must be_==("com.acme.A")
}
"match symbol as object name" in {
textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$") must be_==("com.acme.A$")
}
"match symbol as inner class name" in {
textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$A") must be_==("com.acme.A$A")
}
"match symbol as inner object name" in {
textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$A$") must be_==("com.acme.A$A$")
}
"match symbol as default package class name" in {
textProcessor.potentialClsOrTraitOrObj("A")("A") must be_==("A")
}
"match symbol as default package object name" in {
textProcessor.potentialClsOrTraitOrObj("A")("A$") must be_==("A$")
}
"match object in line version 1" in {
textProcessor.classTraitObjectInLine("A")(" object A ") must contain(("object A", 3))
}
"match object in line version 2" in {
textProcessor.classTraitObjectInLine("A")(" object A ") must contain(("object A", 3))
}
"match object in line version 3" in {
textProcessor.classTraitObjectInLine("A")("object A {") must contain(("object A", 0))
}
"not match object in line" in {
textProcessor.classTraitObjectInLine("B")("object A ") must be empty
}
"match class in line version 1" in {
textProcessor.classTraitObjectInLine("A")(" class A ") must contain(("class A", 3))
}
"match class in line version 2" in {
textProcessor.classTraitObjectInLine("A")(" class A ") must contain(("class A", 3))
}
"match class in line version 3" in {
textProcessor.classTraitObjectInLine("A")("class A {") must contain(("class A", 0))
}
"match class in line version 4" in {
textProcessor.classTraitObjectInLine("A")(" class A[A] ") must contain(
("class A", 3)
)
}
"match class in line version 5" in {
textProcessor.classTraitObjectInLine("A")(" class A [A] ") must contain(
("class A", 3)
)
}
"match class in line version 6" in {
textProcessor.classTraitObjectInLine("A")("class A[A[_]] {") must contain(("class A", 0))
}
"not match class in line" in {
textProcessor.classTraitObjectInLine("B")("class A ") must be empty
}
"match trait in line version 1" in {
textProcessor.classTraitObjectInLine("A")(" trait A ") must contain(("trait A", 3))
}
"match trait in line version 2" in {
textProcessor.classTraitObjectInLine("A")(" trait A ") must contain(("trait A", 3))
}
"match trait in line version 3" in {
textProcessor.classTraitObjectInLine("A")("trait A {") must contain(("trait A", 0))
}
"match trait in line version 4" in {
textProcessor.classTraitObjectInLine("A")(" trait A[A] ") must contain(
("trait A", 3)
)
}
"match trait in line version 5" in {
textProcessor.classTraitObjectInLine("A")(" trait A [A] ") must contain(
("trait A", 3)
)
}
"match trait in line version 6" in {
textProcessor.classTraitObjectInLine("A")("trait A[A[_]] {") must contain(("trait A", 0))
}
"not match trait in line" in {
textProcessor.classTraitObjectInLine("B")("trait A ") must be empty
}
test(
"text processor should find valid standard scala identifier when caret is set at the start of it"
) {
assert(textProcessor.identifier("val identifier = 0", 4) == Some("identifier"))
}
"definition" should {
test("it should not find valid standard scala identifier because it is '='") {
assert(textProcessor.identifier("val identifier = 0", 15) == None)
}
"cache data in cache" in {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
test("it should find valid standard scala identifier when caret is set in the middle of it") {
assert(textProcessor.identifier("val identifier = 0", 11) == Some("identifier"))
}
Definition.updateCache(cache)(cacheFile, useBinary)
test("it should find valid standard scala identifier with comma") {
assert(
textProcessor.identifier("def foo(a: identifier, b: other) = ???", 13) == Some("identifier")
)
}
val actual = Definition.AnalysesAccess.getFrom(cache)
test("it should find valid standard short scala identifier when caret is set at the start of it") {
assert(textProcessor.identifier("val a = 0", 4) == Some("a"))
}
actual.get should contain("Test.scala" -> true -> None)
}
test("it should find valid standard short scala identifier when caret is set at the end of it") {
assert(textProcessor.identifier("def foo(f: Int) = Foo(f)", 19) == Some("Foo"))
}
"replace cache data in cache" in {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
val falseUseBinary = false
test(
"it should find valid non-standard short scala identifier when caret is set at the start of it"
) {
assert(textProcessor.identifier("val == = 0", 4) == Some("=="))
}
Definition.updateCache(cache)(cacheFile, falseUseBinary)
Definition.updateCache(cache)(cacheFile, useBinary)
test(
"it should find valid non-standard short scala identifier when caret is set in the middle of it"
) {
assert(textProcessor.identifier("val == = 0", 5) == Some("=="))
}
val actual = Definition.AnalysesAccess.getFrom(cache)
test(
"it should find valid non-standard short scala identifier when caret is set at the end of it"
) {
assert(textProcessor.identifier("val == = 0", 6) == Some("=="))
}
actual.get should contain("Test.scala" -> true -> None)
}
test(
"it should choose longest valid standard scala identifier from scala keyword when caret is set at the start of it"
) {
assert(
textProcessor.identifier("val k = 0", 0) == Some("va") || textProcessor
.identifier("val k = 0", 0) == Some("al")
)
}
"cache more data in cache" in {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
val otherCacheFile = "OtherTest.scala"
val otherUseBinary = false
test(
"it should choose longest valid standard scala identifier from scala keyword when caret is set in the middle of it"
) {
assert(
textProcessor.identifier("val k = 0", 1) == Some("va") || textProcessor
.identifier("val k = 0", 1) == Some("al")
)
}
Definition.updateCache(cache)(otherCacheFile, otherUseBinary)
Definition.updateCache(cache)(cacheFile, useBinary)
test("it should match symbol as class name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A") == "com.acme.A")
}
val actual = Definition.AnalysesAccess.getFrom(cache)
test("it should match symbol as object name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$") == "com.acme.A$")
}
actual.get should contain("Test.scala" -> true -> None, "OtherTest.scala" -> false -> None)
}
test("it should match symbol as inner class name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$A") == "com.acme.A$A")
}
test("it should match symbol as inner object name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("com.acme.A$A$") == "com.acme.A$A$")
}
test("it should match symbol as default package class name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("A") == "A")
}
test("it should match symbol as default package object name") {
assert(textProcessor.potentialClsOrTraitOrObj("A")("A$") == "A$")
}
test("it should match object in line version 1") {
assert(textProcessor.classTraitObjectInLine("A")(" object A ").contains(("object A", 3)))
}
test("it should match object in line version 2") {
assert(
textProcessor.classTraitObjectInLine("A")(" object A ").contains(("object A", 3))
)
}
test("it should match object in line version 3") {
assert(textProcessor.classTraitObjectInLine("A")("object A {").contains(("object A", 0)))
}
test("it should not match object in line") {
assert(textProcessor.classTraitObjectInLine("B")("object A ").isEmpty)
}
test("it should match class in line version 1") {
assert(textProcessor.classTraitObjectInLine("A")(" class A ").contains(("class A", 3)))
}
test("it should match class in line version 2") {
assert(textProcessor.classTraitObjectInLine("A")(" class A ").contains(("class A", 3)))
}
test("it should match class in line version 3") {
assert(textProcessor.classTraitObjectInLine("A")("class A {").contains(("class A", 0)))
}
test("it should match class in line version 4") {
assert(
textProcessor.classTraitObjectInLine("A")(" class A[A] ").contains(("class A", 3))
)
}
test("it should match class in line version 5") {
assert(
textProcessor
.classTraitObjectInLine("A")(" class A [A] ")
.contains(
("class A", 3)
)
)
}
test("it should match class in line version 6") {
assert(textProcessor.classTraitObjectInLine("A")("class A[A[_]] {").contains(("class A", 0)))
}
test("it should not match class in line") {
assert(textProcessor.classTraitObjectInLine("B")("class A ").isEmpty)
}
test("match trait in line version 1") {
assert(textProcessor.classTraitObjectInLine("A")(" trait A ").contains(("trait A", 3)))
}
test("it should match trait in line version 2") {
assert(textProcessor.classTraitObjectInLine("A")(" trait A ").contains(("trait A", 3)))
}
test("it should match trait in line version 3") {
assert(textProcessor.classTraitObjectInLine("A")("trait A {").contains(("trait A", 0)))
}
test("it should match trait in line version 4") {
assert(
textProcessor
.classTraitObjectInLine("A")(" trait A[A] ")
.contains(
("trait A", 3)
)
)
}
test("it should match trait in line version 5") {
assert(
textProcessor
.classTraitObjectInLine("A")(" trait A [A] ")
.contains(
("trait A", 3)
)
)
}
test("it should match trait in line version 6") {
assert(textProcessor.classTraitObjectInLine("A")("trait A[A[_]] {").contains(("trait A", 0)))
}
test("it should not match trait in line") {
assert(textProcessor.classTraitObjectInLine("B")("trait A ").isEmpty)
}
test("definition should cache data in cache") {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
Definition.updateCache(cache)(cacheFile, useBinary)
val actual = Definition.AnalysesAccess.getFrom(cache)
assert(actual.get.contains(("Test.scala" -> true -> None)))
}
test("it should replace cache data in cache") {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
val falseUseBinary = false
Definition.updateCache(cache)(cacheFile, falseUseBinary)
Definition.updateCache(cache)(cacheFile, useBinary)
val actual = Definition.AnalysesAccess.getFrom(cache)
assert(actual.get.contains(("Test.scala" -> true -> None)))
}
test("it should cache more data in cache") {
val cache = Caffeine.newBuilder().build[String, Definition.Analyses]()
val cacheFile = "Test.scala"
val useBinary = true
val otherCacheFile = "OtherTest.scala"
val otherUseBinary = false
Definition.updateCache(cache)(otherCacheFile, otherUseBinary)
Definition.updateCache(cache)(cacheFile, useBinary)
val actual = Definition.AnalysesAccess.getFrom(cache)
assert(
actual.get.contains("Test.scala" -> true -> Option.empty[Analysis]) &&
actual.get.contains("OtherTest.scala" -> false -> Option.empty[Analysis])
)
}
}

View File

@ -15,6 +15,7 @@ import java.nio.file._
import java.util.concurrent._
import scala.collection.mutable
import scala.util.Properties.versionNumberString
import xsbti.{ Logger => _, _ }
import sbt.io.IO
@ -25,7 +26,7 @@ import sbt.BuildPaths._
import sbt.Def.{ ScopeLocal, ScopedKey, Setting }
import sbt.Keys._
object SettingQueryTest extends org.specs2.mutable.Specification {
object SettingQueryTest extends verify.BasicTestSuite {
implicit class PathOps(val path: Path) extends AnyVal {
def /(other: String): Path = if (other == ".") path else path resolve other
}
@ -201,50 +202,87 @@ object SettingQueryTest extends org.specs2.mutable.Specification {
payload
}
// -.- avoid specs2's ko/ok
import org.specs2.matcher.MatchResult
def qok(x: String, t: String): String => MatchResult[Any] =
query(_) must_== """{"type":"SettingQuerySuccess","value":""" + x + ""","contentType":"""" + t + """"}"""
def qko(msg: String): String => MatchResult[Any] =
query(_) must_== """{"type":"SettingQueryFailure","message":"""" + msg + """"}"""
def qok(x: String, t: String): String =
s"""{"type":"SettingQuerySuccess","value":$x,"contentType":"$t"}"""
def qko(msg: String): String =
s"""{"type":"SettingQueryFailure","message":"$msg"}"""
"setting query" should {
"t/scalaVersion" in qok("\"2.12.1\"", "java.lang.String")
// "t/pollInterval" in qok("500", "Int")
"t/sourcesInBase" in qok("true", "Boolean")
"t/startYear" in qok("null", "scala.Option[Int]")
"t/scalaArtifacts" in {
if (scala.util.Properties.versionNumberString.startsWith("2.12"))
test("t/scalaVersion") {
assertEquals(qok("\"2.12.1\"", "java.lang.String"), query("t/scalaVersion"))
}
// test("t/pollInterval") {
// assertEquals(qok("500", "Int"), query("t/pollInterval"))
// }
test("t/sourcesInBase") {
assertEquals(qok("true", "Boolean"), query("t/sourcesInBase"))
}
test("t/startYear") {
assertEquals(qok("null", "scala.Option[Int]"), query("t/startYear"))
}
test("t/scalaArtifacts") {
if (versionNumberString.startsWith("2.12"))
assertEquals(
qok(
"""["scala-library","scala-compiler","scala-reflect","scala-actors","scalap"]""",
"scala.collection.Seq[java.lang.String]"
)
else
),
query("t/scalaArtifacts"),
)
else
assertEquals(
qok(
"""["scala-library","scala-compiler","scala-reflect","scala-actors","scalap"]""",
"scala.collection.immutable.Seq[java.lang.String]"
)
}
),
query("t/scalaArtifacts"),
)
}
"t/libraryDependencies" in {
if (scala.util.Properties.versionNumberString.startsWith("2.12"))
test("t/libraryDependencies") {
if (versionNumberString.startsWith("2.12"))
assertEquals(
qok(
"""[{"organization":"org.scala-lang","name":"scala-library","revision":"2.12.1","isChanging":false,"isTransitive":true,"isForce":false,"explicitArtifacts":[],"inclusions":[],"exclusions":[],"extraAttributes":{},"crossVersion":{"type":"Disabled"}}]""",
"scala.collection.Seq[sbt.librarymanagement.ModuleID]"
)
else
),
query("t/libraryDependencies"),
)
else
assertEquals(
qok(
"""[{"organization":"org.scala-lang","name":"scala-library","revision":"2.12.1","isChanging":false,"isTransitive":true,"isForce":false,"explicitArtifacts":[],"inclusions":[],"exclusions":[],"extraAttributes":{},"crossVersion":{"type":"Disabled"}}]""",
"scala.collection.immutable.Seq[sbt.librarymanagement.ModuleID]"
)
}
),
query("t/libraryDependencies"),
)
}
"scalaVersion" in qko("Not a valid project ID: scalaVersion\\nscalaVersion\\n ^")
"t/scalacOptions" in qko(
s"""Key ProjectRef(uri(\\"$baseUri\\"), \\"t\\") / Compile / scalacOptions is a task, can only query settings"""
test("scalaVersion") {
assertEquals(
qko("Not a valid project ID: scalaVersion\\nscalaVersion\\n ^"),
query("scalaVersion"),
)
"t/fooo" in qko(
"Expected ':' (if selecting a configuration)\\nNot a valid key: fooo (similar: fork)\\nt/fooo\\n ^"
}
test("t/scalacOptions") {
assertEquals(
qko(
s"""Key ProjectRef(uri(\\"$baseUri\\"), \\"t\\") / Compile / scalacOptions is a task, can only query settings"""
),
query("t/scalacOptions"),
)
}
test("t/fooo") {
assertEquals(
qko(
"Expected ':' (if selecting a configuration)\\nNot a valid key: fooo (similar: fork)\\nt/fooo\\n ^"
),
query("t/fooo"),
)
}
}

View File

@ -94,9 +94,8 @@ object Dependencies {
val jansi = "org.fusesource.jansi" % "jansi" % "2.0.1"
val scalatest = "org.scalatest" %% "scalatest" % "3.0.8"
val scalacheck = "org.scalacheck" %% "scalacheck" % "1.14.0"
val specs2 = "org.specs2" %% "specs2-junit" % "4.10.0"
val junit = "junit" % "junit" % "4.13.1"
val scalaVerify = "com.eed3si9n.verify" %% "verify" % "0.2.0"
val scalaVerify = "com.eed3si9n.verify" %% "verify" % "1.0.0"
val templateResolverApi = "org.scala-sbt" % "template-resolver" % "0.1"
val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.3.0"

View File

@ -13,7 +13,6 @@ object NightlyPlugin extends AutoPlugin {
if (includeTestDependencies.value)
Seq(
scalacheck % Test,
specs2 % Test,
junit % Test,
scalatest % Test,
scalaVerify % Test,