package terminal; import static org.junit.Assert.*; import static terminal.LispTerminal.END_OF_SEGMENT; import java.io.*; import com.googlecode.lanterna.*; import com.googlecode.lanterna.input.*; import com.googlecode.lanterna.terminal.virtual.*; import stream.UncheckedIOException; 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 UncheckedIOException(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.resetFlushCount(); } } 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) { assertEquals(column, virtualTerminal.getCursorPosition().getColumn()); assertEquals(row, virtualTerminal.getCursorPosition().getRow()); } 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()); assertEquals(expected, actual); } public void assertCharacterPositions(char[][] positions) { for (int row = 0; row < positions.length; row++) for (int column = 0; column < positions[row].length; column++) assertCharacterAtPosition(positions[row][column], column, 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 assertInputWritten(String expected) { String actual = ""; try { inputWriter.close(); for (int c = inputReader.read(); c != -1; c = inputReader.read()) actual += (char) c; } catch (IOException ignored) {} assertEquals(expected, actual); } public void assertInputStreamClosed() { try { inputWriter.write(0); fail("input stream not closed"); } catch (IOException ignored) {} } }