diff --git a/src/test/kotlin/terminal/FlushListener.java b/src/test/kotlin/terminal/FlushListener.java deleted file mode 100644 index 7e85885..0000000 --- a/src/test/kotlin/terminal/FlushListener.java +++ /dev/null @@ -1,37 +0,0 @@ -package terminal; - -import com.googlecode.lanterna.TerminalSize; -import com.googlecode.lanterna.terminal.Terminal; -import com.googlecode.lanterna.terminal.virtual.VirtualTerminalListener; - -public class FlushListener implements VirtualTerminalListener { - - private int flushCount; - - public FlushListener() { - this.flushCount = 0; - } - - public synchronized int getFlushCount() { - return flushCount; - } - - public synchronized void reduceFlushCount(int reduction) { - flushCount -= reduction; - } - - @Override - public void onResized(Terminal terminal, TerminalSize newSize) {} - - @Override - public synchronized void onFlush() { - flushCount++; - notify(); - } - - @Override - public void onBell() {} - - @Override - public void onClose() {} -} \ No newline at end of file diff --git a/src/test/kotlin/terminal/FlushListener.kt b/src/test/kotlin/terminal/FlushListener.kt new file mode 100644 index 0000000..b340e4e --- /dev/null +++ b/src/test/kotlin/terminal/FlushListener.kt @@ -0,0 +1,31 @@ +package terminal + +import com.googlecode.lanterna.TerminalSize +import com.googlecode.lanterna.terminal.Terminal +import com.googlecode.lanterna.terminal.virtual.VirtualTerminalListener + +class FlushListener : VirtualTerminalListener { + + val lock = Object() + + var flushCount = 0 + get () = synchronized(lock) { field } + private set + + fun reduceFlushCount(reduction: Int) { + synchronized(lock) { + flushCount -= reduction + } + } + + override fun onFlush() { + synchronized(lock) { + flushCount++ + lock.notify() + } + } + + override fun onResized(terminal: Terminal, newSize: TerminalSize) {} + override fun onBell() {} + override fun onClose() {} +} \ No newline at end of file diff --git a/src/test/kotlin/terminal/VirtualTerminalInteractor.java b/src/test/kotlin/terminal/VirtualTerminalInteractor.java deleted file mode 100644 index 847f512..0000000 --- a/src/test/kotlin/terminal/VirtualTerminalInteractor.java +++ /dev/null @@ -1,178 +0,0 @@ -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 stream.LispIOException; - -import java.io.IOException; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.fail; -import static terminal.LispTerminal.END_OF_SEGMENT; - -public class VirtualTerminalInteractor { - - private PipedOutputStream inputWriter; - private PipedInputStream inputReader; - private PipedOutputStream outputWriter; - private PipedInputStream outputReader; - private VirtualTerminal virtualTerminal; - private FlushListener flushListener; - private LispTerminal lispTerminal; - private TerminalConfiguration configuration; - - public VirtualTerminalInteractor() { - this.inputWriter = new PipedOutputStream(); - this.inputReader = new PipedInputStream(); - this.outputWriter = new PipedOutputStream(); - this.outputReader = new PipedInputStream(); - this.virtualTerminal = new DefaultVirtualTerminal(); - this.flushListener = new FlushListener(); - this.virtualTerminal.addVirtualTerminalListener(flushListener); - this.lispTerminal = new LispTerminal(createTerminalConfiguration()); - } - - private TerminalConfiguration createTerminalConfiguration() { - configuration = new TerminalConfiguration(); - configuration.setInputPair(inputWriter, inputReader); - configuration.setOutputPair(outputWriter, outputReader); - configuration.setTerminal(virtualTerminal); - - return configuration; - } - - public TerminalConfiguration getConfiguration() { - return configuration; - } - - public void start() { - lispTerminal.start(); - } - - public void stop() { - try { - lispTerminal.stop(); - outputWriter.close(); - } catch (IOException e) { - throw new LispIOException(e); - } - } - - public void pressKey(KeyType keyType) { - virtualTerminal.addInput(new KeyStroke(keyType)); - waitForFlushes(1); - } - - public void pressKeyTimes(KeyType keyType, int times) { - for (int i = times; i > 0; i--) - virtualTerminal.addInput(new KeyStroke(keyType)); - - waitForFlushes(times); - } - - public void pressControlKey(KeyType keyType) { - virtualTerminal.addInput(new KeyStroke(keyType, true, false)); - waitForFlushes(1); - } - - public void enterCharacter(char character) { - virtualTerminal.addInput(new KeyStroke(character, false, false)); - waitForFlushes(1); - } - - public void enterControlCharacter(char character) { - virtualTerminal.addInput(new KeyStroke(character, true, false)); - waitForFlushes(1); - } - - public void enterCharacters(String characters) { - for (char c : characters.toCharArray()) - virtualTerminal.addInput(new KeyStroke(c, false, false)); - - waitForFlushes(characters.length()); - } - - public void produceOutput(String output) { - try { - for (char c : output.toCharArray()) - outputWriter.write(c); - - outputWriter.write(END_OF_SEGMENT); - outputWriter.flush(); - waitForFlushes(1); - } catch (IOException ignored) { - } - } - - public void waitForFlushes(int flushCount) { - try { - synchronized (flushListener) { - while (flushListener.getFlushCount() < flushCount) - flushListener.wait(); - - flushListener.reduceFlushCount(flushCount); - } - } catch (InterruptedException ignored) { - } - } - - public void waitForPrompt() { - waitForFlushes(1); - } - - public void setColumns(int columns) { - int rows = virtualTerminal.getTerminalSize().getRows(); - virtualTerminal.setTerminalSize(new TerminalSize(columns, rows)); - } - - public void setRows(int rows) { - int columns = virtualTerminal.getTerminalSize().getColumns(); - virtualTerminal.setTerminalSize(new TerminalSize(columns, rows)); - } - - public void assertCursorPosition(int column, int row) { - assertThat(virtualTerminal.getCursorPosition().getColumn()).isEqualTo(column); - assertThat(virtualTerminal.getCursorPosition().getRow()).isEqualTo(row); - } - - public void assertScreenText(String... rows) { - for (int row = 0; row < rows.length; row++) - for (int column = 0; column < rows[row].length(); column++) - assertCharacterAtPosition(rows[row].charAt(column), column, row); - } - - public void assertCharacterAtPosition(char character, int column, int row) { - TerminalPosition position = new TerminalPosition(column, row); - String expected = String.valueOf(character); - String actual = String.valueOf(virtualTerminal.getCharacter(position).getCharacter()); - assertThat(actual).isEqualTo(expected); - } - - public void assertInputWritten(String expected) { - String actual = ""; - - try { - inputWriter.close(); - - for (int c = inputReader.read(); c != -1; c = inputReader.read()) - actual += (char) c; - } catch (IOException ignored) { - } - - assertThat(actual).isEqualTo(expected); - } - - public void assertInputStreamClosed() { - try { - inputWriter.write(0); - fail("input stream not closed"); - } catch (IOException ignored) { - } - } -} diff --git a/src/test/kotlin/terminal/VirtualTerminalInteractor.kt b/src/test/kotlin/terminal/VirtualTerminalInteractor.kt new file mode 100644 index 0000000..b0596b6 --- /dev/null +++ b/src/test/kotlin/terminal/VirtualTerminalInteractor.kt @@ -0,0 +1,150 @@ +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) { + } + } +}