transcendental-lisp/test/terminal/LispTerminalTest.java

408 lines
12 KiB
Java

package terminal;
import static org.junit.Assert.*;
import static terminal.LispTerminal.END_OF_SEGMENT;
import java.io.*;
import org.junit.*;
import com.googlecode.lanterna.*;
import com.googlecode.lanterna.input.*;
import com.googlecode.lanterna.terminal.virtual.*;
public class LispTerminalTest {
private PipedInputStream inputReader;
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 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 e) {}
}
private void waitForFlushes(int flushCount) {
try {
synchronized (flushListener) {
while (flushListener.getFlushCount() < flushCount)
flushListener.wait();
flushListener.resetFlushCount();
}
} catch (InterruptedException e) {}
}
private void setColumns(int columns) {
virtualTerminal.setTerminalSize(new TerminalSize(columns, virtualTerminal.getTerminalSize().getRows()));
}
private void assertCursorPosition(int column, int row) {
assertEquals(column, virtualTerminal.getCursorBufferPosition().getColumn());
assertEquals(row, virtualTerminal.getCursorBufferPosition().getRow());
}
private void assertCharacterAtPosition(char character, int column, int row) {
TerminalPosition position = new TerminalPosition(column, row);
assertEquals(character, virtualTerminal.getBufferCharacter(position).getCharacter());
}
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 e) {}
assertEquals(expected, actual);
}
private void assertInputStreamClosed() {
try {
inputWriter.write(0);
fail("input stream not closed");
} catch (IOException e) {}
}
@Before
public void setUp() throws IOException {
inputReader = new PipedInputStream();
inputWriter = new PipedOutputStream(inputReader);
outputReader = new PipedInputStream();
outputWriter = new PipedOutputStream(outputReader);
virtualTerminal = new DefaultVirtualTerminal();
flushListener = new FlushListener();
virtualTerminal.addVirtualTerminalListener(flushListener);
lispTerminal = new LispTerminal(virtualTerminal, inputWriter, outputReader);
lispTerminal.run();
}
@After
public void tearDown() throws IOException {
lispTerminal.finish();
outputWriter.close();
}
@Test
public void leftArrowDoesNotMovePastOrigin() {
pressKey(KeyType.ArrowLeft);
assertCursorPosition(0, 0);
}
@Test
public void leftArrowWorksAfterEnteringCharacters() {
enterCharacters("abc");
assertCursorPosition(3, 0);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(2, 0);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(1, 0);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(0, 0);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(0, 0);
}
@Test
public void leftArrowWorksAcrossRows() {
setColumns(5);
enterCharacters("123451");
assertCursorPosition(1, 1);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(4, 0);
}
@Test
public void rightArrowDoesNotMovePastEndOfInput() {
pressKey(KeyType.ArrowRight);
assertCursorPosition(0, 0);
}
@Test
public void rightArrowWorksAfterMovingLeft() {
enterCharacters("12");
assertCursorPosition(2, 0);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(1, 0);
pressKey(KeyType.ArrowRight);
assertCursorPosition(2, 0);
pressKey(KeyType.ArrowRight);
assertCursorPosition(2, 0);
}
@Test
public void rightArrowWorksAcrossRow() {
setColumns(5);
enterCharacters("123451");
assertCursorPosition(1, 1);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
assertCursorPosition(3, 0);
pressKey(KeyType.ArrowRight);
pressKey(KeyType.ArrowRight);
pressKey(KeyType.ArrowRight);
assertCursorPosition(1, 1);
}
@Test
public void characterKeyIsEchoed() {
enterCharacter('a');
assertCursorPosition(1, 0);
assertCharacterAtPosition('a', 0, 0);
}
@Test
public void characterIsInserted() {
enterCharacters("abcd");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
enterCharacter('x');
assertCharacterAtPosition('a', 0, 0);
assertCharacterAtPosition('b', 1, 0);
assertCharacterAtPosition('x', 2, 0);
assertCharacterAtPosition('c', 3, 0);
assertCharacterAtPosition('d', 4, 0);
}
@Test
public void characterIsInserted_PushesInputToNextRow() {
setColumns(4);
enterCharacters("abcd");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
enterCharacter('x');
assertCharacterAtPosition('a', 0, 0);
assertCharacterAtPosition('b', 1, 0);
assertCharacterAtPosition('x', 2, 0);
assertCharacterAtPosition('c', 3, 0);
assertCharacterAtPosition('d', 0, 1);
}
@Test
public void backspaceDoesNothingAtOrigin() {
pressKey(KeyType.Backspace);
assertCursorPosition(0, 0);
}
@Test
public void backspaceWorksAfterInput() {
enterCharacters("12345");
pressKey(KeyType.Backspace);
pressKey(KeyType.Backspace);
assertCursorPosition(3, 0);
assertCharacterAtPosition('1', 0, 0);
assertCharacterAtPosition('2', 1, 0);
assertCharacterAtPosition('3', 2, 0);
assertCharacterAtPosition(' ', 3, 0);
assertCharacterAtPosition(' ', 4, 0);
assertCharacterAtPosition(' ', 5, 0);
}
@Test
public void backspaceWorksAcrossRow() {
setColumns(4);
enterCharacters("1234567");
pressKey(KeyType.Backspace);
pressKey(KeyType.Backspace);
pressKey(KeyType.Backspace);
pressKey(KeyType.Backspace);
pressKey(KeyType.Backspace);
assertCursorPosition(2, 0);
assertCharacterAtPosition('1', 0, 0);
assertCharacterAtPosition('2', 1, 0);
assertCharacterAtPosition(' ', 2, 0);
assertCharacterAtPosition(' ', 3, 0);
assertCharacterAtPosition(' ', 0, 1);
assertCharacterAtPosition(' ', 1, 1);
assertCharacterAtPosition(' ', 2, 1);
}
@Test
public void backspaceWorksInMiddleOfInput() {
enterCharacters("12345");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.Backspace);
assertCursorPosition(2, 0);
assertCharacterAtPosition('1', 0, 0);
assertCharacterAtPosition('2', 1, 0);
assertCharacterAtPosition('4', 2, 0);
assertCharacterAtPosition('5', 3, 0);
}
@Test
public void deleteDoesNothingAtOrigin() {
pressKey(KeyType.Delete);
assertCursorPosition(0, 0);
}
@Test
public void deleteDoesNothingAtEndOfInput() {
enterCharacters("del");
pressKey(KeyType.Delete);
assertCursorPosition(3, 0);
assertCharacterAtPosition('d', 0, 0);
assertCharacterAtPosition('e', 1, 0);
assertCharacterAtPosition('l', 2, 0);
}
@Test
public void deleteWorksAtStartOfInput() {
enterCharacters("del");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.Delete);
pressKey(KeyType.Delete);
pressKey(KeyType.Delete);
assertCursorPosition(0, 0);
assertCharacterAtPosition(' ', 0, 0);
assertCharacterAtPosition(' ', 1, 0);
assertCharacterAtPosition(' ', 2, 0);
}
@Test
public void deleteWorksAcrossRow() {
setColumns(4);
enterCharacters("delete");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.Delete);
assertCursorPosition(1, 0);
assertCharacterAtPosition('d', 0, 0);
assertCharacterAtPosition('l', 1, 0);
assertCharacterAtPosition('e', 2, 0);
assertCharacterAtPosition('t', 3, 0);
assertCharacterAtPosition('e', 0, 1);
assertCharacterAtPosition(' ', 1, 1);
}
@Test
public void enterMovesToNextLine() {
pressKey(KeyType.Enter);
assertCursorPosition(0, 1);
}
@Test
public void enterWritesLineToPipedStream() {
enterCharacters("enter");
pressKey(KeyType.Enter);
assertInputWritten("enter\n");
}
@Test
public void enterPressedInMiddleOfInput_WritesEntireLineToPipedStream() {
enterCharacters("enter");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.Enter);
assertInputWritten("enter\n");
}
@Test
public void controlDWorks() {
enterCharacters("control-d");
enterControlCharacter('d');
assertInputStreamClosed();
assertInputWritten("control-d\n");
}
@Test
public void controlDWorksInMiddleOfInput() {
enterCharacters("control-d");
pressKey(KeyType.ArrowLeft);
pressKey(KeyType.ArrowLeft);
enterControlCharacter('d');
assertInputStreamClosed();
assertInputWritten("control-d\n");
}
@Test
public void escapeDoesNothing() {
pressKey(KeyType.Escape);
assertCursorPosition(0, 0);
assertInputWritten("");
}
@Test
public void controlQDoesNothing() {
enterControlCharacter('q');
assertCursorPosition(0, 0);
assertInputWritten("");
}
@Test
public void controlEnterDoesNothing() {
pressControlKey(KeyType.Enter);
assertCursorPosition(0, 0);
assertInputWritten("");
}
@Test
public void outputIsWritten() {
produceOutput("output");
assertCharacterAtPosition('o', 0, 0);
assertCharacterAtPosition('u', 1, 0);
assertCharacterAtPosition('t', 2, 0);
assertCharacterAtPosition('p', 3, 0);
assertCharacterAtPosition('u', 4, 0);
assertCharacterAtPosition('t', 5, 0);
}
@Test
public void endOfSegmentCharacterIsNotPrinted() {
produceOutput("> " + END_OF_SEGMENT);
assertCursorPosition(2, 0);
assertCharacterAtPosition('>', 0, 0);
assertCharacterAtPosition(' ', 1, 0);
assertCharacterAtPosition(' ', 2, 0);
}
}