/*
* Copyright (C) 2012 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.crsh.console;
import org.crsh.cli.impl.Delimiter;
import org.crsh.cli.impl.completion.CompletionMatch;
import org.crsh.cli.spi.Completion;
import org.crsh.keyboard.KeyHandler;
import org.crsh.keyboard.KeyType;
import test.shell.sync.SyncCompleter;
import test.shell.sync.SyncProcess;
import org.crsh.shell.ShellProcessContext;
import org.crsh.shell.ShellResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* @author Julien Viet
*/
public class ConsoleTestCase extends AbstractConsoleTestCase {
public void testEditor() {
console.init();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
}
public void testInsert() {
console.init();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
console.on(KeyStrokes.b);
driver.assertMoveLeft().assertFlush().assertChars("ba").assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
console.on(KeyStrokes.b);
driver.assertMoveLeft().assertFlush().assertChars("bba").assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
assertEquals("bba", getCurrentLine());
}
public void testDeletePrevChar() {
console.init();
console.on(KeyStrokes.DELETE_PREV_CHAR);
driver.assertEmpty();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_PREV_CHAR);
driver.assertDel().assertFlush().assertEmpty();
}
public void testDeleteNextChar() {
console.init();
console.on(KeyStrokes.DELETE_NEXT_CHAR);
driver.assertEmpty();
console.on(KeyStrokes.a);
console.on(KeyStrokes.b);
driver.assertChar('a').assertFlush();
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_NEXT_CHAR);
driver.assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_NEXT_CHAR);
driver.assertMoveRight().assertMoveLeft().assertChar('b').assertChar(' ').assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
assertEquals("b", getCurrentLine());
console.on(KeyStrokes.DELETE_NEXT_CHAR);
driver.assertMoveRight().assertDel().assertFlush().assertEmpty();
assertEquals("", getCurrentLine());
}
public void testDeleteEnd() {
console.init();
console.on(KeyStrokes.DELETE_END);
driver.assertEmpty();
assertEquals("", getClipboard());
console.on(KeyStrokes.a);
console.on(KeyStrokes.b);
console.on(KeyStrokes.c);
driver.assertChar('a').assertFlush();
driver.assertChar('b').assertFlush();
driver.assertChar('c').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_END);
driver.assertMoveRight().assertMoveRight().assertDel().assertDel().assertFlush().assertEmpty();
assertEquals("a", getCurrentLine());
assertEquals("bc", getClipboard());
}
public void testDeleteBeginning() {
console.init();
console.on(KeyStrokes.DELETE_BEGINNING);
driver.assertEmpty();
console.on(KeyStrokes.a);
console.on(KeyStrokes.b);
console.on(KeyStrokes.c);
driver.assertChar('a').assertFlush();
driver.assertChar('b').assertFlush();
driver.assertChar('c').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_BEGINNING);
assertEquals("c", getCurrentLine());
driver.assertMoveLeft().assertChars("c ").assertMoveLeft().assertMoveLeft().assertMoveLeft().assertChars("c ").assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
}
/*
public void testDeleteNextWord() {
console.init();
console.on(KeyEvents.DELETE_NEXT_WORD);
driver.assertEmpty();
assertEquals("", getClipboard());
console.on(KeyEvents.a, KeyEvents.b, KeyEvents.SPACE, KeyEvents.c, KeyEvents.d);
driver.assertChar('a').assertFlush().assertChar('b').assertFlush().assertChar(' ').assertFlush().assertChar('c').assertFlush().assertChar('d').assertFlush().assertEmpty();
console.on(KeyEvents.LEFT, KeyEvents.LEFT, KeyEvents.LEFT, KeyEvents.LEFT);
driver.assertMoveLeft().assertFlush().assertMoveLeft().assertFlush().assertMoveLeft().assertFlush().assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyEvents.DELETE_NEXT_WORD);
driver.assertMoveRight().assertMoveLeft().assertChars(" cd ").assertMoveLeft(4).assertFlush().assertEmpty();
assertEquals("a cd", getCurrentLine());
assertEquals("b", getClipboard());
console.on(KeyEvents.DELETE_NEXT_WORD);
driver.assertMoveRight(3).assertDel(3).assertFlush().assertEmpty();
assertEquals("a", getCurrentLine());
assertEquals(" cd", getClipboard());
}
*/
public void testDeletePrevWord() {
console.init();
console.on(KeyStrokes.DELETE_PREV_WORD);
driver.assertEmpty();
assertEquals("", getClipboard());
console.on(KeyStrokes.a);
console.on(KeyStrokes.b);
console.on(KeyStrokes.SPACE);
console.on(KeyStrokes.c);
console.on(KeyStrokes.d);
driver.assertChar('a').assertFlush().assertChar('b').assertFlush().assertChar(' ').assertFlush().assertChar('c').assertFlush().assertChar('d').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.DELETE_PREV_WORD);
driver.assertMoveLeft().assertChars("d ").assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
assertEquals("ab d", getCurrentLine());
assertEquals("c", getClipboard());
console.on(KeyStrokes.DELETE_PREV_WORD);
driver.assertMoveLeft().assertChars("d ").assertMoveLeft(3).assertChars("d ").assertMoveLeft(3).assertChars("d ").assertMoveLeft(2).assertFlush().assertEmpty();
assertEquals("d", getCurrentLine());
assertEquals("ab ", getClipboard());
}
/*
public void testPasteBefore() {
console.init();
console.on(KeyEvents.PASTE_BEFORE);
driver.assertEmpty();
setClipboard("ab");
console.on(KeyEvents.PASTE_BEFORE);
driver.assertChar('a').assertChar('b').assertFlush().assertEmpty();
assertEquals("ab", getCurrentLine());
assertEquals("ab", getClipboard());
setClipboard("cd");
console.on(KeyEvents.LEFT, KeyEvents.LEFT);
driver.assertMoveLeft().assertFlush().assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyEvents.PASTE_BEFORE);
driver.assertChars("cdab").assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
assertEquals("cdab", getCurrentLine());
assertEquals("cd", getClipboard());
}
*/
public void testMovePrevChar() {
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.LEFT);
driver.assertChar('a').assertFlush().assertMoveLeft().assertFlush().assertEmpty();
}
public void testMoveNextChar() {
console.init();
console.on(KeyStrokes.RIGHT);
driver.assertEmpty();
console.on(KeyStrokes.a);
console.on(KeyStrokes.LEFT);
driver.assertChar('a').assertFlush().assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.RIGHT);
driver.assertMoveRight().assertFlush().assertEmpty();
}
public void testMovePrevWord() {
console.init();
console.on(KeyStrokes.MOVE_PREV_WORD);
driver.assertEmpty();
console.on(KeyStrokes.SPACE);
driver.assertChar(' ').assertFlush().assertEmpty();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.b);
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.MOVE_PREV_WORD);
driver.assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
}
public void testMoveNextWord() {
console.init();
console.on(KeyStrokes.MOVE_NEXT_WORD);
driver.assertEmpty();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.b);
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.SPACE);
driver.assertChar(' ').assertFlush().assertEmpty();
console.on(KeyStrokes.c);
driver.assertChar('c').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.MOVE_NEXT_WORD);
driver.assertMoveRight().assertMoveRight().assertFlush().assertEmpty();
}
public void testMoveBeginning() {
console.init();
console.on(KeyStrokes.MOVE_BEGINNING);
driver.assertEmpty();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.SPACE);
driver.assertChar(' ').assertFlush().assertEmpty();
console.on(KeyStrokes.b);
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.MOVE_BEGINNING);
driver.assertMoveLeft().assertMoveLeft().assertMoveLeft().assertFlush().assertEmpty();
}
public void testMoveEnd() {
console.init();
console.on(KeyStrokes.MOVE_END);
driver.assertEmpty();
console.on(KeyStrokes.a);
driver.assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.SPACE);
driver.assertChar(' ').assertFlush().assertEmpty();
console.on(KeyStrokes.b);
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.LEFT);
driver.assertMoveLeft().assertFlush().assertEmpty();
console.on(KeyStrokes.MOVE_END);
driver.assertMoveRight().assertMoveRight().assertMoveRight().assertFlush().assertEmpty();
}
public void testProcess() {
final ArrayBlockingQueue<String> requests = new ArrayBlockingQueue<String>(1);
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
requests.add(request);
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.b);
console.on(KeyStrokes.ENTER);
assertEquals("a", requests.poll());
ShellProcessContext context = contexts.poll();
assertNotNull(context);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
context.end(ShellResponse.ok());
context = contexts.poll();
assertNotNull(context);
context.end(ShellResponse.ok());
}
public void testPrompt() {
driver.assertEmpty();
prompt = "% ";
console.init();
driver.assertChar('%').assertChar(' ').assertFlush().assertEmpty();
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
ShellProcessContext context = contexts.poll();
assertNotNull(context);
context.end(ShellResponse.ok());
driver.assertCRLF().assertFlush().assertChar('%').assertChar(' ').assertFlush().assertEmpty();
}
public void testHandleKeyInProcess() {
final ArrayBlockingQueue<Integer> keys = new ArrayBlockingQueue<Integer>(1);
shell.addProcess(new SyncProcess() {
@Override
protected KeyHandler createKeyHandler() {
return new KeyHandler() {
@Override
public void handle(KeyType type, int[] sequence) {
for (int c : sequence) {
keys.add(c);
}
}
};
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.b);
assertEquals(1, keys.size());
assertEquals((int)'b', (int)keys.poll());
assertFalse(console.getKeyBuffer().iterator().hasNext());
}
public void testHandleKeyExceptionInProcess() {
shell.addProcess(new SyncProcess() {
@Override
protected KeyHandler createKeyHandler() {
return new KeyHandler() {
@Override
public void handle(KeyType type, int[] sequence) {
throw new RuntimeException();
}
};
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.b);
}
public void testCompleteEmpty() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
return null;
}
});
console.init();
console.on(KeyStrokes.COMPLETE);
driver.assertEmpty();
}
public void testCompleteSingle1() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
Completion.Builder builder = Completion.builder("");
builder.add("foo", false);
return new CompletionMatch(Delimiter.EMPTY, builder.build());
}
});
console.init();
console.on(KeyStrokes.COMPLETE);
driver.assertChars("foo").assertFlush().assertEmpty();
assertEquals("foo", getCurrentLine());
}
public void testCompleteSingle2() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
Completion.Builder builder = Completion.builder("");
builder.add("foo", true);
return new CompletionMatch(Delimiter.EMPTY, builder.build());
}
});
console.init();
console.on(KeyStrokes.COMPLETE);
driver.assertChars("foo").assertChar(' ').assertFlush().assertEmpty();
assertEquals("foo ", getCurrentLine());
}
public void testCompleteMulti1() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
Completion.Builder builder = Completion.builder("");
builder.add("foo", false);
builder.add("bar", false);
return new CompletionMatch(Delimiter.EMPTY, builder.build());
}
});
console.init();
prompt = "% ";
console.on(KeyStrokes.COMPLETE);
driver.assertChars("\nfoo bar \n% ").assertFlush().assertEmpty();
assertEquals("", getCurrentLine());
}
public void testCompleteMulti2() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
Completion.Builder builder = Completion.builder("");
builder.add("afoo", false);
builder.add("abar", false);
return new CompletionMatch(Delimiter.EMPTY, builder.build());
}
});
console.init();
prompt = "% ";
console.on(KeyStrokes.COMPLETE);
driver.assertChars("\nafoo abar \n% a").assertFlush().assertEmpty();
assertEquals("a", getCurrentLine());
}
public void testMultiline1() {
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.BACKSLASH);
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.b);
assertEquals("b", getCurrentLine());
driver.assertChar('a').assertFlush();
driver.assertChar('\\').assertFlush();
driver.assertCRLF().assertChars("> ").assertFlush();
driver.assertChar('b').assertFlush().assertEmpty();
final ArrayList<String> requests = new ArrayList<String>();
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
requests.add(request);
}
});
console.on(KeyStrokes.ENTER);
assertEquals(Arrays.asList("ab"), requests);
}
public void testMultiline2() {
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.QUOTE);
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.b);
assertEquals("b", getCurrentLine());
driver.assertChar('a').assertFlush();
driver.assertChar('"').assertFlush();
driver.assertCRLF().assertChars("> ").assertFlush();
driver.assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.ENTER);
console.on(KeyStrokes.c);
console.on(KeyStrokes.QUOTE);
console.on(KeyStrokes.d);
driver.assertCRLF().assertChars("> ").assertFlush();
driver.assertChar('c').assertFlush();
driver.assertChar('"').assertFlush();
driver.assertChar('d').assertFlush().assertEmpty();
final ArrayList<String> requests = new ArrayList<String>();
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
requests.add(request);
}
});
console.on(KeyStrokes.ENTER);
assertEquals(Arrays.asList("a\"\nb\nc\"d"), requests);
}
public void testCompleteMultiline() {
shell.setCompleter(new SyncCompleter() {
@Override
public CompletionMatch complete(String prefix) {
Completion.Builder builder = Completion.builder("s");
if (prefix.equals("s")) {
builder.add("end", true);
builder.add("et", true);
} else if (prefix.equals("sen")) {
builder.add("d", true);
}
return new CompletionMatch(Delimiter.EMPTY, builder.build());
}
});
console.init();
console.on(KeyStrokes.s);
console.on(KeyStrokes.BACKSLASH);
console.on(KeyStrokes.ENTER);
driver.assertChar('s').assertFlush();
driver.assertChar('\\').assertFlush();
driver.assertCRLF().assertChars("> ").assertFlush();
console.on(KeyStrokes.COMPLETE);
driver.assertChars("\nsend set \ns\\\n> e").assertFlush().assertEmpty();
console.on(KeyStrokes.n);
driver.assertChar('n').assertFlush().assertEmpty();
console.on(KeyStrokes.COMPLETE);
driver.assertChars("d ").assertFlush().assertEmpty();
}
public void testInterruptMultiline() throws Exception {
final ArrayBlockingQueue<String> keys = new ArrayBlockingQueue<String>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
keys.add(request);
}
});
console.init();
console.on(KeyStrokes.QUOTE);
console.on(KeyStrokes.ENTER);
driver.assertChar('"').assertFlush();
driver.assertCRLF().assertChars("> ").assertFlush().assertEmpty();
console.on(KeyStrokes.INTERRUPT);
driver.assertCRLF().assertFlush().assertEmpty();
console.on(KeyStrokes.ENTER);
driver.assertCRLF().assertFlush().assertEmpty();
String request = keys.poll(1, TimeUnit.SECONDS);
assertEquals("", request);
}
public void testHistory() {
console.init();
console.on(KeyStrokes.UP);
driver.assertEmpty();
console.on(KeyStrokes.DOWN);
driver.assertEmpty();
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
context.end(ShellResponse.ok());
}
});
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertCRLF().assertFlush().assertEmpty();
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
context.end(ShellResponse.ok());
}
});
console.on(KeyStrokes.b);
console.on(KeyStrokes.ENTER);
driver.assertChar('b').assertFlush().assertCRLF().assertFlush().assertCRLF().assertFlush().assertEmpty();
console.on(KeyStrokes.c);
driver.assertChar('c').assertFlush().assertEmpty();
console.on(KeyStrokes.UP);
driver.assertDel().assertChar('b').assertFlush().assertEmpty();
console.on(KeyStrokes.UNDERSCORE);
driver.assertChar('_').assertFlush().assertEmpty();
console.on(KeyStrokes.UP);
driver.assertDel().assertDel().assertChar('a').assertFlush().assertEmpty();
console.on(KeyStrokes.UP);
driver.assertEmpty();
console.on(KeyStrokes.DOWN);
driver.assertDel().assertChar('b').assertChar('_').assertFlush().assertEmpty();
console.on(KeyStrokes.DOWN);
driver.assertDel().assertDel().assertChar('c').assertFlush().assertEmpty();
console.on(KeyStrokes.DOWN);
driver.assertEmpty();
console.on(KeyStrokes.UP);
driver.assertDel().assertChar('b').assertChar('_').assertFlush().assertEmpty();
console.on(KeyStrokes.ONE);
driver.assertChar('1').assertFlush().assertEmpty();
final ArrayList<String> requests = new ArrayList<String>();
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
requests.add(request);
context.end(ShellResponse.ok());
}
});
console.on(KeyStrokes.ENTER);
driver.assertCRLF().assertFlush().assertCRLF().assertFlush().assertEmpty();
assertEquals(Arrays.asList("b_1"), requests);
console.on(KeyStrokes.UP);
driver.assertChar('b').assertChar('_').assertChar('1').assertFlush().assertEmpty();
console.on(KeyStrokes.UP);
driver.assertDel().assertDel().assertDel().assertChar('b').assertChar('_').assertFlush().assertEmpty();
console.on(KeyStrokes.UP);
driver.assertDel().assertDel().assertChar('a').assertFlush().assertEmpty();
}
public void testReadLine1() throws Exception {
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
final ShellProcessContext context = contexts.poll();
assertNotNull(context);
final ArrayBlockingQueue<String> lines = new ArrayBlockingQueue<String>(1);
Thread t = new Thread() {
@Override
public void run() {
try {
String s = context.readLine("m", true);
lines.add(s);
}
catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
while (t.getState() != Thread.State.WAITING) {
// Wait until the other thread is waiting
}
console.on(KeyStrokes.b);
console.on(KeyStrokes.ENTER);
driver.assertChar('m').assertFlush().assertChar('b').assertFlush().assertCRLF().assertFlush().assertEmpty();
String line = lines.poll(3, TimeUnit.SECONDS);
assertEquals("b", line);
}
/**
* Same than {@link #testReadLine1()} but we provide input before the thread read lines effectively
* which leads to a simpler test since we need only one thread
*/
public void testReadLine2() throws Exception {
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
final ShellProcessContext context = contexts.poll();
assertNotNull(context);
console.on(KeyStrokes.b);
console.on(KeyStrokes.ENTER);
driver.assertEmpty();
String line = context.readLine("m", true);
driver.assertChar('m').assertFlush().assertChar('b').assertFlush().assertCRLF().assertFlush().assertEmpty();
assertEquals("b", line);
}
/**
* Make sure that
* - we cannot call readline twice at the same time and
* - if the reading thread is interrupted then it throws InterruptedIOException
*/
public void testReadLine3() throws Exception {
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
final ShellProcessContext context = contexts.poll();
assertNotNull(context);
final ArrayBlockingQueue<Boolean> interrupteds = new ArrayBlockingQueue<Boolean>(1);
Thread t = new Thread() {
@Override
public void run() {
try {
context.readLine("", true);
}
catch (InterruptedException e) {
interrupteds.add(true);
}
catch (Exception e) {
interrupteds.add(false);
}
}
};
t.start();
while (t.getState() != Thread.State.WAITING) {
// Wait until the other thread is waiting
}
try {
context.readLine("", true);
fail();
}
catch (IllegalStateException expected) {
}
t.interrupt();
boolean interrupted = interrupteds.poll(3, TimeUnit.SECONDS);
assertTrue(interrupted);
}
/**
* Make sure that a reading thread is interrupted when the process ends
*/
public void testReadLine4() throws Exception {
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
final ShellProcessContext context = contexts.poll();
assertNotNull(context);
final ArrayBlockingQueue<Boolean> interrupteds = new ArrayBlockingQueue<Boolean>(1);
Thread t = new Thread() {
@Override
public void run() {
try {
context.readLine("", true);
}
catch (InterruptedException e) {
interrupteds.add(true);
}
catch (Exception e) {
interrupteds.add(false);
}
}
};
t.start();
while (t.getState() != Thread.State.WAITING) {
// Wait until the other thread is waiting
}
context.end(ShellResponse.ok());
boolean interrupted = interrupteds.poll(3, TimeUnit.SECONDS);
assertTrue(interrupted);
}
/**
* Make sure that a reading thread is interrupted when the process is cancelled
*/
public void testReadLine5() throws Exception {
final ArrayBlockingQueue<ShellProcessContext> contexts = new ArrayBlockingQueue<ShellProcessContext>(1);
shell.addProcess(new SyncProcess() {
@Override
public void run(String request, ShellProcessContext context) throws Exception {
contexts.add(context);
}
});
console.init();
console.on(KeyStrokes.a);
console.on(KeyStrokes.ENTER);
driver.assertChar('a').assertFlush().assertCRLF().assertFlush().assertEmpty();
driver.assertEmpty();
final ShellProcessContext context = contexts.poll();
assertNotNull(context);
final ArrayBlockingQueue<Boolean> interrupteds = new ArrayBlockingQueue<Boolean>(1);
Thread t = new Thread() {
@Override
public void run() {
try {
context.readLine("", true);
}
catch (InterruptedException e) {
interrupteds.add(true);
}
catch (Exception e) {
interrupteds.add(false);
}
}
};
t.start();
while (t.getState() != Thread.State.WAITING) {
// Wait until the other thread is waiting
}
console.on(KeyStrokes.INTERRUPT);
boolean interrupted = interrupteds.poll(3, TimeUnit.SECONDS);
assertTrue(interrupted);
}
}