mirror of https://github.com/sbt/sbt.git
Use scripted engine from sbt/util
This commit is contained in:
parent
91093b32dd
commit
9bc50e558e
17
build.sbt
17
build.sbt
|
|
@ -130,20 +130,13 @@ lazy val runProj = (project in file("run")).
|
||||||
utilLogging, (utilLogging % Test).classifier("tests"), compilerClasspath)
|
utilLogging, (utilLogging % Test).classifier("tests"), compilerClasspath)
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val scriptedBaseProj = (project in scriptedPath / "base").
|
|
||||||
settings(
|
|
||||||
testedBaseSettings,
|
|
||||||
name := "Scripted Framework",
|
|
||||||
libraryDependencies ++= scalaParsers.value ++ Seq(sbtIO)
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val scriptedSbtProj = (project in scriptedPath / "sbt").
|
lazy val scriptedSbtProj = (project in scriptedPath / "sbt").
|
||||||
dependsOn(scriptedBaseProj, commandProj).
|
dependsOn(commandProj).
|
||||||
settings(
|
settings(
|
||||||
baseSettings,
|
baseSettings,
|
||||||
name := "Scripted sbt",
|
name := "Scripted sbt",
|
||||||
libraryDependencies ++= Seq(launcherInterface % "provided",
|
libraryDependencies ++= Seq(launcherInterface % "provided",
|
||||||
sbtIO, utilLogging, compilerInterface)
|
sbtIO, utilLogging, compilerInterface, utilScripted)
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val scriptedPluginProj = (project in scriptedPath / "plugin").
|
lazy val scriptedPluginProj = (project in scriptedPath / "plugin").
|
||||||
|
|
@ -236,7 +229,7 @@ lazy val myProvided = config("provided") intransitive
|
||||||
|
|
||||||
def allProjects = Seq(
|
def allProjects = Seq(
|
||||||
testingProj, testAgentProj, taskProj, stdTaskProj, runProj,
|
testingProj, testAgentProj, taskProj, stdTaskProj, runProj,
|
||||||
scriptedBaseProj, scriptedSbtProj, scriptedPluginProj,
|
scriptedSbtProj, scriptedPluginProj,
|
||||||
actionsProj, commandProj, mainSettingsProj, mainProj, sbtProj, bundledLauncherProj, mavenResolverPluginProj)
|
actionsProj, commandProj, mainSettingsProj, mainProj, sbtProj, bundledLauncherProj, mavenResolverPluginProj)
|
||||||
|
|
||||||
def projectsWithMyProvided = allProjects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided))
|
def projectsWithMyProvided = allProjects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided))
|
||||||
|
|
@ -266,7 +259,7 @@ def otherRootSettings = Seq(
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
lazy val docProjects: ScopeFilter = ScopeFilter(
|
lazy val docProjects: ScopeFilter = ScopeFilter(
|
||||||
inAnyProject -- inProjects(sbtRoot, sbtProj, scriptedBaseProj, scriptedSbtProj, scriptedPluginProj, mavenResolverPluginProj),
|
inAnyProject -- inProjects(sbtRoot, sbtProj, scriptedSbtProj, scriptedPluginProj, mavenResolverPluginProj),
|
||||||
inConfigurations(Compile)
|
inConfigurations(Compile)
|
||||||
)
|
)
|
||||||
def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq(
|
def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq(
|
||||||
|
|
@ -300,7 +293,7 @@ lazy val otherUnitTests = taskKey[Unit]("Unit test other projects")
|
||||||
lazy val otherProjects: ScopeFilter = ScopeFilter(
|
lazy val otherProjects: ScopeFilter = ScopeFilter(
|
||||||
inProjects(
|
inProjects(
|
||||||
testingProj, testAgentProj, taskProj,
|
testingProj, testAgentProj, taskProj,
|
||||||
scriptedBaseProj, scriptedSbtProj, scriptedPluginProj,
|
scriptedSbtProj, scriptedPluginProj,
|
||||||
commandProj, mainSettingsProj, mainProj,
|
commandProj, mainSettingsProj, mainProj,
|
||||||
sbtProj, mavenResolverPluginProj),
|
sbtProj, mavenResolverPluginProj),
|
||||||
inConfigurations(Test)
|
inConfigurations(Test)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ object Dependencies {
|
||||||
lazy val scala211 = "2.11.7"
|
lazy val scala211 = "2.11.7"
|
||||||
|
|
||||||
// sbt modules
|
// sbt modules
|
||||||
val utilVersion = "0.1.0-M5"
|
val utilVersion = "0.1.0-M8"
|
||||||
val ioVersion = "1.0.0-M3"
|
val ioVersion = "1.0.0-M3"
|
||||||
val incremenalcompilerVersion = "0.1.0-M1-168cb7a4877917e01917e35b9b82a62afe5c2a01"
|
val incremenalcompilerVersion = "0.1.0-M1-168cb7a4877917e01917e35b9b82a62afe5c2a01"
|
||||||
val librarymanagementVersion = "0.1.0-M4"
|
val librarymanagementVersion = "0.1.0-M4"
|
||||||
|
|
@ -23,6 +23,7 @@ object Dependencies {
|
||||||
lazy val utilRelation = "org.scala-sbt" %% "util-relation" % utilVersion
|
lazy val utilRelation = "org.scala-sbt" %% "util-relation" % utilVersion
|
||||||
lazy val utilLogic = "org.scala-sbt" %% "util-logic" % utilVersion
|
lazy val utilLogic = "org.scala-sbt" %% "util-logic" % utilVersion
|
||||||
lazy val utilTracking = "org.scala-sbt" %% "util-tracking" % utilVersion
|
lazy val utilTracking = "org.scala-sbt" %% "util-tracking" % utilVersion
|
||||||
|
lazy val utilScripted = "org.scala-sbt" %% "util-scripted" % utilVersion
|
||||||
lazy val libraryManagement = "org.scala-sbt" %% "librarymanagement" % librarymanagementVersion
|
lazy val libraryManagement = "org.scala-sbt" %% "librarymanagement" % librarymanagementVersion
|
||||||
lazy val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0-M1"
|
lazy val launcherInterface = "org.scala-sbt" % "launcher-interface" % "1.0.0-M1"
|
||||||
lazy val rawLauncher = "org.scala-sbt" % "launcher" % "1.0.0-M1"
|
lazy val rawLauncher = "org.scala-sbt" % "launcher" % "1.0.0-M1"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
Simple Build Tool: Scripted Test Component
|
|
||||||
Copyright 2009 Mark Harrah
|
|
||||||
Licensed under BSD-style license (see LICENSE)
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
object CommentHandler extends BasicStatementHandler {
|
|
||||||
def apply(command: String, args: List[String]) = ()
|
|
||||||
}
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
import scala.sys.process.Process
|
|
||||||
import java.io.File
|
|
||||||
import sbt.io.{ IO, Path }
|
|
||||||
import Path._
|
|
||||||
|
|
||||||
class FileCommands(baseDirectory: File) extends BasicStatementHandler {
|
|
||||||
lazy val commands = commandMap
|
|
||||||
def commandMap =
|
|
||||||
Map(
|
|
||||||
"touch" nonEmpty touch _,
|
|
||||||
"delete" nonEmpty delete _,
|
|
||||||
"exists" nonEmpty exists _,
|
|
||||||
"mkdir" nonEmpty makeDirectories _,
|
|
||||||
"absent" nonEmpty absent _,
|
|
||||||
// "sync" twoArg("Two directory paths", sync _),
|
|
||||||
"newer" twoArg ("Two paths", newer _),
|
|
||||||
"pause" noArg { println("Pausing in " + baseDirectory); readLine("Press enter to continue. "); println() },
|
|
||||||
"sleep" oneArg ("Time in milliseconds", time => Thread.sleep(time.toLong)),
|
|
||||||
"exec" nonEmpty (execute _),
|
|
||||||
"copy" copy (to => rebase(baseDirectory, to)),
|
|
||||||
"copy-file" twoArg ("Two paths", copyFile _),
|
|
||||||
"must-mirror" twoArg ("Two paths", diffFiles _),
|
|
||||||
"copy-flat" copy flat
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply(command: String, arguments: List[String]): Unit =
|
|
||||||
commands.get(command).map(_(arguments)).getOrElse(scriptError("Unknown command " + command))
|
|
||||||
|
|
||||||
def scriptError(message: String): Some[String] = sys.error("Test script error: " + message)
|
|
||||||
def spaced[T](l: Seq[T]) = l.mkString(" ")
|
|
||||||
def fromStrings(paths: List[String]) = paths.map(fromString)
|
|
||||||
def fromString(path: String) = new File(baseDirectory, path)
|
|
||||||
def touch(paths: List[String]) = IO.touch(fromStrings(paths))
|
|
||||||
def delete(paths: List[String]): Unit = IO.delete(fromStrings(paths))
|
|
||||||
/*def sync(from: String, to: String) =
|
|
||||||
IO.sync(fromString(from), fromString(to), log)*/
|
|
||||||
def copyFile(from: String, to: String): Unit =
|
|
||||||
IO.copyFile(fromString(from), fromString(to))
|
|
||||||
def makeDirectories(paths: List[String]) =
|
|
||||||
IO.createDirectories(fromStrings(paths))
|
|
||||||
def diffFiles(file1: String, file2: String) = {
|
|
||||||
val lines1 = IO.readLines(fromString(file1))
|
|
||||||
val lines2 = IO.readLines(fromString(file2))
|
|
||||||
if (lines1 != lines2)
|
|
||||||
scriptError("File contents are different:\n" + lines1.mkString("\n") + "\nAnd:\n" + lines2.mkString("\n"))
|
|
||||||
}
|
|
||||||
|
|
||||||
def newer(a: String, b: String) =
|
|
||||||
{
|
|
||||||
val pathA = fromString(a)
|
|
||||||
val pathB = fromString(b)
|
|
||||||
val isNewer = pathA.exists && (!pathB.exists || pathA.lastModified > pathB.lastModified)
|
|
||||||
if (!isNewer) {
|
|
||||||
scriptError(s"$pathA is not newer than $pathB")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
def exists(paths: List[String]): Unit = {
|
|
||||||
val notPresent = fromStrings(paths).filter(!_.exists)
|
|
||||||
if (notPresent.nonEmpty)
|
|
||||||
scriptError("File(s) did not exist: " + notPresent.mkString("[ ", " , ", " ]"))
|
|
||||||
}
|
|
||||||
def absent(paths: List[String]): Unit = {
|
|
||||||
val present = fromStrings(paths).filter(_.exists)
|
|
||||||
if (present.nonEmpty)
|
|
||||||
scriptError("File(s) existed: " + present.mkString("[ ", " , ", " ]"))
|
|
||||||
}
|
|
||||||
def execute(command: List[String]): Unit = execute0(command.head, command.tail)
|
|
||||||
def execute0(command: String, args: List[String]): Unit = {
|
|
||||||
if (command.trim.isEmpty)
|
|
||||||
scriptError("Command was empty.")
|
|
||||||
else {
|
|
||||||
val exitValue = Process(command :: args, baseDirectory) !;
|
|
||||||
if (exitValue != 0)
|
|
||||||
sys.error("Nonzero exit value (" + exitValue + ")")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// these are for readability of the command list
|
|
||||||
implicit def commandBuilder(s: String): CommandBuilder = new CommandBuilder(s)
|
|
||||||
final class CommandBuilder(commandName: String) extends NotNull {
|
|
||||||
type NamedCommand = (String, List[String] => Unit)
|
|
||||||
def nonEmpty(action: List[String] => Unit): NamedCommand =
|
|
||||||
commandName -> { paths =>
|
|
||||||
if (paths.isEmpty)
|
|
||||||
scriptError("No arguments specified for " + commandName + " command.")
|
|
||||||
else
|
|
||||||
action(paths)
|
|
||||||
}
|
|
||||||
def twoArg(requiredArgs: String, action: (String, String) => Unit): NamedCommand =
|
|
||||||
commandName -> {
|
|
||||||
case List(from, to) => action(from, to)
|
|
||||||
case other => wrongArguments(requiredArgs, other)
|
|
||||||
}
|
|
||||||
def noArg(action: => Unit): NamedCommand =
|
|
||||||
commandName -> {
|
|
||||||
case Nil => action
|
|
||||||
case other => wrongArguments(other)
|
|
||||||
}
|
|
||||||
def oneArg(requiredArgs: String, action: String => Unit): NamedCommand =
|
|
||||||
commandName -> {
|
|
||||||
case List(single) => action(single)
|
|
||||||
case other => wrongArguments(requiredArgs, other)
|
|
||||||
}
|
|
||||||
def copy(mapper: File => FileMap): NamedCommand =
|
|
||||||
commandName -> {
|
|
||||||
case Nil => scriptError("No paths specified for " + commandName + " command.")
|
|
||||||
case path :: Nil => scriptError("No destination specified for " + commandName + " command.")
|
|
||||||
case paths =>
|
|
||||||
val mapped = fromStrings(paths)
|
|
||||||
val map = mapper(mapped.last)
|
|
||||||
IO.copy(mapped.init pair map)
|
|
||||||
}
|
|
||||||
def wrongArguments(args: List[String]): Some[String] =
|
|
||||||
scriptError("Command '" + commandName + "' does not accept arguments (found '" + spaced(args) + "').")
|
|
||||||
def wrongArguments(requiredArgs: String, args: List[String]): Some[String] =
|
|
||||||
scriptError("Wrong number of arguments to " + commandName + " command. " + requiredArgs + " required, found: '" + spaced(args) + "'.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
final class FilteredLoader(parent: ClassLoader) extends ClassLoader(parent) {
|
|
||||||
@throws(classOf[ClassNotFoundException])
|
|
||||||
override final def loadClass(className: String, resolve: Boolean): Class[_] =
|
|
||||||
{
|
|
||||||
if (className.startsWith("java.") || className.startsWith("javax."))
|
|
||||||
super.loadClass(className, resolve)
|
|
||||||
else
|
|
||||||
throw new ClassNotFoundException(className)
|
|
||||||
}
|
|
||||||
override def getResources(name: String) = null
|
|
||||||
override def getResource(name: String) = null
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
final class TestException(statement: Statement, msg: String, exception: Throwable)
|
|
||||||
extends RuntimeException(statement.linePrefix + " " + msg, exception)
|
|
||||||
|
|
||||||
class ScriptRunner {
|
|
||||||
import scala.collection.mutable.HashMap
|
|
||||||
def apply(statements: List[(StatementHandler, Statement)]): Unit = {
|
|
||||||
val states = new HashMap[StatementHandler, Any]
|
|
||||||
def processStatement(handler: StatementHandler, statement: Statement): Unit = {
|
|
||||||
val state = states(handler).asInstanceOf[handler.State]
|
|
||||||
val nextState =
|
|
||||||
try { Right(handler(statement.command, statement.arguments, state)) }
|
|
||||||
catch { case e: Exception => Left(e) }
|
|
||||||
nextState match {
|
|
||||||
case Left(err) =>
|
|
||||||
if (statement.successExpected) {
|
|
||||||
err match {
|
|
||||||
case t: TestFailed => throw new TestException(statement, "Command failed: " + t.getMessage, null)
|
|
||||||
case _ => throw new TestException(statement, "Command failed", err)
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
()
|
|
||||||
case Right(s) =>
|
|
||||||
if (statement.successExpected)
|
|
||||||
states(handler) = s
|
|
||||||
else
|
|
||||||
throw new TestException(statement, "Command succeeded but failure was expected", null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val handlers = Set() ++ statements.map(_._1)
|
|
||||||
|
|
||||||
try {
|
|
||||||
handlers.foreach { handler => states(handler) = handler.initialState }
|
|
||||||
statements foreach (Function.tupled(processStatement))
|
|
||||||
} finally {
|
|
||||||
for (handler <- handlers; state <- states.get(handler)) {
|
|
||||||
try { handler.finish(state.asInstanceOf[handler.State]) }
|
|
||||||
catch { case e: Exception => () }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
trait StatementHandler {
|
|
||||||
type State
|
|
||||||
def initialState: State
|
|
||||||
def apply(command: String, arguments: List[String], state: State): State
|
|
||||||
def finish(state: State): Unit
|
|
||||||
}
|
|
||||||
|
|
||||||
trait BasicStatementHandler extends StatementHandler {
|
|
||||||
final type State = Unit
|
|
||||||
final def initialState = ()
|
|
||||||
final def apply(command: String, arguments: List[String], state: Unit): Unit = apply(command, arguments)
|
|
||||||
def apply(command: String, arguments: List[String]): Unit
|
|
||||||
def finish(state: Unit) = ()
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Use when a stack trace is not useful */
|
|
||||||
final class TestFailed(msg: String) extends RuntimeException(msg) {
|
|
||||||
override def fillInStackTrace = this
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
/* sbt -- Simple Build Tool
|
|
||||||
* Copyright 2009 Mark Harrah
|
|
||||||
*/
|
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
import java.io.{ BufferedReader, File, InputStreamReader }
|
|
||||||
import scala.util.parsing.combinator._
|
|
||||||
import scala.util.parsing.input.Positional
|
|
||||||
import Character.isWhitespace
|
|
||||||
import sbt.io.IO
|
|
||||||
|
|
||||||
/*
|
|
||||||
statement*
|
|
||||||
statement ::= startChar successChar word+ nl
|
|
||||||
startChar ::= <single character>
|
|
||||||
successChar ::= '+' | '-'
|
|
||||||
word ::= [^ \[\]]+
|
|
||||||
comment ::= '#' \S* nl
|
|
||||||
nl ::= '\r' \'n' | '\n' | '\r' | eof
|
|
||||||
*/
|
|
||||||
final case class Statement(command: String, arguments: List[String], successExpected: Boolean, line: Int) {
|
|
||||||
def linePrefix = "{line " + line + "} "
|
|
||||||
}
|
|
||||||
|
|
||||||
private object TestScriptParser {
|
|
||||||
val SuccessLiteral = "success"
|
|
||||||
val FailureLiteral = "failure"
|
|
||||||
val WordRegex = """[^ \[\]\s'\"][^ \[\]\s]*""".r
|
|
||||||
}
|
|
||||||
|
|
||||||
import TestScriptParser._
|
|
||||||
class TestScriptParser(handlers: Map[Char, StatementHandler]) extends RegexParsers {
|
|
||||||
require(handlers.nonEmpty)
|
|
||||||
override def skipWhitespace = false
|
|
||||||
|
|
||||||
import IO.read
|
|
||||||
if (handlers.keys.exists(isWhitespace))
|
|
||||||
sys.error("Start characters cannot be whitespace")
|
|
||||||
if (handlers.keys.exists(key => key == '+' || key == '-'))
|
|
||||||
sys.error("Start characters cannot be '+' or '-'")
|
|
||||||
|
|
||||||
def parse(scriptFile: File): List[(StatementHandler, Statement)] = parse(read(scriptFile), Some(scriptFile.getAbsolutePath))
|
|
||||||
def parse(script: String): List[(StatementHandler, Statement)] = parse(script, None)
|
|
||||||
private def parse(script: String, label: Option[String]): List[(StatementHandler, Statement)] =
|
|
||||||
{
|
|
||||||
parseAll(statements, script) match {
|
|
||||||
case Success(result, next) => result
|
|
||||||
case err: NoSuccess =>
|
|
||||||
{
|
|
||||||
val labelString = label.map("'" + _ + "' ").getOrElse("")
|
|
||||||
sys.error("Could not parse test script, " + labelString + err.toString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy val statements = rep1(space ~> statement <~ newline)
|
|
||||||
def statement: Parser[(StatementHandler, Statement)] =
|
|
||||||
{
|
|
||||||
trait PositionalStatement extends Positional {
|
|
||||||
def tuple: (StatementHandler, Statement)
|
|
||||||
}
|
|
||||||
positioned {
|
|
||||||
val command = (word | err("expected command"))
|
|
||||||
val arguments = rep(space ~> (word | failure("expected argument")))
|
|
||||||
(successParser ~ (space ~> startCharacterParser <~ space) ~! command ~! arguments) ^^
|
|
||||||
{
|
|
||||||
case successExpected ~ start ~ command ~ arguments =>
|
|
||||||
new PositionalStatement {
|
|
||||||
def tuple = (handlers(start), new Statement(command, arguments, successExpected, pos.line))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ^^ (_.tuple)
|
|
||||||
}
|
|
||||||
def successParser: Parser[Boolean] = ('+' ^^^ true) | ('-' ^^^ false) | success(true)
|
|
||||||
def space: Parser[String] = """[ \t]*""".r
|
|
||||||
lazy val word: Parser[String] = ("\'" ~> "[^'\n\r]*".r <~ "\'") | ("\"" ~> "[^\"\n\r]*".r <~ "\"") | WordRegex
|
|
||||||
def startCharacterParser: Parser[Char] = elem("start character", handlers.contains _) |
|
|
||||||
((newline | err("expected start character " + handlers.keys.mkString("(", "", ")"))) ~> failure("end of input"))
|
|
||||||
|
|
||||||
def newline = """\s*([\n\r]|$)""".r
|
|
||||||
}
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
package xsbt.test
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import org.specs2.mutable.Specification
|
|
||||||
import org.specs2.matcher.FileMatchers
|
|
||||||
import sbt._
|
|
||||||
import sbt.io.IO
|
|
||||||
import sbt.io.Path._
|
|
||||||
|
|
||||||
object FileCommandsSpec extends Specification with FileMatchers {
|
|
||||||
|
|
||||||
"The touch command" should {
|
|
||||||
"touch a file that doesn't exist" in withTmpDir { dir =>
|
|
||||||
fileCommands(dir)("touch", List("foo"))
|
|
||||||
dir / "foo" must exist
|
|
||||||
}
|
|
||||||
"update the timestamp of a file that does exist" in withTmpDir { dir =>
|
|
||||||
val file = dir / "foo"
|
|
||||||
IO.write(file, "x")
|
|
||||||
file.setLastModified(1000L)
|
|
||||||
|
|
||||||
fileCommands(dir)("touch", List("foo"))
|
|
||||||
file.lastModified() must beGreaterThan(1000L)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The delete command" should {
|
|
||||||
"delete a file" in withTmpDir { dir =>
|
|
||||||
IO.write(dir / "foo", "x")
|
|
||||||
fileCommands(dir)("delete", List("foo"))
|
|
||||||
dir / "foo" must not(exist)
|
|
||||||
}
|
|
||||||
"delete a directory" in withTmpDir { dir =>
|
|
||||||
IO.write(dir / "foo" / "bar", "x")
|
|
||||||
fileCommands(dir)("delete", List("foo"))
|
|
||||||
dir / "foo" must not(exist)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The exists command" should {
|
|
||||||
"succeed if a file exists" in withTmpDir { dir =>
|
|
||||||
IO.write(dir / "foo", "x")
|
|
||||||
fileCommands(dir)("exists", List("foo"))
|
|
||||||
ok
|
|
||||||
}
|
|
||||||
"fail if a file doesn't exist" in withTmpDir { dir =>
|
|
||||||
fileCommands(dir)("exists", List("foo")) must throwAn[Exception]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The mkdir command" should {
|
|
||||||
"make a directory" in withTmpDir { dir =>
|
|
||||||
fileCommands(dir)("mkdir", List("foo"))
|
|
||||||
dir / "foo" must beADirectory
|
|
||||||
}
|
|
||||||
"make all directories" in withTmpDir { dir =>
|
|
||||||
fileCommands(dir)("mkdir", List("foo/bar"))
|
|
||||||
dir / "foo" / "bar" must beADirectory
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The absent command" should {
|
|
||||||
"succeed if a file is absent" in withTmpDir { dir =>
|
|
||||||
fileCommands(dir)("absent", List("foo"))
|
|
||||||
ok
|
|
||||||
}
|
|
||||||
"fail if a file is not absent" in withTmpDir { dir =>
|
|
||||||
IO.write(dir / "foo", "x")
|
|
||||||
fileCommands(dir)("absent", List("foo")) must throwAn[Exception]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The newer command" should {
|
|
||||||
"succeed if a file is newer" in withTmpDir { dir =>
|
|
||||||
val file1 = dir / "foo"
|
|
||||||
IO.write(file1, "x")
|
|
||||||
file1.setLastModified(1000L)
|
|
||||||
val file2 = dir / "bar"
|
|
||||||
IO.write(file2, "x")
|
|
||||||
file2.setLastModified(2000L)
|
|
||||||
|
|
||||||
fileCommands(dir)("newer", List("bar", "foo"))
|
|
||||||
ok
|
|
||||||
}
|
|
||||||
"fail if a file is not newer" in withTmpDir { dir =>
|
|
||||||
val file1 = dir / "foo"
|
|
||||||
IO.write(file1, "x")
|
|
||||||
file1.setLastModified(1000L)
|
|
||||||
val file2 = dir / "bar"
|
|
||||||
IO.write(file2, "x")
|
|
||||||
file2.setLastModified(2000L)
|
|
||||||
|
|
||||||
fileCommands(dir)("newer", List("foo", "bar")) must throwAn[Exception]
|
|
||||||
}
|
|
||||||
"fail if the tested file doesn't exist" in withTmpDir { dir =>
|
|
||||||
val file1 = dir / "foo"
|
|
||||||
IO.write(file1, "x")
|
|
||||||
file1.setLastModified(1000L)
|
|
||||||
|
|
||||||
fileCommands(dir)("newer", List("bar", "foo")) must throwAn[Exception]
|
|
||||||
}
|
|
||||||
"succeed if the target file doesn't exist" in withTmpDir { dir =>
|
|
||||||
val file1 = dir / "foo"
|
|
||||||
IO.write(file1, "x")
|
|
||||||
file1.setLastModified(1000L)
|
|
||||||
|
|
||||||
fileCommands(dir)("newer", List("foo", "bar"))
|
|
||||||
ok
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
"The copy-file command" should {
|
|
||||||
"copy a file" in withTmpDir { dir =>
|
|
||||||
IO.write(dir / "foo", "x")
|
|
||||||
fileCommands(dir)("copy-file", List("foo", "bar"))
|
|
||||||
dir / "bar" must exist
|
|
||||||
IO.read(dir / "bar") must_== "x"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def fileCommands(dir: File) = new FileCommands(dir)
|
|
||||||
|
|
||||||
def withTmpDir[A](block: File => A): A = {
|
|
||||||
val tmpDir = File.createTempFile("filecommands", "")
|
|
||||||
try {
|
|
||||||
tmpDir.delete()
|
|
||||||
tmpDir.mkdir()
|
|
||||||
block(tmpDir)
|
|
||||||
} finally {
|
|
||||||
IO.delete(tmpDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,7 +6,8 @@ package test
|
||||||
|
|
||||||
import java.io.{ File, IOException }
|
import java.io.{ File, IOException }
|
||||||
import xsbt.IPC
|
import xsbt.IPC
|
||||||
import xsbt.test.{ StatementHandler, TestFailed }
|
|
||||||
|
import sbt.internal.scripted.{ StatementHandler, TestFailed }
|
||||||
|
|
||||||
import sbt.util.Logger
|
import sbt.util.Logger
|
||||||
import sbt.util.Logger._
|
import sbt.util.Logger._
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import java.io.File
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
import xsbt.IPC
|
import xsbt.IPC
|
||||||
import xsbt.test.{ CommentHandler, FileCommands, ScriptRunner, TestScriptParser }
|
import sbt.internal.scripted.{ CommentHandler, FileCommands, ScriptRunner, TestScriptParser }
|
||||||
import sbt.io.{ DirectoryFilter, GlobFilter, HiddenFileFilter, Path }
|
import sbt.io.{ DirectoryFilter, GlobFilter, HiddenFileFilter, Path }
|
||||||
import sbt.io.IO.wrapNull
|
import sbt.io.IO.wrapNull
|
||||||
import sbt.internal.io.Resources
|
import sbt.internal.io.Resources
|
||||||
|
|
@ -17,6 +17,8 @@ import sbt.internal.io.Resources
|
||||||
import sbt.internal.util.{ BufferedLogger, ConsoleLogger, FullLogger }
|
import sbt.internal.util.{ BufferedLogger, ConsoleLogger, FullLogger }
|
||||||
import sbt.util.{ AbstractLogger, Logger }
|
import sbt.util.{ AbstractLogger, Logger }
|
||||||
|
|
||||||
|
import sbt.internal.scripted.TestException
|
||||||
|
|
||||||
final class ScriptedTests(resourceBaseDirectory: File, bufferLog: Boolean, launcher: File, launchOpts: Seq[String]) {
|
final class ScriptedTests(resourceBaseDirectory: File, bufferLog: Boolean, launcher: File, launchOpts: Seq[String]) {
|
||||||
import ScriptedTests._
|
import ScriptedTests._
|
||||||
private val testResources = new Resources(resourceBaseDirectory)
|
private val testResources = new Resources(resourceBaseDirectory)
|
||||||
|
|
@ -45,7 +47,7 @@ final class ScriptedTests(resourceBaseDirectory: File, bufferLog: Boolean, launc
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
try { scriptedTest(str, testDirectory, prescripted, log); None }
|
try { scriptedTest(str, testDirectory, prescripted, log); None }
|
||||||
catch { case _: xsbt.test.TestException | _: PendingTestSuccessException => Some(str) }
|
catch { case _: TestException | _: PendingTestSuccessException => Some(str) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +90,7 @@ final class ScriptedTests(resourceBaseDirectory: File, bufferLog: Boolean, launc
|
||||||
buffered.info("+ " + label + pendingString)
|
buffered.info("+ " + label + pendingString)
|
||||||
if (pending) throw new PendingTestSuccessException(label)
|
if (pending) throw new PendingTestSuccessException(label)
|
||||||
} catch {
|
} catch {
|
||||||
case e: xsbt.test.TestException =>
|
case e: TestException =>
|
||||||
testFailed()
|
testFailed()
|
||||||
e.getCause match {
|
e.getCause match {
|
||||||
case null | _: java.net.SocketException => buffered.error(" " + e.getMessage)
|
case null | _: java.net.SocketException => buffered.error(" " + e.getMessage)
|
||||||
|
|
@ -147,7 +149,7 @@ class ScriptedRunner {
|
||||||
run(resourceBaseDirectory, bufferLog, tests, logger, bootProperties, launchOpts, emptyCallback)
|
run(resourceBaseDirectory, bufferLog, tests, logger, bootProperties, launchOpts, emptyCallback)
|
||||||
|
|
||||||
def run(resourceBaseDirectory: File, bufferLog: Boolean, tests: Array[String], logger: AbstractLogger, bootProperties: File,
|
def run(resourceBaseDirectory: File, bufferLog: Boolean, tests: Array[String], logger: AbstractLogger, bootProperties: File,
|
||||||
launchOpts: Array[String], prescripted: File => Unit) {
|
launchOpts: Array[String], prescripted: File => Unit): Unit = {
|
||||||
val runner = new ScriptedTests(resourceBaseDirectory, bufferLog, bootProperties, launchOpts)
|
val runner = new ScriptedTests(resourceBaseDirectory, bufferLog, bootProperties, launchOpts)
|
||||||
val allTests = get(tests, resourceBaseDirectory, logger) flatMap {
|
val allTests = get(tests, resourceBaseDirectory, logger) flatMap {
|
||||||
case ScriptedTest(group, name) =>
|
case ScriptedTest(group, name) =>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue