mirror of https://github.com/sbt/sbt.git
Changes to assist with scripted testing of sbt 0.6.x series
This commit is contained in:
parent
20983c7dc2
commit
f139e5a9c1
|
|
@ -1,7 +1,5 @@
|
|||
#Project properties
|
||||
#Sat Nov 14 17:25:10 EST 2009
|
||||
project.organization=org.scala-tools.sbt
|
||||
project.name=xsbt
|
||||
sbt.version=0.5.6
|
||||
project.version=0.6.4
|
||||
project.version=0.6.5-p1
|
||||
scala.version=2.7.5
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ class ScriptRunner
|
|||
def apply(statements: List[(StatementHandler, Statement)])
|
||||
{
|
||||
val states = new HashMap[StatementHandler, Any]
|
||||
def processStatement(handler: StatementHandler, statement: Statement)
|
||||
{
|
||||
val state = states.getOrElseUpdate(handler, handler.initialState).asInstanceOf[handler.State]
|
||||
def processStatement(handler: StatementHandler, statement: Statement)
|
||||
{
|
||||
val state = states(handler).asInstanceOf[handler.State]
|
||||
val nextState =
|
||||
try { Right( handler(statement.command, statement.arguments, state) ) }
|
||||
catch { case e: Exception => Left(e) }
|
||||
|
|
@ -23,7 +23,12 @@ class ScriptRunner
|
|||
{
|
||||
case Left(err) =>
|
||||
if(statement.successExpected)
|
||||
throw new TestException(statement, "Command failed", err)
|
||||
{
|
||||
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) =>
|
||||
|
|
@ -33,7 +38,20 @@ class ScriptRunner
|
|||
throw new TestException(statement, "Command succeeded but failure was expected", null)
|
||||
}
|
||||
}
|
||||
statements.foreach { case (handler, _) => states(handler) = handler.initialState }
|
||||
statements foreach( Function.tupled(processStatement) )
|
||||
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 => () }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ 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
|
||||
|
|
@ -13,4 +14,11 @@ trait BasicStatementHandler extends StatementHandler
|
|||
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
|
||||
}
|
||||
|
|
@ -114,6 +114,7 @@ class StandardCompile(val sources: Task[Set[File]], val classpath: Task[Set[File
|
|||
def jarDependency(jar: File, source: File) { tracking.use(source, jar) }
|
||||
def classDependency(clazz: File, source: File) { tracking.dependency(source, clazz) }
|
||||
def generatedClass(source: File, clazz: File) { tracking.product(source, clazz) }
|
||||
def api(source: File, api: xsbti.api.Source) = ()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009 Mark Harrah
|
||||
*/
|
||||
package xsbt
|
||||
|
||||
import java.io.{BufferedReader, BufferedWriter, InputStream, InputStreamReader, OutputStreamWriter, OutputStream}
|
||||
import java.net.{InetAddress, ServerSocket, Socket}
|
||||
|
||||
object IPC
|
||||
{
|
||||
private val portMin = 1025
|
||||
private val portMax = 65536
|
||||
private val loopback = InetAddress.getByName(null) // loopback
|
||||
|
||||
def client[T](port: Int)(f: IPC => T): T =
|
||||
ipc(new Socket(loopback, port))(f)
|
||||
|
||||
def pullServer[T](f: Server => T): T =
|
||||
{
|
||||
val server = makeServer
|
||||
try { f(new Server(server)) }
|
||||
finally { server.close() }
|
||||
}
|
||||
def makeServer: ServerSocket =
|
||||
{
|
||||
val random = new java.util.Random
|
||||
def nextPort = random.nextInt(portMax - portMin + 1) + portMin
|
||||
def createServer(attempts: Int): ServerSocket =
|
||||
if(attempts > 0)
|
||||
try { new ServerSocket(nextPort, 1, loopback) }
|
||||
catch { case _: Exception => createServer(attempts - 1) }
|
||||
else
|
||||
error("Could not connect to socket: maximum attempts exceeded")
|
||||
createServer(10)
|
||||
}
|
||||
def server[T](f: IPC => Option[T]): T = serverImpl(makeServer, f)
|
||||
def server[T](port: Int)(f: IPC => Option[T]): T =
|
||||
serverImpl(new ServerSocket(port, 1, loopback), f)
|
||||
private def serverImpl[T](server: ServerSocket, f: IPC => Option[T]): T =
|
||||
{
|
||||
def listen(): T =
|
||||
{
|
||||
ipc(server.accept())(f) match
|
||||
{
|
||||
case Some(done) => done
|
||||
case None => listen()
|
||||
}
|
||||
}
|
||||
|
||||
try { listen() }
|
||||
finally { server.close() }
|
||||
}
|
||||
private def ipc[T](s: Socket)(f: IPC => T): T =
|
||||
try { f(new IPC(s)) }
|
||||
finally { s.close() }
|
||||
|
||||
final class Server private[IPC](s: ServerSocket) extends NotNull
|
||||
{
|
||||
def port = s.getLocalPort
|
||||
def close() = s.close()
|
||||
def connection[T](f: IPC => T): T = IPC.ipc(s.accept())(f)
|
||||
}
|
||||
}
|
||||
final class IPC private(s: Socket) extends NotNull
|
||||
{
|
||||
def port = s.getLocalPort
|
||||
private val in = new BufferedReader(new InputStreamReader(s.getInputStream))
|
||||
private val out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream))
|
||||
|
||||
def send(s: String) = { out.write(s); out.newLine(); out.flush() }
|
||||
def receive: String = in.readLine()
|
||||
}
|
||||
|
|
@ -59,7 +59,7 @@ object OpenResource
|
|||
|
||||
def resource[Source, T <: Closeable](openF: Source => T): OpenResource[Source,T] =
|
||||
resource(openF, _.close)
|
||||
def resource[Source, T <: Closeable](openF: Source => T, closeF: T => Unit): OpenResource[Source,T] =
|
||||
def resource[Source, T](openF: Source => T, closeF: T => Unit): OpenResource[Source,T] =
|
||||
new OpenResource[Source,T]
|
||||
{
|
||||
def open(s: Source) = openF(s)
|
||||
|
|
|
|||
Loading…
Reference in New Issue