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