Skip to content

Commit 036201f

Browse files
committed
Add worksheet cancellation test
1 parent a8bc74b commit 036201f

File tree

5 files changed

+104
-17
lines changed

5 files changed

+104
-17
lines changed

language-server/test/dotty/tools/languageserver/WorksheetTest.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,12 @@ class WorksheetTest {
184184
.symbol("Baz", (m5 to m6).symInfo("Baz", SymbolKind.Class))
185185
}
186186

187+
@Test def worksheetCancel(): Unit = {
188+
ws"""${m1}val foo = 1
189+
val bar = 2
190+
while (true) {}
191+
val baz = 3""".withSource
192+
.cancelEvaluation(m1, afterMs = 5000)
193+
}
194+
187195
}

language-server/test/dotty/tools/languageserver/util/CodeTester.scala

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,30 @@ class CodeTester(sources: List[SourceWithPositions], actions: List[Action]) {
117117
def symbol(query: String, symbols: SymInfo*): this.type =
118118
doAction(new CodeSymbol(query, symbols))
119119

120+
/**
121+
* Triggers evaluation of the worksheet specified by `marker`, verifies that the results of
122+
* evaluation match `expected.
123+
*
124+
* @param marker A marker a identifies the worksheet to evaluate.
125+
* @param expected The expected output.
126+
*
127+
* @see dotty.tools.languageserver.util.actions.WorksheetEvaluate
128+
*/
120129
def evaluate(marker: CodeMarker, expected: String*): this.type =
121130
doAction(new WorksheetEvaluate(marker, expected))
122131

132+
/**
133+
* Triggers evaluation of the worksheet specified by `marker`, then verifies that execution can be
134+
* cancelled after `afterMs` milliseconds.
135+
*
136+
* @param marker A marker that identifier the worksheet to evaluate.
137+
* @param afterMs The delay in milliseconds before cancelling execution.
138+
*
139+
* @see dotty.tools.languageserver.util.actions.WorksheetCancel
140+
*/
141+
def cancelEvaluation(marker: CodeMarker, afterMs: Long): this.type =
142+
doAction(new WorksheetCancel(marker, afterMs))
143+
123144
private def doAction(action: Action): this.type = {
124145
try {
125146
action.execute()(testServer, testServer.client, positions)
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dotty.tools.languageserver.util.actions
2+
3+
import dotty.tools.languageserver.util.embedded.CodeMarker
4+
5+
import org.eclipse.lsp4j.{DidSaveTextDocumentParams, MessageParams, MessageType}
6+
7+
abstract class WorksheetAction extends Action {
8+
9+
def triggerEvaluation(marker: CodeMarker): Exec[Unit] = {
10+
val file = marker.toTextDocumentIdentifier
11+
server.didSave(new DidSaveTextDocumentParams(file))
12+
}
13+
14+
def triggerCancellation(marker: CodeMarker): Exec[Unit] = {
15+
val file = {
16+
val file = marker.toTextDocumentIdentifier
17+
file.setUri(file.getUri.replaceFirst("file:", "cancel:"))
18+
file
19+
}
20+
server.didSave(new DidSaveTextDocumentParams(file))
21+
}
22+
23+
def getLogs(marker: CodeMarker): Exec[List[String]] = {
24+
def matches(params: MessageParams): Boolean =
25+
params.getType == MessageType.Info && params.getMessage.startsWith(marker.file.uri)
26+
client.log.get.collect {
27+
case params: MessageParams if matches(params) =>
28+
params.getMessage.substring(marker.file.uri.length).trim
29+
}
30+
}
31+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package dotty.tools.languageserver.util.actions
2+
3+
import dotty.tools.languageserver.util.PositionContext
4+
import dotty.tools.languageserver.util.embedded.CodeMarker
5+
6+
import org.junit.Assert.{assertEquals, fail}
7+
8+
class WorksheetCancel(marker: CodeMarker, afterMs: Long) extends WorksheetAction {
9+
10+
private final val cancellationTimeoutMs = 10 * 1000
11+
12+
override def execute(): Exec[Unit] = {
13+
triggerEvaluation(marker)
14+
Thread.sleep(afterMs)
15+
triggerCancellation(marker)
16+
17+
val timeAtCancellation = System.currentTimeMillis()
18+
while (!getLogs(marker).contains("FINISHED")) {
19+
if (System.currentTimeMillis() - timeAtCancellation > cancellationTimeoutMs) {
20+
fail(s"Couldn't cancel worksheet evaluation after ${cancellationTimeoutMs} ms.")
21+
}
22+
Thread.sleep(100)
23+
}
24+
25+
client.log.clear()
26+
}
27+
28+
override def show: PositionContext.PosCtx[String] =
29+
s"WorksheetCancel(${marker.file}, ${afterMs})"
30+
}
Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
11
package dotty.tools.languageserver.util.actions
22

3-
import dotty.tools.languageserver.util.{PositionContext}
3+
import dotty.tools.languageserver.util.PositionContext
44
import dotty.tools.languageserver.util.embedded.CodeMarker
55

6-
import org.eclipse.lsp4j.{DidSaveTextDocumentParams, MessageParams, MessageType}
6+
import org.junit.Assert.{assertEquals, fail}
77

8-
import org.junit.Assert.assertEquals
8+
class WorksheetEvaluate(marker: CodeMarker, expected: Seq[String]) extends WorksheetAction {
99

10-
class WorksheetEvaluate(marker: CodeMarker, expected: Seq[String]) extends Action {
11-
override def execute(): Exec[Unit] = {
12-
val file = marker.toTextDocumentIdentifier
13-
server.didSave(new DidSaveTextDocumentParams(file))
10+
private final val evaluationTimeoutMs = 30 * 1000
1411

15-
while (!getLogs(marker).contains("FINISHED")) Thread.sleep(100)
12+
override def execute(): Exec[Unit] = {
13+
triggerEvaluation(marker)
14+
15+
val timeAtEvaluation = System.currentTimeMillis()
16+
while (!getLogs(marker).contains("FINISHED")) {
17+
if (System.currentTimeMillis() - timeAtEvaluation > evaluationTimeoutMs) {
18+
fail(s"Evaluation didn't finish after ${evaluationTimeoutMs} ms.")
19+
}
20+
Thread.sleep(100)
21+
}
1622

1723
assertEquals(expected, getLogs(marker).init)
1824
client.log.clear()
1925
}
2026

2127
override def show: PositionContext.PosCtx[String] =
2228
s"WorksheetEvaluate(${marker.file}, ${expected})"
23-
24-
private def getLogs(marker: CodeMarker): Exec[List[String]] = {
25-
def matches(params: MessageParams): Boolean =
26-
params.getType == MessageType.Info && params.getMessage.startsWith(marker.file.uri)
27-
client.log.get.collect {
28-
case params: MessageParams if matches(params) =>
29-
params.getMessage.substring(marker.file.uri.length).trim
30-
}
31-
}
3229
}

0 commit comments

Comments
 (0)