151 lines
4.3 KiB
Kotlin
151 lines
4.3 KiB
Kotlin
package terminal
|
|
|
|
import com.googlecode.lanterna.TerminalPosition
|
|
import com.googlecode.lanterna.TerminalSize
|
|
import com.googlecode.lanterna.input.KeyStroke
|
|
import com.googlecode.lanterna.input.KeyType
|
|
import com.googlecode.lanterna.terminal.virtual.DefaultVirtualTerminal
|
|
import com.googlecode.lanterna.terminal.virtual.VirtualTerminal
|
|
import org.assertj.core.api.Assertions.assertThat
|
|
import org.junit.Assert.fail
|
|
import terminal.LispTerminal.END_OF_SEGMENT
|
|
import java.io.IOException
|
|
import java.io.PipedInputStream
|
|
import java.io.PipedOutputStream
|
|
|
|
class VirtualTerminalInteractor {
|
|
|
|
private val inputWriter = PipedOutputStream()
|
|
private val inputReader = PipedInputStream()
|
|
private val outputWriter = PipedOutputStream()
|
|
private val outputReader = PipedInputStream()
|
|
private val flushListener = FlushListener()
|
|
|
|
private val virtualTerminal: VirtualTerminal = DefaultVirtualTerminal().apply {
|
|
addVirtualTerminalListener(flushListener)
|
|
}
|
|
|
|
val configuration = TerminalConfiguration().also {
|
|
it.setInputPair(inputWriter, inputReader)
|
|
it.setOutputPair(outputWriter, outputReader)
|
|
it.terminal = virtualTerminal
|
|
}
|
|
|
|
private val lispTerminal = LispTerminal(configuration)
|
|
|
|
fun start() {
|
|
lispTerminal.start()
|
|
}
|
|
|
|
fun stop() {
|
|
lispTerminal.stop()
|
|
outputWriter.close()
|
|
}
|
|
|
|
fun pressKey(keyType: KeyType) {
|
|
virtualTerminal.addInput(KeyStroke(keyType))
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
fun pressKeyTimes(keyType: KeyType, times: Int) {
|
|
for (i in times downTo 1)
|
|
virtualTerminal.addInput(KeyStroke(keyType))
|
|
|
|
waitForFlushes(times)
|
|
}
|
|
|
|
fun pressControlKey(keyType: KeyType) {
|
|
virtualTerminal.addInput(KeyStroke(keyType, true, false))
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
fun enterCharacter(character: Char) {
|
|
virtualTerminal.addInput(KeyStroke(character, false, false))
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
fun enterControlCharacter(character: Char) {
|
|
virtualTerminal.addInput(KeyStroke(character, true, false))
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
fun enterCharacters(characters: String) {
|
|
for (c in characters.toCharArray())
|
|
virtualTerminal.addInput(KeyStroke(c, false, false))
|
|
|
|
waitForFlushes(characters.length)
|
|
}
|
|
|
|
fun produceOutput(output: String) {
|
|
for (c in output.toCharArray())
|
|
outputWriter.write(c.toInt())
|
|
|
|
outputWriter.write(END_OF_SEGMENT.toInt())
|
|
outputWriter.flush()
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
private fun waitForFlushes(flushCount: Int) {
|
|
synchronized(flushListener.lock) {
|
|
while (flushListener.flushCount < flushCount)
|
|
flushListener.lock.wait()
|
|
|
|
flushListener.reduceFlushCount(flushCount)
|
|
}
|
|
}
|
|
|
|
fun waitForPrompt() {
|
|
waitForFlushes(1)
|
|
}
|
|
|
|
fun setColumns(columns: Int) {
|
|
val rows = virtualTerminal.terminalSize.rows
|
|
virtualTerminal.terminalSize = TerminalSize(columns, rows)
|
|
}
|
|
|
|
fun setRows(rows: Int) {
|
|
val columns = virtualTerminal.terminalSize.columns
|
|
virtualTerminal.terminalSize = TerminalSize(columns, rows)
|
|
}
|
|
|
|
fun assertCursorPosition(column: Int, row: Int) {
|
|
assertThat(virtualTerminal.cursorPosition.column).isEqualTo(column)
|
|
assertThat(virtualTerminal.cursorPosition.row).isEqualTo(row)
|
|
}
|
|
|
|
fun assertScreenText(vararg rows: String) {
|
|
for (row in rows.indices)
|
|
for (column in 0 until rows[row].length)
|
|
assertCharacterAtPosition(rows[row][column], column, row)
|
|
}
|
|
|
|
private fun assertCharacterAtPosition(character: Char, column: Int, row: Int) {
|
|
val position = TerminalPosition(column, row)
|
|
val expected = character.toString()
|
|
val actual = virtualTerminal.getCharacter(position).character.toString()
|
|
assertThat(actual).isEqualTo(expected)
|
|
}
|
|
|
|
fun assertInputWritten(expected: String) {
|
|
var actual = ""
|
|
|
|
inputWriter.close()
|
|
|
|
var c = inputReader.read()
|
|
while (c != -1) {
|
|
actual += c.toChar()
|
|
c = inputReader.read()
|
|
}
|
|
|
|
assertThat(actual).isEqualTo(expected)
|
|
}
|
|
|
|
fun assertInputStreamClosed() {
|
|
try {
|
|
inputWriter.write(0)
|
|
fail("input stream not closed")
|
|
} catch (ignored: IOException) {
|
|
}
|
|
}
|
|
}
|