Home | History | Annotate | Download | only in command
      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 
     55     CtsConsole() {
     56         super();
     57     }
     58 
     59     @Override
     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
     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
    135     protected String getConsolePrompt() {
    136         return "cts-tf > ";
    137     }
    138 
    139     @Override
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    260     public static void main(String[] args) throws InterruptedException, ConfigurationException {
    261         Console console = new CtsConsole();
    262         Console.startConsole(console, args);
    263     }
    264 }
    265