• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 
17 package com.android.cts.verifier;
18 
19 import android.content.Context;
20 import android.os.Build;
21 import android.text.TextUtils;
22 
23 import com.android.compatibility.common.util.DevicePropertyInfo;
24 import com.android.compatibility.common.util.ICaseResult;
25 import com.android.compatibility.common.util.IInvocationResult;
26 import com.android.compatibility.common.util.IModuleResult;
27 import com.android.compatibility.common.util.ITestResult;
28 import com.android.compatibility.common.util.InvocationResult;
29 import com.android.compatibility.common.util.ReportLog;
30 import com.android.compatibility.common.util.TestResultHistory;
31 import com.android.compatibility.common.util.TestScreenshotsMetadata;
32 import com.android.compatibility.common.util.TestStatus;
33 import com.android.cts.verifier.TestListActivity.DisplayMode;
34 import com.android.cts.verifier.TestListAdapter.TestListItem;
35 
36 import java.text.DateFormat;
37 import java.text.SimpleDateFormat;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.HashSet;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Map.Entry;
44 import java.util.Set;
45 
46 /**
47  * Helper class for creating an {@code InvocationResult} for CTS result generation.
48  */
49 class TestResultsReport {
50 
51     /** Version of the test report. Increment whenever adding new tags and attributes. */
52     private static final int REPORT_VERSION = 2;
53 
54     /** Format of the report's creation time. Maintain the same format at CTS. */
55     private static DateFormat DATE_FORMAT =
56             new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
57 
58     private static final String PREFIX_TAG = "build_";
59     private static final String TEST_RESULTS_REPORT_TAG = "test-results-report";
60     private static final String VERIFIER_INFO_TAG = "verifier-info";
61     private static final String DEVICE_INFO_TAG = "device-info";
62     private static final String BUILD_INFO_TAG = "build-info";
63     private static final String TEST_RESULTS_TAG = "test-results";
64     private static final String TEST_TAG = "test";
65     private static final String TEST_DETAILS_TAG = "details";
66 
67     private static final String TEST_CASE_NAME = "manualTests";
68     private static final String HOST_TEST_CASE_NAME = "hostTests";
69 
70     private final Context mContext;
71 
72     private final TestListAdapter mAdapter;
73 
TestResultsReport(Context context, TestListAdapter adapter)74     TestResultsReport(Context context, TestListAdapter adapter) {
75         this.mContext = context;
76         this.mAdapter = adapter;
77     }
78 
generateResult()79     IInvocationResult generateResult() {
80         String abis = null;
81         String abis32 = null;
82         String abis64 = null;
83         String versionBaseOs = null;
84         String versionSecurityPatch = null;
85         String versionRelease = null;
86         IInvocationResult result = new InvocationResult();
87         IModuleResult moduleResult = result.getOrCreateModule(
88                 mContext.getResources().getString(R.string.module_id));
89 
90         // Collect build fields available in API level 21
91         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
92             abis = TextUtils.join(",", Build.SUPPORTED_ABIS);
93             abis32 = TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS);
94             abis64 = TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS);
95         }
96 
97         // Collect build fields available in API level 23
98         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
99             versionBaseOs = Build.VERSION.BASE_OS;
100             versionSecurityPatch = Build.VERSION.SECURITY_PATCH;
101         }
102 
103         versionRelease = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
104                 ? Build.VERSION.RELEASE_OR_CODENAME : Build.VERSION.RELEASE;
105 
106         // at the time of writing, the build class has no REFERENCE_FINGERPRINT property
107         String referenceFingerprint = null;
108 
109         DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo(Build.CPU_ABI,
110                 Build.CPU_ABI2, abis, abis32, abis64, Build.BOARD, Build.BRAND, Build.DEVICE,
111                 Build.FINGERPRINT, null, Build.ID, Build.MANUFACTURER, Build.MODEL, Build.PRODUCT,
112                 referenceFingerprint, Build.getSerial(), Build.TAGS, Build.TYPE, versionBaseOs,
113                 versionRelease, Integer.toString(Build.VERSION.SDK_INT),
114                 versionSecurityPatch, Build.VERSION.INCREMENTAL);
115 
116         // add device properties to the result with a prefix tag for each key
117         for (Entry<String, String> entry :
118                 devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) {
119             String entryValue = entry.getValue();
120             if (entryValue != null) {
121                 result.addInvocationInfo(entry.getKey(), entry.getValue());
122             }
123         }
124 
125         // Get test result, including test name, result, report log, details and histories.
126         getCaseResult(moduleResult);
127         getHostCaseResult(moduleResult);
128 
129         return result;
130     }
131 
getContents()132     String getContents() {
133         // TODO: remove getContents and everything that depends on it
134         return "Report viewing is deprecated. See contents on the SD Card.";
135     }
136 
137     /**
138      * Get case results per test, including result, report log, details and histories.
139      *
140      * @param IModuleResult The module result bound with {@link IInvocationResult}.
141      */
getCaseResult(IModuleResult moduleResult)142     private void getCaseResult(IModuleResult moduleResult) {
143         ICaseResult caseResult = moduleResult.getOrCreateResult(TEST_CASE_NAME);
144         String hostTestTitle = mContext.getResources().getString(R.string.host_tests_title);
145         int notExecutedCount = 0;
146         for (DisplayMode mode: DisplayMode.values()) {
147             String displayMode = mode.toString();
148             int count = mAdapter.getCount(displayMode);
149             for (int i = 0; i < count; i++) {
150                 TestListItem item = mAdapter.getItem(displayMode, i);
151                 String testName = item.testName;
152                 if (item.isTest() && !item.title.equals(hostTestTitle)) {
153                     createTestResult(caseResult, testName, testName);
154                     if (mAdapter.getTestResult(testName) == TestResult.TEST_RESULT_NOT_EXECUTED) {
155                         ++notExecutedCount;
156                     }
157                 }
158             }
159         }
160         moduleResult.setDone(true);
161         moduleResult.setNotExecuted(notExecutedCount);
162     }
163 
164     /**
165      * Get case results per host test, including result, report log, details and histories.
166      *
167      * @param moduleResult The module result bound with {@link IInvocationResult}.
168      */
getHostCaseResult(IModuleResult moduleResult)169     private void getHostCaseResult(IModuleResult moduleResult) {
170         ICaseResult caseResult = moduleResult.getOrCreateResult(HOST_TEST_CASE_NAME);
171         for (String module : mContext.getResources().getStringArray(R.array.host_modules)) {
172             for (String testName : mAdapter.getTestResultNames()) {
173                 if (!testName.startsWith(module)) {
174                     continue;
175                 }
176                 // Split Module and Class#TestCase
177                 String[] parts = testName.split(HostTestsActivity.TEST_ID_SEPARATOR, 2);
178                 if (parts.length < 2 || !parts[1].contains(HostTestsActivity.TEST_ID_SEPARATOR)) {
179                     continue;
180                 }
181                 createTestResult(caseResult, testName, parts[1]);
182             }
183         }
184     }
185 
createTestResult(ICaseResult caseResult, String testName, String resultName)186     private void createTestResult(ICaseResult caseResult, String testName, String resultName) {
187         ITestResult currentTestResult = caseResult.getOrCreateResult(resultName);
188         TestStatus resultStatus = getTestResultStatus(mAdapter.getTestResult(testName));
189 
190         currentTestResult.setResultStatus(resultStatus);
191         // TODO: report test details with Extended Device Info (EDI) or CTS metrics
192         String details = mAdapter.getTestDetails(testName);
193         currentTestResult.setMessage(details);
194 
195         ReportLog reportLog = mAdapter.getReportLog(testName);
196         if (reportLog != null) {
197             currentTestResult.setReportLog(reportLog);
198         }
199 
200         TestResultHistoryCollection historyCollection = mAdapter.getHistoryCollection(testName);
201         if (historyCollection != null) {
202             List<TestResultHistory> leafTestHistories = getTestResultHistories(historyCollection);
203             currentTestResult.setTestResultHistories(leafTestHistories);
204         }
205 
206         TestScreenshotsMetadata screenshotsMetadata = mAdapter.getScreenshotsMetadata(testName);
207         if (screenshotsMetadata != null) {
208             currentTestResult.setTestScreenshotsMetadata(screenshotsMetadata);
209         }
210     }
211 
getTestResultStatus(int testResult)212     private TestStatus getTestResultStatus(int testResult) {
213         switch (testResult) {
214             case TestResult.TEST_RESULT_PASSED:
215                 return TestStatus.PASS;
216 
217             case TestResult.TEST_RESULT_FAILED:
218                 return TestStatus.FAIL;
219 
220             case TestResult.TEST_RESULT_NOT_EXECUTED:
221                 return null;
222 
223             default:
224                 throw new IllegalArgumentException("Unknown test result: " + testResult);
225         }
226     }
227 
228     /**
229      * Get test histories per test by filtering out non-leaf histories.
230      *
231      * @param TestResultHistoryCollection The raw test history collection.
232      * @return A list containing test result histories per test.
233      */
234     @SuppressWarnings("ReturnValueIgnored")
getTestResultHistories( TestResultHistoryCollection historyCollection)235     private List<TestResultHistory> getTestResultHistories(
236         TestResultHistoryCollection historyCollection) {
237         // Get non-terminal prefixes.
238         Set<String> prefixes = new HashSet<>();
239         for (TestResultHistory history : historyCollection.asSet()) {
240             Arrays.stream(history.getTestName().split(":")).reduce(
241                 (total, current) -> {
242                     prefixes.add(total);
243                     return total + ":" + current;
244                 });
245         }
246 
247         // Filter out non-leaf test histories.
248         List<TestResultHistory> leafTestHistories =
249             new ArrayList<TestResultHistory>();
250         for (TestResultHistory history : historyCollection.asSet()) {
251             if (!prefixes.contains(history.getTestName())) {
252                 leafTestHistories.add(history);
253             }
254         }
255         return leafTestHistories;
256     }
257 }
258