• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cts;
18 
19 import com.android.cts.TestHost.ActionType;
20 import com.android.cts.TestHost.MODE;
21 
22 import org.xml.sax.SAXException;
23 
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.security.NoSuchAlgorithmException;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.HashMap;
33 import java.util.List;
34 
35 import javax.xml.parsers.ParserConfigurationException;
36 import javax.xml.transform.TransformerException;
37 import javax.xml.transform.TransformerFactoryConfigurationError;
38 
39 /**
40  * Main console of CTS providing user with the interface to interact. <BR>
41  * Using CommandParser to parse command line argument and process.
42  * <ul>
43  *    <li> start a test plan
44  *    <li> remove a test plan
45  *    <li> add a test package
46  *    <li> remove a test package
47  *    <li> list current available devices
48  *    <li> list current available test plan
49  *    <li> list current available package
50  *    <li> list current test result
51  *    <li> view CTS' status, uninitialized, idle or running
52  *    <li> view command history
53  *    <li> select a history command to run
54  * </ul>
55  */
56 public class ConsoleUi {
57 
58     private static final String OS_NAME_LINUX = "Linux";
59     private static final String LS_PLAN_SEPARATOR = "=================================";
60     private static final String CMD_TYPE_LEADING_SPACE = "  ";
61     private static final String CMD_OPT_LEADING_SPACE = "    ";
62     private static final String CREATE_SESSION = "create a new session";
63     private static final String CHOOSE_SESSION = "choose a session";
64 
65     private TestHost mHost;
66     private boolean mKeepRunning;
67     private BufferedReader mCommandInput;
68     // private static ConsoleInputStream sConsoleReader;
69     private CommandHistory mCommandHistory = new CommandHistory();
70     private String mOsName = "none";
71 
72     // Define test case name pattern
73     static final String CASE_NAME_PATTERN_STR = "((\\S+\\.)+\\S+)\\.(\\S+):(\\S+)";
74     private static HashMap<String, Integer> mResultCodeMap;
75 
76     static {
77         mResultCodeMap = new HashMap<String, Integer>();
mResultCodeMap.put(CtsTestResult.STR_PASS, CtsTestResult.CODE_PASS)78         mResultCodeMap.put(CtsTestResult.STR_PASS, CtsTestResult.CODE_PASS);
mResultCodeMap.put(CtsTestResult.STR_FAIL, CtsTestResult.CODE_FAIL)79         mResultCodeMap.put(CtsTestResult.STR_FAIL, CtsTestResult.CODE_FAIL);
mResultCodeMap.put(CtsTestResult.STR_ERROR, CtsTestResult.CODE_ERROR)80         mResultCodeMap.put(CtsTestResult.STR_ERROR, CtsTestResult.CODE_ERROR);
mResultCodeMap.put(CtsTestResult.STR_NOT_EXECUTED, CtsTestResult.CODE_NOT_EXECUTED)81         mResultCodeMap.put(CtsTestResult.STR_NOT_EXECUTED, CtsTestResult.CODE_NOT_EXECUTED);
mResultCodeMap.put(CtsTestResult.STR_TIMEOUT, CtsTestResult.CODE_TIMEOUT)82         mResultCodeMap.put(CtsTestResult.STR_TIMEOUT, CtsTestResult.CODE_TIMEOUT);
83     }
84 
ConsoleUi(TestHost host)85     public ConsoleUi(TestHost host) {
86         mHost = host;
87         mCommandInput = new BufferedReader(new InputStreamReader(System.in));
88         mKeepRunning = true;
89 
90         initInputStream();
91     }
92 
93     /**
94      * Start the console user interface.
95      *
96      */
startUi()97     public void startUi() {
98         while (mKeepRunning) {
99             try {
100                 String cmdLine = readLine(CUIOutputStream.CTS_PROMPT_SIGN);
101                 CommandParser cp = CommandParser.parse(cmdLine);
102                 processCommand(cp);
103                 mCommandHistory.addCommand(cp, cmdLine);
104             } catch (CommandNotFoundException e) {
105                 // avoid displaying help message for empty
106                 // command by pressing ENTER over console directly
107             } catch (Exception e) {
108                 Log.e("Got exception while processing command.", e);
109                 showHelp();
110             }
111         }
112     }
113 
114     /**
115      * Initialize the CommandProcessor.
116      */
initInputStream()117     private void initInputStream() {
118         // mOsName = System.getProperty("os.name");
119         if (mOsName.equals(OS_NAME_LINUX)) {
120             // sConsoleReader = new ConsoleInputStream(new FileInputStream(
121             // FileDescriptor.in), mCommandHistory);
122             // sConsoleReader.setup();
123         } else {
124             mCommandInput = new BufferedReader(new InputStreamReader(System.in));
125         }
126     }
127 
128     /**
129      * Read a message line from console.
130      *
131      * @param prompt The notification message print out to console before reading.
132      * @return The string user typed in.
133      */
readLine(String prompt)134     private String readLine(String prompt) throws IOException {
135         String cmdLine = null;
136         if (mOsName.equals(OS_NAME_LINUX)) {
137             // cmdLine = sConsoleReader.readLine(prompt).trim();
138         } else {
139             CUIOutputStream.print(prompt);
140             cmdLine = mCommandInput.readLine().trim();
141         }
142         return cmdLine;
143     }
144 
145     /**
146      * Display the help message.
147      */
showHelp()148     private void showHelp() {
149         CUIOutputStream.println("Usage: command options");
150         CUIOutputStream.println("Avaiable commands and options:");
151         showHostCmdHelp();
152         showPlanCmdHelp();
153         showPackageCmdHelp();
154         showResultCmdHelp();
155         showHistoryCmdHelp();
156         showDeviceCmdHelp();
157     }
158 
159     /**
160      * Display the help message related to history commands.
161      */
showHistoryCmdHelp()162     private void showHistoryCmdHelp() {
163         final String cmdStr = CTSCommand.HISTORY + "/" + CTSCommand.H;
164 
165         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "History:");
166         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
167                 + cmdStr + ": list all commands in command history");
168         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
169                 + cmdStr + " count: list the latest count records in command history");
170         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
171                 + cmdStr + " " + CTSCommand.OPTION_E
172                 + " num: run the command designated by 'num' in command history");
173     }
174 
175     /**
176      * Display the help message related to result commands.
177      */
showResultCmdHelp()178     private void showResultCmdHelp() {
179         final String cmdStr = CTSCommand.LIST + " " + CTSCommand.OPTION_R
180                 + "/" + CTSCommand.OPTION_RESULT;
181         final String sessionStr = CTSCommand.OPTION_S + "/" + CTSCommand.OPTION_SESSION;
182         final String resultsStr = " [" + CtsTestResult.STR_PASS
183                        + "/" + CtsTestResult.STR_FAIL
184                        + "/" + CtsTestResult.STR_NOT_EXECUTED
185                        + "/" + CtsTestResult.STR_TIMEOUT
186                        + "] ";
187 
188         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "Result:");
189         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
190                 + cmdStr + ": list all result of sessions");
191         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
192                 + cmdStr + " " + sessionStr
193                 + " session_id: list detail case result of a specified session");
194         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
195                 + cmdStr + resultsStr + sessionStr
196                 + " session_id: list detail cases of a specified"
197                 + " session by the specified result.");
198     }
199 
200     /**
201      * Display the help message related to package commands.
202      */
showPackageCmdHelp()203     private void showPackageCmdHelp() {
204         final String cmdStr = CTSCommand.LIST + " " + CTSCommand.OPTION_P
205                 + "/" + CTSCommand.OPTION_PACKAGE;
206         final String pkgStr = CTSCommand.OPTION_P + "/" + CTSCommand.OPTION_PACKAGE;
207 
208         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "Package:");
209         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
210                 + cmdStr + ": list available packages");
211         CUIOutputStream.println(CMD_OPT_LEADING_SPACE + cmdStr + " package_name: "
212                 + "list contents of the package with specified name");
213 
214         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
215                 + CTSCommand.ADD + " " + pkgStr
216                 + " root: add packages from root to repository");
217         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
218                 + CTSCommand.REMOVE + " " + pkgStr + " package_name/all: "
219                 + "remove a package or all packages from repository");
220     }
221 
222     /**
223      * Display the help message related to plan commands.
224      */
showPlanCmdHelp()225     private void showPlanCmdHelp() {
226         final String lsPlanStr = CTSCommand.LIST + " " + CTSCommand.OPTION_PLAN;
227         final String addPlanStr = CTSCommand.ADD + " " + CTSCommand.OPTION_PLAN;
228         final String rmPlanStr = CTSCommand.REMOVE + " " + CTSCommand.OPTION_PLAN;
229         final String addDerivedPlanStr = CTSCommand.ADD + " " + CTSCommand.OPTION_DERIVED_PLAN;
230 
231         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "Plan:");
232         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
233                 + lsPlanStr + ": list available plans");
234         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
235                 + lsPlanStr + " plan_name: list contents of the plan with specified name");
236         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
237                 + addPlanStr + " plan_name: add a new plan with specified name");
238         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
239                 + addDerivedPlanStr + " plan_name "
240                 + CTSCommand.OPTION_S + "/" + CTSCommand.OPTION_SESSION + " session_id "
241                 + CTSCommand.OPTION_R + "/" + CTSCommand.OPTION_RESULT + " result_type"
242                 + ": derive a plan from the given session");
243         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
244                 + rmPlanStr + " plan_name/all: remove a plan or all plans from repository");
245         showStartSessionHelp();
246     }
247 
248     /**
249      * Display the help message related to start session command.
250      */
showStartSessionHelp()251     private void showStartSessionHelp() {
252         final String cmdStr = CTSCommand.START + " " + CTSCommand.OPTION_PLAN;
253         final String testStr = CTSCommand.OPTION_T + "/" + CTSCommand.OPTION_TEST;
254         final String deviceStr = CTSCommand.OPTION_D + "/" + CTSCommand.OPTION_DEVICE;
255         final String pkgStr = CTSCommand.OPTION_P + "/" + CTSCommand.OPTION_PACKAGE;
256 
257         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
258                 + cmdStr + " test_plan_name: run a test plan");
259         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
260                 + cmdStr + " test_plan_name " + deviceStr + " device_ID"
261                 +  ": run a test plan using the specified device");
262         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
263                 + cmdStr + " test_plan_name " + testStr + " test_name"
264                 + ": run a specific test");
265         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
266                 + cmdStr + " test_plan_name " + pkgStr + " java_package_name"
267                 + ": run a specific java package");
268         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
269                 + cmdStr + " test_plan_name " + testStr + " test_name "
270                 + deviceStr + " device_ID"
271                 + ": run a specific test using the specified device");
272         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
273                 + cmdStr + " test_plan_name " + pkgStr + " java_package_name "
274                 + deviceStr + " device_ID"
275                 + ": run a specific java package using the specified device");
276     }
277 
278     /**
279      * Display the help message related to host commands.
280      */
showHostCmdHelp()281     private void showHostCmdHelp() {
282         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "Host:");
283         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
284                 + CTSCommand.HELP + ": show this message");
285         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
286                 + CTSCommand.EXIT + ": exit cts command line");
287     }
288 
289     /**
290      * Display the help message related to device commands.
291      */
showDeviceCmdHelp()292     private void showDeviceCmdHelp() {
293         final String deviceStr = CTSCommand.OPTION_D + "/" + CTSCommand.OPTION_DEVICE;
294 
295         CUIOutputStream.println(CMD_TYPE_LEADING_SPACE + "Device:");
296         CUIOutputStream.println(CMD_OPT_LEADING_SPACE
297                 + CTSCommand.LIST + " " + deviceStr + ": list available devices");
298     }
299 
300     /**
301      * Process the command from user's input.
302      *
303      * @param cp Command container.
304      */
processCommand(final CommandParser cp)305     public void processCommand(final CommandParser cp) throws Exception {
306         String action = cp.getAction();
307 
308         if (action.equals(CTSCommand.EXIT)) {
309             if (cp.getArgSize() != 1) {
310                 showHelp();
311                 return;
312             }
313             Log.d("exit cts host");
314             mKeepRunning = false;
315             mHost.tearDown();
316         } else if (action.equals(CTSCommand.HELP)) {
317             showHelp();
318         } else if (mCommandHistory.isHistoryCommand(action)) {
319             processHistoryCommands(cp);
320         } else if (action.equals(CTSCommand.ADD)) {
321             processAddCommand(cp);
322         } else if (action.equals(CTSCommand.START)) {
323             processStartCommand(cp);
324         } else if (action.equals(CTSCommand.REMOVE)) {
325             processRmCommand(cp);
326         } else if (action.equals(CTSCommand.LIST)) {
327             processListCommand(cp);
328         } else {
329             showHelp();
330         }
331     }
332 
333     /**
334      * Process start command.
335      *
336      * @param cp Command container.
337      */
processStartCommand(CommandParser cp)338     private void processStartCommand(CommandParser cp) throws SAXException,
339             ParserConfigurationException {
340         if (cp.containsKey(CTSCommand.OPTION_PLAN)) {
341             processStartSessionCommand(cp);
342         } else if (cp.containsKey(CTSCommand.OPTION_P)
343                 || cp.containsKey(CTSCommand.OPTION_PACKAGE)) {
344             processStartPackageCommand(cp);
345         } else {
346             showHelp();
347         }
348     }
349 
350     /**
351      * Process start package command.
352      *
353      * <ul>
354      *     <li> Syntax:
355      *            start --package zipped-package-file
356      * </ul>
357      * @param cp Command container.
358      */
processStartPackageCommand(CommandParser cp)359     private void processStartPackageCommand(CommandParser cp) {
360         try {
361             String pathName = cp.getValue(CTSCommand.OPTION_PACKAGE);
362             mHost.startZippedPackage(pathName);
363         } catch (DeviceDisconnectedException e) {
364           Log.e("Device " + e.getMessage() + " disconnected", e);
365         } catch (Exception e) {
366             Log.e("Met exception during running zipped package.", e);
367         }
368     }
369 
370     /**
371      * Validate the command parameters used to activate CTS.
372      *
373      * @param cp Command container.
374      * @return If command parameters are valid, return true; else, return false.
375      */
validateCommandParams(CommandParser cp)376     public boolean validateCommandParams(CommandParser cp) {
377         if (cp == null) {
378             return false;
379         }
380 
381         if (cp.getAction() == null) {
382             return true;
383         } else if (isValidCommandOption(cp, CTSCommand.START,
384                 CTSCommand.OPTION_PLAN)) {
385             return true;
386         } else if (isValidCommandOption(cp, CTSCommand.START,
387                 CTSCommand.OPTION_PACKAGE)) {
388             return true;
389         } else if (isValidCommandOption(cp, CTSCommand.START,
390                 CTSCommand.OPTION_P)) {
391             return true;
392         } else {
393             return false;
394         }
395     }
396 
397     /**
398      * Check if the command option is valid.
399      *
400      * @param cp CommandParser which contains the command and options.
401      * @param command Command the user typed in.
402      * @param option Option the user typed in.
403      * @return If command option valid, return true; else, return false.
404      */
isValidCommandOption(CommandParser cp, String command, String option)405     private static boolean isValidCommandOption(CommandParser cp,
406             String command, String option) {
407         return (cp.getAction().equals(command)) && (cp.containsKey(option))
408                 && (cp.getValue(option) != null)
409                 && (cp.getValue(option).length() != 0);
410     }
411 
412     /**
413      * Process start session command.
414      * <ul>
415      *     <li> Syntax 1:
416      *            start --plan plan-name
417      *              [ --device device-id ]
418      *              [ --test test-name ]
419      *              [ --profile profile-name ]
420      *     <li> Syntax 2:
421      *            start --plan plan-name
422      *              [ --device device-id ]
423      *              [ --package java-package-name ]
424      *              [ --profile profile-name ]
425      * </ul>
426      * @param cp container which contained start command options and values
427      *           Process the list commands.
428      */
processStartSessionCommand(CommandParser cp)429     private void processStartSessionCommand(CommandParser cp)
430             throws SAXException, ParserConfigurationException {
431 
432         if (mHost.getDeviceList().length == 0) {
433             Log.e("No device connected", null);
434             return;
435         }
436 
437         String testPlanPath = null;
438         String deviceId = null;
439         String testName = null;
440         String javaPkgName = null;
441         String testPlanName = mHost.getPlanName(cp.getValue(CTSCommand.OPTION_PLAN));
442         try {
443             if (cp.getActionValues().size() != 0 || cp.getOptionSize() < 1
444                     || cp.getOptionSize() > 3) {
445                 showStartSessionHelp();
446                 return;
447             }
448             testPlanName = mHost.getPlanName(cp
449                     .getValue(CTSCommand.OPTION_PLAN));
450             testPlanPath = HostConfig.getInstance().getPlanRepository()
451                     .getPlanPath(testPlanName);
452             if (testPlanPath == null) {
453                 CUIOutputStream.println("Plan " + testPlanName
454                         + " is not in repository, please create it!");
455                 return;
456             }
457 
458             ActionType actionType = ActionType.START_NEW_SESSION;
459             if (cp.containsKey(CTSCommand.OPTION_TEST)) {
460                 testName = cp.getValue(CTSCommand.OPTION_TEST);
461                 if (-1 == testName.indexOf(Test.METHOD_SEPARATOR)) {
462                     Log.e("Test full name must be in the form of:"
463                             + " java_package_name.class_name#method_name.", null);
464                     return;
465                 }
466                 actionType = ActionType.RUN_SINGLE_TEST;
467             } else if (cp.containsKey(CTSCommand.OPTION_PACKAGE)) {
468                 javaPkgName = cp.getValue(CTSCommand.OPTION_PACKAGE);
469                 actionType = ActionType.RUN_SINGLE_JAVA_PACKAGE;
470             }
471 
472             TestSession ts = null;
473             ArrayList<TestSession> sessionList = mHost.getSessionList(testPlanName);
474             if ((sessionList != null) && (sessionList.size() > 0)) {
475                 if ((testName == null) || (testName.length() == 0)) {
476                     String mode = chooseMode(sessionList);
477                     if (CREATE_SESSION.equals(mode)) {
478                         ts = TestHost.createSession(testPlanName);
479                     }
480                 }
481                 if (ts == null) {
482                     ts = chooseTestSession(sessionList);
483                     deviceId = ts.getDeviceId();
484                     if ((actionType != ActionType.RUN_SINGLE_TEST)
485                             && (actionType != ActionType.RUN_SINGLE_JAVA_PACKAGE)) {
486                         actionType = ActionType.RESUME_SESSION;
487                     }
488                 }
489             }
490 
491             if (cp.containsKey(CTSCommand.OPTION_DEVICE)) {
492                 deviceId = cp.getValue(CTSCommand.OPTION_DEVICE);
493                 String[] deviceIdList = deviceId.trim().split(",");
494                 if (deviceIdList.length > 1) {
495                     Log.e("Just allow choosing one device ID.", null);
496                     return;
497                 }
498             }
499 
500             if (deviceId == null) {
501                 TestDevice td = mHost.getFirstAvailableDevice();
502                 if (td == null) {
503                     // no devices attached
504                     CUIOutputStream.println("No idle devices found.");
505                     return;
506                 }
507                 deviceId = td.getSerialNumber();
508             }
509 
510             if (!checkDeviceExists(mHost.getDeviceList(), deviceId)) {
511                 CUIOutputStream.println("Can't find specified device id.  Is it attached?");
512                 return;
513             }
514 
515             if (ts == null) {
516                 ts = TestHost.createSession(testPlanName);
517             }
518 
519             mHost.startSession(ts, deviceId, testName, javaPkgName, actionType);
520         } catch (IOException e) {
521             Log.e("Can't create test session", e);
522         } catch (DeviceNotAvailableException e) {
523             CUIOutputStream.println("Test plan(" + testPlanName + ") "
524                     + e.getMessage());
525             showStartSessionHelp();
526         } catch (TestNotFoundException e) {
527             CUIOutputStream.println(e.getMessage());
528         } catch (TestPlanNotFoundException e) {
529             CUIOutputStream.println("Can't find test plan " + testPlanName);
530         } catch (IllegalTestNameException e) {
531             CUIOutputStream.println("Illegal case name: " + testName);
532         } catch (DeviceDisconnectedException e) {
533             Log.e("Device " + e.getMessage() + " disconnected ", null);
534         } catch (NoSuchAlgorithmException e) {
535             Log.e("Fail to initialise SHA-1 algorithm", e);
536         } catch (InvalidApkPathException e) {
537             Log.e(e.getMessage(), null);
538         } catch (InvalidNameSpaceException e) {
539             Log.e(e.getMessage(), null);
540         }
541     }
542 
543     /**
544      * Choose test session among the available test session list.
545      *
546      * @param sessionList The available test session list.
547      * @return The test session chosen.
548      */
chooseTestSession(ArrayList<TestSession> sessionList)549     private TestSession chooseTestSession(ArrayList<TestSession> sessionList) throws IOException {
550         if ((sessionList == null) || (sessionList.size() == 0)) {
551             return null;
552         }
553 
554         if (sessionList.size() == 1) {
555             return sessionList.get(0);
556         }
557 
558         int index = 0;
559         String notification = "Please choose a session from the existed session(s):\n";
560         for (TestSession session : sessionList) {
561             notification += "  " + session.getId() + "  [" + index + "] \n";
562             index ++;
563         }
564 
565         return sessionList.get(getUserInputId(notification, 0, index));
566     }
567 
568     /**
569      * Choose  between creating a new session and choosing a session among available ones.
570      *
571      * @param sessionList The available test session list.
572      * @return If choose to create a new session, return CREATE_SESSION;
573      *         else return CHOOSE_SESSION.
574      */
chooseMode(ArrayList<TestSession> sessionList)575     private String chooseMode(ArrayList<TestSession> sessionList) throws IOException {
576         if (TestHost.sMode == MODE.RUN || (sessionList == null) || (sessionList.size() == 0)) {
577             // do not prompt if the test run was started from command line mode, or when
578             // there are no existing sessions
579             return CREATE_SESSION;
580         }
581 
582         String planName = sessionList.get(0).getSessionLog().getTestPlanName();
583         String notification = "There are " + sessionList.size()
584             + " existing session(s) for plan " + planName + ".\n"
585             + "Create a new session or choose an existing one?\n"
586             + "  Create a new session [0]\n"
587             + "  Choose a session     [1]\n";
588 
589         int indexSelected = getUserInputId(notification, 0, 2);
590         if (indexSelected == 0) {
591             return CREATE_SESSION;
592         } else {
593             return CHOOSE_SESSION;
594         }
595     }
596 
597     /**
598      * Validate the specified device ID against the available device array.
599      *
600      * @param availableDevices The available device array.
601      * @param specifiedId The specified device ID list.
602      * @return true if the id is valid
603      */
checkDeviceExists(TestDevice[] availableDevices, String specifiedId)604     public boolean checkDeviceExists(TestDevice[] availableDevices, String specifiedId) {
605         for (TestDevice dev : availableDevices) {
606             if (specifiedId.equals(dev.getSerialNumber())) {
607                 return true;
608             }
609         }
610         return false;
611     }
612 
613     /**
614      * Get device ID from the device ID string against the available devices.
615      *
616      * @param availableDevices The available devices.
617      * @param idStr The device ID string.
618      * @return The device ID.
619      */
getDeviceId(TestDevice[] availableDevices, String idStr)620     public int getDeviceId(TestDevice[] availableDevices, String idStr) {
621         for (int i = 0; i < availableDevices.length; i++) {
622             TestDevice dev = availableDevices[i];
623             if (idStr.equals(dev.getSerialNumber())) {
624                 return i;
625             }
626         }
627         return -1;
628     }
629 
630     /**
631      * Get the ID input by the against the specified range.
632      *
633      * @param notification The notification message to notify the user.
634      * @param startIndex The start index.
635      * @param endIndex The end index.
636      * @return The selected index of the ID the user chosen.
637      */
getUserInputId(String notification, int startIndex, int endIndex)638     private int getUserInputId(String notification, int startIndex, int endIndex)
639                 throws IOException {
640         int indexSelected = 0;
641         boolean success = false;
642         while (!success) {
643             String answer = readLine(notification);
644             try {
645                 indexSelected = Integer.parseInt(answer);
646                 if ((indexSelected >= 0) && (indexSelected < endIndex)) {
647                     success = true;
648                 } else {
649                     CUIOutputStream.println("" + indexSelected
650                             + " is out of range [0," + (endIndex -1 ) + "].");
651                 }
652             } catch (NumberFormatException e) {
653                 CUIOutputStream.println("Invalid nuber is typed in.");
654             }
655         }
656         return indexSelected;
657     }
658 
659     /**
660      * Check if the specified device ID is valid.
661      *
662      * @param numOfAvailableDevices The number of available devices.
663      * @param specifiedId The specified device ID.
664      * @return If the specified ID contained in available ID list,
665      *         return true; else, return false.
666      */
isValidDeviceId(int numOfAvailableDevices, int specifiedId)667     public boolean isValidDeviceId(int numOfAvailableDevices, int specifiedId) {
668         if (specifiedId < 0 || specifiedId >= numOfAvailableDevices) {
669             return false;
670         }
671         return true;
672     }
673 
674     /**
675      * Process list commands.
676      * <ul>
677      *     <li> Syntax 1:
678      *            ls --device
679      *     <li> Syntax 2:
680      *            ls --plan [ plan-name ]
681      *     <li> Syntax 3:
682      *            ls --package [ package-name ]
683      *     <li> Syntax 4:
684      *            ls --result
685      *              [ pass/fail/notExecuted/timeout ]
686      *              [ --session session_id ]
687      * </ul>
688      *
689      * @param cp Command container.
690      */
processListCommand(CommandParser cp)691     private void processListCommand(CommandParser cp) throws SAXException,
692             IOException, ParserConfigurationException {
693         if (cp.containsKey(CTSCommand.OPTION_DEVICE)) {
694             if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
695                 showDeviceCmdHelp();
696                 return;
697             }
698             if (cp.getValue(CTSCommand.OPTION_DEVICE).equals("")) {
699                 listDevices();
700             } else {
701                 showDeviceCmdHelp();
702             }
703         } else if (cp.containsKey(CTSCommand.OPTION_PLAN)) {
704             if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
705                 showPlanCmdHelp();
706                 return;
707             }
708             String planValue = cp.getValue(CTSCommand.OPTION_PLAN);
709             if (planValue.equals("")) {
710                 listPlans();
711             } else {
712                 listSinglePlan(mHost.getPlanName(planValue));
713             }
714         } else if (cp.containsKey(CTSCommand.OPTION_RESULT)) {
715             if (cp.getActionValues().size() != 0
716                     || (cp.getOptionSize() < 1 || cp.getOptionSize() > 2)) {
717                 showResultCmdHelp();
718                 return;
719             }
720             String resultValue = cp.getValue(CTSCommand.OPTION_RESULT);
721             String sessionId = cp.getValue(CTSCommand.OPTION_SESSION);
722             Integer resultCode = null;
723 
724             if (sessionId != null) {
725                 if (resultValue.length() != 0
726                         && !mResultCodeMap.containsKey(resultValue)) {
727                     showResultCmdHelp();
728                 } else {
729                     resultCode = mResultCodeMap.get(resultValue);
730                     listSessionResult(sessionId, resultCode);
731                 }
732             } else if (resultValue.length() == 0) {
733                 listResults();
734             } else {
735                 showHelp();
736             }
737         } else if (cp.containsKey(CTSCommand.OPTION_PACKAGE)) {
738             if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
739                 showPackageCmdHelp();
740                 return;
741             }
742             listPackages(cp);
743         } else {
744             showHelp();
745         }
746     }
747 
748     /**
749      * Process the removing commands.
750      * <ul>
751      *     <li> Syntax 1:
752      *            rm --plan [ plan-name ] [ all ]
753      *     <li> Syntax 2:
754      *            rm --package [ package-name ] [ all ]
755      * </ul>
756      *
757      * @param cp Command container.
758      */
processRmCommand(CommandParser cp)759     private void processRmCommand(CommandParser cp) throws IOException {
760         if (cp.containsKey(CTSCommand.OPTION_PLAN)) {
761             if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
762                 showPlanCmdHelp();
763                 return;
764             }
765 
766             String planName = mHost.getPlanName(cp.getValue(CTSCommand.OPTION_PLAN));
767             if (HostConfig.ALL.equals(planName)) {
768                 String prompt = "Remove all of the plans?([y/N])";
769                 String answer = readLine(prompt).trim();
770                 if (!isConfirmation(answer, false)) {
771                     return;
772                 }
773             }
774 
775             mHost.removePlans(planName);
776         } else if (cp.containsKey(CTSCommand.OPTION_PACKAGE)) {
777             if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
778                 showPackageCmdHelp();
779                 return;
780             }
781 
782             String packageName = cp.getValue(CTSCommand.OPTION_PACKAGE);
783             if (HostConfig.ALL.equals(packageName)) {
784                 String prompt = "Remove all of the packages?([y/N])";
785                 String answer = readLine(prompt).trim();
786                 if (!isConfirmation(answer, false)) {
787                     return;
788                 }
789             }
790 
791             mHost.removePackages(packageName);
792         } else {
793             showHelp();
794         }
795     }
796 
797     /**
798      * Check if the answer is confirmation.
799      *
800      * @param answer The answer user typed in.
801      * @param defaultResult If true, default to yes; else, default to no.
802      * @return If confirmation, return true; else, return false.
803      */
isConfirmation(String answer, boolean defaultResult)804     public static boolean isConfirmation(String answer, boolean defaultResult) {
805         if ("".equals(answer)) {
806             return defaultResult;
807         }
808 
809         return ("y".equals(answer.toLowerCase()) || "yes".equals(answer.toLowerCase()));
810     }
811 
812     /**
813      * Process the add commands.
814      * <ul>
815      *     <li> Syntax 1:
816      *            add --plan plan-name
817      *     <li> Syntax 2:
818      *            add --package package-name
819      * </ul>
820      *
821      * @param cp Command container.
822      */
processAddCommand(CommandParser cp)823     private void processAddCommand(CommandParser cp) {
824         if (cp.containsKey(CTSCommand.OPTION_PLAN)) {
825             if (isValidAddPlanArguments(cp)) {
826                 createPlan(cp, CTSCommand.OPTION_PLAN);
827             } else {
828                 showPlanCmdHelp();
829             }
830         } else if (cp.containsKey(CTSCommand.OPTION_DERIVED_PLAN)) {
831             if (isValidDerivedPlanArguments(cp)) {
832                 createPlan(cp, CTSCommand.OPTION_DERIVED_PLAN);
833             } else {
834                 showPlanCmdHelp();
835             }
836         } else if (cp.containsKey(CTSCommand.OPTION_PACKAGE)) {
837             try {
838                 addPackage(cp);
839             } catch (IOException e) {
840                 Log.e("Can't add package", e);
841             } catch (IndexOutOfBoundsException e) {
842                 Log.e("Can't add package", e);
843             } catch (NoSuchAlgorithmException e) {
844                 Log.e("Can't add package", e);
845             }
846         } else {
847             showHelp();
848         }
849     }
850 
851     /**
852      * Check if it's valid arguments for adding plan.
853      *
854      * @param cp The command processor.
855      * @return if valid, return true; else, return false.
856      */
isValidAddPlanArguments(CommandParser cp)857     private boolean isValidAddPlanArguments(CommandParser cp) {
858         return (cp.getArgSize() == 3) && (cp.getActionValues().size() == 0)
859                 && (cp.getOptionSize() == 1);
860     }
861 
862     /**
863      * Check if it's valid arguments for deriving plan.
864      *
865      * @param cp The command processor.
866      * @return if valid, return true; else, return false.
867      */
isValidDerivedPlanArguments(CommandParser cp)868     private boolean isValidDerivedPlanArguments(CommandParser cp) {
869         //argument size: it's at least 3, as "add --plan plan_name"
870         //action values: no option contains more than one value
871         //option size: it's at least 1, as "add --plan plan_name"
872         return (cp.getArgSize() >= 3) && (cp.getActionValues().size() == 0)
873                 && (cp.getOptionSize() >= 1);
874     }
875 
876     /**
877      * Process the history commands.
878      * <ul>
879      *     <li> Syntax:
880      *            history [ -e ] [ number]
881      * </ul>
882      *
883      * @param cp Command container.
884      */
processHistoryCommands(final CommandParser cp)885     private void processHistoryCommands(final CommandParser cp)
886             throws Exception {
887         try {
888             if ((cp.getOptionSize() == 0) && (cp.getActionValues().size() == 0)) {
889                 mCommandHistory.show(mCommandHistory.size());
890             } else if (cp.containsKey(CTSCommand.OPTION_E)
891                     && (cp.getActionValues().size() == 0)) {
892                 int cmdNum = 0;
893                 cmdNum = Integer.parseInt(cp.getValue(CTSCommand.OPTION_E));
894                 if (cmdNum >= 0 && cmdNum < mCommandHistory.size()) {
895                     String cmdLine = mCommandHistory.get(cmdNum);
896                     CommandParser cpH = CommandParser.parse(cmdLine);
897                     CUIOutputStream.printPrompt();
898                     CUIOutputStream.println(cmdLine);// print(CTS_PROMPT_SIGN
899                                                         // + cmdLine);
900                     processCommand(cpH);
901                     mCommandHistory.addCommand(cpH, cmdLine);
902                 } else {
903                     if (mCommandHistory.size() > 0) {
904                         Log.e("Command index " + cmdNum
905                                 + " is out of command history range [0,"
906                                 + (mCommandHistory.size() - 1) + "].", null);
907                     } else {
908                         Log.e("No command exists in command history.", null);
909                     }
910                 }
911             } else if ((cp.getOptionSize() == 0)
912                     && (cp.getActionValues().size() == 1)) {
913                 int cmdCount = Integer.parseInt(cp.getActionValues().iterator()
914                         .next());
915                 if (cmdCount < 0 || cmdCount > mCommandHistory.size()) {
916                     cmdCount = mCommandHistory.size();
917                 }
918                 mCommandHistory.show(cmdCount);
919             } else {
920                 showHistoryCmdHelp();
921             }
922 
923         } catch (NumberFormatException e) {
924             showHistoryCmdHelp();
925         }
926     }
927 
928     /**
929      * List a single plan by the plan name given.
930      *
931      * @param name The plan name.
932      */
listSinglePlan(String name)933     private void listSinglePlan(String name) throws SAXException, IOException,
934             ParserConfigurationException {
935         String planName = null;
936         for (String str : mHost.getPlanRepository().getAllPlanNames()) {
937             if (str.startsWith(name)) {
938                 planName = str;
939                 break;
940             }
941         }
942 
943         if (planName == null) {
944             Log.e("No plan named " + name + " in repository!", null);
945             return;
946         }
947 
948         String planPath = mHost.getPlanRepository().getPlanPath(planName);
949         ArrayList<String> removedPkgList = new ArrayList<String>();
950         Collection<String> pkgNames = TestPlan.getEntries(planPath, removedPkgList);
951 
952         if (removedPkgList.size() != 0) {
953             CUIOutputStream.println("The following package(s) contained in plan "
954                     + planName + " have been removed:");
955             for (String pkgName : removedPkgList) {
956                 CUIOutputStream.println("    " + pkgName);
957             }
958         }
959 
960         if (pkgNames.size() > 0) {
961             CUIOutputStream.println("Packages of plan " + planName
962                     + " (" + pkgNames.size() + " in total):");
963             CUIOutputStream.println(LS_PLAN_SEPARATOR);
964             for (String pkgName : pkgNames) {
965                 CUIOutputStream.println(pkgName);
966             }
967         }
968     }
969 
970     /**
971      * Create test plan via the test session and result type given.
972      *
973      * @param name The test plan name.
974      * @param ts The test session.
975      * @param resultType The result type.
976      */
createPlanFromSession(final String name, TestSession ts, final String resultType)977     private void createPlanFromSession(final String name, TestSession ts, final String resultType)
978             throws FileNotFoundException, IOException, ParserConfigurationException,
979             TransformerFactoryConfigurationError, TransformerException {
980 
981         HashMap<String, ArrayList<String>> selectedResult =
982             new HashMap<String, ArrayList<String>>();
983         ArrayList<String> packageNames = new ArrayList<String>();
984 
985         for (TestPackage pkg : ts.getSessionLog().getTestPackages()) {
986             String pkgName = pkg.getAppPackageName();
987             ArrayList<String> excludedList = pkg.getExcludedList(resultType);
988             if (excludedList != null) {
989                 packageNames.add(pkgName);
990                 selectedResult.put(pkgName, excludedList);
991             }
992         }
993 
994         if ((selectedResult != null) && (selectedResult.size() > 0)) {
995             TestSessionBuilder.getInstance().serialize(name, packageNames, selectedResult);
996         } else {
997             if (resultType == null) {
998                 Log.i("All tests of session " + ts.getId()
999                         + " have passed execution. The plan is not created!");
1000             } else {
1001                 Log.i("No " + resultType +  " tests of session " + ts.getId()
1002                         + ". The plan is not created!");
1003             }
1004         }
1005     }
1006 
1007     /**
1008      * Add a derived plan from a given session.
1009      *
1010      * @param cp Command container.
1011      * @param name The plan name.
1012      * @param packageNames The package name list.
1013      */
addDerivedPlan(final CommandParser cp, final String name, ArrayList<String> packageNames)1014     private void addDerivedPlan(final CommandParser cp, final String name,
1015             ArrayList<String> packageNames) {
1016 
1017         try {
1018             String sessionId = null;
1019             String resultType = null;
1020             int id = TestSession.getLastSessionId();
1021 
1022             if (cp.containsKey(CTSCommand.OPTION_SESSION)) {
1023                 sessionId = cp.getValue(CTSCommand.OPTION_SESSION);
1024                 id = Integer.parseInt(sessionId);
1025             }
1026             TestSession ts = mHost.getSession(id);
1027             if (ts == null) {
1028                 Log.e("The session ID of " + id + " doesn't exist.", null);
1029                 return;
1030             }
1031 
1032             if (cp.containsKey(CTSCommand.OPTION_RESULT)) {
1033                 resultType = cp.getValue(CTSCommand.OPTION_RESULT);
1034                 if (!CtsTestResult.isValidResultType(resultType)) {
1035                     Log.e("The following result type is invalid: " + resultType, null);
1036                     return;
1037                 }
1038             }
1039             createPlanFromSession(name, ts, resultType);
1040         } catch (Exception e) {
1041             Log.e("Got exception while trying to add a plan!", e);
1042             return;
1043         }
1044     }
1045 
1046     /**
1047      * Add a plan by the plan name given.
1048      *
1049      * @param cp Command container.
1050      * @param name The plan name.
1051      * @param packageNames The package name list.
1052      */
addPlan(final CommandParser cp, final String name, ArrayList<String> packageNames)1053     private void addPlan(final CommandParser cp, final String name,
1054             ArrayList<String> packageNames) {
1055 
1056         try {
1057             PlanBuilder planBuilder = new PlanBuilder(packageNames);
1058 
1059             if (mOsName.equals(OS_NAME_LINUX)) {
1060                 // planBuilder.setInputStream(sConsoleReader);
1061             } else {
1062                 planBuilder.setInputStream(mCommandInput);
1063             }
1064 
1065             HashMap<String, ArrayList<String>> selectedResult = planBuilder.doSelect();
1066             if (selectedResult != null) {
1067                 TestSessionBuilder.getInstance().serialize(name, packageNames, selectedResult);
1068             } else {
1069                 Log.i("Selected nothing for the plan of " + name + ". The plan is not created!");
1070             }
1071         } catch (Exception e) {
1072             Log.e("Got exception while trying to add a plan!", e);
1073             return;
1074         }
1075     }
1076 
1077     /**
1078      * Create a plan.
1079      *
1080      * @param cp Command container.
1081      * @param type the action type.
1082      */
createPlan(final CommandParser cp, final String type)1083     private void createPlan(final CommandParser cp, final String type) {
1084         String name = null;
1085         if (CTSCommand.OPTION_PLAN.equals(type)) {
1086             name = cp.getValue(CTSCommand.OPTION_PLAN);
1087         } else if (CTSCommand.OPTION_DERIVED_PLAN.equals(type)) {
1088             name = cp.getValue(CTSCommand.OPTION_DERIVED_PLAN);
1089         } else {
1090             return;
1091         }
1092 
1093         if (HostUtils.isFileExist(HostConfig.getInstance().getPlanRepository()
1094                 .getPlanPath(name)) == true) {
1095             Log.e("Plan " + name + " already exist, please use another name!", null);
1096             return;
1097         }
1098 
1099         try {
1100             if ((name != null) && (!name.matches("\\w+"))) {
1101                 CUIOutputStream.println("Only letter of the alphabet, number and '_'"
1102                         + " are available for test plan name");
1103                 return;
1104             }
1105 
1106             ArrayList<String> packageNames =
1107                 HostConfig.getInstance().getCaseRepository().getPackageNames();
1108             Collection<TestPackage> testPackages = HostConfig.getInstance().getTestPackages();
1109             if (testPackages.size() == 0) {
1110                 CUIOutputStream.println("No package found in repository, please add package first!");
1111                 return;
1112             }
1113             if (CTSCommand.OPTION_PLAN.equals(type)) {
1114                 addPlan(cp, name, packageNames);
1115             } else if (CTSCommand.OPTION_DERIVED_PLAN.equals(type)) {
1116                 addDerivedPlan(cp, name, packageNames);
1117             }
1118         } catch (Exception e) {
1119             Log.e("Got exception while trying to add a plan!", e);
1120             return;
1121         }
1122     }
1123 
1124     /**
1125      * List all of the plans in the plan repository.
1126      */
listPlans()1127     private void listPlans() {
1128         ArrayList<String> plans = mHost.getPlanRepository().getAllPlanNames();
1129 
1130         if (plans.size() == 0) {
1131             CUIOutputStream.println("No plan created!");
1132         } else {
1133             CUIOutputStream.println("List of plans (" + plans.size() + " in total):");
1134             for (String name : plans) {
1135                 CUIOutputStream.println(name);
1136             }
1137         }
1138     }
1139 
1140     /**
1141      * List detailed case result of specified session. The result can be
1142      * filtered, if resultType isn't null, by the specified resultType.
1143      *
1144      * @param idStr the session id.
1145      * @param resultType the type of result, [pass, fail, notExecuted, timeout, null].
1146      */
listSessionResult(final String idStr, final Integer resultType)1147     private void listSessionResult(final String idStr, final Integer resultType) {
1148         if (!idStr.matches("\\d+")) {
1149             showResultCmdHelp();
1150             return;
1151         }
1152 
1153         int sessionId = Integer.parseInt(idStr);
1154 
1155         TestSession ts = mHost.getSession(sessionId);
1156         if (null == ts) {
1157             Log.e("Can't find specified session", null);
1158             return;
1159         }
1160 
1161         TestSessionLog log = ts.getSessionLog();
1162         CUIOutputStream.println("Result of session " + ts.getId());
1163         CUIOutputStream.println("Result\t\tCase name");
1164         CUIOutputStream
1165                 .println("==============================================================");
1166         for (Test test : log.getAllResults()) {
1167             CtsTestResult result = test.getResult();
1168             if ((resultType != null) && (result.getResultCode() != resultType.intValue())) {
1169                 continue;
1170             }
1171             CUIOutputStream.println(result.getResultString() + "\t\t"
1172                     + test.getFullName());
1173         }
1174     }
1175 
1176     /**
1177      * List all of the test results.
1178      */
listResults()1179     private void listResults() {
1180         Collection<TestSession> sessions = mHost.getSessions();
1181         if (sessions.isEmpty()) {
1182             CUIOutputStream.println("There aren't any test results!");
1183         } else {
1184             CUIOutputStream.println("List of all results: ");
1185             CUIOutputStream.println("Session\t\tTest result\t\t\t\tStart time\t\tEnd time\t"
1186                     + "\tTest plan name\t");
1187             CUIOutputStream.println("\t\tPass\tFail\tTimeout\tNotExecuted");
1188 
1189             for (TestSession session : sessions) {
1190                 TestSessionLog log = session.getSessionLog();
1191                 int passNum = log.getTestList(
1192                         CtsTestResult.CODE_PASS).size();
1193                 int failNum = log.getTestList(
1194                         CtsTestResult.CODE_FAIL).size();
1195                 int notExecutedNum = log.getTestList(
1196                         CtsTestResult.CODE_NOT_EXECUTED).size();
1197                 int timeOutNum = log.getTestList(
1198                         CtsTestResult.CODE_TIMEOUT).size();
1199 
1200                 String resStr = Long.toString(passNum) + "\t" + failNum;
1201                 resStr += "\t" + timeOutNum;
1202                 resStr += "\t" + notExecutedNum;
1203 
1204                 String startTimeStr =
1205                     HostUtils.getFormattedTimeString(log.getStartTime().getTime(), " ", ".", ":");
1206                 String endTimeStr =
1207                     HostUtils.getFormattedTimeString(log.getEndTime().getTime(), " ", ".", ":");
1208                 CUIOutputStream.println(Long.toString(session.getId()) + "\t\t"
1209                         + resStr + "\t\t" + startTimeStr
1210                         + "\t" + endTimeStr
1211                         + "\t" + log.getTestPlanName());
1212 
1213             }
1214         }
1215     }
1216 
1217     /**
1218      * Add a package by the path and package name.
1219      *
1220      * @param cp Command container.
1221      */
addPackage(final CommandParser cp)1222     private void addPackage(final CommandParser cp) throws IOException,
1223             IndexOutOfBoundsException, NoSuchAlgorithmException {
1224         if (cp.getActionValues().size() != 0 || cp.getOptionSize() != 1) {
1225             showPackageCmdHelp();
1226             return;
1227         }
1228         String pathName = cp.getValue(CTSCommand.OPTION_PACKAGE);
1229         mHost.addPackage(pathName);
1230     }
1231 
1232     /**
1233      * List current package in the case repository.
1234      *
1235      * @param cp Command container
1236      */
listPackages(final CommandParser cp)1237     private void listPackages(final CommandParser cp) {
1238         // walk through the case root path
1239         // and list available packages
1240         String expectPackage = cp.getValue(CTSCommand.OPTION_PACKAGE);
1241         String caseRoot = mHost.getCaseRepository().getRoot();
1242         if (caseRoot == null) {
1243             Log.e("Case repository is null", null);
1244             return;
1245         }
1246 
1247         File root = new File(caseRoot);
1248         if (!root.isDirectory()) {
1249             Log.e("Case repository must be a directory!", null);
1250             return;
1251         }
1252 
1253         Collection<TestPackage> testPackages = HostConfig.getInstance().getTestPackages();
1254 
1255         if (testPackages.size() == 0) {
1256             CUIOutputStream
1257                     .println("No package available under case repository!");
1258         } else {
1259             if (expectPackage.equals("")) {
1260                 CUIOutputStream.println("Available packages ("
1261                         + testPackages.size() + " in total):");
1262                 for (TestPackage pkg : testPackages) {
1263                     CUIOutputStream.println(pkg.getAppPackageName());
1264                 }
1265             } else {
1266                 List<ArrayList<String>> list = mHost.getCaseRepository()
1267                         .listAvailablePackage(expectPackage);
1268                 ArrayList<String> packageList = list.get(0);
1269                 ArrayList<String> suiteList = list.get(1);
1270                 ArrayList<String> caseList = list.get(2);
1271                 ArrayList<String> testList = list.get(3);
1272                 if ((packageList.size() == 0) && (suiteList.size() == 0)
1273                         && (caseList.size() == 0) && (testList.size() == 0)) {
1274                     CUIOutputStream
1275                             .println("Not available test package, suite, cases or tests: "
1276                                     + expectPackage);
1277                 } else {
1278                     if (packageList.size() != 0) {
1279                         CUIOutputStream.println(
1280                                 "Test packages (" + packageList.size() + " in total):");
1281                         for (String packageName : packageList) {
1282                             CUIOutputStream.println(packageName);
1283                         }
1284                     }
1285                     if (suiteList.size() != 0) {
1286                         CUIOutputStream.println(
1287                                 "Test suites (" + suiteList.size() + " in total):");
1288                         for (String suiteName : suiteList) {
1289                             CUIOutputStream.println(suiteName);
1290                         }
1291                     }
1292                     if (caseList.size() != 0) {
1293                         CUIOutputStream.println("Test cases (" + caseList.size() + " in total):");
1294                         for (String caseName : caseList) {
1295                             CUIOutputStream.println(caseName);
1296                         }
1297                     }
1298                     if (testList.size() != 0) {
1299                         CUIOutputStream.println("Tests (" + testList.size() + " in total):");
1300                         for (String testName : testList) {
1301                             CUIOutputStream.println(testName);
1302                         }
1303                     }
1304                 }
1305             }
1306         }
1307     }
1308 
1309     /**
1310      * List all of the devices connected.
1311      */
listDevices()1312     private void listDevices() {
1313         String[] deviceNames = mHost.listDevices();
1314         if (deviceNames.length == 0) {
1315             CUIOutputStream.println("No device connected.");
1316             return;
1317         }
1318 
1319         CUIOutputStream.println("Id\t\tDevice Name\t\tStatus");
1320 
1321         for (int i = 0; i < deviceNames.length; i++) {
1322             CUIOutputStream.println(i + "\t\t" + deviceNames[i]);
1323         }
1324     }
1325 }
1326