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 package com.android.cts.tradefed.result; 17 18 import com.android.cts.tradefed.build.CtsBuildProvider; 19 import com.android.tradefed.log.LogUtil.CLog; 20 21 import org.kxml2.io.KXmlSerializer; 22 import org.xmlpull.v1.XmlPullParser; 23 import org.xmlpull.v1.XmlPullParserException; 24 25 import java.io.IOException; 26 import java.net.InetAddress; 27 import java.net.UnknownHostException; 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.Collections; 31 import java.util.Comparator; 32 import java.util.LinkedHashMap; 33 import java.util.List; 34 import java.util.Map; 35 36 /** 37 * Data structure for the detailed CTS test results. 38 * <p/> 39 * Can deserialize results for test packages from XML 40 */ 41 class TestResults extends AbstractXmlPullParser { 42 43 private static final String ns = CtsXmlResultReporter.ns; 44 45 // XML constants 46 static final String SUMMARY_TAG = "Summary"; 47 static final String PASS_ATTR = "pass"; 48 static final String TIMEOUT_ATTR = "timeout"; 49 static final String NOT_EXECUTED_ATTR = "notExecuted"; 50 static final String FAILED_ATTR = "failed"; 51 52 private Map<String, TestPackageResult> mPackageMap = 53 new LinkedHashMap<String, TestPackageResult>(); 54 private DeviceInfoResult mDeviceInfo = new DeviceInfoResult(); 55 56 /** 57 * {@inheritDoc} 58 */ 59 @Override 60 void parse(XmlPullParser parser) throws XmlPullParserException, IOException { 61 int eventType = parser.getEventType(); 62 while (eventType != XmlPullParser.END_DOCUMENT) { 63 if (eventType == XmlPullParser.START_TAG && parser.getName().equals( 64 DeviceInfoResult.TAG)) { 65 mDeviceInfo.parse(parser); 66 } 67 if (eventType == XmlPullParser.START_TAG && parser.getName().equals( 68 TestPackageResult.TAG)) { 69 TestPackageResult pkg = new TestPackageResult(); 70 pkg.parse(parser); 71 if (pkg.getAppPackageName() != null) { 72 mPackageMap.put(pkg.getAppPackageName(), pkg); 73 } else { 74 CLog.w("Found package with no app package name"); 75 } 76 } 77 eventType = parser.next(); 78 } 79 } 80 81 /** 82 * @return the list of {@link TestPackageResult}. 83 */ 84 public Collection<TestPackageResult> getPackages() { 85 return mPackageMap.values(); 86 } 87 88 /** 89 * Count the number of tests with given status 90 * @param pass 91 * @return 92 */ 93 public int countTests(CtsTestStatus status) { 94 int total = 0; 95 for (TestPackageResult result : mPackageMap.values()) { 96 total += result.countTests(status); 97 } 98 return total; 99 } 100 101 /** 102 * Serialize the test results to XML. 103 * 104 * @param serializer 105 * @throws IOException 106 */ 107 public void serialize(KXmlSerializer serializer) throws IOException { 108 mDeviceInfo.serialize(serializer); 109 serializeHostInfo(serializer); 110 serializeTestSummary(serializer); 111 // sort before serializing 112 List<TestPackageResult> pkgs = new ArrayList<TestPackageResult>(mPackageMap.values()); 113 Collections.sort(pkgs, new PkgComparator()); 114 for (TestPackageResult r : pkgs) { 115 r.serialize(serializer); 116 } 117 } 118 119 /** 120 * Output the host info XML. 121 * 122 * @param serializer 123 */ 124 private void serializeHostInfo(KXmlSerializer serializer) throws IOException { 125 serializer.startTag(ns, "HostInfo"); 126 127 String hostName = ""; 128 try { 129 hostName = InetAddress.getLocalHost().getHostName(); 130 } catch (UnknownHostException ignored) {} 131 serializer.attribute(ns, "name", hostName); 132 133 serializer.startTag(ns, "Os"); 134 serializer.attribute(ns, "name", System.getProperty("os.name")); 135 serializer.attribute(ns, "version", System.getProperty("os.version")); 136 serializer.attribute(ns, "arch", System.getProperty("os.arch")); 137 serializer.endTag(ns, "Os"); 138 139 serializer.startTag(ns, "Java"); 140 serializer.attribute(ns, "name", System.getProperty("java.vendor")); 141 serializer.attribute(ns, "version", System.getProperty("java.version")); 142 serializer.endTag(ns, "Java"); 143 144 serializer.startTag(ns, "Cts"); 145 serializer.attribute(ns, "version", CtsBuildProvider.CTS_BUILD_VERSION); 146 // TODO: consider outputting other tradefed options here 147 serializer.startTag(ns, "IntValue"); 148 serializer.attribute(ns, "name", "testStatusTimeoutMs"); 149 // TODO: create a constant variable for testStatusTimeoutMs value. Currently it cannot be 150 // changed 151 serializer.attribute(ns, "value", "600000"); 152 serializer.endTag(ns, "IntValue"); 153 serializer.endTag(ns, "Cts"); 154 155 serializer.endTag(ns, "HostInfo"); 156 } 157 158 /** 159 * Output the test summary XML containing summary totals for all tests. 160 * 161 * @param serializer 162 * @throws IOException 163 */ 164 private void serializeTestSummary(KXmlSerializer serializer) throws IOException { 165 serializer.startTag(ns, SUMMARY_TAG); 166 serializer.attribute(ns, FAILED_ATTR, Integer.toString(countTests(CtsTestStatus.FAIL))); 167 serializer.attribute(ns, NOT_EXECUTED_ATTR, 168 Integer.toString(countTests(CtsTestStatus.NOT_EXECUTED))); 169 // ignore timeouts - these are reported as errors 170 serializer.attribute(ns, TIMEOUT_ATTR, "0"); 171 serializer.attribute(ns, PASS_ATTR, Integer.toString(countTests(CtsTestStatus.PASS))); 172 serializer.endTag(ns, SUMMARY_TAG); 173 } 174 175 private static class PkgComparator implements Comparator<TestPackageResult> { 176 177 /** 178 * {@inheritDoc} 179 */ 180 @Override 181 public int compare(TestPackageResult o1, TestPackageResult o2) { 182 return o1.getAppPackageName().compareTo(o2.getAppPackageName()); 183 } 184 185 } 186 187 /** 188 * Return existing package with given app package name. If not found, create a new one. 189 * @param name 190 * @return 191 */ 192 public TestPackageResult getOrCreatePackage(String appPackageName) { 193 TestPackageResult pkgResult = mPackageMap.get(appPackageName); 194 if (pkgResult == null) { 195 pkgResult = new TestPackageResult(); 196 pkgResult.setAppPackageName(appPackageName); 197 mPackageMap.put(appPackageName, pkgResult); 198 } 199 return pkgResult; 200 } 201 202 /** 203 * Populate the results with collected device info metrics. 204 * @param runMetrics 205 */ 206 public void populateDeviceInfoMetrics(Map<String, String> runMetrics) { 207 mDeviceInfo.populateMetrics(runMetrics); 208 } 209 } 210