More CTS Coverage Build Improvements
Bug 3245588
The build server couldn't display the XML report with the XSL
transformation. Thus, when you clicked on the XML file, you
would just see the raw XML which wasn't very useful. So make
the report generator output a single HTML file by transforming
the XML into HTML in code.
Change-Id: Ie8b585551e4150f360a6622b3c6f7298ebd0a1e8
diff --git a/tools/cts-api-coverage/src/Android.mk b/tools/cts-api-coverage/src/Android.mk
index 67ce8b6..d1fe4ed 100644
--- a/tools/cts-api-coverage/src/Android.mk
+++ b/tools/cts-api-coverage/src/Android.mk
@@ -20,6 +20,7 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_JAVA_RESOURCE_DIRS := res
LOCAL_JAR_MANIFEST := MANIFEST.mf
LOCAL_MODULE := cts-api-coverage
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
index 4aaae69..d6a218e 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/CtsApiCoverage.java
@@ -29,6 +29,8 @@
import java.util.ArrayList;
import java.util.List;
+import javax.xml.transform.TransformerException;
+
/**
* Tool that generates a report of what Android framework methods are being called from a given
* set of APKS. See the {@link #printUsage()} method for more details.
@@ -39,6 +41,8 @@
private static final int FORMAT_XML = 1;
+ private static final int FORMAT_HTML = 2;
+
private static void printUsage() {
System.out.println("Usage: cts-api-coverage [OPTION]... [APK]...");
System.out.println();
@@ -51,9 +55,9 @@
System.out.println("directory and dexdeps must be built via \"make dexdeps\".");
System.out.println();
System.out.println("Options:");
- System.out.println(" -o FILE output file or standard out if not given");
- System.out.println(" -f [txt|xml] format of output either text or xml");
- System.out.println(" -d PATH path to dexdeps or expected to be in $PATH");
+ System.out.println(" -o FILE output file or standard out if not given");
+ System.out.println(" -f [txt|xml|html] format of output");
+ System.out.println(" -d PATH path to dexdeps or expected to be in $PATH");
System.out.println();
System.exit(1);
}
@@ -74,6 +78,8 @@
format = FORMAT_XML;
} else if ("txt".equalsIgnoreCase(formatSpec)) {
format = FORMAT_TXT;
+ } else if ("html".equalsIgnoreCase(formatSpec)) {
+ format = FORMAT_HTML;
} else {
printUsage();
}
@@ -160,7 +166,9 @@
}
private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
- File outputFile, int format) throws IOException {
+ File outputFile, int format) throws IOException, TransformerException,
+ InterruptedException {
+
OutputStream out = outputFile != null
? new FileOutputStream(outputFile)
: System.out;
@@ -174,6 +182,10 @@
case FORMAT_XML:
XmlReport.printXmlReport(testApks, apiCoverage, out);
break;
+
+ case FORMAT_HTML:
+ HtmlReport.printHtmlReport(testApks, apiCoverage, out);
+ break;
}
} finally {
out.close();
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
new file mode 100644
index 0000000..de9b7a6
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 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.apicoverage;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.List;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+/**
+ * Class that outputs an HTML report of the {@link ApiCoverage} collected. It is the XML report
+ * transformed into HTML.
+ */
+class HtmlReport {
+
+ public static void printHtmlReport(final List<File> testApks, final ApiCoverage apiCoverage,
+ final OutputStream out) throws IOException, TransformerException, InterruptedException {
+ final PipedOutputStream xmlOut = new PipedOutputStream();
+ final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
+
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ XmlReport.printXmlReport(testApks, apiCoverage, xmlOut);
+
+ // Close the output stream to avoid "Write dead end" errors.
+ try {
+ xmlOut.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t.start();
+
+ InputStream xsl = CtsApiCoverage.class.getResourceAsStream("/api-coverage.xsl");
+ StreamSource xslSource = new StreamSource(xsl);
+ TransformerFactory factory = TransformerFactory.newInstance();
+ Transformer transformer = factory.newTransformer(xslSource);
+
+ StreamSource xmlSource = new StreamSource(xmlIn);
+ StreamResult result = new StreamResult(out);
+ transformer.transform(xmlSource, result);
+ }
+}
diff --git a/tools/cts-api-coverage/src/res/api-coverage.xsl b/tools/cts-api-coverage/src/res/api-coverage.xsl
new file mode 100644
index 0000000..91fe802
--- /dev/null
+++ b/tools/cts-api-coverage/src/res/api-coverage.xsl
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2010 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>
+ <head>
+ <script type="text/javascript">
+ function toggleVisibility(id) {
+ element = document.getElementById(id);
+ if (element.style.display == "none") {
+ element.style.display = "";
+ } else {
+ element.style.display = "none";
+ }
+ }
+ </script>
+ <style type="text/css">
+ body {
+ background-color: #CCCCCC;
+ font-family: sans-serif;
+ margin: 10px;
+ }
+
+ .info {
+ margin-bottom: 10px;
+ }
+
+ .apks, .package, .class {
+ cursor: pointer;
+ text-decoration: underline;
+ }
+
+ .packageDetails {
+ padding-left: 20px;
+ }
+
+ .classDetails {
+ padding-left: 40px;
+ }
+
+ .method {
+ font-family: courier;
+ white-space: nowrap;
+ }
+
+ .red {
+ background-color: #FF0000;
+ }
+
+ .yellow {
+ background-color: #FFFF00;
+ }
+
+ .green {
+ background-color: #00FF00;
+ }
+ </style>
+ </head>
+ <body>
+ <h1>CTS API Coverage</h1>
+ <div class="info">
+ Generated: <xsl:value-of select="api-coverage/@generatedTime" />
+ </div>
+ <div class="apks" onclick="toggleVisibility('sourceApks')">
+ Source APKs (<xsl:value-of select="count(api-coverage/debug/sources/apk)" />)
+ </div>
+ <div id="sourceApks" style="display: none">
+ <ul>
+ <xsl:for-each select="api-coverage/debug/sources/apk">
+ <li><xsl:value-of select="@path" /></li>
+ </xsl:for-each>
+ </ul>
+ </div>
+ <ul>
+ <xsl:for-each select="api-coverage/api/package">
+ <xsl:call-template name="packageOrClassListItem">
+ <xsl:with-param name="bulletClass" select="'package'" />
+ </xsl:call-template>
+ <div class="packageDetails" id="{@name}" style="display: none">
+ <ul>
+ <xsl:for-each select="class">
+ <xsl:call-template name="packageOrClassListItem">
+ <xsl:with-param name="bulletClass" select="'class'" />
+ </xsl:call-template>
+ <div class="classDetails" id="{@name}" style="display: none">
+ <xsl:for-each select="constructor">
+ <xsl:call-template name="methodListItem" />
+ </xsl:for-each>
+ <xsl:for-each select="method">
+ <xsl:call-template name="methodListItem" />
+ </xsl:for-each>
+ </div>
+ </xsl:for-each>
+ </ul>
+ </div>
+ </xsl:for-each>
+ </ul>
+ </body>
+ </html>
+ </xsl:template>
+
+ <xsl:template name="packageOrClassListItem">
+ <xsl:param name="bulletClass" />
+
+ <xsl:variable name="colorClass">
+ <xsl:choose>
+ <xsl:when test="@coveragePercentage <= 50">red</xsl:when>
+ <xsl:when test="@coveragePercentage <= 80">yellow</xsl:when>
+ <xsl:otherwise>green</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <li class="{$bulletClass}" onclick="toggleVisibility('{@name}')">
+ <span class="{$colorClass}">
+ <b><xsl:value-of select="@name" /></b>
+ <xsl:value-of select="@coveragePercentage" />%
+ (<xsl:value-of select="@numCovered" />/<xsl:value-of select="@numTotal" />)
+ </span>
+ </li>
+ </xsl:template>
+
+ <xsl:template name="methodListItem">
+ <span class="method">
+ <xsl:choose>
+ <xsl:when test="@covered = 'true'">[X]</xsl:when>
+ <xsl:otherwise>[ ]</xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@returnType != ''"> <xsl:value-of select="@returnType" /></xsl:if>
+ <b> <xsl:value-of select="@name" /></b><xsl:call-template name="formatParameters" />
+ </span>
+ <br />
+ </xsl:template>
+
+ <xsl:template name="formatParameters">(<xsl:for-each select="parameter">
+ <xsl:value-of select="@type" />
+ <xsl:if test="not(position() = last())">, </xsl:if>
+ </xsl:for-each>)
+ </xsl:template>
+
+</xsl:stylesheet>
+