/*
* 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.telnet.term;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import test.shell.base.BaseProcess;
import test.shell.base.BaseProcessFactory;
import test.shell.base.BaseShell;
import org.crsh.cli.impl.completion.CompletionMatch;
import org.crsh.cli.impl.Delimiter;
import org.crsh.cli.spi.Completion;
import org.crsh.telnet.term.processor.Processor;
import org.crsh.shell.Shell;
import org.crsh.shell.ShellProcess;
import org.crsh.shell.ShellProcessContext;
import org.crsh.shell.ShellResponse;
import org.crsh.telnet.term.spi.TestTermIO;
import org.crsh.telnet.term.console.ConsoleTerm;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class ProcessorTestCase extends TestCase {
public void testLine() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("abc\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("b").assertFlush();
controller.connector.assertChars("c").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("abc").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testDel() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("abc");
controller.connector.appendDel();
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("b").assertFlush();
controller.connector.assertChars("c").assertFlush();
controller.connector.assertDel().assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("ab").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testBreak() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("abc");
controller.connector.appendBreak();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("b").assertFlush();
controller.connector.assertChars("c").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.connector.append("def\r\n");
controller.connector.assertChars("d").assertFlush();
controller.connector.assertChars("e").assertFlush();
controller.connector.assertChars("f").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("def").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testInsert() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("ab");
controller.connector.appendMoveLeft();
controller.connector.append("c\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("b").assertFlush();
controller.connector.assertMoveLeft().assertFlush();
controller.connector.assertChars("cb").assertMoveLeft().assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("acb").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testIdempotentMoveRight() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("a");
controller.connector.appendMoveRight();
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testIdempotentMoveLeft() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.appendMoveLeft();
controller.connector.append("a");
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testMove() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("a");
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.connector.appendMoveUp();
controller.connector.assertChars("a").assertFlush();
controller.connector.append("\r\n");
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.connector.appendMoveUp();
controller.connector.assertChars("a").assertFlush();
controller.connector.appendMoveDown();
controller.connector.assertDel().assertFlush();
//
controller.assertStop();
}
public void testIdempotentMoveUp() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("a");
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.connector.appendMoveUp();
controller.connector.appendMoveUp();
controller.connector.assertChars("a").assertFlush();
controller.connector.append("\r\n");
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testIdempotentMoveDown() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO));
controller.assertStart();
//
controller.connector.append("a");
controller.connector.append("\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertFlush();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.connector.appendMoveDown();
controller.connector.append("\r\n");
controller.connector.assertCRLF().assertFlush();
controller.connector.assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testCompletion1() throws Exception {
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO) {
@Override
public CompletionMatch complete(String prefix) {
return new CompletionMatch(Delimiter.EMPTY, Completion.create(new StringBuilder(prefix).reverse().toString(), false));
}
});
controller.assertStart();
//
controller.connector.append("ab");
controller.connector.appendTab();
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("b").assertFlush();
controller.connector.assertChars("ba").assertFlush();
}
public void testMultiLine() throws Exception {
final LinkedList<String> requests = new LinkedList<String>();
final CountDownLatch latch = new CountDownLatch(1);
Controller controller = create(new BaseShell(BaseProcessFactory.ECHO) {
@Override
public ShellProcess createProcess(String request) {
return new BaseProcess(request) {
@Override
protected ShellResponse execute(String request) {
requests.add(request);
latch.countDown();
return super.execute(request);
}
};
}
});
controller.assertStart();
//
controller.connector.append("a\\\r\n");
controller.connector.assertChars("a").assertFlush();
controller.connector.assertChars("\\").assertFlush();
controller.connector.assertCRLF().assertFlush().assertChars("> ").assertFlush();
assertEquals(Collections.<String>emptyList(), requests);
controller.connector.append("b\r\n");
controller.connector.assertChars("b").assertFlush();
controller.connector.assertCRLF().assertFlush();
latch.await(5, TimeUnit.SECONDS);
assertEquals(Collections.singletonList("ab"), requests);
}
public void testCLS() throws Exception {
Controller controller = create(new BaseShell(new BaseProcessFactory() {
@Override
public BaseProcess create(String request) {
return new BaseProcess(request) {
@Override
public void process(String request, ShellProcessContext processContext) throws IOException {
if ("bye".equals(request)) {
processContext.end(ShellResponse.close());
} else {
processContext.cls();
processContext.end(ShellResponse.ok());
}
}
};
}
}));
//
controller.assertStart();
controller.connector.append("\r\n");
controller.connector.assertCRLF().assertFlush();
controller.connector.assertCLS().assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
public void testFlush() throws Exception {
Controller controller = create(new BaseShell(new BaseProcessFactory() {
@Override
public BaseProcess create(String request) {
return new BaseProcess(request) {
@Override
public void process(String request, ShellProcessContext processContext) throws IOException {
if ("bye".equals(request)) {
processContext.end(ShellResponse.close());
} else {
processContext.flush();
processContext.end(ShellResponse.ok());
}
}
};
}
}));
//
controller.assertStart();
controller.connector.append("\r\n");
controller.connector.assertCRLF().assertFlush();
controller.connector.assertFlush(); // The good one
controller.connector.assertFlush();
controller.connector.assertCRLF().assertChars("% ").assertFlush();
//
controller.assertStop();
}
private Controller create(Shell shell) throws IOException {
return new Controller(new TestTermIO(), shell);
}
private class Controller implements Runnable {
/** . */
private volatile boolean running;
/** . */
private final CountDownLatch startSync;
/** . */
private final CountDownLatch stopSync;
/** . */
private final Thread thread;
/** . */
private final TestTermIO connector;
/** . */
private final Processor processor;
private Controller(TestTermIO connector, Shell shell) {
this.running = true;
this.startSync = new CountDownLatch(1);
this.stopSync = new CountDownLatch(1);
this.thread = new Thread(this);
this.connector = connector;
this.processor = new Processor(new ConsoleTerm(connector), shell);
}
public void assertStart() {
thread.start();
//
try {
assertTrue(startSync.await(1, TimeUnit.SECONDS));
}
catch (InterruptedException e) {
AssertionFailedError afe = new AssertionFailedError();
afe.initCause(e);
throw afe;
}
//
assertTrue(running);
//
connector.assertCRLF();
connector.assertChars("% ");
connector.assertFlush();
}
public void run() {
running = true;
startSync.countDown();
try {
processor.run();
}
finally {
running = false;
stopSync.countDown();
}
}
public void assertStop() {
assertTrue(running);
//
connector.append("bye\r\n");
connector.assertChars("b").assertFlush();
connector.assertChars("y").assertFlush();
connector.assertChars("e").assertFlush();
connector.assertCRLF().assertFlush();
//
try {
assertTrue(stopSync.await(4, TimeUnit.SECONDS));
}
catch (InterruptedException e) {
AssertionFailedError afe = new AssertionFailedError();
afe.initCause(e);
throw afe;
}
//
connector.assertEmpty();
//
assertFalse(running);
}
}
}