1 /*
2  * Copyright (C) 2011 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 package com.android.cts.tradefed.command;
17 
18 import com.android.cts.tradefed.build.CtsBuildHelper;
19 import com.android.cts.tradefed.build.CtsBuildProvider;
20 import com.android.cts.tradefed.result.ITestResultRepo;
21 import com.android.cts.tradefed.result.ITestSummary;
22 import com.android.cts.tradefed.result.PlanCreator;
23 import com.android.cts.tradefed.result.TestResultRepo;
24 import com.android.cts.tradefed.testtype.ITestPackageRepo;
25 import com.android.cts.tradefed.testtype.TestPackageRepo;
26 import com.android.cts.util.AbiUtils;
27 import com.android.tradefed.build.IFolderBuildInfo;
28 import com.android.tradefed.command.Console;
29 import com.android.tradefed.config.ArgsOptionParser;
30 import com.android.tradefed.config.ConfigurationException;
31 import com.android.tradefed.util.FileUtil;
32 import com.android.tradefed.util.RegexTrie;
33 import com.android.tradefed.util.TableFormatter;
34 
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.FilenameFilter;
38 import java.io.PrintWriter;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.Map;
43 import java.util.Set;
44 
45 /**
46  * Specialization of trade federation console that adds CTS commands to list plans and packages.
47  */
48 public class CtsConsole extends Console {
49 
50     protected static final String ADD_PATTERN = "a(?:dd)?";
51 
52     private IFolderBuildInfo mBuildInfo = null;
53     private CtsBuildHelper mBuildHelper = null;
54 
CtsConsole()55     CtsConsole() {
56         super();
57     }
58 
59     @Override
run()60     public void run() {
61         printLine(String.format("Android CTS %s build:%s",
62                 CtsBuildProvider.CTS_BUILD_VERSION, getCtsBuildInfo().getBuildId()));
63         super.run();
64     }
65 
66     /**
67      * Adds the 'list packages' and 'list plans' commands
68      */
69     @Override
setCustomCommands(RegexTrie<Runnable> trie, List<String> genericHelp, Map<String, String> commandHelp)70     protected void setCustomCommands(RegexTrie<Runnable> trie, List<String> genericHelp,
71             Map<String, String> commandHelp) {
72         trie.put(new Runnable() {
73             @Override
74             public void run() {
75                 CtsBuildHelper ctsBuild = getCtsBuildHelper();
76                 if (ctsBuild != null) {
77                     listPlans(ctsBuild);
78                 }
79             }
80         }, LIST_PATTERN, "p(?:lans)?");
81         trie.put(new Runnable() {
82             @Override
83             public void run() {
84                 CtsBuildHelper ctsBuild = getCtsBuildHelper();
85                 if (ctsBuild != null) {
86                     listPackages(ctsBuild);
87                 }
88             }
89         }, LIST_PATTERN, "packages");
90         trie.put(new Runnable() {
91             @Override
92             public void run() {
93                 CtsBuildHelper ctsBuild = getCtsBuildHelper();
94                 if (ctsBuild != null) {
95                     listResults(ctsBuild);
96                 }
97             }
98         }, LIST_PATTERN, "r(?:esults)?");
99 
100         // find existing help for 'LIST_PATTERN' commands, and append these commands help
101         String listHelp = commandHelp.get(LIST_PATTERN);
102         if (listHelp == null) {
103             // no help? Unexpected, but soldier on
104             listHelp = new String();
105         }
106         String combinedHelp = listHelp +
107                 "\tp[lans]\t\tList all CTS test plans" + LINE_SEPARATOR +
108                 "\tpackages\tList all CTS packages" + LINE_SEPARATOR +
109                 "\tr[esults]\tList all CTS results" + LINE_SEPARATOR;
110         commandHelp.put(LIST_PATTERN, combinedHelp);
111 
112         ArgRunnable<CaptureList> addDerivedCommand = new ArgRunnable<CaptureList>() {
113             @Override
114             public void run(CaptureList args) {
115                 // Skip 2 tokens to get past addPattern and "derivedplan"
116                 String[] flatArgs = new String[args.size() - 2];
117                 for (int i = 2; i < args.size(); i++) {
118                     flatArgs[i - 2] = args.get(i).get(0);
119                 }
120                 CtsBuildHelper ctsBuild = getCtsBuildHelper();
121                 if (ctsBuild != null) {
122                     // FIXME may want to only add certain ABIs
123                     addDerivedPlan(ctsBuild, AbiUtils.getAbisSupportedByCts(), flatArgs);
124                 }
125             }
126         };
127         trie.put(addDerivedCommand, ADD_PATTERN, "d(?:erivedplan?)", null);
128         commandHelp.put(ADD_PATTERN, String.format(
129                 "%s help:" + LINE_SEPARATOR +
130                 "\tderivedplan      Add a derived plan" + LINE_SEPARATOR,
131                 ADD_PATTERN));
132     }
133 
134     @Override
getConsolePrompt()135     protected String getConsolePrompt() {
136         return "cts-tf > ";
137     }
138 
139     @Override
getGenericHelpString(List<String> genericHelp)140     protected String getGenericHelpString(List<String> genericHelp) {
141         StringBuilder helpBuilder = new StringBuilder();
142         helpBuilder.append("CTS-tradefed host version ");
143         helpBuilder.append(CtsBuildProvider.CTS_BUILD_VERSION);
144         helpBuilder.append("\n\n");
145         helpBuilder.append("CTS-tradefed is the test harness for running the Android ");
146         helpBuilder.append("Compatibility Suite, built on top of the tradefed framework.\n\n");
147         helpBuilder.append("Available commands and options\n");
148         helpBuilder.append("Host:\n");
149         helpBuilder.append("  help: show this message\n");
150         helpBuilder.append("  help all: show the complete tradefed help\n");
151         helpBuilder.append("  exit: gracefully exit the cts console, waiting till all ");
152         helpBuilder.append("invocations are complete\n");
153         helpBuilder.append("Run:\n");
154         helpBuilder.append("  run cts --plan test_plan_name: run a test plan\n");
155         helpBuilder.append("  run cts --package/-p : run a CTS test package\n");
156         helpBuilder.append("  run cts --class/-c [--method/-m] : run a specific test class and/or");
157         helpBuilder.append("method\n");
158         helpBuilder.append("  run cts --continue-session session_ID: run all not executed ");
159         helpBuilder.append("tests from a previous CTS session\n");
160         helpBuilder.append("  run cts [options] --serial/-s device_ID: run CTS on specified ");
161         helpBuilder.append("device\n");
162         helpBuilder.append("  run cts [options] --shards number_of_shards: shard a CTS run into ");
163         helpBuilder.append("given number of independent chunks, to run on multiple devices in");
164         helpBuilder.append("parallel\n");
165         helpBuilder.append("  run cts --help/--help-all: get more help on running CTS\n");
166         helpBuilder.append("List:\n");
167         helpBuilder.append("  l/list d/devices: list connected devices and their state\n");
168         helpBuilder.append("  l/list packages: list CTS test packages\n");
169         helpBuilder.append("  l/list p/plans: list CTS test plans\n");
170         helpBuilder.append("  l/list i/invocations: list invocations aka CTS test runs currently");
171         helpBuilder.append("in progress\n");
172         helpBuilder.append("  l/list c/commands: list commands: aka CTS test run commands ");
173         helpBuilder.append("currently in the queue waiting to be allocated devices\n");
174         helpBuilder.append("  l/list r/results: list CTS results currently present in the ");
175         helpBuilder.append("repository\n");
176         helpBuilder.append("Add:\n");
177         helpBuilder.append("  add derivedplan --plan plane_name --session/-s session_id -r ");
178         helpBuilder.append("[pass/fail/notExecuted/timeout]: derive a plan from the given ");
179         helpBuilder.append("session\n");
180         helpBuilder.append("Dump:\n");
181         helpBuilder.append("  d/dump l/logs: dump the tradefed logs for all running invocations\n");
182         helpBuilder.append("Options:\n");
183         helpBuilder.append("  --disable-reboot : Do not reboot device after running some amount of tests.\n");
184         return helpBuilder.toString();
185     }
186 
listPlans(CtsBuildHelper ctsBuild)187     private void listPlans(CtsBuildHelper ctsBuild) {
188         FilenameFilter xmlFilter = new FilenameFilter() {
189             @Override
190             public boolean accept(File dir, String name) {
191                 return name.endsWith(".xml");
192             }
193         };
194         for (File planFile : ctsBuild.getTestPlansDir().listFiles(xmlFilter)) {
195             printLine(FileUtil.getBaseName(planFile.getName()));
196         }
197     }
198 
listPackages(CtsBuildHelper ctsBuild)199     private void listPackages(CtsBuildHelper ctsBuild) {
200         ITestPackageRepo testCaseRepo = new TestPackageRepo(ctsBuild.getTestCasesDir(), false);
201         for (String packageName : testCaseRepo.getPackageNames()) {
202             printLine(packageName);
203         }
204     }
205 
listResults(CtsBuildHelper ctsBuild)206     private void listResults(CtsBuildHelper ctsBuild) {
207         TableFormatter tableFormatter = new TableFormatter();
208         List<List<String>> table = new ArrayList<List<String>>();
209         table.add(Arrays.asList("Session","Pass", "Fail","Not Executed","Start time","Plan name",
210                 "Device serial(s)"));
211         ITestResultRepo testResultRepo = new TestResultRepo(ctsBuild.getResultsDir());
212         for (ITestSummary result : testResultRepo.getSummaries()) {
213             table.add(Arrays.asList(Integer.toString(result.getId()),
214                     Integer.toString(result.getNumPassed()),
215                     Integer.toString(result.getNumFailed()),
216                     Integer.toString(result.getNumIncomplete()),
217                     result.getTimestamp(),
218                     result.getTestPlan(),
219                     result.getDeviceSerials()));
220         }
221         tableFormatter.displayTable(table, new PrintWriter(System.out, true));
222     }
223 
addDerivedPlan(CtsBuildHelper ctsBuild, Set<String> abis, String[] flatArgs)224     private void addDerivedPlan(CtsBuildHelper ctsBuild, Set<String> abis, String[] flatArgs) {
225         PlanCreator creator = new PlanCreator();
226         try {
227             ArgsOptionParser optionParser = new ArgsOptionParser(creator);
228             optionParser.parse(Arrays.asList(flatArgs));
229             creator.createAndSerializeDerivedPlan(ctsBuild, abis);
230         } catch (ConfigurationException e) {
231             printLine("Error: " + e.getMessage());
232             printLine(ArgsOptionParser.getOptionHelp(false, creator));
233         }
234     }
235 
getCtsBuildInfo()236     private IFolderBuildInfo getCtsBuildInfo() {
237         if (mBuildInfo == null) {
238             try {
239                 mBuildInfo = (IFolderBuildInfo) new CtsBuildProvider().getBuild();
240             } catch (IllegalArgumentException e) {
241                 printLine("Could not find CTS install location: CTS_ROOT env variable not set");
242             }
243         }
244         return mBuildInfo;
245     }
246 
getCtsBuildHelper()247     private CtsBuildHelper getCtsBuildHelper() {
248         if (mBuildHelper == null) {
249             try {
250                 mBuildHelper = new CtsBuildHelper(getCtsBuildInfo());
251                 mBuildHelper.validateStructure();
252             } catch (FileNotFoundException e) {
253                 printLine(String.format("Invalid cts install: %s", e.getMessage()));
254                 mBuildHelper = null;
255             }
256         }
257         return mBuildHelper;
258     }
259 
main(String[] args)260     public static void main(String[] args) throws InterruptedException, ConfigurationException {
261         Console console = new CtsConsole();
262         Console.startConsole(console, args);
263     }
264 }
265