Add and refactor unit tests
This commit is contained in:
parent
23dd1c0654
commit
52762a6152
6
pom.xml
6
pom.xml
|
@ -63,6 +63,12 @@
|
||||||
<artifactId>lanterna</artifactId>
|
<artifactId>lanterna</artifactId>
|
||||||
<version>3.0.0-rc1</version>
|
<version>3.0.0-rc1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.stefanbirkner</groupId>
|
||||||
|
<artifactId>system-rules</artifactId>
|
||||||
|
<version>1.16.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
|
|
@ -9,17 +9,18 @@ import java.util.function.Function;
|
||||||
import com.googlecode.lanterna.terminal.*;
|
import com.googlecode.lanterna.terminal.*;
|
||||||
|
|
||||||
import interpreter.*;
|
import interpreter.*;
|
||||||
import terminal.LispTerminal;
|
import stream.UncheckedIOException;
|
||||||
|
import terminal.*;
|
||||||
|
|
||||||
public class LispMain {
|
public class LispMain {
|
||||||
|
|
||||||
private static final String GREETING = "Transcendental Lisp - Version 1.0.1";
|
private static final String GREETING = "Transcendental Lisp - Version 1.0.1";
|
||||||
|
|
||||||
private static final String ANSI_RESET = "\u001B[0m";
|
public static final String ANSI_RESET = "\u001B[0m";
|
||||||
private static final String ANSI_RED = "\u001B[31m";
|
public static final String ANSI_RED = "\u001B[31m";
|
||||||
private static final String ANSI_GREEN = "\u001B[32m";
|
public static final String ANSI_GREEN = "\u001B[32m";
|
||||||
private static final String ANSI_YELLOW = "\u001B[33m";
|
public static final String ANSI_YELLOW = "\u001B[33m";
|
||||||
private static final String ANSI_PURPLE = "\u001B[35m";
|
public static final String ANSI_PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
public static void main(String[] arguments) {
|
public static void main(String[] arguments) {
|
||||||
LispMain lispMain = new LispMain();
|
LispMain lispMain = new LispMain();
|
||||||
|
@ -143,35 +144,4 @@ public class LispMain {
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class TerminalConfiguration {
|
|
||||||
|
|
||||||
private PipedOutputStream inputWriter;
|
|
||||||
private PipedInputStream outputReader;
|
|
||||||
private IOSafeTerminal terminal;
|
|
||||||
|
|
||||||
public PipedOutputStream getInputWriter() {
|
|
||||||
return inputWriter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInputWriter(PipedOutputStream inputWriter) {
|
|
||||||
this.inputWriter = inputWriter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipedInputStream getOutputReader() {
|
|
||||||
return outputReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOutputReader(PipedInputStream outputReader) {
|
|
||||||
this.outputReader = outputReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IOSafeTerminal getTerminal() {
|
|
||||||
return terminal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTerminal(IOSafeTerminal terminal) {
|
|
||||||
this.terminal = terminal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
package terminal;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.terminal.IOSafeTerminal;
|
||||||
|
|
||||||
|
public class TerminalConfiguration {
|
||||||
|
|
||||||
|
private PipedOutputStream inputWriter;
|
||||||
|
private PipedInputStream inputReader;
|
||||||
|
private PipedOutputStream outputWriter;
|
||||||
|
private PipedInputStream outputReader;
|
||||||
|
private IOSafeTerminal terminal;
|
||||||
|
|
||||||
|
public void setInputWriter(PipedOutputStream inputWriter) {
|
||||||
|
this.inputWriter = inputWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInputReader(PipedInputStream inputReader) {
|
||||||
|
this.inputReader = inputReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputWriter(PipedOutputStream outputWriter) {
|
||||||
|
this.outputWriter = outputWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputReader(PipedInputStream outputReader) {
|
||||||
|
this.outputReader = outputReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTerminal(IOSafeTerminal terminal) {
|
||||||
|
this.terminal = terminal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipedOutputStream getInputWriter() {
|
||||||
|
return inputWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipedInputStream getInputReader() {
|
||||||
|
return inputReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipedOutputStream getOutputWriter() {
|
||||||
|
return outputWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PipedInputStream getOutputReader() {
|
||||||
|
return outputReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IOSafeTerminal getTerminal() {
|
||||||
|
return terminal;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -157,7 +157,7 @@ public class LispInterpreterTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void fileBasedInterpreterWorks() {
|
public void fileBasedInterpreterWorks_PrintsLastValueOnly() {
|
||||||
setCommonFeatures();
|
setCommonFeatures();
|
||||||
builder.useFile("test/interpreter/test-files/file.lisp");
|
builder.useFile("test/interpreter/test-files/file.lisp");
|
||||||
builder.build().interpret();
|
builder.build().interpret();
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
'onion
|
||||||
'pickle
|
'pickle
|
|
@ -1,13 +1,92 @@
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
|
import static java.text.MessageFormat.format;
|
||||||
|
import static main.LispMain.*;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
import org.junit.contrib.java.lang.system.*;
|
||||||
|
|
||||||
|
import com.googlecode.lanterna.terminal.virtual.*;
|
||||||
|
|
||||||
|
import environment.RuntimeEnvironment;
|
||||||
|
import interpreter.LispInterpreterBuilderImpl;
|
||||||
|
import terminal.*;
|
||||||
|
|
||||||
public class MainTest {
|
public class MainTest {
|
||||||
|
|
||||||
|
LispMain main;
|
||||||
|
PipedOutputStream inputWriter;
|
||||||
|
PipedInputStream outputReader;
|
||||||
|
VirtualTerminal terminal;
|
||||||
|
RuntimeEnvironment environment;
|
||||||
|
|
||||||
|
public MainTest() {
|
||||||
|
this.environment = RuntimeEnvironment.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedSystemExit exit = ExpectedSystemExit.none();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public SystemErrRule systemErrRule = new SystemErrRule().enableLog().mute();
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public SystemOutRule systemOutRule = new SystemOutRule().enableLog().mute();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {}
|
public void setUp() throws Exception {
|
||||||
|
environment.reset();
|
||||||
|
TerminalConfiguration configuration = new TerminalConfiguration();
|
||||||
|
inputWriter = new PipedOutputStream();
|
||||||
|
outputReader = new PipedInputStream();
|
||||||
|
terminal = new DefaultVirtualTerminal();
|
||||||
|
configuration.setInputWriter(inputWriter);
|
||||||
|
configuration.setOutputReader(outputReader);
|
||||||
|
configuration.setTerminal(terminal);
|
||||||
|
main = new LispMain(new LispInterpreterBuilderImpl() {}, configuration);
|
||||||
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {}
|
public void tearDown() throws Exception {
|
||||||
|
terminal.close();
|
||||||
|
environment.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithBadFile() {
|
||||||
|
String expectedMessage = "[critical] test/main/test-files/bad.lisp (No such file or directory)";
|
||||||
|
|
||||||
|
exit.expectSystemExitWithStatus(1);
|
||||||
|
exit.checkAssertionAfterwards(() -> {
|
||||||
|
assertEquals(format("{0}{1}{2}\n", ANSI_PURPLE, expectedMessage, ANSI_RESET),
|
||||||
|
systemErrRule.getLogWithNormalizedLineSeparator());
|
||||||
|
assertEquals("", systemOutRule.getLogWithNormalizedLineSeparator());
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
main.runWithFile("test/main/test-files/bad.lisp");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runWithFile_PrintsDecoratedLastValueOnly() {
|
||||||
|
main.runWithFile("test/main/test-files/file.lisp");
|
||||||
|
assertEquals("", systemErrRule.getLogWithNormalizedLineSeparator());
|
||||||
|
assertEquals(format("{0}{1}{2}\n\n", ANSI_GREEN, "RADISH", ANSI_RESET),
|
||||||
|
systemOutRule.getLogWithNormalizedLineSeparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void runInteractive() {
|
||||||
|
VirtualTerminalInteractor t = new VirtualTerminalInteractor();
|
||||||
|
try {
|
||||||
|
t.start();
|
||||||
|
} finally {
|
||||||
|
t.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
'pickle
|
||||||
|
'radish
|
|
@ -1,562 +1,437 @@
|
||||||
package terminal;
|
package terminal;
|
||||||
|
|
||||||
import static com.googlecode.lanterna.input.KeyType.*;
|
import static com.googlecode.lanterna.input.KeyType.*;
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static terminal.LispTerminal.END_OF_SEGMENT;
|
import static terminal.LispTerminal.END_OF_SEGMENT;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
import org.junit.*;
|
import org.junit.*;
|
||||||
|
|
||||||
import com.googlecode.lanterna.*;
|
|
||||||
import com.googlecode.lanterna.input.*;
|
|
||||||
import com.googlecode.lanterna.terminal.virtual.*;
|
|
||||||
|
|
||||||
public class LispTerminalTest {
|
public class LispTerminalTest {
|
||||||
|
|
||||||
private PipedInputStream inputReader;
|
private VirtualTerminalInteractor terminal;
|
||||||
private PipedOutputStream inputWriter;
|
|
||||||
private PipedInputStream outputReader;
|
|
||||||
private PipedOutputStream outputWriter;
|
|
||||||
private FlushListener flushListener;
|
|
||||||
private VirtualTerminal virtualTerminal;
|
|
||||||
private LispTerminal lispTerminal;
|
|
||||||
|
|
||||||
private void pressKey(KeyType keyType) {
|
|
||||||
virtualTerminal.addInput(new KeyStroke(keyType));
|
|
||||||
waitForFlushes(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pressKeyTimes(KeyType keyType, int times) {
|
|
||||||
for (int i = times; i > 0; i--)
|
|
||||||
virtualTerminal.addInput(new KeyStroke(keyType));
|
|
||||||
|
|
||||||
waitForFlushes(times);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pressControlKey(KeyType keyType) {
|
|
||||||
virtualTerminal.addInput(new KeyStroke(keyType, true, false));
|
|
||||||
waitForFlushes(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enterCharacter(char character) {
|
|
||||||
virtualTerminal.addInput(new KeyStroke(character, false, false));
|
|
||||||
waitForFlushes(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enterControlCharacter(char character) {
|
|
||||||
virtualTerminal.addInput(new KeyStroke(character, true, false));
|
|
||||||
waitForFlushes(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void enterCharacters(String characters) {
|
|
||||||
for (char c : characters.toCharArray())
|
|
||||||
virtualTerminal.addInput(new KeyStroke(c, false, false));
|
|
||||||
|
|
||||||
waitForFlushes(characters.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitForFlushes(int flushCount) {
|
|
||||||
try {
|
|
||||||
synchronized (flushListener) {
|
|
||||||
while (flushListener.getFlushCount() < flushCount)
|
|
||||||
flushListener.wait();
|
|
||||||
|
|
||||||
flushListener.resetFlushCount();
|
|
||||||
}
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setColumns(int columns) {
|
|
||||||
int rows = virtualTerminal.getTerminalSize().getRows();
|
|
||||||
virtualTerminal.setTerminalSize(new TerminalSize(columns, rows));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setRows(int rows) {
|
|
||||||
int columns = virtualTerminal.getTerminalSize().getColumns();
|
|
||||||
virtualTerminal.setTerminalSize(new TerminalSize(columns, rows));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertCursorPosition(int column, int row) {
|
|
||||||
assertEquals(column, virtualTerminal.getCursorPosition().getColumn());
|
|
||||||
assertEquals(row, virtualTerminal.getCursorPosition().getRow());
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertInputStreamClosed() {
|
|
||||||
try {
|
|
||||||
inputWriter.write(0);
|
|
||||||
fail("input stream not closed");
|
|
||||||
} catch (IOException ignored) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws IOException {
|
public void setUp() {
|
||||||
inputReader = new PipedInputStream();
|
terminal = new VirtualTerminalInteractor();
|
||||||
inputWriter = new PipedOutputStream(inputReader);
|
terminal.start();
|
||||||
outputReader = new PipedInputStream();
|
|
||||||
outputWriter = new PipedOutputStream(outputReader);
|
|
||||||
virtualTerminal = new DefaultVirtualTerminal();
|
|
||||||
flushListener = new FlushListener();
|
|
||||||
virtualTerminal.addVirtualTerminalListener(flushListener);
|
|
||||||
lispTerminal = new LispTerminal(virtualTerminal, inputWriter, outputReader);
|
|
||||||
lispTerminal.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws IOException {
|
public void tearDown() {
|
||||||
lispTerminal.stop();
|
terminal.stop();
|
||||||
outputWriter.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void leftArrowDoesNotMovePastOrigin() {
|
public void leftArrowDoesNotMovePastOrigin() {
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void leftArrowWorksAfterEnteringCharacters() {
|
public void leftArrowWorksAfterEnteringCharacters() {
|
||||||
enterCharacters("abc");
|
terminal.enterCharacters("abc");
|
||||||
assertCursorPosition(3, 0);
|
terminal.assertCursorPosition(3, 0);
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(1, 0);
|
terminal.assertCursorPosition(1, 0);
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void leftArrowWorksAcrossRows() {
|
public void leftArrowWorksAcrossRows() {
|
||||||
setColumns(5);
|
terminal.setColumns(5);
|
||||||
enterCharacters("123451");
|
terminal.enterCharacters("123451");
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
assertCursorPosition(4, 0);
|
terminal.assertCursorPosition(4, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rightArrowDoesNotMovePastEndOfInput() {
|
public void rightArrowDoesNotMovePastEndOfInput() {
|
||||||
pressKey(ArrowRight);
|
terminal.pressKey(ArrowRight);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rightArrowWorksAfterMovingLeft() {
|
public void rightArrowWorksAfterMovingLeft() {
|
||||||
enterCharacters("12");
|
terminal.enterCharacters("12");
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
pressKey(ArrowLeft);
|
terminal.pressKey(ArrowLeft);
|
||||||
assertCursorPosition(1, 0);
|
terminal.assertCursorPosition(1, 0);
|
||||||
pressKey(ArrowRight);
|
terminal.pressKey(ArrowRight);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
pressKey(ArrowRight);
|
terminal.pressKey(ArrowRight);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void rightArrowWorksAcrossRow() {
|
public void rightArrowWorksAcrossRow() {
|
||||||
setColumns(5);
|
terminal.setColumns(5);
|
||||||
enterCharacters("123451");
|
terminal.enterCharacters("123451");
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
assertCursorPosition(3, 0);
|
terminal.assertCursorPosition(3, 0);
|
||||||
pressKeyTimes(ArrowRight, 3);
|
terminal.pressKeyTimes(ArrowRight, 3);
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void characterKeyIsEchoed() {
|
public void characterKeyIsEchoed() {
|
||||||
enterCharacter('a');
|
terminal.enterCharacter('a');
|
||||||
assertCursorPosition(1, 0);
|
terminal.assertCursorPosition(1, 0);
|
||||||
assertCharacterAtPosition('a', 0, 0);
|
terminal.assertCharacterAtPosition('a', 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void characterIsInserted() {
|
public void characterIsInserted() {
|
||||||
enterCharacters("abcd");
|
terminal.enterCharacters("abcd");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
enterCharacter('x');
|
terminal.enterCharacter('x');
|
||||||
assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c', 'd' } });
|
terminal.assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c', 'd' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void characterIsInserted_PushesInputToNextRow() {
|
public void characterIsInserted_PushesInputToNextRow() {
|
||||||
setColumns(4);
|
terminal.setColumns(4);
|
||||||
enterCharacters("abcd");
|
terminal.enterCharacters("abcd");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
enterCharacter('x');
|
terminal.enterCharacter('x');
|
||||||
assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c' }, { 'd', ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { 'a', 'b', 'x', 'c' }, { 'd', ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backspaceDoesNothingAtOrigin() {
|
public void backspaceDoesNothingAtOrigin() {
|
||||||
pressKey(Backspace);
|
terminal.pressKey(Backspace);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backspaceWorksAfterInput() {
|
public void backspaceWorksAfterInput() {
|
||||||
enterCharacters("12345");
|
terminal.enterCharacters("12345");
|
||||||
pressKeyTimes(Backspace, 2);
|
terminal.pressKeyTimes(Backspace, 2);
|
||||||
assertCursorPosition(3, 0);
|
terminal.assertCursorPosition(3, 0);
|
||||||
assertCharacterPositions(new char[][] { { '1', '2', '3', ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '1', '2', '3', ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backspaceWorksAcrossRow() {
|
public void backspaceWorksAcrossRow() {
|
||||||
setColumns(4);
|
terminal.setColumns(4);
|
||||||
enterCharacters("1234567");
|
terminal.enterCharacters("1234567");
|
||||||
pressKeyTimes(Backspace, 5);
|
terminal.pressKeyTimes(Backspace, 5);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
assertCharacterPositions(new char[][] { { '1', '2', ' ', ' ' }, { ' ', ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '1', '2', ' ', ' ' }, { ' ', ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backspaceWorksInMiddleOfInput() {
|
public void backspaceWorksInMiddleOfInput() {
|
||||||
enterCharacters("12345");
|
terminal.enterCharacters("12345");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
pressKey(Backspace);
|
terminal.pressKey(Backspace);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
assertCharacterPositions(new char[][] { { '1', '2', '4', '5' } });
|
terminal.assertCharacterPositions(new char[][] { { '1', '2', '4', '5' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteDoesNothingAtOrigin() {
|
public void deleteDoesNothingAtOrigin() {
|
||||||
pressKey(Delete);
|
terminal.pressKey(Delete);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteDoesNothingAtEndOfInput() {
|
public void deleteDoesNothingAtEndOfInput() {
|
||||||
enterCharacters("del");
|
terminal.enterCharacters("del");
|
||||||
pressKey(Delete);
|
terminal.pressKey(Delete);
|
||||||
assertCursorPosition(3, 0);
|
terminal.assertCursorPosition(3, 0);
|
||||||
assertCharacterPositions(new char[][] { { 'd', 'e', 'l' } });
|
terminal.assertCharacterPositions(new char[][] { { 'd', 'e', 'l' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWorksAtStartOfInput() {
|
public void deleteWorksAtStartOfInput() {
|
||||||
enterCharacters("del");
|
terminal.enterCharacters("del");
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
pressKeyTimes(Delete, 3);
|
terminal.pressKeyTimes(Delete, 3);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertCharacterPositions(new char[][] { { ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWorksAcrossRow() {
|
public void deleteWorksAcrossRow() {
|
||||||
setColumns(4);
|
terminal.setColumns(4);
|
||||||
enterCharacters("delete");
|
terminal.enterCharacters("delete");
|
||||||
pressKeyTimes(ArrowLeft, 5);
|
terminal.pressKeyTimes(ArrowLeft, 5);
|
||||||
pressKey(Delete);
|
terminal.pressKey(Delete);
|
||||||
assertCursorPosition(1, 0);
|
terminal.assertCursorPosition(1, 0);
|
||||||
assertCharacterPositions(new char[][] { { 'd', 'l', 'e', 't' }, { 'e', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { 'd', 'l', 'e', 't' }, { 'e', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterMovesToNextLine() {
|
public void enterMovesToNextLine() {
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertCursorPosition(0, 1);
|
terminal.assertCursorPosition(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterWritesLineToPipedStream() {
|
public void enterWritesLineToPipedStream() {
|
||||||
enterCharacters("enter");
|
terminal.enterCharacters("enter");
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertInputWritten("enter\n");
|
terminal.assertInputWritten("enter\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterPressedInMiddleOfInput_WritesEntireLineToPipedStream() {
|
public void enterPressedInMiddleOfInput_WritesEntireLineToPipedStream() {
|
||||||
enterCharacters("enter");
|
terminal.enterCharacters("enter");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertInputWritten("enter\n");
|
terminal.assertInputWritten("enter\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterAfterInsertedText_WritesLineToPipedStream() {
|
public void enterAfterInsertedText_WritesLineToPipedStream() {
|
||||||
enterCharacters("enter");
|
terminal.enterCharacters("enter");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
enterCharacters("||");
|
terminal.enterCharacters("||");
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertInputWritten("ent||er\n");
|
terminal.assertInputWritten("ent||er\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterAfterBackspace_WritesLineToPipedStream() {
|
public void enterAfterBackspace_WritesLineToPipedStream() {
|
||||||
enterCharacters("enter");
|
terminal.enterCharacters("enter");
|
||||||
pressKeyTimes(Backspace, 2);
|
terminal.pressKeyTimes(Backspace, 2);
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertInputWritten("ent\n");
|
terminal.assertInputWritten("ent\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterAfterDelete_WritesLineToPipedStream() {
|
public void enterAfterDelete_WritesLineToPipedStream() {
|
||||||
enterCharacters("enter");
|
terminal.enterCharacters("enter");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
pressKeyTimes(Delete, 2);
|
terminal.pressKeyTimes(Delete, 2);
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
assertInputWritten("ent\n");
|
terminal.assertInputWritten("ent\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlDWorks() {
|
public void controlDWorks() {
|
||||||
enterCharacters("control-d");
|
terminal.enterCharacters("control-d");
|
||||||
enterControlCharacter('d');
|
terminal.enterControlCharacter('d');
|
||||||
assertInputStreamClosed();
|
terminal.assertInputStreamClosed();
|
||||||
assertInputWritten("control-d\n");
|
terminal.assertInputWritten("control-d\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlCWorks() {
|
public void controlCWorks() {
|
||||||
enterCharacters("ctrl-c");
|
terminal.enterCharacters("ctrl-c");
|
||||||
enterControlCharacter('c');
|
terminal.enterControlCharacter('c');
|
||||||
produceOutput("");
|
terminal.produceOutput("");
|
||||||
assertInputStreamClosed();
|
terminal.assertInputStreamClosed();
|
||||||
assertInputWritten("");
|
terminal.assertInputWritten("");
|
||||||
assertCharacterPositions(new char[][] { { 'c', 't', 'r', 'l', '-', 'c', ' ', ' ', ' ' },
|
terminal.assertCharacterPositions(new char[][] { { 'c', 't', 'r', 'l', '-', 'c', ' ', ' ', ' ' },
|
||||||
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } });
|
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlDWorksInMiddleOfInput() {
|
public void controlDWorksInMiddleOfInput() {
|
||||||
enterCharacters("control-d");
|
terminal.enterCharacters("control-d");
|
||||||
pressKeyTimes(ArrowLeft, 2);
|
terminal.pressKeyTimes(ArrowLeft, 2);
|
||||||
enterControlCharacter('d');
|
terminal.enterControlCharacter('d');
|
||||||
assertInputStreamClosed();
|
terminal.assertInputStreamClosed();
|
||||||
assertInputWritten("control-d\n");
|
terminal.assertInputWritten("control-d\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void escapeDoesNothing() {
|
public void escapeDoesNothing() {
|
||||||
pressKey(Escape);
|
terminal.pressKey(Escape);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertInputWritten("");
|
terminal.assertInputWritten("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlQDoesNothing() {
|
public void controlQDoesNothing() {
|
||||||
enterControlCharacter('q');
|
terminal.enterControlCharacter('q');
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertInputWritten("");
|
terminal.assertInputWritten("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlEnterDoesNothing() {
|
public void controlEnterDoesNothing() {
|
||||||
pressControlKey(Enter);
|
terminal.pressControlKey(Enter);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertInputWritten("");
|
terminal.assertInputWritten("");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputIsWritten() {
|
public void outputIsWritten() {
|
||||||
produceOutput("output");
|
terminal.produceOutput("output");
|
||||||
assertCursorPosition(6, 0);
|
terminal.assertCursorPosition(6, 0);
|
||||||
assertCharacterPositions(new char[][] { { 'o', 'u', 't', 'p', 'u', 't' } });
|
terminal.assertCharacterPositions(new char[][] { { 'o', 'u', 't', 'p', 'u', 't' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void endOfSegmentCharacterIsNotPrinted() {
|
public void endOfSegmentCharacterIsNotPrinted() {
|
||||||
produceOutput("> " + END_OF_SEGMENT);
|
terminal.produceOutput("> " + END_OF_SEGMENT);
|
||||||
assertCursorPosition(2, 0);
|
terminal.assertCursorPosition(2, 0);
|
||||||
assertCharacterPositions(new char[][] { { '>', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '>', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void enterTextPastLastLineOfBuffer() {
|
public void enterTextPastLastLineOfBuffer() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(2);
|
terminal.setRows(2);
|
||||||
enterCharacters("01201201");
|
terminal.enterCharacters("01201201");
|
||||||
assertCursorPosition(2, 1);
|
terminal.assertCursorPosition(2, 1);
|
||||||
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void insertingTextPushesInputPastEndOfBuffer() {
|
public void insertingTextPushesInputPastEndOfBuffer() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(4);
|
terminal.setRows(4);
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
enterCharacters("00011122");
|
terminal.enterCharacters("00011122");
|
||||||
pressKeyTimes(ArrowLeft, 4);
|
terminal.pressKeyTimes(ArrowLeft, 4);
|
||||||
assertCursorPosition(1, 2);
|
terminal.assertCursorPosition(1, 2);
|
||||||
enterCharacters("zz");
|
terminal.enterCharacters("zz");
|
||||||
assertCursorPosition(0, 2);
|
terminal.assertCursorPosition(0, 2);
|
||||||
assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', 'z', 'z' }, { '1', '1', '2' },
|
terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', 'z', 'z' }, { '1', '1', '2' },
|
||||||
{ '2', ' ', ' ' } });
|
{ '2', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void insertingTextDoesNothingWhenBufferFilled() {
|
public void insertingTextDoesNothingWhenBufferFilled() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(3);
|
terminal.setRows(3);
|
||||||
enterCharacters("00011122");
|
terminal.enterCharacters("00011122");
|
||||||
pressKeyTimes(ArrowLeft, 4);
|
terminal.pressKeyTimes(ArrowLeft, 4);
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
enterCharacters("zz");
|
terminal.enterCharacters("zz");
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void appendingTextDoesNothingWhenBufferFilled() {
|
public void appendingTextDoesNothingWhenBufferFilled() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(3);
|
terminal.setRows(3);
|
||||||
enterCharacters("000111222333444");
|
terminal.enterCharacters("000111222333444");
|
||||||
assertCursorPosition(2, 2);
|
terminal.assertCursorPosition(2, 2);
|
||||||
assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { '0', '0', '0' }, { '1', '1', '1' }, { '2', '2', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void printedOutputToEndOfRow_MovesCursorToNextRow() {
|
public void printedOutputToEndOfRow_MovesCursorToNextRow() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(0, 1);
|
terminal.assertCursorPosition(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void printedOutputToEndOfBuffer_MovesCursorToNewRow() {
|
public void printedOutputToEndOfBuffer_MovesCursorToNewRow() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(2);
|
terminal.setRows(2);
|
||||||
produceOutput("output");
|
terminal.produceOutput("output");
|
||||||
assertCursorPosition(0, 1);
|
terminal.assertCursorPosition(0, 1);
|
||||||
assertCharacterPositions(new char[][] { { 'p', 'u', 't' }, { ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { 'p', 'u', 't' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputDoesNotOverwriteInput_AndRedisplaysInput() {
|
public void outputDoesNotOverwriteInput_AndRedisplaysInput() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
enterCharacters("0123");
|
terminal.enterCharacters("0123");
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(2, 3);
|
terminal.assertCursorPosition(2, 3);
|
||||||
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', 'o', 'u' }, { 't', '0', '1' },
|
terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', 'o', 'u' }, { 't', '0', '1' },
|
||||||
{ '2', '3', ' ' }, { ' ', ' ', ' ' } });
|
{ '2', '3', ' ' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputEndsOnSecondToLastColumn_MovesToNewRow() {
|
public void outputEndsOnSecondToLastColumn_MovesToNewRow() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
enterCharacters("01234");
|
terminal.enterCharacters("01234");
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(2, 4);
|
terminal.assertCursorPosition(2, 4);
|
||||||
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', 'o' }, { 'u', 't', ' ' },
|
terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', 'o' }, { 'u', 't', ' ' },
|
||||||
{ '0', '1', '2' }, { '3', '4', ' ' } });
|
{ '0', '1', '2' }, { '3', '4', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputEndsOnLastColumn_MovesToNewRow() {
|
public void outputEndsOnLastColumn_MovesToNewRow() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
enterCharacters("012345");
|
terminal.enterCharacters("012345");
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(0, 5);
|
terminal.assertCursorPosition(0, 5);
|
||||||
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { 'o', 'u', 't' },
|
terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '3', '4', '5' }, { 'o', 'u', 't' },
|
||||||
{ '0', '1', '2' }, { '3', '4', '5' }, { ' ', ' ', ' ' } });
|
{ '0', '1', '2' }, { '3', '4', '5' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputRedisplaysInputAtEndOfBuffer() {
|
public void outputRedisplaysInputAtEndOfBuffer() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
setRows(4);
|
terminal.setRows(4);
|
||||||
enterCharacters("01234");
|
terminal.enterCharacters("01234");
|
||||||
pressKeyTimes(ArrowLeft, 3);
|
terminal.pressKeyTimes(ArrowLeft, 3);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(2, 3);
|
terminal.assertCursorPosition(2, 3);
|
||||||
assertCharacterPositions(new char[][] { { '3', '4', 'o' }, { 'u', 't', ' ' }, { '0', '1', '2' },
|
terminal.assertCharacterPositions(new char[][] { { '3', '4', 'o' }, { 'u', 't', ' ' }, { '0', '1', '2' },
|
||||||
{ '3', '4', ' ' } });
|
{ '3', '4', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void outputDoesNotOverwriteInput_AfterEnter() {
|
public void outputDoesNotOverwriteInput_AfterEnter() {
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
enterCharacters("01201201");
|
terminal.enterCharacters("01201201");
|
||||||
pressKeyTimes(ArrowLeft, 5);
|
terminal.pressKeyTimes(ArrowLeft, 5);
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
produceOutput("out");
|
terminal.produceOutput("out");
|
||||||
assertCursorPosition(0, 4);
|
terminal.assertCursorPosition(0, 4);
|
||||||
assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' },
|
terminal.assertCharacterPositions(new char[][] { { '0', '1', '2' }, { '0', '1', '2' }, { '0', '1', ' ' },
|
||||||
{ 'o', 'u', 't' }, { ' ', ' ', ' ' } });
|
{ 'o', 'u', 't' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resizeIsHandledGracefully() {
|
public void resizeIsHandledGracefully() {
|
||||||
enterCharacters("resize");
|
terminal.enterCharacters("resize");
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
enterCharacters("test");
|
terminal.enterCharacters("test");
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
assertCursorPosition(1, 1);
|
terminal.assertCursorPosition(1, 1);
|
||||||
assertCharacterPositions(new char[][] { { 't', 'e', 's' }, { 't', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { 't', 'e', 's' }, { 't', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void backspaceWorksAfterResize() {
|
public void backspaceWorksAfterResize() {
|
||||||
enterCharacters("resize");
|
terminal.enterCharacters("resize");
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
enterCharacters("test");
|
terminal.enterCharacters("test");
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
pressKeyTimes(Backspace, 20);
|
terminal.pressKeyTimes(Backspace, 20);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteWorksAfterResize() {
|
public void deleteWorksAfterResize() {
|
||||||
enterCharacters("resize");
|
terminal.enterCharacters("resize");
|
||||||
pressKey(Enter);
|
terminal.pressKey(Enter);
|
||||||
enterCharacters("test");
|
terminal.enterCharacters("test");
|
||||||
setColumns(3);
|
terminal.setColumns(3);
|
||||||
pressKeyTimes(ArrowLeft, 20);
|
terminal.pressKeyTimes(ArrowLeft, 20);
|
||||||
pressKeyTimes(Delete, 20);
|
terminal.pressKeyTimes(Delete, 20);
|
||||||
pressKeyTimes(ArrowRight, 20);
|
terminal.pressKeyTimes(ArrowRight, 20);
|
||||||
assertCursorPosition(0, 0);
|
terminal.assertCursorPosition(0, 0);
|
||||||
assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } });
|
terminal.assertCharacterPositions(new char[][] { { ' ', ' ', ' ' }, { ' ', ' ', ' ' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void controlSequencesAreNotPrinted() {
|
public void controlSequencesAreNotPrinted() {
|
||||||
produceOutput("\u001B[32mcontrol\u001B[0mseq");
|
terminal.produceOutput("\u001B[32mcontrol\u001B[0mseq");
|
||||||
assertCharacterPositions(new char[][] { { 'c', 'o', 'n', 't', 'r', 'o', 'l', 's', 'e', 'q' } });
|
terminal.assertCharacterPositions(new char[][] { { 'c', 'o', 'n', 't', 'r', 'o', 'l', 's', 'e', 'q' } });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
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 VirtualTerminal virtualTerminal;
|
||||||
|
private FlushListener flushListener;
|
||||||
|
private PipedInputStream inputReader;
|
||||||
|
private PipedOutputStream inputWriter;
|
||||||
|
private PipedInputStream outputReader;
|
||||||
|
private PipedOutputStream outputWriter;
|
||||||
|
private LispTerminal lispTerminal;
|
||||||
|
|
||||||
|
public VirtualTerminalInteractor() {
|
||||||
|
try {
|
||||||
|
this.inputReader = new PipedInputStream();
|
||||||
|
this.inputWriter = new PipedOutputStream(inputReader);
|
||||||
|
this.outputReader = new PipedInputStream();
|
||||||
|
this.outputWriter = new PipedOutputStream(outputReader);
|
||||||
|
this.virtualTerminal = new DefaultVirtualTerminal();
|
||||||
|
this.flushListener = new FlushListener();
|
||||||
|
this.virtualTerminal.addVirtualTerminalListener(flushListener);
|
||||||
|
this.lispTerminal = new LispTerminal(virtualTerminal, inputWriter, outputReader);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 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) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue