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 scriptedtest
import scala.collection.mutable
import java.util.concurrent.{ Executors, TimeUnit, TimeoutException }
import scala.collection.mutable
import scala.concurrent.duration._
import sbt.internal.scripted._
private[sbt] object BatchScriptRunner {
@ -17,8 +19,9 @@ private[sbt] object BatchScriptRunner {
}
/** 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
private[this] val service = Executors.newCachedThreadPool()
/** Defines a method to run batched execution.
*
@ -40,26 +43,35 @@ private[sbt] class BatchScriptRunner extends ScriptRunner {
}
}
private val timeout = 5.minutes
def processStatement(handler: StatementHandler, statement: Statement, states: States): 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 nextStateFuture = service.submit(
() =>
try Right(handler(statement.command, statement.arguments, state))
catch { case e: Exception => Left(e) }
)
try {
nextStateFuture.get(timeout.toMillis, TimeUnit.MILLISECONDS) 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)
}
} 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)
val runner = new BatchScriptRunner
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)
}
@ -362,7 +363,10 @@ final class ScriptedTests(
}
try runBatchTests
finally runner.cleanUpHandlers(seqHandlers, states)
finally {
runner.cleanUpHandlers(seqHandlers, states)
runner.close()
}
}
private def runOrHandleDisabled(
@ -415,6 +419,7 @@ final class ScriptedTests(
case null | _: SocketException => log.error(s" Cause of test exception: ${t.getMessage}")
case _ => t.printStackTrace()
}
log.play()
}
if (pending) None else Some(label)
}