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 69 private final Context mContext; 70 71 private final TestListAdapter mAdapter; 72 TestResultsReport(Context context, TestListAdapter adapter)73 TestResultsReport(Context context, TestListAdapter adapter) { 74 this.mContext = context; 75 this.mAdapter = adapter; 76 } 77 generateResult()78 IInvocationResult generateResult() { 79 String abis = null; 80 String abis32 = null; 81 String abis64 = null; 82 String versionBaseOs = null; 83 String versionSecurityPatch = null; 84 String versionRelease = null; 85 IInvocationResult result = new InvocationResult(); 86 IModuleResult moduleResult = result.getOrCreateModule( 87 mContext.getResources().getString(R.string.module_id)); 88 89 // Collect build fields available in API level 21 90 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 91 abis = TextUtils.join(",", Build.SUPPORTED_ABIS); 92 abis32 = TextUtils.join(",", Build.SUPPORTED_32_BIT_ABIS); 93 abis64 = TextUtils.join(",", Build.SUPPORTED_64_BIT_ABIS); 94 } 95 96 // Collect build fields available in API level 23 97 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 98 versionBaseOs = Build.VERSION.BASE_OS; 99 versionSecurityPatch = Build.VERSION.SECURITY_PATCH; 100 } 101 102 versionRelease = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) 103 ? Build.VERSION.RELEASE_OR_CODENAME : Build.VERSION.RELEASE; 104 105 // at the time of writing, the build class has no REFERENCE_FINGERPRINT property 106 String referenceFingerprint = null; 107 108 DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo(Build.CPU_ABI, 109 Build.CPU_ABI2, abis, abis32, abis64, Build.BOARD, Build.BRAND, Build.DEVICE, 110 Build.FINGERPRINT, null, Build.ID, Build.MANUFACTURER, Build.MODEL, Build.PRODUCT, 111 referenceFingerprint, Build.getSerial(), Build.TAGS, Build.TYPE, versionBaseOs, 112 versionRelease, Integer.toString(Build.VERSION.SDK_INT), 113 versionSecurityPatch, Build.VERSION.INCREMENTAL); 114 115 // add device properties to the result with a prefix tag for each key 116 for (Entry<String, String> entry : 117 devicePropertyInfo.getPropertytMapWithPrefix(PREFIX_TAG).entrySet()) { 118 String entryValue = entry.getValue(); 119 if (entryValue != null) { 120 result.addInvocationInfo(entry.getKey(), entry.getValue()); 121 } 122 } 123 124 // Get test result, including test name, result, report log, details and histories. 125 getCaseResult(moduleResult); 126 127 return result; 128 } 129 getContents()130 String getContents() { 131 // TODO: remove getContents and everything that depends on it 132 return "Report viewing is deprecated. See contents on the SD Card."; 133 } 134 135 /** 136 * Get case results per test, including result, report log, details and histories. 137 * 138 * @param IModuleResult The module result bound with {@link IInvocationResult}. 139 */ getCaseResult(IModuleResult moduleResult)140 private void getCaseResult(IModuleResult moduleResult) { 141 ICaseResult caseResult = moduleResult.getOrCreateResult(TEST_CASE_NAME); 142 int notExecutedCount = 0; 143 for (DisplayMode mode: DisplayMode.values()) { 144 String displayMode = mode.toString(); 145 int count = mAdapter.getCount(displayMode); 146 for (int i = 0; i < count; i++) { 147 TestListItem item = mAdapter.getItem(displayMode, i); 148 if (item.isTest()) { 149 ITestResult currentTestResult = caseResult.getOrCreateResult(item.testName); 150 TestStatus resultStatus = 151 getTestResultStatus(mAdapter.getTestResult(displayMode, i)); 152 if (resultStatus == null) { 153 ++notExecutedCount; 154 } 155 currentTestResult.setResultStatus(resultStatus); 156 // TODO: report test details with Extended Device Info (EDI) or CTS metrics 157 String details = mAdapter.getTestDetails(displayMode, i); 158 currentTestResult.setMessage(details); 159 160 ReportLog reportLog = mAdapter.getReportLog(displayMode, i); 161 if (reportLog != null) { 162 currentTestResult.setReportLog(reportLog); 163 } 164 165 TestResultHistoryCollection historyCollection = mAdapter 166 .getHistoryCollection(displayMode, i); 167 if (historyCollection != null) { 168 List<TestResultHistory> leafTestHistories = 169 getTestResultHistories(historyCollection); 170 currentTestResult.setTestResultHistories(leafTestHistories); 171 } 172 173 TestScreenshotsMetadata screenshotsMetadata = mAdapter 174 .getScreenshotsMetadata(displayMode, i); 175 if (screenshotsMetadata != null) { 176 currentTestResult.setTestScreenshotsMetadata(screenshotsMetadata); 177 } 178 } 179 } 180 } 181 moduleResult.setDone(true); 182 moduleResult.setNotExecuted(notExecutedCount); 183 } 184 getTestResultStatus(int testResult)185 private TestStatus getTestResultStatus(int testResult) { 186 switch (testResult) { 187 case TestResult.TEST_RESULT_PASSED: 188 return TestStatus.PASS; 189 190 case TestResult.TEST_RESULT_FAILED: 191 return TestStatus.FAIL; 192 193 case TestResult.TEST_RESULT_NOT_EXECUTED: 194 return null; 195 196 default: 197 throw new IllegalArgumentException("Unknown test result: " + testResult); 198 } 199 } 200 201 /** 202 * Get test histories per test by filtering out non-leaf histories. 203 * 204 * @param TestResultHistoryCollection The raw test history collection. 205 * @return A list containing test result histories per test. 206 */ 207 @SuppressWarnings("ReturnValueIgnored") getTestResultHistories( TestResultHistoryCollection historyCollection)208 private List<TestResultHistory> getTestResultHistories( 209 TestResultHistoryCollection historyCollection) { 210 // Get non-terminal prefixes. 211 Set<String> prefixes = new HashSet<>(); 212 for (TestResultHistory history : historyCollection.asSet()) { 213 Arrays.stream(history.getTestName().split(":")).reduce( 214 (total, current) -> { 215 prefixes.add(total); 216 return total + ":" + current; 217 }); 218 } 219 220 // Filter out non-leaf test histories. 221 List<TestResultHistory> leafTestHistories = 222 new ArrayList<TestResultHistory>(); 223 for (TestResultHistory history : historyCollection.asSet()) { 224 if (!prefixes.contains(history.getTestName())) { 225 leafTestHistories.add(history); 226 } 227 } 228 return leafTestHistories; 229 } 230 } 231