Merge pull request #5151 from eatkins/scripted-timeout

Add timeout to scripted statements
This commit is contained in:
eugene yokota 2019-10-03 20:45:57 -04:00 committed by GitHub
commit ee471a2a82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 39 additions and 22 deletions

View File

@ -8,8 +8,10 @@
package sbt package sbt
package scriptedtest package scriptedtest
import scala.collection.mutable import java.util.concurrent.{ Executors, TimeUnit, TimeoutException }
import scala.collection.mutable
import scala.concurrent.duration._
import sbt.internal.scripted._ import sbt.internal.scripted._
private[sbt] object BatchScriptRunner { private[sbt] object BatchScriptRunner {
@ -17,8 +19,9 @@ private[sbt] object BatchScriptRunner {
} }
/** Defines an alternative script runner that allows batch execution. */ /** Defines an alternative script runner that allows batch execution. */
private[sbt] class BatchScriptRunner extends ScriptRunner { private[sbt] class BatchScriptRunner extends ScriptRunner with AutoCloseable {
import BatchScriptRunner.States import BatchScriptRunner.States
private[this] val service = Executors.newCachedThreadPool()
/** Defines a method to run batched execution. /** Defines a method to run batched execution.
* *
@ -40,12 +43,16 @@ private[sbt] class BatchScriptRunner extends ScriptRunner {
} }
} }
private val timeout = 5.minutes
def processStatement(handler: StatementHandler, statement: Statement, states: States): Unit = { def processStatement(handler: StatementHandler, statement: Statement, states: States): Unit = {
val state = states(handler).asInstanceOf[handler.State] val state = states(handler).asInstanceOf[handler.State]
val nextState = val nextStateFuture = service.submit(
() =>
try Right(handler(statement.command, statement.arguments, state)) try Right(handler(statement.command, statement.arguments, state))
catch { case e: Exception => Left(e) } catch { case e: Exception => Left(e) }
nextState match { )
try {
nextStateFuture.get(timeout.toMillis, TimeUnit.MILLISECONDS) match {
case Left(err) => case Left(err) =>
if (statement.successExpected) { if (statement.successExpected) {
err match { err match {
@ -61,5 +68,10 @@ private[sbt] class BatchScriptRunner extends ScriptRunner {
else else
throw new TestException(statement, "Command succeeded but failure was expected", null) throw new TestException(statement, "Command succeeded but failure was expected", null)
} }
} catch {
case e: TimeoutException => throw new TestException(statement, "Command timed out", e)
} }
} }
override def close(): Unit = service.shutdown()
}

View File

@ -72,7 +72,8 @@ final class ScriptedTests(
createScriptedHandlers(testDirectory, buffer, RemoteSbtCreatorKind.LauncherBased) createScriptedHandlers(testDirectory, buffer, RemoteSbtCreatorKind.LauncherBased)
val runner = new BatchScriptRunner val runner = new BatchScriptRunner
val states = new mutable.HashMap[StatementHandler, StatementHandler#State]() val states = new mutable.HashMap[StatementHandler, StatementHandler#State]()
commonRunTest(label, testDirectory, prescripted, handlers, runner, states, buffer) try commonRunTest(label, testDirectory, prescripted, handlers, runner, states, buffer)
finally runner.close()
} }
runOrHandleDisabled(label, testDirectory, singleTestRunner, buffer) runOrHandleDisabled(label, testDirectory, singleTestRunner, buffer)
} }
@ -362,7 +363,10 @@ final class ScriptedTests(
} }
try runBatchTests try runBatchTests
finally runner.cleanUpHandlers(seqHandlers, states) finally {
runner.cleanUpHandlers(seqHandlers, states)
runner.close()
}
} }
private def runOrHandleDisabled( private def runOrHandleDisabled(
@ -415,6 +419,7 @@ final class ScriptedTests(
case null | _: SocketException => log.error(s" Cause of test exception: ${t.getMessage}") case null | _: SocketException => log.error(s" Cause of test exception: ${t.getMessage}")
case _ => t.printStackTrace() case _ => t.printStackTrace()
} }
log.play()
} }
if (pending) None else Some(label) if (pending) None else Some(label)
} }