Merge "Modify cts-tradefed xml generator to match current schema." into honeycomb
diff --git a/tools/tradefed-host/Android.mk b/tools/tradefed-host/Android.mk
index c1e5c54..ceec5db 100644
--- a/tools/tradefed-host/Android.mk
+++ b/tools/tradefed-host/Android.mk
@@ -18,7 +18,7 @@
# Only compile source java files in this lib.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_RESOURCE_DIRS := res
+LOCAL_JAVA_RESOURCE_DIRS := res ../host/src/res
LOCAL_MODULE := cts-tradefed
LOCAL_MODULE_TAGS := optional
diff --git a/tools/tradefed-host/etc/cts-tradefed b/tools/tradefed-host/etc/cts-tradefed
index 82eebe7..8bbce80 100755
--- a/tools/tradefed-host/etc/cts-tradefed
+++ b/tools/tradefed-host/etc/cts-tradefed
@@ -52,7 +52,7 @@
echo "Unrecognized OS"
exit
fi;
- CTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/cts/android-cts
+ CTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/cts
if [ ! -d ${CTS_ROOT} ]; then
echo "Could not find $CTS_ROOT in Android build environment. Try 'make cts'"
exit
@@ -61,10 +61,10 @@
if [ -z ${CTS_ROOT} ]; then
# assume we're in an extracted cts install
- CTS_ROOT="$(dirname $0)/.."
+ CTS_ROOT="$(dirname $0)/../.."
fi;
-JAR_DIR=${CTS_ROOT}/tools
+JAR_DIR=${CTS_ROOT}/android-cts/tools
JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar"
for JAR in $JARS; do
diff --git a/tools/tradefed-host/res/result/cts_result.css b/tools/tradefed-host/res/result/cts_result.css
deleted file mode 100644
index d7ce510..0000000
--- a/tools/tradefed-host/res/result/cts_result.css
+++ /dev/null
@@ -1,234 +0,0 @@
-/* Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-body {
- font-family:arial,sans-serif;
- color:#000;
- font-size:13px;
- color:#333;
- padding:10;
- margin:10;
-}
-
-table {
- font-size:1em;
- margin:0 0 1em;
- padding:0;
- border-collapse:collapse;
- border-width:0;
- empty-cells:show;
- width: 95%;
-}
-
-/* Report logo and device name */
-#title table {
- padding:5px;
- border-width: 0px;
- margin-left:auto;
- margin-right:auto;
- vertical-align:middle;
-}
-
-/* Device and test plan summary below the title */
-#summary table {
- background-color: rgb(212, 233, 169);
- -moz-border-radius:5px;
- border-radius:5px;
- padding:5px;
- border-color: #A5C639 #A5C639 #A5C639 #A5C639;
- border-width: 0px 0px 0px 0px;
- margin-left:auto;
- margin-right:auto;
- width:80%;
-}
-
-#summary th {
- background-color: #A5C639;
- font-size:1.2em;
- height: 2em;
- width: 50%;
-}
-
-#summary td {
- border-width: 0px 0px 0px 0px;
- border-color: gray;
- border-style: inset;
- font-size:1em;
- vertical-align: top;
-}
-
-#summaryinfo table {
- background-color: rgb(212, 233, 169);
- padding:5px;
- border-width:0;
- margin-left:auto;
- margin-right:auto;
-}
-
-#summaryinfo td {
- padding:1px;
- border-width: 0px 0px 0px 0px;
- vertical-align: top;
-}
-
-/* The test summary */
-#testsummary table {
- background-color: rgb(212, 233, 169);
- padding:5px;
- border-width:1;
- border-color: #A5C639;
- margin-left:auto;
- margin-right:auto;
- width: 40%;
-}
-
-#testsummary th {
- background-color: #A5C639;
- border-width: 1px;
- border-color: gray;
- border-style: outset;
- height: 2em;
-}
-
-#testsummary td {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: center;
-}
-
-/* The test details */
-#testdetail table {
- background-color: rgb(212, 233, 169);
- padding:5px;
- border-width:1;
- border-color: #A5C639;
- margin-left:auto;
- margin-right:auto;
- width: 95%;
- table-layout:fixed;
- vertical-align: top;
-}
-
-#testdetail th {
- background-color: #A5C639;
- border-width: 1px;
- border-color: gray;
- border-style: outset;
- height: 2em;
-}
-
-#testdetail td {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: left;
- vertical-align: top;
- padding:1;
-}
-
-/* The test package name */
-#none table {
- border-width:0;
- border-color: white;
- background-color: white;
- text-align:left;
- border-collapse:collapse;
-}
-
-#none td {
- border-width:0;
- border-color: white;
- background-color: white;
- text-align:left;
- border-collapse:collapse;
- font-weight:bold;
-}
-
-/* Test cell details */
-td.failed {
- background-color: #FA5858;
- font-weight:bold;
- vertical-align: top;
- text-align: center;
-}
-
-td.failuredetails {
- text-align: left;
-}
-
-td.pass {
- text-align: center;
- margin-left:auto;
- margin-right:auto;
-}
-
-td.timeout, td.omitted, td.notExecuted {
- background-color: #A5C639;
- vertical-align: top;
- text-align: center;
-}
-
-td.testname {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: left;
- vertical-align: top;
- padding:1;
- overflow:hidden;
-}
-
-td.testcase {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: left;
- vertical-align: top;
- padding:1;
- overflow:hidden;
- font-weight:bold;
-}
-
-td.testcasespacer {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: left;
- vertical-align: top;
- padding:1;
- overflow:hidden;
- font-weight:bold;
-}
-
-td.testsuite {
- border-width: 1px;
- border-color: #A5C639;
- border-style: outset;
- text-align: left;
- vertical-align: top;
- padding:1;
- overflow:hidden;
- font-weight:bold;
-}
-
-#details {
- white-space: pre-wrap; /* css-3 */
- white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
- white-space: -pre-wrap; /* Opera 4-6 */
- white-space: -o-pre-wrap; /* Opera 7 */
- word-wrap: break-word; /* Internet Explorer 5.5+ */
- overflow:auto;
-}
diff --git a/tools/tradefed-host/res/result/cts_result.xsd b/tools/tradefed-host/res/result/cts_result.xsd
deleted file mode 100644
index f2fc3a8..0000000
--- a/tools/tradefed-host/res/result/cts_result.xsd
+++ /dev/null
@@ -1,192 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- -->
-
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
- targetNamespace="http://compatibility.android.com/cts_result/2.0"
- xmlns="http://compatibility.android.com/cts_result/2.0"
- elementFormDefault="qualified">
-
-<xs:element name="TestResult">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="DeviceInfo" type="deviceInfoType"/>
- <xs:element name="HostInfo" type="hostInfoType"/>
- <xs:element name="Summary" type="summaryType"/>
- <xs:element name="TestPackage" type="testPackageType" maxOccurs="unbounded" minOccurs="1"/>
- </xs:sequence>
- <xs:attribute name="starttime" type="xs:string"/>
- <xs:attribute name="endtime" type="xs:string"/>
- <xs:attribute name="testPlan" type="xs:string"/>
- <xs:attribute name="version" type="xs:string"/>
- <xs:attribute name="profile" type="xs:string"/>
- </xs:complexType>
-</xs:element>
-
-<xs:complexType name="deviceInfoType">
- <xs:sequence>
- <xs:element name="Screen">
- <xs:complexType>
- <xs:attribute name="resolution" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="PhoneSubInfo">
- <xs:complexType>
- <xs:attribute name="subscriberId" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="BuildInfo">
- <xs:complexType>
- <xs:attribute name="Xdpi" type="xs:decimal"/>
- <xs:attribute name="Ydpi" type="xs:decimal"/>
- <xs:attribute name="androidPlatformVersion" type="xs:integer"/>
- <xs:attribute name="buildID" type="xs:string"/>
- <xs:attribute name="buildName" type="xs:string"/>
- <xs:attribute name="buildVersion" type="xs:string"/>
- <xs:attribute name="build_board" type="xs:string"/>
- <xs:attribute name="build_brand" type="xs:string"/>
- <xs:attribute name="build_device" type="xs:string"/>
- <xs:attribute name="build_fingerprint" type="xs:string"/>
- <xs:attribute name="build_model" type="xs:string"/>
- <xs:attribute name="build_type" type="xs:string"/>
- <xs:attribute name="deviceID" type="xs:string"/>
- <xs:attribute name="imei" type="xs:integer"/>
- <xs:attribute name="imsi" type="xs:integer"/>
- <xs:attribute name="keypad" type="xs:string"/>
- <xs:attribute name="locales" type="xs:string"/>
- <xs:attribute name="navigation" type="xs:string"/>
- <xs:attribute name="network" type="xs:string"/>
- <xs:attribute name="touch" type="xs:string"/>
- <xs:attribute name="openGlEsVersion" type="xs:string"/>
- <xs:attribute name="build_abi" type="xs:string"/>
- <xs:attribute name="build_abi2" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="FeatureInfo" type="featureInfoType"/>
- <xs:element name="ProcessInfo" type="processInfoType"/>
- </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="hostInfoType">
- <xs:sequence>
- <xs:element name="Os">
- <xs:complexType>
- <xs:attribute name="arch" type="xs:string"/>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="version" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Java">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="version" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- <xs:element name="Cts">
- <xs:complexType>
- <xs:sequence>
- <xs:element name="IntValue" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string"/>
- <xs:attribute name="value" type="xs:integer"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="version" type="xs:string"/>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="name" type="xs:string"/>
-</xs:complexType>
-
-<xs:complexType name="featureInfoType">
- <xs:sequence>
- <xs:element name="Feature" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string" />
- <xs:attribute name="type" type="xs:string" />
- <xs:attribute name="available" type="xs:string" />
- </xs:complexType>
- </xs:element>
- </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="processInfoType">
- <xs:sequence>
- <xs:element name="Process" minOccurs="0" maxOccurs="unbounded">
- <xs:complexType>
- <xs:attribute name="name" type="xs:string" />
- <xs:attribute name="uid" type="xs:integer" />
- </xs:complexType>
- </xs:element>
- </xs:sequence>
-</xs:complexType>
-
-<xs:complexType name="summaryType">
- <xs:attribute name="failed" type="xs:integer"/>
- <xs:attribute name="notExecuted" type="xs:integer"/>
- <xs:attribute name="pass" type="xs:integer"/>
- <xs:attribute name="timeout" type="xs:integer"/>
- <xs:attribute name="omitted" type="xs:integer"/>
- <xs:attribute name="total" type="xs:integer"/>
-</xs:complexType>
-
-<xs:complexType name="testPackageType">
- <xs:complexContent>
- <xs:extension base="summaryType">
- <xs:sequence>
- <xs:element name="TestCase" type="testCaseType" />
- </xs:sequence>
- <xs:attribute name="digest" type="xs:hexBinary" />
- <xs:attribute name="name" type="xs:string" use="required" />
- <xs:attribute name="runtime" type="xs:string" />
- </xs:extension>
- </xs:complexContent>
-</xs:complexType>
-
-<xs:complexType name="testCaseType">
- <xs:sequence>
- <xs:element name="Test" type="testType" minOccurs="0" maxOccurs="unbounded"/>
- </xs:sequence>
- <xs:attribute name="name" type="xs:string" use="required"/>
-</xs:complexType>
-
-<xs:complexType name="testType">
- <xs:sequence>
- <xs:element name="FailedScene" minOccurs="0" maxOccurs="1">
- <xs:complexType>
- <xs:simpleContent>
- <xs:extension base="xs:string">
- <xs:attribute name="message" type="xs:string" />
- </xs:extension>
- </xs:simpleContent>
- </xs:complexType>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="name" type="xs:string" use="required"/>
- <xs:attribute name="result" type="resultType" use="required"/>
-</xs:complexType>
-
-<xs:simpleType name="resultType">
- <xs:restriction base="xs:string">
- <xs:enumeration value="pass"/>
- <xs:enumeration value="fail"/>
- <xs:enumeration value="timeout"/>
- <xs:enumeration value="notExecuted"/>
- <xs:enumeration value="omitted"/>
- </xs:restriction>
-</xs:simpleType>
-</xs:schema>
diff --git a/tools/tradefed-host/res/result/cts_result.xsl b/tools/tradefed-host/res/result/cts_result.xsl
deleted file mode 100644
index cb220e1..0000000
--- a/tools/tradefed-host/res/result/cts_result.xsl
+++ /dev/null
@@ -1,513 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp " "> ]>
-<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
-
- <xsl:template match="/">
-
- <html>
- <STYLE type="text/css">
- @import "cts_result.css";
- </STYLE>
-
- <body>
- <!-- Title of the Report -->
- <DIV id="title">
- <TABLE>
- <TR>
- <TD width="40%" align="left"><img src="logo.gif"></img></TD>
- <TD width="60%" align="left">
- <h1>Test Report for <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_model"/> -
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@deviceID"/>
- </h1>
- </TD>
- </TR>
- </TABLE>
- </DIV>
- <img src="newrule-green.png" align="left"></img>
-
- <br></br>
- <br></br>
-
- <!-- Header with phone and plan information -->
- <DIV id="summary">
- <TABLE width="90%" frame="none">
- <TR>
- <TH>Device Information</TH>
- <TH>Test Summary</TH>
- </TR>
-
- <TR>
- <TD>
- <!-- Device information -->
- <div id="summaryinfo">
- <TABLE width="75%">
- <TR>
- <TD class="rowtitle">Build Model</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_model"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Build Name</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildName"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Device ID</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@deviceID"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Firmware Version</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildVersion"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Firmware Build Number</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@buildID"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Build Fingerprint</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@build_fingerprint"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Build ABI</TD>
- <TD>
- <xsl:value-of
- select="TestResult/DeviceInfo/BuildInfo/@build_abi"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Build ABI2</TD>
- <TD>
- <xsl:value-of
- select="TestResult/DeviceInfo/BuildInfo/@build_abi2"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Android Platform Version</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@androidPlatformVersion"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Supported Locales</TD>
- <TD>
- <xsl:call-template name="formatDelimitedString">
- <xsl:with-param name="string" select="TestResult/DeviceInfo/BuildInfo/@locales"/>
- </xsl:call-template>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Screen size</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/Screen/@resolution"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Phone number</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/PhoneSubInfo/@subscriberId"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">x dpi</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@Xdpi"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">y dpi</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@Ydpi"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Touch</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@touch"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Navigation</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@navigation"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Keypad</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@keypad"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Network</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@network"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">IMEI</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@imei"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">IMSI</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@imsi"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Open GL ES Version</TD>
- <TD>
- <xsl:value-of select="TestResult/DeviceInfo/BuildInfo/@openGlEsVersion"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Features</TD>
- <TD>
- <xsl:for-each select="TestResult/DeviceInfo/FeatureInfo/Feature[@type='sdk']">
- <xsl:text>[</xsl:text>
- <xsl:choose>
- <xsl:when test="@available = 'true'">
- <xsl:text>X</xsl:text>
- </xsl:when>
- <xsl:otherwise>
- <xsl:text>_</xsl:text>
- </xsl:otherwise>
- </xsl:choose>
- <xsl:text>] </xsl:text>
-
- <xsl:value-of select="@name" />
- <br />
- </xsl:for-each>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Other Features</TD>
- <TD>
- <UL>
- <xsl:for-each select="TestResult/DeviceInfo/FeatureInfo/Feature[@type='other']">
- <LI><xsl:value-of select="@name" /></LI>
- </xsl:for-each>
- </UL>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Root Processes</TD>
- <TD>
- <UL>
- <xsl:for-each select="TestResult/DeviceInfo/ProcessInfo/Process[@uid='0']">
- <LI><xsl:value-of select="@name" /></LI>
- </xsl:for-each>
- </UL>
- </TD>
- </TR>
- </TABLE>
- </div>
- </TD>
-
- <!-- plan information -->
- <TD>
- <div id="summaryinfo">
- <TABLE width="75%">
- <TR>
- <TD class="rowtitle">CTS version</TD>
- <TD>
- <xsl:value-of select="TestResult/HostInfo/Cts/@version"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Test timeout</TD>
- <TD>
- <xsl:value-of select="TestResult/HostInfo/Cts/IntValue[@name='testStatusTimeoutMs']/@value" /> ms
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Host Info</TD>
- <TD>
- <xsl:value-of select="TestResult/HostInfo/@name"/>
- (<xsl:value-of select="TestResult/HostInfo/Os/@name"/> -
- <xsl:value-of select="TestResult/HostInfo/Os/@version"/>)
- </TD>
- </TR>
- <TR><TD><BR></BR></TD><TD></TD></TR>
- <TR>
- <TD class="rowtitle">Plan name</TD>
- <TD>
- <xsl:value-of select="TestResult/@testPlan"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Profile</TD>
- <TD>
- <xsl:value-of select="TestResult/@profile"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Start time</TD>
- <TD>
- <xsl:value-of select="TestResult/@starttime"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">End time</TD>
- <TD>
- <xsl:value-of select="TestResult/@endtime"/>
- </TD>
- </TR>
-
- <!-- Test Summary -->
- <TR><TD><BR></BR></TD><TD></TD></TR>
- <TR>
- <TD class="rowtitle">Tests Passed</TD>
- <TD>
- <xsl:value-of select="TestResult/Summary/@pass"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Tests Failed</TD>
- <TD>
- <xsl:value-of select="TestResult/Summary/@failed"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Tests Timed out</TD>
- <TD>
- <xsl:value-of select="TestResult/Summary/@timeout"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Tests Omitted</TD>
- <TD>
- <xsl:value-of select="TestResult/Summary/@omitted"/>
- </TD>
- </TR>
- <TR>
- <TD class="rowtitle">Tests Not Executed</TD>
- <TD>
- <xsl:value-of select="TestResult/Summary/@notExecuted"/>
- </TD>
- </TR>
- </TABLE>
- </div>
- </TD>
- </TR>
- </TABLE>
- </DIV>
-
- <!-- High level summary of test execution -->
- <h2 align="center">Test Summary by Package</h2>
- <DIV id="testsummary">
- <TABLE>
- <TR>
- <TH>Test Package</TH>
- <TH>Passed</TH>
- <TH>Failed</TH>
- <TH>Timed Out</TH>
- <TH>Total Tests</TH>
- </TR>
- <xsl:for-each select="TestResult/TestPackage">
- <TR>
- <TD>
- <xsl:variable name="href"><xsl:value-of select="@name"/></xsl:variable>
- <a href="#{$href}"><xsl:value-of select="@name"/></a>
- </TD>
- <TD>
- <xsl:value-of select="@pass"/>
- </TD>
- <TD>
- <xsl:value-of select="@failed"/>
- </TD>
- <TD>
- <xsl:value-of select="@timeout"/>
- </TD>
- <TD>
- <xsl:value-of select="@total"/>
- </TD>
- </TR>
- </xsl:for-each> <!-- end package -->
- </TABLE>
- </DIV>
-
- <!-- Details of all the executed tests -->
- <h2 align="center">Detailed Test Report</h2>
-
- <!-- test package -->
- <DIV id="testdetail">
- <xsl:for-each select="TestResult/TestPackage">
- <DIV id="none">
- <TABLE>
- <TR>
- <TD class="none" align="left">
- <xsl:variable name="href"><xsl:value-of select="@name"/></xsl:variable>
- <a name="{$href}">Compatibility Test Package: <xsl:value-of select="@name"/></a>
- </TD>
- </TR>
- </TABLE>
- </DIV>
-
- <TABLE>
- <TR>
- <TH width="25%">Test</TH>
- <TH width="7%">Result</TH>
- <TH width="68%">Failure Details</TH>
- </TR>
-
- <!-- test case -->
- <xsl:for-each select="TestCase">
-
- <!-- emit a blank row before every test suite name -->
- <xsl:if test="position()!=1">
- <TR> <TD class="testcasespacer" colspan="3"></TD> </TR>
- </xsl:if>
-
-
- <TR>
- <TD class="testcase" colspan="3">
- <xsl:value-of select="@name"/>
- </TD>
- </TR>
-
- <!-- test -->
- <xsl:for-each select="Test">
- <TR>
- <TD class="testname"> -- <xsl:value-of select="@name"/></TD>
-
- <!-- test results -->
- <xsl:choose>
- <xsl:when test="string(@KnownFailure)">
- <!-- "pass" indicates the that test actually passed (results have been inverted already) -->
- <xsl:if test="@result='pass'">
- <TD class="pass">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- known problem
- </div>
- </TD>
- <TD class="failuredetails"></TD>
- </xsl:if>
-
- <!-- "fail" indicates that a known failure actually passed (results have been inverted already) -->
- <xsl:if test="@result='fail'">
- <TD class="failed">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </TD>
- <TD class="failuredetails">
- <div id="details">
- A test that was a known failure actually passed. Please check.
- </div>
- </TD>
- </xsl:if>
- </xsl:when>
-
- <xsl:otherwise>
- <xsl:if test="@result='pass'">
- <TD class="pass">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </TD>
- <TD class="failuredetails"></TD>
- </xsl:if>
-
- <xsl:if test="@result='fail'">
- <TD class="failed">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </TD>
- <TD class="failuredetails">
- <div id="details">
- <xsl:value-of select="FailedScene/@message"/>
- </div>
- </TD>
- </xsl:if>
-
- <xsl:if test="@result='timeout'">
- <TD class="timeout">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- <TD class="failuredetails"></TD>
- </TD>
- </xsl:if>
-
- <xsl:if test="@result='omitted'">
- <TD class="omitted">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </TD>
- <TD class="failuredetails"></TD>
- </xsl:if>
-
- <xsl:if test="@result='notExecuted'">
- <TD class="notExecuted">
- <div style="text-align: center; margin-left:auto; margin-right:auto;">
- <xsl:value-of select="@result"/>
- </div>
- </TD>
- <TD class="failuredetails"></TD>
- </xsl:if>
- </xsl:otherwise>
- </xsl:choose>
- </TR> <!-- finished with a row -->
- </xsl:for-each> <!-- end test -->
- </xsl:for-each> <!-- end test case -->
- </TABLE>
- </xsl:for-each> <!-- end test package -->
- </DIV>
- </body>
- </html>
- </xsl:template>
-
- <!-- Take a delimited string and insert line breaks after a some number of elements. -->
- <xsl:template name="formatDelimitedString">
- <xsl:param name="string" />
- <xsl:param name="numTokensPerRow" select="10" />
- <xsl:param name="tokenIndex" select="1" />
- <xsl:if test="$string">
- <!-- Requires the last element to also have a delimiter after it. -->
- <xsl:variable name="token" select="substring-before($string, ';')" />
- <xsl:value-of select="$token" />
- <xsl:text> </xsl:text>
-
- <xsl:if test="$tokenIndex mod $numTokensPerRow = 0">
- <br />
- </xsl:if>
-
- <xsl:call-template name="formatDelimitedString">
- <xsl:with-param name="string" select="substring-after($string, ';')" />
- <xsl:with-param name="numTokensPerRow" select="$numTokensPerRow" />
- <xsl:with-param name="tokenIndex" select="$tokenIndex + 1" />
- </xsl:call-template>
- </xsl:if>
- </xsl:template>
-
-</xsl:stylesheet>
diff --git a/tools/tradefed-host/res/result/logo.gif b/tools/tradefed-host/res/result/logo.gif
deleted file mode 100644
index 61970b3..0000000
--- a/tools/tradefed-host/res/result/logo.gif
+++ /dev/null
Binary files differ
diff --git a/tools/tradefed-host/res/result/newrule-green.png b/tools/tradefed-host/res/result/newrule-green.png
deleted file mode 100644
index 10a4194..0000000
--- a/tools/tradefed-host/res/result/newrule-green.png
+++ /dev/null
Binary files differ
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index 4c29b01..fcbb5ee 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -26,7 +26,6 @@
import com.android.tradefed.result.LogDataType;
import com.android.tradefed.result.TestResult;
import com.android.tradefed.result.TestRunResult;
-import com.android.tradefed.result.TestResult.TestStatus;
import com.android.tradefed.targetsetup.IBuildInfo;
import com.android.tradefed.targetsetup.IFolderBuildInfo;
import com.android.tradefed.util.FileUtil;
@@ -44,7 +43,6 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -60,15 +58,14 @@
private static final String LOG_TAG = "CtsXmlResultReporter";
private static final String TEST_RESULT_FILE_NAME = "testResult.xml";
- private static final String CTS_RESULT_FILE_VERSION = "2.0";
+ private static final String CTS_RESULT_FILE_VERSION = "1.10";
private static final String CTS_VERSION = "99";
-
private static final String[] CTS_RESULT_RESOURCES = {"cts_result.xsl", "cts_result.css",
"logo.gif", "newrule-green.png"};
/** the XML namespace */
- private static final String ns = null;
+ static final String ns = null;
private static final String REPORT_DIR_NAME = "output-file-path";
@Option(name=REPORT_DIR_NAME, description="root file system path to directory to store xml " +
@@ -80,6 +77,8 @@
private String mStartTime;
+ private String mReportPath = "";
+
public void setReportDir(File reportDir) {
mReportDir = reportDir;
}
@@ -115,7 +114,17 @@
*/
@Override
public void testLog(String dataName, LogDataType dataType, InputStream dataStream) {
- // TODO: implement this
+ // save as zip file in report dir
+ // TODO: ensure uniqueness of file name
+ // TODO: use dataType.getFileExt() when its made public
+ String fileName = String.format("%s.%s", dataName, dataType.name().toLowerCase());
+ // TODO: consider compressing large files
+ File logFile = new File(mReportDir, fileName);
+ try {
+ FileUtil.writeToFile(dataStream, logFile);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, String.format("Failed to write log %s", logFile.getAbsolutePath()));
+ }
}
/**
@@ -171,7 +180,7 @@
serializer.endDocument();
// TODO: output not executed timeout omitted counts
String msg = String.format("XML test result file generated at %s. Total tests %d, " +
- "Failed %d, Error %d", reportDir.getAbsolutePath(), getNumTotalTests(),
+ "Failed %d, Error %d", getReportPath(), getNumTotalTests(),
getNumFailedTests(), getNumErrorTests());
Log.logAndDisplay(LogLevel.INFO, LOG_TAG, msg);
Log.logAndDisplay(LogLevel.INFO, LOG_TAG, String.format("Time: %s",
@@ -188,6 +197,10 @@
}
}
+ private String getReportPath() {
+ return mReportPath;
+ }
+
/**
* Output the results XML.
*
@@ -201,7 +214,6 @@
serializer.startTag(ns, "TestResult");
// TODO: output test plan and profile values
serializer.attribute(ns, "testPlan", "unknown");
- serializer.attribute(ns, "profile", "unknown");
serializer.attribute(ns, "starttime", startTime);
serializer.attribute(ns, "endtime", endTime);
serializer.attribute(ns, "version", CTS_RESULT_FILE_VERSION);
@@ -387,12 +399,10 @@
serializer.startTag(ns, "Summary");
serializer.attribute(ns, "failed", Integer.toString(getNumErrorTests() +
getNumFailedTests()));
- // TODO: output notExecuted, timeout, and omitted count
+ // TODO: output notExecuted, timeout count
serializer.attribute(ns, "notExecuted", "0");
serializer.attribute(ns, "timeout", "0");
- serializer.attribute(ns, "omitted", "0");
serializer.attribute(ns, "pass", Integer.toString(getNumPassedTests()));
- serializer.attribute(ns, "total", Integer.toString(getNumTotalTests()));
serializer.endTag(ns, "Summary");
}
@@ -423,130 +433,34 @@
}
serializer.startTag(ns, "TestPackage");
serializer.attribute(ns, "name", runResult.getName());
- serializer.attribute(ns, "runTime", formatElapsedTime(runResult.getElapsedTime()));
- // TODO: generate digest
- serializer.attribute(ns, "digest", "");
- serializer.attribute(ns, "failed", Integer.toString(runResult.getNumErrorTests() +
- runResult.getNumFailedTests()));
- // TODO: output notExecuted, timeout, and omitted count
- serializer.attribute(ns, "notExecuted", "0");
- serializer.attribute(ns, "timeout", "0");
- serializer.attribute(ns, "omitted", "0");
- serializer.attribute(ns, "pass", Integer.toString(runResult.getNumPassedTests()));
- serializer.attribute(ns, "total", Integer.toString(runResult.getNumTests()));
+ serializer.attribute(ns, "appPackageName", runResult.getName());
+ serializer.attribute(ns, "digest", getMetric(runResult, "digest"));
- // the results XML needs to organize test's by class. Build a nested data structure that
- // group's the results by class name
- Map<String, Map<TestIdentifier, TestResult>> classResultsMap = buildClassNameMap(
- runResult.getTestResults());
+ // Dump the results.
- for (Map.Entry<String, Map<TestIdentifier, TestResult>> resultsEntry :
- classResultsMap.entrySet()) {
- serializer.startTag(ns, "TestCase");
- serializer.attribute(ns, "name", resultsEntry.getKey());
- serializeTests(serializer, resultsEntry.getValue());
- serializer.endTag(ns, "TestCase");
+ // organize the tests into data structures that mirror the expected xml output.
+ TestSuiteRoot suiteRoot = new TestSuiteRoot();
+ for (Map.Entry<TestIdentifier, TestResult> testEntry : runResult.getTestResults()
+ .entrySet()) {
+ suiteRoot.insertTest(testEntry.getKey(), testEntry.getValue());
}
+ suiteRoot.serialize(serializer);
serializer.endTag(ns, "TestPackage");
}
/**
- * Organizes the test run results into a format organized by class name.
- */
- private Map<String, Map<TestIdentifier, TestResult>> buildClassNameMap(
- Map<TestIdentifier, TestResult> results) {
- // use a linked hashmap to have predictable iteration order
- Map<String, Map<TestIdentifier, TestResult>> classResultMap =
- new LinkedHashMap<String, Map<TestIdentifier, TestResult>>();
- for (Map.Entry<TestIdentifier, TestResult> resultEntry : results.entrySet()) {
- String className = resultEntry.getKey().getClassName();
- Map<TestIdentifier, TestResult> resultsForClass = classResultMap.get(className);
- if (resultsForClass == null) {
- resultsForClass = new LinkedHashMap<TestIdentifier, TestResult>();
- classResultMap.put(className, resultsForClass);
- }
- resultsForClass.put(resultEntry.getKey(), resultEntry.getValue());
- }
- return classResultMap;
- }
-
- /**
- * Output XML for given map of tests their results
+ * Helper method to retrieve the metric value with given name, or blank if not found
*
- * @param serializer
- * @param results
- * @throws IOException
- */
- private void serializeTests(KXmlSerializer serializer, Map<TestIdentifier, TestResult> results)
- throws IOException {
- for (Map.Entry<TestIdentifier, TestResult> resultEntry : results.entrySet()) {
- serializeTest(serializer, resultEntry.getKey(), resultEntry.getValue());
- }
- }
-
- /**
- * Output the XML for given test and result.
- *
- * @param serializer
- * @param testId
- * @param result
- * @throws IOException
- */
- private void serializeTest(KXmlSerializer serializer, TestIdentifier testId, TestResult result)
- throws IOException {
- serializer.startTag(ns, "Test");
- serializer.attribute(ns, "name", testId.getTestName());
- serializer.attribute(ns, "result", convertStatus(result.getStatus()));
-
- if (result.getStackTrace() != null) {
- String sanitizedStack = sanitizeStackTrace(result.getStackTrace());
- serializer.startTag(ns, "FailedScene");
- serializer.attribute(ns, "message", getFailureMessageFromStackTrace(sanitizedStack));
- serializer.text(sanitizedStack);
- serializer.endTag(ns, "FailedScene");
- }
- serializer.endTag(ns, "Test");
- }
-
- /**
- * Convert a {@link TestStatus} to the result text to output in XML
- *
- * @param status the {@link TestStatus}
+ * @param runResult
+ * @param string
* @return
*/
- private String convertStatus(TestStatus status) {
- switch (status) {
- case ERROR:
- return "fail";
- case FAILURE:
- return "fail";
- case PASSED:
- return "pass";
- // TODO add notExecuted, omitted timeout
+ private String getMetric(TestRunResult runResult, String keyName) {
+ String value = runResult.getRunMetrics().get(keyName);
+ if (value == null) {
+ return "";
}
- return "omitted";
- }
-
- /**
- * Strip out any invalid XML characters that might cause the report to be unviewable.
- * http://www.w3.org/TR/REC-xml/#dt-character
- */
- private static String sanitizeStackTrace(String trace) {
- if (trace != null) {
- return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
- } else {
- return null;
- }
- }
-
- private static String getFailureMessageFromStackTrace(String stack) {
- // This is probably too simplistic to work in all cases, but for now, just return first
- // line of stack as failure message
- int firstNewLine = stack.indexOf('\n');
- if (firstNewLine != -1) {
- return stack.substring(0, firstNewLine);
- }
- return stack;
+ return value;
}
/**
@@ -594,11 +508,14 @@
/**
* Creates the output stream to use for test results. Exposed for mocking.
+ * @param mReportPath
*/
OutputStream createOutputResultStream(File reportDir) throws IOException {
File reportFile = new File(reportDir, TEST_RESULT_FILE_NAME);
Log.i(LOG_TAG, String.format("Created xml report file at %s",
reportFile.getAbsolutePath()));
+ // TODO: convert to path relative to cts root
+ mReportPath = reportFile.getAbsolutePath();
return new FileOutputStream(reportFile);
}
@@ -610,7 +527,7 @@
private void copyFormattingFiles(File resultsDir) {
for (String resultFileName : CTS_RESULT_RESOURCES) {
InputStream configStream = getClass().getResourceAsStream(
- String.format("/result/%s", resultFileName));
+ String.format("%s", resultFileName));
if (configStream != null) {
File resultFile = new File(resultsDir, resultFileName);
try {
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java
new file mode 100644
index 0000000..3fce8c4
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestCase.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.result;
+
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestResult.TestStatus;
+
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Data structure that represents a "TestCase" XML element and its children.
+ */
+class TestCase {
+
+ private final String mName;
+
+ Map<String, TestResult> mChildTestMap = new LinkedHashMap<String, TestResult>();
+
+ /**
+ * Create a {@link TestCase}
+ * @param testCaseName
+ */
+ public TestCase(String testCaseName) {
+ mName = testCaseName;
+ }
+
+ /**
+ * Inserts given test result
+ *
+ * @param testName
+ * @param testResult
+ */
+ public void insertTest(String testName, TestResult testResult) {
+ mChildTestMap.put(testName, testResult);
+ }
+
+ /**
+ * Serialize this object and all its contents to XML.
+ *
+ * @param serializer
+ * @throws IOException
+ */
+ public void serialize(KXmlSerializer serializer) throws IOException {
+ serializer.startTag(CtsXmlResultReporter.ns, "TestCase");
+ serializer.attribute(CtsXmlResultReporter.ns, "name", mName);
+ // unused
+ serializer.attribute(CtsXmlResultReporter.ns, "priority", "");
+ for (Map.Entry<String, TestResult> resultEntry: mChildTestMap.entrySet()) {
+ serializeTestResult(serializer, resultEntry.getKey(), resultEntry.getValue());
+ }
+ serializer.endTag(CtsXmlResultReporter.ns, "TestCase");
+ }
+
+ private void serializeTestResult(KXmlSerializer serializer, String name, TestResult result)
+ throws IOException {
+ serializer.startTag(CtsXmlResultReporter.ns, "Test");
+ serializer.attribute(CtsXmlResultReporter.ns, "name", name);
+ serializer.attribute(CtsXmlResultReporter.ns, "result", convertStatus(result.getStatus()));
+
+ if (result.getStackTrace() != null) {
+ String sanitizedStack = sanitizeStackTrace(result.getStackTrace());
+ serializer.startTag(CtsXmlResultReporter.ns, "FailedScene");
+ serializer.attribute(CtsXmlResultReporter.ns, "message",
+ getFailureMessageFromStackTrace(sanitizedStack));
+ serializer.text(sanitizedStack);
+ serializer.endTag(CtsXmlResultReporter.ns, "FailedScene");
+ }
+
+ serializer.endTag(CtsXmlResultReporter.ns, "Test");
+
+ }
+
+ /**
+ * Convert a {@link TestStatus} to the result text to output in XML
+ *
+ * @param status the {@link TestStatus}
+ * @return
+ */
+ private String convertStatus(TestStatus status) {
+ switch (status) {
+ case ERROR:
+ return "fail";
+ case FAILURE:
+ return "fail";
+ case PASSED:
+ return "pass";
+ // TODO add notExecuted
+ }
+ return "omitted";
+ }
+
+ /**
+ * Strip out any invalid XML characters that might cause the report to be unviewable.
+ * http://www.w3.org/TR/REC-xml/#dt-character
+ */
+ private static String sanitizeStackTrace(String trace) {
+ if (trace != null) {
+ return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", "");
+ } else {
+ return null;
+ }
+ }
+
+ private static String getFailureMessageFromStackTrace(String stack) {
+ // This is probably too simplistic to work in all cases, but for now, just return first
+ // line of stack as failure message
+ int firstNewLine = stack.indexOf('\n');
+ if (firstNewLine != -1) {
+ return stack.substring(0, firstNewLine);
+ }
+ return stack;
+ }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
new file mode 100644
index 0000000..7711740
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuite.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.result;
+
+import com.android.tradefed.result.TestResult;
+
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Data structure that represents a "TestSuite" XML element and its children.
+ */
+class TestSuite {
+
+ private final String mName;
+
+ // use linked hash map for predictable iteration order
+ Map<String, TestSuite> mChildSuiteMap = new LinkedHashMap<String, TestSuite>();
+ Map<String, TestCase> mChildTestCaseMap = new LinkedHashMap<String, TestCase>();
+
+ /**
+ * @param testSuite
+ */
+ public TestSuite(String suiteName) {
+ mName = suiteName;
+ }
+
+ /**
+ * Insert the given test result into this suite.
+ *
+ * @param suiteNames list of remaining suite names for this test
+ * @param testClassName the test class name
+ * @param testName the test method name
+ * @param testResult the {@link TestResult}
+ */
+ public void insertTest(List<String> suiteNames, String testClassName, String testName,
+ TestResult testResult) {
+ if (suiteNames.size() <= 0) {
+ // no more package segments
+ TestCase testCase = getTestCase(testClassName);
+ testCase.insertTest(testName, testResult);
+ } else {
+ String rootName = suiteNames.remove(0);
+ TestSuite suite = getTestSuite(rootName);
+ suite.insertTest(suiteNames, testClassName, testName, testResult);
+ }
+ }
+
+ /**
+ * Get the child {@link TestSuite} with given name, creating if necessary.
+ *
+ * @param suiteName
+ * @return the {@link TestSuite}
+ */
+ private TestSuite getTestSuite(String suiteName) {
+ TestSuite testSuite = mChildSuiteMap.get(suiteName);
+ if (testSuite == null) {
+ testSuite = new TestSuite(suiteName);
+ mChildSuiteMap.put(suiteName, testSuite);
+ }
+ return testSuite;
+ }
+
+ /**
+ * Get the child {@link TestCase} with given name, creating if necessary.
+ * @param testCaseName
+ * @return
+ */
+ private TestCase getTestCase(String testCaseName) {
+ TestCase testCase = mChildTestCaseMap.get(testCaseName);
+ if (testCase == null) {
+ testCase = new TestCase(testCaseName);
+ mChildTestCaseMap.put(testCaseName, testCase);
+ }
+ return testCase;
+ }
+
+ /**
+ * Serialize this object and all its contents to XML.
+ *
+ * @param serializer
+ * @throws IOException
+ */
+ public void serialize(KXmlSerializer serializer) throws IOException {
+ if (mName != null) {
+ serializer.startTag(CtsXmlResultReporter.ns, "TestSuite");
+ serializer.attribute(CtsXmlResultReporter.ns, "name", mName);
+ }
+ for (TestSuite childSuite : mChildSuiteMap.values()) {
+ childSuite.serialize(serializer);
+ }
+ for (TestCase childCase : mChildTestCaseMap.values()) {
+ childCase.serialize(serializer);
+ }
+ if (mName != null) {
+ serializer.endTag(CtsXmlResultReporter.ns, "TestSuite");
+ }
+ }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java
new file mode 100644
index 0000000..bb0b0fb
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestSuiteRoot.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.result;
+
+import com.android.ddmlib.Log;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.result.TestResult;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Helper class for converting test results into the CTS XML serialization format.
+ * <p/>
+ * A TestIdentifier with name "com.example.ExampleTest#testExample will get serialized as the
+ * following XML
+ * <pre>
+ * TestSuite name="com"
+ * TestSuite name ="example"
+ * TestCase name = "ExampleTest"
+ * Test name="testExample"
+ * </pre>
+ */
+class TestSuiteRoot extends TestSuite {
+
+ private static final String LOG_TAG = "TestSuiteRoot";
+
+ public TestSuiteRoot() {
+ super(null);
+ }
+
+ /**
+ * Insert the given test result.
+ *
+ * @param testId
+ * @param testResult
+ */
+ public void insertTest(TestIdentifier testId, TestResult testResult) {
+ List<String> classNameSegments = new LinkedList<String>();
+ classNameSegments.addAll(Arrays.asList(testId.getClassName().split("\\.")));
+ if (classNameSegments.size() <= 0) {
+ Log.e(LOG_TAG, String.format("Unrecognized package name format for test class '%s'",
+ testId.getClassName()));
+ } else {
+ String testCaseName = classNameSegments.remove(classNameSegments.size()-1);
+ insertTest(classNameSegments, testCaseName, testId.getTestName(), testResult);
+ }
+ }
+}
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
index 9aeaccd..88bb5d1 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/result/CtsXmlResultReporterTest.java
@@ -78,7 +78,7 @@
final String expectedHeaderOutput = "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
"<?xml-stylesheet type=\"text/xsl\" href=\"cts_result.xsl\"?>";
final String expectedTestOutput =
- "<TestResult testPlan=\"unknown\" profile=\"unknown\" starttime=\"ignore\" endtime=\"ignore\" version=\"2.0\"> ";
+ "<TestResult testPlan=\"unknown\" starttime=\"ignore\" endtime=\"ignore\" version=\"1.10\"> ";
final String expectedSummaryOutput =
"<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"0\" total=\"0\" />";
final String expectedEndTag = "</TestResult>";
@@ -110,8 +110,8 @@
// TODO: consider doing xml based compare
assertTrue(output.contains(
"<Summary failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"1\" total=\"1\" />"));
- assertTrue(output.contains("<TestPackage name=\"run\" runTime=\"3s\" digest=\"\" " +
- "failed=\"0\" notExecuted=\"0\" timeout=\"0\" omitted=\"0\" pass=\"1\" total=\"1\">"));
+ assertTrue(output.contains("<TestPackage name=\"run\" digest=\"\" " +
+ "failed=\"0\" notExecuted=\"0\" timeout=\"0\" pass=\"1\" >"));
assertTrue(output.contains(String.format("<TestCase name=\"%s\">", testId.getClassName())));
final String testCaseTag = String.format(