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