/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tradefed.command;
import com.android.tradefed.command.Console.CaptureList;
import com.android.tradefed.util.RegexTrie;
import junit.framework.TestCase;
import org.easymock.EasyMock;
import java.util.Arrays;
import java.util.List;
/**
* Unit tests for {@link Console}.
*/
public class ConsoleTest extends TestCase {
private ICommandScheduler mMockScheduler;
private Console mConsole;
private ProxyExceptionHandler mProxyExceptionHandler;
private boolean mIsConsoleFunctional;
private static class ProxyExceptionHandler implements Thread.UncaughtExceptionHandler {
private Throwable mThrowable = null;
@Override
public void uncaughtException(Thread t, Throwable e) {
mThrowable = e;
}
public void verify() throws Throwable {
if (mThrowable != null) {
throw mThrowable;
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected void setUp() throws Exception {
super.setUp();
mMockScheduler = EasyMock.createStrictMock(ICommandScheduler.class);
mIsConsoleFunctional = false;
/**
* Note: Eclipse doesn't play nice with consoles allocated like {@code new ConsoleReader()}.
* To make an actual ConsoleReader instance, you should likely use the four-arg
* {@link jline.ConsoleReader} constructor and use {@link jline.UnsupportedTerminal} or
* similar as the implementation.
*/
mConsole = new Console(null) {
@Override
boolean isConsoleFunctional() {
return mIsConsoleFunctional;
}
};
mConsole.setCommandScheduler(mMockScheduler);
mProxyExceptionHandler = new ProxyExceptionHandler();
mConsole.setUncaughtExceptionHandler(mProxyExceptionHandler);
}
/**
* Test normal Console run when system console is available
*/
public void testRun_withConsole() throws Throwable {
mIsConsoleFunctional = true;
mMockScheduler.start();
mMockScheduler.await();
EasyMock.expectLastCall().anyTimes();
mMockScheduler.shutdown(); // after we discover that we can't read console input
EasyMock.replay(mMockScheduler);
// non interactive mode needs some args to start
mConsole.setArgs(Arrays.asList("help"));
mConsole.start();
mConsole.join();
mProxyExceptionHandler.verify();
EasyMock.verify(mMockScheduler);
}
/**
* Test normal Console run when system console is _not_ available
*/
public void testRun_noConsole() throws Throwable {
mIsConsoleFunctional = false;
mMockScheduler.start();
mMockScheduler.await();
EasyMock.expectLastCall().anyTimes();
mMockScheduler.shutdown(); // after we run the initial command and then immediately quit.
EasyMock.replay(mMockScheduler);
// non interactive mode needs some args to start
mConsole.setArgs(Arrays.asList("help"));
mConsole.start();
mConsole.join();
mProxyExceptionHandler.verify();
EasyMock.verify(mMockScheduler);
}
/**
* Make sure that "run command foo config.xml" works properly.
*/
public void testRunCommand() throws Exception {
String[] command = new String[] {"run", "command", "--arg", "value", "config.xml"};
String[] expected = new String[] {"--arg", "value", "config.xml"};
CaptureList captures = new CaptureList();
RegexTrie<Runnable> trie = mConsole.getCommandTrie();
EasyMock.expect(mMockScheduler.addCommand(EasyMock.aryEq(expected))).andReturn(
Boolean.TRUE);
EasyMock.replay(mMockScheduler);
Runnable runnable = trie.retrieve(captures, command);
assertNotNull(String.format("Console didn't match input %s", Arrays.toString(command)),
runnable);
mConsole.executeCmdRunnable(runnable, captures);
EasyMock.verify(mMockScheduler);
}
/**
* Make sure that the "run foo config.xml" shortcut works properly.
*/
public void testRunCommand_shortcut() throws Exception {
String[] command = new String[] {"run", "--arg", "value", "config.xml"};
String[] expected = new String[] {"--arg", "value", "config.xml"};
CaptureList captures = new CaptureList();
RegexTrie<Runnable> trie = mConsole.getCommandTrie();
EasyMock.expect(mMockScheduler.addCommand(EasyMock.aryEq(expected))).andReturn(
Boolean.TRUE);
EasyMock.replay(mMockScheduler);
Runnable runnable = trie.retrieve(captures, command);
assertNotNull(String.format("Console didn't match input %s", Arrays.toString(command)),
runnable);
mConsole.executeCmdRunnable(runnable, captures);
EasyMock.verify(mMockScheduler);
}
/**
* Make sure that the command "run command command foo config.xml" properly considers the second
* "command" to be the first token of the command to be executed.
*/
public void testRunCommand_startsWithCommand() throws Exception {
String[] command = new String[] {"run", "command", "command", "--arg", "value",
"config.xml"};
String[] expected = new String[] {"command", "--arg", "value", "config.xml"};
CaptureList captures = new CaptureList();
RegexTrie<Runnable> trie = mConsole.getCommandTrie();
EasyMock.expect(mMockScheduler.addCommand(EasyMock.aryEq(expected))).andReturn(
Boolean.TRUE);
EasyMock.replay(mMockScheduler);
Runnable runnable = trie.retrieve(captures, command);
assertNotNull(String.format("Console didn't match input %s", Arrays.toString(command)),
runnable);
mConsole.executeCmdRunnable(runnable, captures);
EasyMock.verify(mMockScheduler);
}
/**
* Make sure that {@link Console#getFlatArgs} works as expected.
*/
public void testFlatten() throws Exception {
CaptureList cl = new CaptureList();
cl.add(Arrays.asList("run", null));
cl.add(Arrays.asList("alpha"));
cl.add(Arrays.asList("beta"));
List<String> flat = Console.getFlatArgs(1, cl);
assertEquals(2, flat.size());
assertEquals("alpha", flat.get(0));
assertEquals("beta", flat.get(1));
}
/**
* Make sure that {@link Console#getFlatArgs} throws an exception when argIdx is wrong.
*/
public void testFlatten_wrongArgIdx() throws Exception {
CaptureList cl = new CaptureList();
cl.add(Arrays.asList("run", null));
cl.add(Arrays.asList("alpha"));
cl.add(Arrays.asList("beta"));
// argIdx is 0, and element 0 has size 2
try {
Console.getFlatArgs(0, cl);
fail("IllegalArgumentException not thrown!");
} catch (IllegalArgumentException e) {
// expected
}
}
/**
* Make sure that {@link Console#getFlatArgs} throws an exception when argIdx is OOB.
*/
public void testFlatten_argIdxOOB() throws Exception {
CaptureList cl = new CaptureList();
cl.add(Arrays.asList("run", null));
cl.add(Arrays.asList("alpha"));
cl.add(Arrays.asList("beta"));
try {
Console.getFlatArgs(1 + cl.size(), cl);
fail("IndexOutOfBoundsException not thrown!");
} catch (IndexOutOfBoundsException e) {
// expected
}
}
}