package io.termd.core.readline; import io.termd.core.TestBase; import io.termd.core.tty.TtyEvent; import io.termd.core.util.Vector; import org.junit.Test; import java.util.Collections; import java.util.LinkedList; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; /** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */ public class ReadlineTest extends TestBase { @Test public void testPrompt() { TestTerm term = new TestTerm(this); term.readline(event -> testComplete()); term.assertScreen("% "); term.assertAt(0, 2); } @Test public void testEnter() { TestTerm term = new TestTerm(this); term.readline(event -> testComplete()); term.read('\r'); term.assertScreen("% "); term.assertAt(1, 0); await(); } @Test public void cancel() { TestTerm term = new TestTerm(this); assertFalse(term.readline.cancel()); term.readline(s -> { assertNull(s); testComplete(); }); assertTrue(term.readline.cancel()); assertFalse(term.readline.cancel()); await(); } @Test public void testInsertChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.assertScreen("% A"); term.assertAt(0, 3); } @Test public void testInsertCharEnter() throws Exception { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.read('A'); term.read('\r'); term.assertScreen("% A"); term.assertAt(1, 0); assertEquals("A", line.get()); } @Test public void testEscapeCR() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('\\'); term.assertScreen("% \\"); term.read('\r'); term.assertScreen( "% \\", "> " ); term.assertAt(1, 2); } @Test public void testBackwardDeleteChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.read(BACKWARD_DELETE_KEY); term.assertScreen("% "); term.assertAt(0, 2); } @Test public void testBackwardDelete() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read(BACKWARD_DELETE_KEY); term.assertScreen( "% " ); term.assertAt(0, 2); } @Test public void testBackwardDeleteLastChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.read('B'); term.read(8); term.assertScreen( "% A" ); term.assertAt(0, 3); } @Test public void testBackwardCharBackwardDeleteChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.read('B'); term.read(BACKWARD_KEY); term.read(BACKWARD_DELETE_KEY); term.assertScreen( "% B" ); term.assertAt(0, 2); } @Test public void testBackwardDeleteEscape() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('\\'); term.assertScreen("% \\"); term.read(BACKWARD_DELETE_KEY); term.assertScreen( "% " ); term.assertAt(0, 2); } @Test public void testBackwardChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read(BACKWARD_KEY); term.assertScreen("% "); term.assertAt(0, 2); } @Test public void testInsertCharBackwardChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.read(BACKWARD_KEY); term.assertScreen("% A"); term.assertAt(0, 2); } @Test public void testForwardChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read(FORWARD_KEY); term.assertScreen("% "); term.assertAt(0, 2); } @Test public void testInsertCharForwardChar() { TestTerm term = new TestTerm(this); term.readlineFail(); term.read('A'); term.read(BACKWARD_KEY); term.read(FORWARD_KEY); term.assertScreen("% A"); term.assertAt(0, 3); } @Test public void testQuotedMultiline() { TestTerm term = new TestTerm(this); Supplier<String> a = term.readlineComplete(); term.read('A'); term.read('"'); term.read('\r'); assertNull(a.get()); term.assertScreen( "% A\"", "> "); term.read('B'); term.read('\r'); term.assertScreen( "% A\"", "> B", "> "); assertNull(a.get()); term.read('C'); term.read('"'); term.read('\r'); term.assertScreen( "% A\"", "> B", "> C\""); term.assertAt(3, 0); assertEquals("A\"\nB\nC\"", a.get()); } @Test public void testPreserveOriginalHandlers() { TestTerm term = new TestTerm(this); Consumer<int[]> readHandler = buf -> {}; Consumer<Vector> sizeHandler = size -> {}; term.readHandler = readHandler; term.sizeHandler = sizeHandler; term.readlineComplete(); assertFalse(term.readHandler == readHandler); assertFalse(term.sizeHandler == sizeHandler); term.read('\r'); assertEquals(term.readHandler, readHandler); assertEquals(term.sizeHandler, sizeHandler); } @Test public void testBuffering() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.read('h', 'e', 'l', 'l', 'o', '\r', 'b', 'y', 'e', '\r'); assertEquals("hello", line.get()); term.assertScreen("% hello"); term.assertAt(1, 0); line = term.readlineComplete(); term.executeTasks(); assertEquals("bye", line.get()); term.assertScreen("% hello", "% bye"); term.assertAt(2, 0); } @Test public void testHistory() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('0', '\r'); term.readlineComplete(); term.read('1', '\r'); term.readlineComplete(); term.read('2', '\r'); term.assertScreen("% 0", "% 1", "% 2"); term.readlineComplete(); term.read('3'); term.assertScreen("% 0", "% 1", "% 2", "% 3"); term.read(UP_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 2"); term.read(UP_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 1"); term.read(UP_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 0"); term.read(UP_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 0"); term.read(DOWN_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 1"); term.read('_'); term.assertScreen("% 0", "% 1", "% 2", "% 1_"); term.read(DOWN_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 2"); term.read(UP_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 1"); term.read(DOWN_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 2"); term.read(DOWN_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 3"); term.read(DOWN_KEY); term.assertScreen("% 0", "% 1", "% 2", "% 3"); } @Test public void testEndOfLine() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('a', 'b', 'c', 'd'); term.read(CTRL_A_KEY); term.assertScreen("% abcd"); term.assertAt(0, 2); term.read(CTRL_A_KEY); term.assertScreen("% abcd"); term.assertAt(0, 2); } @Test public void testBeginningOfLine() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('a', 'b', 'c', 'd'); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.assertScreen("% abcd"); term.assertAt(0, 2); term.read(CTRL_E_KEY); term.assertScreen("% abcd"); term.assertAt(0, 6); term.assertScreen("% abcd"); term.assertAt(0, 6); } @Test public void testResetDuringInteraction1() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.read('a', 'b', 'c', 'd'); term.read(CTRL_C_KEY); term.read('e'); term.assertScreen("% abcd", "% e"); term.assertAt(1, 3); term.read('\r'); assertEquals("e", line.get()); } @Test public void testResetDuringInteraction2() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.read('a', 'b', 'c', 'd', '\\', '\r'); term.read(CTRL_C_KEY); term.read('e'); term.assertScreen("% abcd\\", "> ", "% e"); term.assertAt(2, 3); term.read('\r'); assertEquals("e", line.get()); } @Test public void testIllegalChar() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); assertEquals(0, term.getBellCount()); term.read('a', 6, 'b', '\r'); assertEquals(1, term.getBellCount()); assertEquals("ab", line.get()); } @Test public void testEventHandler() { TestTerm term = new TestTerm(this); LinkedList<TtyEvent> events = new LinkedList<>(); BiConsumer<TtyEvent, Integer> handler = (event,cp) -> events.add(event); term.eventHandler = handler; Supplier<String> line = term.readlineComplete(); term.read(CTRL_C_KEY); term.read('\r'); assertEquals("", line.get()); assertEquals(Collections.emptyList(), events); term.eventHandler.accept(TtyEvent.EOF, 4); assertEquals(Collections.singletonList(TtyEvent.EOF), events); } @Test public void testEOF() { TestTerm term = new TestTerm(this); LinkedList<String> lines = new LinkedList<>(); term.readline(lines::add); term.read(TtyEvent.EOF.codePoint()); assertEquals(Collections.singletonList(null), lines); } @Test public void testDeleteChar() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.read('a', 'b', 'c'); term.read(CTRL_D_KEY); term.assertScreen("% abc"); term.assertAt(0, 5); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.read(CTRL_D_KEY); term.assertScreen("% ac"); term.assertAt(0, 3); term.read('\r'); assertEquals("ac", line.get()); } @Test public void testKillLine() { TestTerm term = new TestTerm(this); Supplier<String> line = term.readlineComplete(); term.setWidth(4); term.read('a', 'b', 'c', 'd', 'e'); term.assertScreen("% ab", "cde"); term.assertAt(1, 3); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.read(BACKWARD_KEY); term.assertScreen("% ab", "cde"); term.assertAt(0, 3); term.read(KILL_LINE); term.assertScreen("% a", ""); term.assertAt(0, 3); term.read('\r'); assertEquals("a", line.get()); } @Test public void testBackwardWord() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('a', '0', '1', ' ', 'e', '9', '_', '_' ,'5', 'a'); term.read(BACKWARD_KEY); term.assertAt(0, 11); term.read(BACKWARD_WORD_SEQ); term.assertAt(0, 10); term.read(BACKWARD_WORD_SEQ); term.assertAt(0, 6); term.read(BACKWARD_WORD_SEQ); term.assertAt(0, 2); term.read(BACKWARD_WORD_SEQ); term.assertAt(0, 2); } @Test public void testForwardWord() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('a', '0', '1', ' ', 'e', '9', '_', '_', '5', 'a'); term.read(CTRL_A_KEY); term.assertAt(0, 2); term.read(FORWARD_KEY); term.assertAt(0, 3); term.read(FORWARD_WORD_SEQ); term.assertAt(0, 5); term.read(FORWARD_WORD_SEQ); term.assertAt(0, 8); term.read(FORWARD_WORD_SEQ); term.assertAt(0, 12); term.read(FORWARD_WORD_SEQ); term.assertAt(0, 12); } @Test public void testBackwardKillWord() { TestTerm term = new TestTerm(this); term.readlineComplete(); term.read('a', '0', '1', ' ', 'e', '9', '_', '_', '5', 'a'); term.read(BACKWARD_KEY); term.assertAt(0, 11); term.read(META_BACKSPACE); term.assertAt(0, 10); term.assertScreen("% a01 e9__a"); term.read(META_BACKSPACE); term.assertAt(0, 6); term.assertScreen("% a01 a"); term.read(META_BACKSPACE); term.assertAt(0, 2); term.assertScreen("% a"); term.read(META_BACKSPACE); term.assertAt(0, 2); term.assertScreen("% a"); } }