Repl: enhance test framework to wait for commands to be processed, not some text to appear
This commit is contained in:
@@ -25,7 +25,8 @@ class CommandHistory {
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val entries = arrayListOf<Entry>()
|
private val entries = arrayListOf<Entry>()
|
||||||
private var processedEntriesCount: Int = 0
|
var processedEntriesCount: Int = 0
|
||||||
|
private set
|
||||||
|
|
||||||
val listeners = arrayListOf<HistoryUpdateListener>()
|
val listeners = arrayListOf<HistoryUpdateListener>()
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public class KotlinConsoleRunner(
|
|||||||
title: String,
|
title: String,
|
||||||
path: String?
|
path: String?
|
||||||
) : AbstractConsoleRunnerWithHistory<LanguageConsoleView>(myProject, title, path) {
|
) : AbstractConsoleRunnerWithHistory<LanguageConsoleView>(myProject, title, path) {
|
||||||
internal val commandHistory = CommandHistory()
|
val commandHistory = CommandHistory()
|
||||||
|
|
||||||
var isReadLineMode: Boolean = false
|
var isReadLineMode: Boolean = false
|
||||||
set(value) {
|
set(value) {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import kotlin.test.assertTrue
|
|||||||
@FixMethodOrder(MethodSorters.JVM)
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
public class KotlinReplTest : PlatformTestCase() {
|
public class KotlinReplTest : PlatformTestCase() {
|
||||||
private var consoleRunner: KotlinConsoleRunner by Delegates.notNull()
|
private var consoleRunner: KotlinConsoleRunner by Delegates.notNull()
|
||||||
|
private var commandsSent = 0
|
||||||
|
|
||||||
override fun setUp() {
|
override fun setUp() {
|
||||||
super.setUp()
|
super.setUp()
|
||||||
@@ -45,45 +46,51 @@ public class KotlinReplTest : PlatformTestCase() {
|
|||||||
private fun sendCommand(command: String) {
|
private fun sendCommand(command: String) {
|
||||||
consoleRunner.consoleView.editorDocument.setText(command)
|
consoleRunner.consoleView.editorDocument.setText(command)
|
||||||
consoleRunner.executor.executeCommand()
|
consoleRunner.executor.executeCommand()
|
||||||
|
commandsSent++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun waitForExpectedOutput(expectedOutput: String) {
|
private fun checkOutput(expectedOutput: String) {
|
||||||
val endsWithPredicate = { x: String -> x.trim().endsWith(expectedOutput) }
|
val output = getReplOutput(textOnTimeOut = { "Only ${consoleRunner.commandHistory.processedEntriesCount} commands were processed" }) {
|
||||||
|
consoleRunner.commandHistory.processedEntriesCount >= commandsSent
|
||||||
val historyText = checkHistoryUpdate { endsWithPredicate(it) }
|
}
|
||||||
|
assertTrue(output.trim().endsWith(expectedOutput), "'$expectedOutput' should be printed but document text is:\n$output")
|
||||||
assertTrue(endsWithPredicate(historyText), "'$expectedOutput' should be printed but document text is:\n$historyText")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkHistoryUpdate(maxIterations: Int = 50, sleepTime: Long = 500, stopPredicate: (String) -> Boolean): String {
|
private fun getReplOutput(maxIterations: Int = 50, sleepTime: Long = 500, textOnTimeOut: () -> String, predicate: () -> Boolean): String {
|
||||||
val consoleView = consoleRunner.consoleView as LanguageConsoleImpl
|
|
||||||
|
|
||||||
for (i in 1..maxIterations) {
|
for (i in 1..maxIterations) {
|
||||||
UIUtil.dispatchAllInvocationEvents()
|
UIUtil.dispatchAllInvocationEvents()
|
||||||
consoleView.flushDeferredText()
|
if (predicate()) {
|
||||||
|
return refreshAndGetHistoryEditorText()
|
||||||
val historyText = consoleView.historyViewer.document.text
|
}
|
||||||
if (stopPredicate(historyText)) return historyText
|
|
||||||
|
|
||||||
Thread.sleep(sleepTime)
|
Thread.sleep(sleepTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "<empty text>"
|
return textOnTimeOut()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshAndGetHistoryEditorText(): String {
|
||||||
|
val consoleView = consoleRunner.consoleView as LanguageConsoleImpl
|
||||||
|
consoleView.flushDeferredText()
|
||||||
|
|
||||||
|
return consoleView.historyViewer.document.text
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testSimpleCommand(command: String, expectedOutput: String) {
|
private fun testSimpleCommand(command: String, expectedOutput: String) {
|
||||||
sendCommand(command)
|
sendCommand(command)
|
||||||
waitForExpectedOutput(expectedOutput)
|
checkOutput(expectedOutput)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun testRunPossibility() {
|
@Test fun testRunPossibility() {
|
||||||
val allOk = { x: String -> x.contains(":help for help") }
|
val allOk = { x: String -> x.contains(":help for help") }
|
||||||
val hasErrors = { x: String -> x.contains("Process finished with exit code 1") || x.contains("Exception in") || x.contains("Error") }
|
val hasErrors = { x: String -> x.contains("Process finished with exit code 1") || x.contains("Exception in") || x.contains("Error") }
|
||||||
|
|
||||||
val historyText = checkHistoryUpdate { hasErrors(it) || allOk(it) }
|
val output = getReplOutput(textOnTimeOut = { "Repl startup timed out" }) {
|
||||||
|
val editorText = refreshAndGetHistoryEditorText()
|
||||||
|
hasErrors(editorText) || allOk(editorText)
|
||||||
|
}
|
||||||
|
|
||||||
assertFalse(hasErrors(historyText), "Cannot run kotlin repl")
|
assertFalse(hasErrors(output), "Cannot run kotlin repl")
|
||||||
assertTrue(allOk(historyText), "Successful run should contain text: ':help for help'")
|
assertTrue(allOk(output), "Successful run should contain text: ':help for help'")
|
||||||
assertFalse(consoleRunner.processHandler.isProcessTerminated, "Process accidentally terminated")
|
assertFalse(consoleRunner.processHandler.isProcessTerminated, "Process accidentally terminated")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +106,7 @@ public class KotlinReplTest : PlatformTestCase() {
|
|||||||
"}\n")
|
"}\n")
|
||||||
sendCommand("f()")
|
sendCommand("f()")
|
||||||
|
|
||||||
waitForExpectedOutput(printText)
|
checkOutput(printText)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun testReadLineSingle() {
|
@Test fun testReadLineSingle() {
|
||||||
@@ -108,7 +115,7 @@ public class KotlinReplTest : PlatformTestCase() {
|
|||||||
sendCommand("val a = readLine()")
|
sendCommand("val a = readLine()")
|
||||||
sendCommand(readLineText)
|
sendCommand(readLineText)
|
||||||
sendCommand("a")
|
sendCommand("a")
|
||||||
waitForExpectedOutput(readLineText)
|
checkOutput(readLineText)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun testReadLineMultiple() {
|
@Test fun testReadLineMultiple() {
|
||||||
@@ -121,16 +128,16 @@ public class KotlinReplTest : PlatformTestCase() {
|
|||||||
sendCommand(readLineTextB)
|
sendCommand(readLineTextB)
|
||||||
|
|
||||||
sendCommand("a")
|
sendCommand("a")
|
||||||
waitForExpectedOutput(readLineTextA)
|
checkOutput(readLineTextA)
|
||||||
sendCommand("b")
|
sendCommand("b")
|
||||||
waitForExpectedOutput(readLineTextB)
|
checkOutput(readLineTextB)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun testCorrectAfterError() {
|
@Test fun testCorrectAfterError() {
|
||||||
val message = "MyMessage"
|
val message = "MyMessage"
|
||||||
sendCommand("fun f() { println(x)\n println(y) ")
|
sendCommand("fun f() { println(x)\n println(y) ")
|
||||||
sendCommand("println(\"$message\")")
|
sendCommand("println(\"$message\")")
|
||||||
waitForExpectedOutput(message)
|
checkOutput(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test fun testMultipleErrorsHandling() {
|
@Test fun testMultipleErrorsHandling() {
|
||||||
@@ -139,6 +146,6 @@ public class KotlinReplTest : PlatformTestCase() {
|
|||||||
sendCommand(veryLongTextWithErrors)
|
sendCommand(veryLongTextWithErrors)
|
||||||
sendCommand(veryLongTextWithErrors)
|
sendCommand(veryLongTextWithErrors)
|
||||||
sendCommand("println(\"OK\")")
|
sendCommand("println(\"OK\")")
|
||||||
waitForExpectedOutput("OK")
|
checkOutput("OK")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user