blob: 24239e6ad49ba70accb7bea3d98a6c9029cf5940 [file] [log] [blame]
/*
* Copyright (C) 2011 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.cts.tradefed.command;
import com.android.cts.tradefed.build.CtsBuildHelper;
import com.android.cts.tradefed.build.CtsBuildProvider;
import com.android.cts.tradefed.result.ITestResultRepo;
import com.android.cts.tradefed.result.ITestSummary;
import com.android.cts.tradefed.result.PlanCreator;
import com.android.cts.tradefed.result.TestResultRepo;
import com.android.cts.tradefed.testtype.ITestPackageRepo;
import com.android.cts.tradefed.testtype.TestPackageRepo;
import com.android.cts.util.AbiUtils;
import com.android.tradefed.build.IFolderBuildInfo;
import com.android.tradefed.command.Console;
import com.android.tradefed.config.ArgsOptionParser;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.RegexTrie;
import com.android.tradefed.util.TableFormatter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Specialization of trade federation console that adds CTS commands to list plans and packages.
*/
public class CtsConsole extends Console {
protected static final String ADD_PATTERN = "a(?:dd)?";
private IFolderBuildInfo mBuildInfo = null;
private CtsBuildHelper mBuildHelper = null;
CtsConsole() {
super();
}
@Override
public void run() {
printLine(String.format("Android CTS %s build:%s",
CtsBuildProvider.CTS_BUILD_VERSION, getCtsBuildInfo().getBuildId()));
super.run();
}
/**
* Adds the 'list packages' and 'list plans' commands
*/
@Override
protected void setCustomCommands(RegexTrie<Runnable> trie, List<String> genericHelp,
Map<String, String> commandHelp) {
trie.put(new Runnable() {
@Override
public void run() {
CtsBuildHelper ctsBuild = getCtsBuildHelper();
if (ctsBuild != null) {
listPlans(ctsBuild);
}
}
}, LIST_PATTERN, "p(?:lans)?");
trie.put(new Runnable() {
@Override
public void run() {
CtsBuildHelper ctsBuild = getCtsBuildHelper();
if (ctsBuild != null) {
listPackages(ctsBuild);
}
}
}, LIST_PATTERN, "packages");
trie.put(new Runnable() {
@Override
public void run() {
CtsBuildHelper ctsBuild = getCtsBuildHelper();
if (ctsBuild != null) {
listResults(ctsBuild);
}
}
}, LIST_PATTERN, "r(?:esults)?");
// find existing help for 'LIST_PATTERN' commands, and append these commands help
String listHelp = commandHelp.get(LIST_PATTERN);
if (listHelp == null) {
// no help? Unexpected, but soldier on
listHelp = new String();
}
String combinedHelp = listHelp +
"\tp[lans]\t\tList all CTS test plans" + LINE_SEPARATOR +
"\tpackages\tList all CTS packages" + LINE_SEPARATOR +
"\tr[esults]\tList all CTS results" + LINE_SEPARATOR;
commandHelp.put(LIST_PATTERN, combinedHelp);
ArgRunnable<CaptureList> addDerivedCommand = new ArgRunnable<CaptureList>() {
@Override
public void run(CaptureList args) {
// Skip 2 tokens to get past addPattern and "derivedplan"
String[] flatArgs = new String[args.size() - 2];
for (int i = 2; i < args.size(); i++) {
flatArgs[i - 2] = args.get(i).get(0);
}
CtsBuildHelper ctsBuild = getCtsBuildHelper();
if (ctsBuild != null) {
// FIXME may want to only add certain ABIs
addDerivedPlan(ctsBuild, AbiUtils.getAbisSupportedByCts(), flatArgs);
}
}
};
trie.put(addDerivedCommand, ADD_PATTERN, "d(?:erivedplan?)", null);
commandHelp.put(ADD_PATTERN, String.format(
"%s help:" + LINE_SEPARATOR +
"\tderivedplan Add a derived plan" + LINE_SEPARATOR,
ADD_PATTERN));
}
@Override
protected String getConsolePrompt() {
return "cts-tf > ";
}
@Override
protected String getGenericHelpString(List<String> genericHelp) {
StringBuilder helpBuilder = new StringBuilder();
helpBuilder.append("CTS-tradefed host version ");
helpBuilder.append(CtsBuildProvider.CTS_BUILD_VERSION);
helpBuilder.append("\n\n");
helpBuilder.append("CTS-tradefed is the test harness for running the Android ");
helpBuilder.append("Compatibility Suite, built on top of the tradefed framework.\n\n");
helpBuilder.append("Available commands and options\n");
helpBuilder.append("Host:\n");
helpBuilder.append(" help: show this message\n");
helpBuilder.append(" help all: show the complete tradefed help\n");
helpBuilder.append(" exit: gracefully exit the cts console, waiting till all ");
helpBuilder.append("invocations are complete\n");
helpBuilder.append("Run:\n");
helpBuilder.append(" run cts --plan test_plan_name: run a test plan\n");
helpBuilder.append(" run cts --package/-p : run a CTS test package\n");
helpBuilder.append(" run cts --class/-c [--method/-m] : run a specific test class and/or");
helpBuilder.append("method\n");
helpBuilder.append(" run cts --continue-session session_ID: run all not executed ");
helpBuilder.append("tests from a previous CTS session\n");
helpBuilder.append(" run cts [options] --serial/-s device_ID: run CTS on specified ");
helpBuilder.append("device\n");
helpBuilder.append(" run cts [options] --shards number_of_shards: shard a CTS run into ");
helpBuilder.append("given number of independent chunks, to run on multiple devices in");
helpBuilder.append("parallel\n");
helpBuilder.append(" run cts --help/--help-all: get more help on running CTS\n");
helpBuilder.append("List:\n");
helpBuilder.append(" l/list d/devices: list connected devices and their state\n");
helpBuilder.append(" l/list packages: list CTS test packages\n");
helpBuilder.append(" l/list p/plans: list CTS test plans\n");
helpBuilder.append(" l/list i/invocations: list invocations aka CTS test runs currently");
helpBuilder.append("in progress\n");
helpBuilder.append(" l/list c/commands: list commands: aka CTS test run commands ");
helpBuilder.append("currently in the queue waiting to be allocated devices\n");
helpBuilder.append(" l/list r/results: list CTS results currently present in the ");
helpBuilder.append("repository\n");
helpBuilder.append("Add:\n");
helpBuilder.append(" add derivedplan --plan plane_name --session/-s session_id -r ");
helpBuilder.append("[pass/fail/notExecuted/timeout]: derive a plan from the given ");
helpBuilder.append("session\n");
helpBuilder.append("Dump:\n");
helpBuilder.append(" d/dump l/logs: dump the tradefed logs for all running invocations\n");
helpBuilder.append("Options:\n");
helpBuilder.append(" --disable-reboot : Do not reboot device after running some amount of tests.\n");
return helpBuilder.toString();
}
private void listPlans(CtsBuildHelper ctsBuild) {
FilenameFilter xmlFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".xml");
}
};
for (File planFile : ctsBuild.getTestPlansDir().listFiles(xmlFilter)) {
printLine(FileUtil.getBaseName(planFile.getName()));
}
}
private void listPackages(CtsBuildHelper ctsBuild) {
ITestPackageRepo testCaseRepo = new TestPackageRepo(ctsBuild.getTestCasesDir(), false);
for (String packageName : testCaseRepo.getPackageNames()) {
printLine(packageName);
}
}
private void listResults(CtsBuildHelper ctsBuild) {
TableFormatter tableFormatter = new TableFormatter();
List<List<String>> table = new ArrayList<List<String>>();
table.add(Arrays.asList("Session","Pass", "Fail","Not Executed","Start time","Plan name",
"Device serial(s)"));
ITestResultRepo testResultRepo = new TestResultRepo(ctsBuild.getResultsDir());
for (ITestSummary result : testResultRepo.getSummaries()) {
table.add(Arrays.asList(Integer.toString(result.getId()),
Integer.toString(result.getNumPassed()),
Integer.toString(result.getNumFailed()),
Integer.toString(result.getNumIncomplete()),
result.getTimestamp(),
result.getTestPlan(),
result.getDeviceSerials()));
}
tableFormatter.displayTable(table, new PrintWriter(System.out, true));
}
private void addDerivedPlan(CtsBuildHelper ctsBuild, Set<String> abis, String[] flatArgs) {
PlanCreator creator = new PlanCreator();
try {
ArgsOptionParser optionParser = new ArgsOptionParser(creator);
optionParser.parse(Arrays.asList(flatArgs));
creator.createAndSerializeDerivedPlan(ctsBuild, abis);
} catch (ConfigurationException e) {
printLine("Error: " + e.getMessage());
printLine(ArgsOptionParser.getOptionHelp(false, creator));
}
}
private IFolderBuildInfo getCtsBuildInfo() {
if (mBuildInfo == null) {
try {
mBuildInfo = (IFolderBuildInfo) new CtsBuildProvider().getBuild();
} catch (IllegalArgumentException e) {
printLine("Could not find CTS install location: CTS_ROOT env variable not set");
}
}
return mBuildInfo;
}
private CtsBuildHelper getCtsBuildHelper() {
if (mBuildHelper == null) {
try {
mBuildHelper = new CtsBuildHelper(getCtsBuildInfo());
mBuildHelper.validateStructure();
} catch (FileNotFoundException e) {
printLine(String.format("Invalid cts install: %s", e.getMessage()));
mBuildHelper = null;
}
}
return mBuildHelper;
}
public static void main(String[] args) throws InterruptedException, ConfigurationException {
Console console = new CtsConsole();
Console.startConsole(console, args);
}
}