Add Runtime Tests (#1869)

Add extra runtime tests
This commit is contained in:
Dmitry Bushev 2021-07-15 19:44:50 +03:00 committed by GitHub
parent 66ba1a598c
commit 214495ad56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 415 additions and 91 deletions

View File

@ -130,53 +130,6 @@ class RuntimeErrorsTest
Api.Response(Api.ExecutionComplete(contextId))
}
object Update {
def panic(
contextId: UUID,
expressionId: UUID,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
Api.Response(
Api.ExpressionUpdates(
contextId,
Set(
Api.ExpressionUpdate(
expressionId,
Some(Constants.PANIC),
None,
Vector(Api.ProfilingInfo.ExecutionTime(0)),
false,
payload
)
)
)
)
def panic(
contextId: UUID,
expressionId: UUID,
methodPointer: Api.MethodPointer,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
Api.Response(
Api.ExpressionUpdates(
contextId,
Set(
Api.ExpressionUpdate(
expressionId,
Some(Constants.PANIC),
Some(methodPointer),
Vector(Api.ProfilingInfo.ExecutionTime(0)),
false,
payload
)
)
)
)
}
def contentsVersion(content: String): ContentVersion =
Sha3_224VersionCalculator.evalVersion(content)
@ -247,7 +200,7 @@ class RuntimeErrorsTest
)
)
),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -255,7 +208,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
@ -263,7 +216,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
@ -331,7 +284,7 @@ class RuntimeErrorsTest
)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainBodyId,
Api.MethodPointer("Enso_Test.Test.Main", "Enso_Test.Test.Main", "foo"),
@ -482,7 +435,7 @@ class RuntimeErrorsTest
)
)
),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -710,7 +663,7 @@ class RuntimeErrorsTest
context.consumeOut shouldEqual List("499999999999")
}
it should "not send updates when dataflow error changes" in {
it should "not send updates when dataflow error changes in expression" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
@ -796,6 +749,96 @@ class RuntimeErrorsTest
context.consumeOut shouldEqual List("(Error: MyError2)")
}
it should "not send updates when dataflow error changes in method" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val xId = metadata.addItem(111, 8)
val yId = metadata.addItem(128, 5)
val mainResId = metadata.addItem(138, 12)
val code =
"""from Standard.Builtins import all
|
|type MyError1
|type MyError2
|
|foo =
| Error.throw MyError1
|
|main =
| x = this.foo
| y = x - 1
| IO.println y
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// Open the new file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, true))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, "Enso_Test.Test.Main", "main"),
None,
Vector()
)
)
)
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.error(
contextId,
xId,
Api.MethodPointer(moduleName, moduleName, "foo"),
Api.ExpressionUpdate.Payload.DataflowError(Seq())
),
TestMessages.error(
contextId,
yId,
Api.ExpressionUpdate.Payload.DataflowError(Seq())
),
TestMessages.update(contextId, mainResId, Constants.NOTHING),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual Seq("(Error: MyError1)")
// Modify the file
context.send(
Api.Request(
Api.EditFileNotification(
mainFile,
Seq(
TextEdit(
model.Range(model.Position(6, 16), model.Position(6, 24)),
"MyError2"
)
)
)
)
)
context.receive(1) should contain theSameElementsAs Seq(
context.executionComplete(contextId)
)
context.consumeOut shouldEqual List("(Error: MyError2)")
}
it should "continue execution after thrown panics" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
@ -846,7 +889,7 @@ class RuntimeErrorsTest
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -854,7 +897,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
@ -862,7 +905,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
@ -958,7 +1001,7 @@ class RuntimeErrorsTest
)
)
),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -966,7 +1009,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
@ -974,7 +1017,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
@ -1010,7 +1053,7 @@ class RuntimeErrorsTest
}
it should "send updates when panic changes" in {
it should "send updates when panic changes in expression" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
@ -1061,7 +1104,7 @@ class RuntimeErrorsTest
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -1069,7 +1112,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
@ -1077,7 +1120,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
@ -1104,7 +1147,7 @@ class RuntimeErrorsTest
)
)
context.receive(4) should contain theSameElementsAs Seq(
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -1112,7 +1155,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
@ -1120,7 +1163,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
@ -1133,6 +1176,212 @@ class RuntimeErrorsTest
context.consumeOut shouldEqual List()
}
it should "send updates when panic is resolved in method" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val xId = metadata.addItem(75, 8)
val yId = metadata.addItem(92, 5)
val mainResId = metadata.addItem(102, 12)
val code =
"""from Standard.Builtins import all
|
|foo =
| Panic.throw 9
|
|main =
| x = this.foo
| y = x + 1
| IO.println y
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// Open the new file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, true))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, "Enso_Test.Test.Main", "main"),
None,
Vector()
)
)
)
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.panic(
contextId,
xId,
Api.MethodPointer(moduleName, moduleName, "foo"),
Api.ExpressionUpdate.Payload.Panic(
"9 (Integer)",
Seq(xId)
)
),
TestMessages.panic(
contextId,
yId,
Api.ExpressionUpdate.Payload.Panic(
"9 (Integer)",
Seq(xId)
)
),
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(
"9 (Integer)",
Seq(xId)
)
),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual Seq()
// Modify the file
context.send(
Api.Request(
Api.EditFileNotification(
mainFile,
Seq(
TextEdit(
model.Range(model.Position(3, 4), model.Position(3, 17)),
"10002 - 10000"
)
)
)
)
)
context.receive(4) should contain theSameElementsAs Seq(
TestMessages.update(
contextId,
xId,
Constants.INTEGER,
Api.MethodPointer(moduleName, moduleName, "foo")
),
TestMessages.update(contextId, yId, Constants.INTEGER),
TestMessages.update(contextId, mainResId, Constants.NOTHING),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual List("3")
}
it should "send updates when dataflow error is resolved in method" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
val moduleName = "Enso_Test.Test.Main"
val metadata = new Metadata
val xId = metadata.addItem(75, 8)
val yId = metadata.addItem(92, 5)
val mainResId = metadata.addItem(102, 12)
val code =
"""from Standard.Builtins import all
|
|foo =
| Error.throw 9
|
|main =
| x = this.foo
| y = x + 1
| IO.println y
|""".stripMargin.linesIterator.mkString("\n")
val contents = metadata.appendToCode(code)
val mainFile = context.writeMain(contents)
// create context
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
context.receive shouldEqual Some(
Api.Response(requestId, Api.CreateContextResponse(contextId))
)
// Open the new file
context.send(
Api.Request(Api.OpenFileNotification(mainFile, contents, true))
)
context.receiveNone shouldEqual None
// push main
context.send(
Api.Request(
requestId,
Api.PushContextRequest(
contextId,
Api.StackItem.ExplicitCall(
Api.MethodPointer(moduleName, "Enso_Test.Test.Main", "main"),
None,
Vector()
)
)
)
)
context.receive(5) should contain theSameElementsAs Seq(
Api.Response(requestId, Api.PushContextResponse(contextId)),
TestMessages.error(
contextId,
xId,
Api.MethodPointer(moduleName, moduleName, "foo"),
Api.ExpressionUpdate.Payload.DataflowError(Seq())
),
TestMessages.error(
contextId,
yId,
Api.ExpressionUpdate.Payload.DataflowError(Seq())
),
TestMessages.update(
contextId,
mainResId,
Constants.NOTHING
),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual Seq("(Error: 9)")
// Modify the file
context.send(
Api.Request(
Api.EditFileNotification(
mainFile,
Seq(
TextEdit(
model.Range(model.Position(3, 4), model.Position(3, 17)),
"10002 - 10000"
)
)
)
)
)
context.receive(3) should contain theSameElementsAs Seq(
TestMessages.update(
contextId,
xId,
Constants.INTEGER,
Api.MethodPointer(moduleName, moduleName, "foo")
),
TestMessages.update(contextId, yId, Constants.INTEGER),
context.executionComplete(contextId)
)
context.consumeOut shouldEqual List("3")
}
it should "not cache panics" in {
val contextId = UUID.randomUUID()
val requestId = UUID.randomUUID()
@ -1194,7 +1443,7 @@ class RuntimeErrorsTest
)
)
),
Update.panic(
TestMessages.panic(
contextId,
xId,
Api.ExpressionUpdate.Payload.Panic(
@ -1202,7 +1451,7 @@ class RuntimeErrorsTest
Seq(xId)
)
),
Update.panic(
TestMessages.panic(
contextId,
mainResId,
Api.ExpressionUpdate.Payload.Panic(

View File

@ -188,11 +188,13 @@ class RuntimeStdlibTest
context.executionComplete(contextId),
timeout = 60
)
// sanity check
responses should contain allOf (
Api.Response(requestId, Api.PushContextResponse(contextId)),
context.executionComplete(contextId)
)
// check that the suggestion notifications are received
val suggestions = responses.collect {
case Api.Response(
None,
@ -202,6 +204,18 @@ class RuntimeStdlibTest
}
suggestions.isEmpty shouldBe false
// check that the Standard.Base library is indexed
val stdlibSuggestions = responses.collect {
case Api.Response(
None,
Api.SuggestionsDatabaseModuleUpdateNotification(file, _, as, xs)
) if file.getPath.contains("Vector") =>
(xs.nonEmpty || as.nonEmpty) shouldBe true
xs.toVector.head.suggestion.module shouldEqual "Standard.Base.Data.Vector"
}
stdlibSuggestions.nonEmpty shouldBe true
// check that builtins are indexed
val builtinsSuggestions = responses.collect {
case Api.Response(
None,
@ -211,6 +225,7 @@ class RuntimeStdlibTest
}
builtinsSuggestions.length shouldBe 1
// check LibraryLoaded notifications
val contentRootNotifications = responses.collect {
case Api.Response(
None,

View File

@ -122,27 +122,10 @@ object TestMessages {
contextId: UUID,
expressionId: UUID,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
error(contextId, expressionId, Constants.ERROR, payload)
/** Create an error update response.
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param expressionType a type of the expression
* @param payload the error payload
* @return the expression update response
*/
def error(
contextId: UUID,
expressionId: UUID,
expressionType: String,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
errorBuilder(
contextId,
expressionId,
Some(expressionType),
None,
false,
payload
@ -152,7 +135,28 @@ object TestMessages {
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param expressionType a type of the expression
* @param methodPointer a pointer to the method definition
* @param payload the error payload
* @return the expression update response
*/
def error(
contextId: UUID,
expressionId: UUID,
methodPointer: Api.MethodPointer,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
error(
contextId,
expressionId,
methodPointer,
false,
payload
)
/** Create an error update response.
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param methodPointer a pointer to the method definition
* @param fromCache whether or not the value for this expression came
* from the cache
@ -162,7 +166,6 @@ object TestMessages {
def error(
contextId: UUID,
expressionId: UUID,
expressionType: String,
methodPointer: Api.MethodPointer,
fromCache: Boolean,
payload: Api.ExpressionUpdate.Payload
@ -170,7 +173,6 @@ object TestMessages {
errorBuilder(
contextId,
expressionId,
Some(expressionType),
Some(methodPointer),
fromCache,
payload
@ -180,7 +182,6 @@ object TestMessages {
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param expressionTypeOpt a type of the expression
* @param methodPointerOpt a pointer to the method definition
* @param fromCache whether or not the value for this expression came
* from the cache
@ -190,7 +191,6 @@ object TestMessages {
private def errorBuilder(
contextId: UUID,
expressionId: UUID,
expressionTypeOpt: Option[String],
methodPointerOpt: Option[Api.MethodPointer],
fromCache: Boolean,
payload: Api.ExpressionUpdate.Payload
@ -201,7 +201,7 @@ object TestMessages {
Set(
Api.ExpressionUpdate(
expressionId,
expressionTypeOpt,
Some(Constants.ERROR),
methodPointerOpt,
Vector(Api.ProfilingInfo.ExecutionTime(0)),
fromCache,
@ -211,4 +211,64 @@ object TestMessages {
)
)
/** Create a panic update response.
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param payload the error payload
* @return the expression update response
*/
def panic(
contextId: UUID,
expressionId: UUID,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
panicBuilder(contextId, expressionId, None, payload)
/** Create a panic update response.
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param methodPointer a pointer to the method definition
* @param payload the error payload
* @return the expression update response
*/
def panic(
contextId: UUID,
expressionId: UUID,
methodPointer: Api.MethodPointer,
payload: Api.ExpressionUpdate.Payload
): Api.Response =
panicBuilder(contextId, expressionId, Some(methodPointer), payload)
/** Create a panic update response.
*
* @param contextId an identifier of the context
* @param expressionId an identifier of the expression
* @param methodPointer a pointer to the method definition
* @param payload the error payload
* @return the expression update response
*/
private def panicBuilder(
contextId: UUID,
expressionId: UUID,
methodPointer: Option[Api.MethodPointer],
payload: Api.ExpressionUpdate.Payload
): Api.Response =
Api.Response(
Api.ExpressionUpdates(
contextId,
Set(
Api.ExpressionUpdate(
expressionId,
Some(Constants.PANIC),
methodPointer,
Vector(Api.ProfilingInfo.ExecutionTime(0)),
false,
payload
)
)
)
)
}