Merge "Create an exception to be thrown when the device fails to boot."
diff --git a/src/com/android/tradefed/command/Console.java b/src/com/android/tradefed/command/Console.java
index b1faaae..c4e63d8 100644
--- a/src/com/android/tradefed/command/Console.java
+++ b/src/com/android/tradefed/command/Console.java
@@ -686,6 +686,15 @@
     }
 
     /**
+     * Return whether we should expect the console to be usable.
+     * <p />
+     * Exposed for unit testing.
+     */
+    boolean isConsoleFunctional() {
+        return System.console() != null;
+    }
+
+    /**
      * The main method to launch the console. Will keep running until shutdown command is issued.
      *
      * @param args
@@ -697,12 +706,12 @@
         try {
             // Check System.console() since jline doesn't seem to consistently know whether or not
             // the console is functional.
-            if (System.console() == null) {
+            if (!isConsoleFunctional()) {
                 if (arrrgs.isEmpty()) {
                     printLine("No commands for non-interactive mode; exiting.");
                     return;
                 } else {
-                    printLine("Running indefinitely in non-interactive mode.");
+                    printLine("Non-interactive mode: Running initial command then exiting.");
                     mShouldExit = true;
                 }
             }
@@ -727,7 +736,7 @@
                         // Usually the result of getting EOF on the console
                         printLine("");
                         printLine("Received EOF; quitting...");
-                        mScheduler.shutdown();
+                        mShouldExit = true;
                         break;
                     }
 
@@ -770,8 +779,8 @@
         } catch (Exception e) {
             printLine("Console received an unexpected exception (shown below); shutting down TF.");
             e.printStackTrace();
-            mScheduler.shutdown();
         } finally {
+            mScheduler.shutdown();
             // Make sure that we don't quit with messages still in the buffers
             System.err.flush();
             System.out.flush();
diff --git a/tests/src/com/android/tradefed/command/ConsoleTest.java b/tests/src/com/android/tradefed/command/ConsoleTest.java
index ccee769..fea48ae 100644
--- a/tests/src/com/android/tradefed/command/ConsoleTest.java
+++ b/tests/src/com/android/tradefed/command/ConsoleTest.java
@@ -33,6 +33,7 @@
     private ICommandScheduler mMockScheduler;
     private Console mConsole;
     private ProxyExceptionHandler mProxyExceptionHandler;
+    private boolean mIsConsoleFunctional;
 
     private static class ProxyExceptionHandler implements Thread.UncaughtExceptionHandler {
         private Throwable mThrowable = null;
@@ -56,21 +57,29 @@
     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(mMockScheduler, null);
+        mConsole = new Console(mMockScheduler, null) {
+            @Override
+            boolean isConsoleFunctional() {
+                return mIsConsoleFunctional;
+            }
+        };
         mProxyExceptionHandler = new ProxyExceptionHandler();
         mConsole.setUncaughtExceptionHandler(mProxyExceptionHandler);
      }
 
     /**
-     * Test normal console run.
+     * Test normal Console run when system console is available
      */
-    public void testRun() throws Throwable {
+    public void testRun_withConsole() throws Throwable {
+        mIsConsoleFunctional = true;
+
         mMockScheduler.start();
         mMockScheduler.await();
         EasyMock.expectLastCall().anyTimes();
@@ -87,6 +96,27 @@
     }
 
     /**
+     * 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(new String[] {"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 {