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.result;
17 
18 import com.android.cts.tradefed.build.CtsBuildHelper;
19 import com.android.cts.tradefed.testtype.CtsTest;
20 import com.android.cts.tradefed.testtype.ITestPackageDef;
21 import com.android.cts.tradefed.testtype.ITestPackageRepo;
22 import com.android.cts.tradefed.testtype.ITestPlan;
23 import com.android.cts.tradefed.testtype.TestPackageRepo;
24 import com.android.cts.tradefed.testtype.TestPlan;
25 import com.android.cts.util.AbiUtils;
26 import com.android.ddmlib.Log;
27 import com.android.ddmlib.Log.LogLevel;
28 import com.android.ddmlib.testrunner.TestIdentifier;
29 import com.android.tradefed.config.ConfigurationException;
30 import com.android.tradefed.config.Option;
31 import com.android.tradefed.config.Option.Importance;
32 import com.android.tradefed.log.LogUtil.CLog;
33 
34 import java.io.BufferedOutputStream;
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.FileOutputStream;
38 import java.io.IOException;
39 import java.util.Collection;
40 import java.util.LinkedHashSet;
41 import java.util.Set;
42 
43 /**
44  * Class for creating test plans from CTS result XML.
45  */
46 public class PlanCreator {
47 
48     @Option (name = "plan", shortName = 'p', description = "the name of the plan to create",
49             importance=Importance.IF_UNSET)
50     private String mPlanName = null;
51 
52     @Option (name = "session", shortName = 's', description = "the session id to derive from",
53             importance=Importance.IF_UNSET)
54     private Integer mSessionId = null;
55 
56     @Option (name = "result", shortName = 'r',
57             description = "the result type to filter. One of pass, fail, notExecuted.",
58             importance=Importance.IF_UNSET)
59     private String mResultFilterString = null;
60 
61     @Option(name = CtsTest.RUN_KNOWN_FAILURES_OPTION)
62     private boolean mIncludeKnownFailures = false;
63 
64     private CtsTestStatus mResultFilter = null;
65     private TestResults mResult = null;
66 
67     private File mPlanFile;
68 
69     /**
70      * Create an empty {@link PlanCreator}.
71      * <p/>
72      * All {@link Option} fields must be populated via
73      * {@link com.android.tradefed.config.ArgsOptionParser}
74      */
PlanCreator()75     public PlanCreator() {
76     }
77 
78     /**
79      * Create a {@link PlanCreator} using the specified option values.
80      */
PlanCreator(String planName, int session, CtsTestStatus result)81     public PlanCreator(String planName, int session, CtsTestStatus result) {
82         mPlanName = planName;
83         mSessionId = session;
84         mResultFilterString = result.getValue();
85     }
86 
87     /**
88      * Create and serialize a test plan derived from a result.
89      * <p/>
90      * {@link Option} values must all be set before this is called.
91      * @throws ConfigurationException
92      */
createAndSerializeDerivedPlan(CtsBuildHelper build, Set<String> abis)93     public void createAndSerializeDerivedPlan(CtsBuildHelper build, Set<String> abis)
94             throws ConfigurationException {
95         ITestPlan derivedPlan = createDerivedPlan(build, abis);
96         if (derivedPlan != null) {
97             try {
98                 derivedPlan.serialize(new BufferedOutputStream(new FileOutputStream(mPlanFile)));
99             } catch (IOException e) {
100                 Log.logAndDisplay(LogLevel.ERROR, "", String.format("Failed to create plan file %s",
101                         mPlanName));
102                 CLog.e(e);
103             }
104         }
105     }
106 
107     /**
108      * Create a test plan derived from a result.
109      * <p/>
110      * {@link Option} values must all be set before this is called.
111      *
112      * @param build
113      * @return test plan
114      * @throws ConfigurationException
115      */
createDerivedPlan(CtsBuildHelper build, Set<String> abis)116     public ITestPlan createDerivedPlan(CtsBuildHelper build, Set<String> abis)
117             throws ConfigurationException {
118         checkFields(build);
119         ITestPackageRepo pkgDefRepo =
120                 new TestPackageRepo(build.getTestCasesDir(), mIncludeKnownFailures);
121         ITestPlan derivedPlan = new TestPlan(mPlanName, abis);
122         for (TestPackageResult pkg : mResult.getPackages()) {
123             Collection<TestIdentifier> filteredTests = pkg.getTestsWithStatus(mResultFilter);
124             String pkgId = pkg.getId();
125             ITestPackageDef pkgDef = pkgDefRepo.getTestPackage(pkgId);
126             if (pkgDef != null) {
127                 Collection<TestIdentifier> excludedTests =
128                         new LinkedHashSet<TestIdentifier>(pkgDef.getTests());
129                 excludedTests.removeAll(filteredTests);
130                 derivedPlan.addPackage(pkgId);
131                 derivedPlan.addExcludedTests(pkgId, excludedTests);
132             } else {
133                 CLog.e("Could not find package %s in repository", pkgId);
134             }
135         }
136         return derivedPlan;
137     }
138 
139     /**
140      * Check that all {@Option}s have been populated with valid values.
141      * @param build
142      * @throws ConfigurationException if any option has an invalid value
143      */
checkFields(CtsBuildHelper build)144     private void checkFields(CtsBuildHelper build) throws ConfigurationException {
145         if (mSessionId == null) {
146             throw new ConfigurationException("Missing --session argument");
147         }
148         ITestResultRepo repo = new TestResultRepo(build.getResultsDir());
149         mResult = repo.getResult(mSessionId);
150         if (mResult == null) {
151             throw new ConfigurationException(String.format("Could not find session with id %d",
152                     mSessionId));
153         }
154         if (mResultFilterString == null) {
155             throw new ConfigurationException("Missing --result argument");
156         }
157         mResultFilter = CtsTestStatus.getStatus(mResultFilterString);
158         if (mResultFilter == null) {
159             throw new ConfigurationException(
160                     "Invalid result argument. Expected one of pass,fail,notExecuted");
161         }
162         if (mPlanName == null) {
163             throw new ConfigurationException("Missing --plan argument");
164         }
165         try {
166             mPlanFile = build.getTestPlanFile(mPlanName);
167             if (mPlanFile.exists()) {
168                 throw new ConfigurationException(String.format("Test plan %s already exists",
169                         mPlanName));
170             }
171         } catch (FileNotFoundException e) {
172             throw new ConfigurationException("Could not find plans directory");
173         }
174     }
175 }
176