Add DISABLE_PARALLEL_EXECUTION runtime option (#1087)

Add runtime option for sequential command execution
This commit is contained in:
Dmitry Bushev 2020-08-19 08:00:21 +03:00 committed by GitHub
parent 74e56c0d48
commit 6da3b9252f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 272 additions and 135 deletions

View File

@ -1,11 +1,11 @@
package org.enso.polyglot;
import java.util.logging.Level;
import org.graalvm.options.OptionDescriptor;
import org.graalvm.options.OptionDescriptors;
import org.graalvm.options.OptionKey;
import java.util.Arrays;
import java.util.logging.Level;
/** Class representing runtime options supported by the Enso engine. */
public class RuntimeOptions {
@ -29,13 +29,24 @@ public class RuntimeOptions {
private static final OptionDescriptor LOG_LEVEL_DESCRIPTOR =
OptionDescriptor.newBuilder(LOG_LEVEL_KEY, LOG_LEVEL).build();
public static final String INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION =
interpreterOptionName(".sequentialCommandExecution");
public static final OptionKey<Boolean> INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_KEY =
new OptionKey<>(false);
public static final OptionDescriptor INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR =
OptionDescriptor.newBuilder(
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_KEY,
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION)
.build();
public static final OptionDescriptors OPTION_DESCRIPTORS =
OptionDescriptors.create(
Arrays.asList(
PACKAGES_PATH_DESCRIPTOR,
STRICT_ERRORS_DESCRIPTOR,
LOG_LEVEL_DESCRIPTOR,
DISABLE_INLINE_CACHES_DESCRIPTOR));
DISABLE_INLINE_CACHES_DESCRIPTOR,
INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_DESCRIPTOR));
/**
* Canonicalizes the option name by prefixing it with the language name.
@ -46,4 +57,14 @@ public class RuntimeOptions {
private static String optionName(String name) {
return LanguageInfo.ID + "." + name;
}
/**
* Canonicalizes the option name by prefixing it with the 'interpreter' subname.
*
* @param name the simplified option name
* @return the canonicalized representation of the option.
*/
private static String interpreterOptionName(String name) {
return LanguageInfo.ID + ".interpreter." + name;
}
}

View File

@ -132,6 +132,10 @@ object Runtime {
value = classOf[Api.ExecutionFailed],
name = "executionFailed"
),
new JsonSubTypes.Type(
value = classOf[Api.ExecutionSuccessful],
name = "executionSuccessful"
),
new JsonSubTypes.Type(
value = classOf[Api.VisualisationExpressionFailed],
name = "visualisationExpressionFailed"
@ -534,6 +538,13 @@ object Runtime {
case class ExecutionFailed(contextId: ContextId, message: String)
extends ApiNotification
/**
* Signals that execution of a context was successful.
*
* @param contextId the context's id
*/
case class ExecutionSuccessful(contextId: ContextId) extends ApiNotification
/**
* Signals that an expression specified in a [[AttachVisualisation]] or
* a [[ModifyVisualisation]] cannot be evaluated.

View File

@ -7,8 +7,9 @@ import org.enso.interpreter.instrument.InterpreterContext
import org.enso.interpreter.instrument.command.Command
import org.enso.interpreter.instrument.execution.Completion.{Done, Interrupted}
import org.enso.interpreter.runtime.control.ThreadInterruptedException
import org.enso.polyglot.RuntimeOptions
import scala.concurrent.{ExecutionContext, Future}
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor, Future}
import scala.util.control.NonFatal
import scala.util.{Failure, Success}
@ -17,26 +18,42 @@ import scala.util.{Failure, Success}
* pending commands and activates command execution in FIFO order.
*
* @param interpreterContext suppliers of services that provide interpreter
* specific functionality
* specific functionality
*/
class CommandExecutionEngine(
interpreterContext: InterpreterContext
) extends CommandProcessor {
class CommandExecutionEngine(interpreterContext: InterpreterContext)
extends CommandProcessor {
private val context = interpreterContext.executionService.getContext
private val commandExecutor = Executors.newCachedThreadPool(
new TruffleThreadFactory(context, "command-pool")
)
implicit private val commandExecutionContext =
ExecutionContext.fromExecutor(commandExecutor)
private val isSequential =
interpreterContext.executionService.getContext.getEnvironment.getOptions
.get(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION_KEY)
.booleanValue()
private val locking = new ReentrantLocking
private val jobExecutionEngine =
new JobExecutionEngine(interpreterContext, locking)
private val commandExecutor =
if (isSequential) {
interpreterContext.executionService.getLogger.fine(
"Executing commands sequentially"
)
jobExecutionEngine.jobExecutor
} else {
interpreterContext.executionService.getLogger.fine(
"Executing commands in a separate command pool"
)
Executors.newCachedThreadPool(
new TruffleThreadFactory(
interpreterContext.executionService.getContext,
"command-pool"
)
)
}
implicit private val commandExecutionContext: ExecutionContextExecutor =
ExecutionContext.fromExecutor(commandExecutor)
private val runtimeContext =
RuntimeContext(
executionService = interpreterContext.executionService,
@ -48,7 +65,7 @@ class CommandExecutionEngine(
locking = locking
)
/** @inheritdoc **/
/** @inheritdoc */
def invoke(cmd: Command): Future[Completion] = {
val logger = runtimeContext.executionService.getLogger
val doIt = () =>
@ -59,7 +76,7 @@ class CommandExecutionEngine(
Future.successful(Done)
case Failure(
_: InterruptedException | _: ThreadInterruptedException
_: InterruptedException | _: ThreadInterruptedException
) =>
Future.successful[Completion](Interrupted)
@ -80,7 +97,7 @@ class CommandExecutionEngine(
}
/** @inheritdoc **/
/** @inheritdoc */
override def stop(): Unit = {
jobExecutionEngine.stop()
commandExecutor.shutdownNow()

View File

@ -36,7 +36,7 @@ class JobExecutionEngine(
.get(RuntimeServerInfo.JOB_PARALLELISM_KEY)
.intValue()
private val jobExecutor = Executors.newFixedThreadPool(
val jobExecutor = Executors.newFixedThreadPool(
jobParallelism,
new TruffleThreadFactory(context, "job-pool")
)
@ -52,7 +52,7 @@ class JobExecutionEngine(
locking = locking
)
/** @inheritdoc * */
/** @inheritdoc */
override def run[A](job: Job[A]): Future[A] = {
val jobId = UUID.randomUUID()
val promise = Promise[A]()
@ -78,7 +78,7 @@ class JobExecutionEngine(
promise.future
}
/** @inheritdoc * */
/** @inheritdoc */
override def abortAllJobs(): Unit = {
val allJobs = runningJobsRef.get()
val cancellableJobs = allJobs.filter(_.job.isCancellable)
@ -89,7 +89,7 @@ class JobExecutionEngine(
.checkInterrupts()
}
/** @inheritdoc * */
/** @inheritdoc */
override def abortJobs(contextId: UUID): Unit = {
val allJobs = runningJobsRef.get()
val contextJobs = allJobs.filter(_.job.contextIds.contains(contextId))
@ -102,7 +102,7 @@ class JobExecutionEngine(
.checkInterrupts()
}
/** @inheritdoc * */
/** @inheritdoc */
override def stop(): Unit = {
val allJobs = runningJobsRef.get()
allJobs.foreach(_.future.cancel(true))

View File

@ -47,10 +47,12 @@ class ExecuteJob(
errorOrOk match {
case Left(e) =>
ctx.endpoint.sendToClient(
Api.Response(None, Api.ExecutionFailed(contextId, e))
Api.Response(Api.ExecutionFailed(contextId, e))
)
case Right(()) =>
ctx.endpoint.sendToClient(
Api.Response(Api.ExecutionSuccessful(contextId))
)
case Right(()) => //nop
}
} finally {
ctx.executionService.getContext.getThreadManager.leave()

View File

@ -44,6 +44,7 @@ class RuntimeServerTest
.allowAllAccess(true)
.option(RuntimeOptions.PACKAGES_PATH, pkg.root.getAbsolutePath)
.option(RuntimeOptions.LOG_LEVEL, "WARNING")
.option(RuntimeOptions.INTERPRETER_SEQUENTIAL_COMMAND_EXECUTION, "true")
.option(RuntimeServerInfo.ENABLE_OPTION, "true")
.out(out)
.serverTransport { (uri, peer) =>
@ -80,6 +81,10 @@ class RuntimeServerTest
def send(msg: Api.Request): Unit = endPoint.sendBinary(Api.serialize(msg))
def receiveNone: Option[Api.Response] = {
Option(messageQueue.poll())
}
def receive: Option[Api.Response] = {
Option(messageQueue.poll(3, TimeUnit.SECONDS))
}
@ -94,6 +99,9 @@ class RuntimeServerTest
result.linesIterator.toList
}
def executionSuccessful(contextId: UUID): Api.Response =
Api.Response(Api.ExecutionSuccessful(contextId))
object Main {
val metadata = new Metadata
@ -304,7 +312,8 @@ class RuntimeServerTest
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// push foo call
@ -315,7 +324,8 @@ class RuntimeServerTest
context.receive(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.fooY(contextId),
context.Main.Update.fooZ(contextId)
context.Main.Update.fooZ(contextId),
context.executionSuccessful(contextId)
)
// push method pointer on top of the non-empty stack
@ -349,12 +359,13 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// pop main
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
context.receive(2) should contain theSameElementsAs Seq(
context.receive shouldEqual Some(
Api.Response(requestId, Api.PopContextResponse(contextId))
)
@ -393,7 +404,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -409,7 +420,7 @@ class RuntimeServerTest
)
)
)
context.receive(4) should contain theSameElementsAs Seq(
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -461,7 +472,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
}
@ -493,7 +505,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -561,12 +573,13 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("3")
}
it should "Run State getting the initial state" in {
it should "run State getting the initial state" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Test.Main"
@ -593,7 +606,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -609,7 +622,7 @@ class RuntimeServerTest
)
)
)
context.receive(4) should contain theSameElementsAs Seq(
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -657,12 +670,13 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("42")
}
it should "Run State setting the state" in {
it should "run State setting the state" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Test.Main"
@ -691,7 +705,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -707,7 +721,7 @@ class RuntimeServerTest
)
)
)
context.receive(4) should contain theSameElementsAs Seq(
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -755,7 +769,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("10")
}
@ -789,7 +804,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -805,7 +820,7 @@ class RuntimeServerTest
)
)
)
context.receive(4) should contain theSameElementsAs Seq(
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -857,7 +872,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
}
@ -886,7 +902,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -991,7 +1007,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// push foo call
@ -1002,7 +1019,8 @@ class RuntimeServerTest
context.receive(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.fooY(contextId),
context.Main.Update.fooZ(contextId)
context.Main.Update.fooZ(contextId),
context.executionSuccessful(contextId)
)
// pop foo call
@ -1020,12 +1038,13 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// pop main
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
context.receive(2) should contain theSameElementsAs Seq(
context.receive(1) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PopContextResponse(contextId))
)
}
@ -1057,7 +1076,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -1122,7 +1141,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("1337")
@ -1146,7 +1166,8 @@ class RuntimeServerTest
contextId,
Vector(Api.ExpressionValueUpdate(idResult, Some("Text"), None))
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("Hi")
}
@ -1187,7 +1208,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -1299,7 +1320,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("144")
@ -1329,7 +1351,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("4")
@ -1347,7 +1370,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receive shouldEqual Some(context.executionSuccessful(contextId))
context.consumeOut shouldEqual List("5")
// Edit s/1000.x 5/Main.pie/
@ -1376,7 +1399,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("3")
@ -1406,7 +1430,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("7")
@ -1436,7 +1461,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("hie!")
@ -1460,7 +1486,8 @@ class RuntimeServerTest
contextId,
Vector(Api.ExpressionValueUpdate(idMainA, Some("Text"), None))
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("Hello!")
}
@ -1500,7 +1527,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
context.send(
@ -1635,7 +1662,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// push call1
@ -1649,7 +1677,8 @@ class RuntimeServerTest
)
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId))
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// pop call1
@ -1691,7 +1720,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// push call2
@ -1705,7 +1735,8 @@ class RuntimeServerTest
)
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId))
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// pop call2
@ -1747,7 +1778,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// push call3
@ -1761,7 +1793,8 @@ class RuntimeServerTest
)
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId))
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// pop call3
@ -1803,7 +1836,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
}
@ -1830,7 +1864,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
context.consumeOut shouldEqual List()
// Push new item on the stack to trigger the re-execution
@ -1867,7 +1901,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("I'm a file!")
@ -1885,7 +1920,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receive shouldEqual Some(context.executionSuccessful(contextId))
context.consumeOut shouldEqual List("I'm a modified!")
// Close the file
@ -1919,7 +1954,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// Push new item on the stack to trigger the re-execution
context.send(
@ -1936,7 +1971,7 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -1963,7 +1998,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// Modify the file
@ -1980,10 +2016,10 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receive shouldEqual Some(context.executionSuccessful(contextId))
}
it should "send suggestion notifications when file executed" in {
it should "send suggestion notifications when file is executed" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val idMain = context.Main.metadata.addItem(7, 47)
@ -2013,7 +2049,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// push main
val item1 = Api.StackItem.ExplicitCall(
@ -2111,7 +2147,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// push foo call
@ -2122,7 +2159,8 @@ class RuntimeServerTest
context.receive(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.fooY(contextId),
context.Main.Update.fooZ(contextId)
context.Main.Update.fooZ(contextId),
context.executionSuccessful(contextId)
)
// pop foo call
@ -2140,12 +2178,13 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// pop main
context.send(Api.Request(requestId, Api.PopContextRequest(contextId)))
context.receive(2) should contain theSameElementsAs Seq(
context.receive(1) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PopContextResponse(contextId))
)
@ -2156,7 +2195,7 @@ class RuntimeServerTest
)
}
it should "send suggestion notifications when file modified" in {
it should "send suggestion notifications when file is modified" in {
val fooFile = new File(context.pkg.sourceDir, "Foo.enso")
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
@ -2179,7 +2218,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
context.consumeOut shouldEqual List()
// Push new item on the stack to trigger the re-execution
@ -2216,7 +2255,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("I'm a file!")
@ -2255,13 +2295,14 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("I'm a modified!")
// Close the file
context.send(Api.Request(Api.CloseFileNotification(fooFile)))
context.receive shouldEqual None
context.receiveNone shouldEqual None
context.consumeOut shouldEqual List()
}
@ -2289,7 +2330,8 @@ class RuntimeServerTest
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// recompute
@ -2297,7 +2339,8 @@ class RuntimeServerTest
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None))
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
}
@ -2325,7 +2368,8 @@ class RuntimeServerTest
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// recompute
@ -2339,7 +2383,8 @@ class RuntimeServerTest
)
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
}
@ -2367,7 +2412,8 @@ class RuntimeServerTest
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// recompute
@ -2382,8 +2428,9 @@ class RuntimeServerTest
)
)
)
context.receive(1) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
}
@ -2525,7 +2572,7 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExecutionFailed(contextId, "Object 42 is not invokable.")
@ -2566,7 +2613,7 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(Api.ExecutionFailed(contextId, "Error in function main."))
)
@ -2605,7 +2652,7 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExecutionFailed(
@ -2646,7 +2693,7 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Api.Response(
Api.ExecutionFailed(
@ -2680,18 +2727,18 @@ class RuntimeServerTest
context.receive(4) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main2.Update.mainY(contextId),
context.Main2.Update.mainZ(contextId)
context.Main2.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List("I'm expensive!", "I'm more expensive!")
// recompute
context.send(
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None))
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
context.consumeOut shouldEqual List()
}
@ -2730,14 +2777,15 @@ class RuntimeServerTest
context.send(
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// attach visualisation
context.send(
Api.Request(
requestId,
@ -2753,8 +2801,9 @@ class RuntimeServerTest
)
)
val attachVisualisationResponses = context.receive(3)
attachVisualisationResponses should contain(
Api.Response(requestId, Api.VisualisationAttached())
attachVisualisationResponses should contain allOf (
Api.Response(requestId, Api.VisualisationAttached()),
context.executionSuccessful(contextId)
)
val expectedExpressionId = context.Main.idMainX
val Some(data) = attachVisualisationResponses.collectFirst {
@ -2777,8 +2826,9 @@ class RuntimeServerTest
context.send(
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None))
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
context.receive(2) should contain allOf (
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// recompute invalidating x
@ -2794,8 +2844,9 @@ class RuntimeServerTest
)
)
val recomputeResponses2 = context.receive(3)
recomputeResponses2 should contain(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
recomputeResponses2 should contain allOf (
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
val Some(data2) = recomputeResponses2.collectFirst {
case Api.Response(
@ -2838,7 +2889,7 @@ class RuntimeServerTest
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, false))
)
context.receive shouldEqual None
context.receiveNone shouldEqual None
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
@ -2942,7 +2993,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
// attach visualization
@ -2960,9 +3012,10 @@ class RuntimeServerTest
)
)
)
val attachVisualisationResponses = context.receive(2)
attachVisualisationResponses should contain(
Api.Response(requestId, Api.VisualisationAttached())
val attachVisualisationResponses = context.receive(3)
attachVisualisationResponses should contain allOf (
Api.Response(requestId, Api.VisualisationAttached()),
context.executionSuccessful(contextId)
)
val expectedExpressionId = context.Main.idMainX
val Some(data) = attachVisualisationResponses.collectFirst {
@ -2996,7 +3049,9 @@ class RuntimeServerTest
)
)
val Some(data1) = context.receive(1).collectFirst {
val editFileResponse = context.receive(2)
editFileResponse should contain(context.executionSuccessful(contextId))
val Some(data1) = editFileResponse.collectFirst {
case Api.Response(
None,
Api.VisualisationUpdate(
@ -3027,6 +3082,7 @@ class RuntimeServerTest
)
)
)
context.receiveNone shouldEqual None
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
@ -3047,14 +3103,15 @@ class RuntimeServerTest
context.send(
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// attach visualisation
context.send(
Api.Request(
requestId,
@ -3071,8 +3128,9 @@ class RuntimeServerTest
)
val attachVisualisationResponses = context.receive(3)
attachVisualisationResponses should contain(
Api.Response(requestId, Api.VisualisationAttached())
attachVisualisationResponses should contain allOf (
Api.Response(requestId, Api.VisualisationAttached()),
context.executionSuccessful(contextId)
)
val expectedExpressionId = context.Main.idMainX
val Some(data) = attachVisualisationResponses.collectFirst {
@ -3091,6 +3149,7 @@ class RuntimeServerTest
}
data.sameElements("6".getBytes) shouldBe true
// modify visualisation
context.send(
Api.Request(
requestId,
@ -3105,8 +3164,9 @@ class RuntimeServerTest
)
)
val modifyVisualisationResponses = context.receive(3)
modifyVisualisationResponses should contain(
Api.Response(requestId, Api.VisualisationModified())
modifyVisualisationResponses should contain allOf (
Api.Response(requestId, Api.VisualisationModified()),
context.executionSuccessful(contextId)
)
val Some(dataAfterModification) =
modifyVisualisationResponses.collectFirst {
@ -3147,10 +3207,11 @@ class RuntimeServerTest
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive(2) should contain theSameElementsAs Seq(
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// attach visualisation
context.send(
Api.Request(
requestId,
@ -3165,10 +3226,11 @@ class RuntimeServerTest
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.VisualisationAttached()),
Api.Response(Api.ExecutionFailed(contextId, "Stack is empty."))
)
// push main
val item1 = Api.StackItem.ExplicitCall(
Api.MethodPointer("Test.Main", "Main", "main"),
@ -3178,14 +3240,33 @@ class RuntimeServerTest
context.send(
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
)
context.receive(6) should contain allOf (
val pushResponses = context.receive(6)
pushResponses should contain allOf (
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
val expectedExpressionId = context.Main.idMainX
val Some(data) =
pushResponses.collectFirst {
case Api.Response(
None,
Api.VisualisationUpdate(
Api.VisualisationContext(
`visualisationId`,
`contextId`,
`expectedExpressionId`
),
data
)
) =>
data
}
util.Arrays.equals(data, "6".getBytes) shouldEqual true
// detach visualisation
context.send(
Api.Request(
requestId,
@ -3196,7 +3277,7 @@ class RuntimeServerTest
)
)
)
context.receive shouldBe Some(
context.receive shouldEqual Some(
Api.Response(requestId, Api.VisualisationDetached())
)
@ -3205,7 +3286,8 @@ class RuntimeServerTest
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None))
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// recompute invalidating x
@ -3221,7 +3303,8 @@ class RuntimeServerTest
)
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
}
@ -3254,13 +3337,14 @@ class RuntimeServerTest
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.Main.Update.mainX(contextId),
context.Main.Update.mainY(contextId),
context.Main.Update.mainZ(contextId)
context.Main.Update.mainZ(contextId),
context.executionSuccessful(contextId)
)
// rename Test -> Foo
context.pkg.rename("Foo")
context.send(Api.Request(requestId, Api.RenameProject("Test", "Foo")))
context.receive(2) should contain theSameElementsAs Seq(
context.receive(1) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.ProjectRenamed("Foo"))
)
@ -3269,7 +3353,8 @@ class RuntimeServerTest
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None))
)
context.receive(2) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
context.executionSuccessful(contextId)
)
// recompute invalidating all
@ -3282,7 +3367,7 @@ class RuntimeServerTest
)
)
)
context.receive(2) should contain theSameElementsAs Seq(
context.receive(3) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
Api.Response(
Api.ExpressionValuesComputed(
@ -3295,7 +3380,8 @@ class RuntimeServerTest
)
)
)
)
),
context.executionSuccessful(contextId)
)
}