CTS coverage tool improvements
* remove default package prefix filter on 'android' package
* enabled multiple package prefix filters
* improved sorting logic:
* first compare by coverage percentage segments (0, 50%, 80%)
* then compare by member sizes for classes/packages in
in descending order
Bug: 19272826
Change-Id: I8416a08d152e2028daf5cb945388be590d3feab8
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
index 2a62aa0..31e1f8d 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiClass.java
@@ -121,4 +121,9 @@
return (float) getNumCoveredMethods() / getTotalMethods() * 100;
}
}
+
+ @Override
+ public int getMemberSize() {
+ return getTotalMethods();
+ }
}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiPackage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiPackage.java
index c83256c..e0bf73f 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiPackage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/ApiPackage.java
@@ -72,6 +72,11 @@
return (float) getNumCoveredMethods() / getTotalMethods() * 100;
}
+ @Override
+ public int getMemberSize() {
+ return getTotalMethods();
+ }
+
public void removeEmptyAbstractClasses() {
Iterator<Entry<String, ApiClass>> it = mApiClassMap.entrySet().iterator();
while (it.hasNext()) {
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 d596cba..05cb4e1 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
@@ -71,8 +71,7 @@
int format = FORMAT_TXT;
String dexDeps = "dexDeps";
String apiXmlPath = "";
- // By default only care about packages starting with "android"
- String packageFilter = "android";
+ PackageFilter packageFilter = new PackageFilter();
String reportTitle = "CTS API Coverage";
for (int i = 0; i < args.length; i++) {
@@ -95,7 +94,7 @@
} else if ("-a".equals(args[i])) {
apiXmlPath = getExpectedArg(args, ++i);
} else if ("-p".equals(args[i])) {
- packageFilter = getExpectedArg(args, ++i);
+ packageFilter.addPrefixToFilter(getExpectedArg(args, ++i));
} else if ("-t".equals(args[i])) {
reportTitle = getExpectedArg(args, ++i);
} else {
@@ -188,7 +187,7 @@
}
private static void outputCoverageReport(ApiCoverage apiCoverage, List<File> testApks,
- File outputFile, int format, String packageFilter, String reportTitle)
+ File outputFile, int format, PackageFilter packageFilter, String reportTitle)
throws IOException, TransformerException, InterruptedException {
OutputStream out = outputFile != null
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HasCoverage.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HasCoverage.java
index 3b369bb..f8d8054 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HasCoverage.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HasCoverage.java
@@ -20,13 +20,33 @@
interface HasCoverage {
float getCoveragePercentage();
+ int getMemberSize();
String getName();
}
class CoverageComparator implements Comparator<HasCoverage> {
public int compare(HasCoverage entity, HasCoverage otherEntity) {
- int diff = Math.round(entity.getCoveragePercentage())
- - Math.round(otherEntity.getCoveragePercentage());
- return diff != 0 ? diff : entity.getName().compareTo(otherEntity.getName());
+ int lhsPct = Math.round(entity.getCoveragePercentage());
+ int rhsPct = Math.round(otherEntity.getCoveragePercentage());
+ int diff = Integer.compare(getCoveragePercentageSegment(lhsPct),
+ getCoveragePercentageSegment(rhsPct));
+ return diff != 0 ? diff :
+ Integer.compare(otherEntity.getMemberSize(), entity.getMemberSize());
+ }
+
+ /**
+ * Distill coverage percentage down to 3 major segments
+ * @param coveragePercentage
+ * @return
+ */
+ private int getCoveragePercentageSegment(int coveragePercentage) {
+ // note that this segmentation logic is duplicated in api-coverage.xsl
+ if (coveragePercentage <= 50) {
+ return 0;
+ } else if (coveragePercentage <= 80) {
+ return 1;
+ } else {
+ return 2;
+ }
}
}
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
index dfe609d..0e6b54a 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/HtmlReport.java
@@ -37,7 +37,7 @@
class HtmlReport {
public static void printHtmlReport(final List<File> testApks, final ApiCoverage apiCoverage,
- final String packageFilter, final String reportTitle, final OutputStream out)
+ final PackageFilter packageFilter, final String reportTitle, final OutputStream out)
throws IOException, TransformerException {
final PipedOutputStream xmlOut = new PipedOutputStream();
final PipedInputStream xmlIn = new PipedInputStream(xmlOut);
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/PackageFilter.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/PackageFilter.java
new file mode 100644
index 0000000..b196d8f
--- /dev/null
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/PackageFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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.util.ArrayList;
+import java.util.List;
+
+/**
+ * Util class to support package filtering logic
+ * <p>
+ * A list of package prefixes can be added to the filter, and {{@link #accept(String)} method will
+ * decide if the provided package name matches any of the prefixes.
+ */
+public class PackageFilter {
+
+ private List<String> mFilters = new ArrayList<>();
+
+ /**
+ * Check if a particular package name matches any of the package prefixes configured in filter.
+ * If no filters are configured, any package names will be accepted
+ * @param packageName
+ * @return
+ */
+ public boolean accept(String packageName) {
+ if (mFilters.isEmpty()) {
+ return true;
+ }
+ for (String filter : mFilters) {
+ if (packageName.startsWith(filter)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void addPrefixToFilter(String prefix) {
+ mFilters.add(prefix);
+ }
+
+ public void clearFilter() {
+ mFilters.clear();
+ }
+}
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
index 23b44c3..e3e2e7c 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/TextReport.java
@@ -27,7 +27,8 @@
*/
class TextReport {
- public static void printTextReport(ApiCoverage api, String packageFilter, OutputStream outputStream) {
+ public static void printTextReport(ApiCoverage api, PackageFilter packageFilter,
+ OutputStream outputStream) {
PrintStream out = new PrintStream(outputStream);
CoverageComparator comparator = new CoverageComparator();
@@ -35,8 +36,7 @@
Collections.sort(packages, comparator);
for (ApiPackage apiPackage : packages) {
- if (apiPackage.getName().startsWith(packageFilter)
- && apiPackage.getTotalMethods() > 0) {
+ if (packageFilter.accept(apiPackage.getName()) && apiPackage.getTotalMethods() > 0) {
printPackage(apiPackage, out);
}
}
@@ -45,7 +45,7 @@
out.println();
for (ApiPackage apiPackage : packages) {
- if (apiPackage.getName().startsWith(packageFilter)) {
+ if (packageFilter.accept(apiPackage.getName())) {
printPackage(apiPackage, out);
List<ApiClass> classes = new ArrayList<ApiClass>(apiPackage.getClasses());
diff --git a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
index df10fa4..570b316 100644
--- a/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
+++ b/tools/cts-api-coverage/src/com/android/cts/apicoverage/XmlReport.java
@@ -32,7 +32,7 @@
class XmlReport {
public static void printXmlReport(List<File> testApks, ApiCoverage apiCoverage,
- String packageFilter, String reportTitle, OutputStream outputStream) {
+ PackageFilter packageFilter, String reportTitle, OutputStream outputStream) {
PrintStream out = new PrintStream(outputStream);
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
out.println("<?xml-stylesheet type=\"text/xsl\" href=\"api-coverage.xsl\"?>");
@@ -57,8 +57,7 @@
int totalMethods = 0;
int totalCoveredMethods = 0;
for (ApiPackage pkg : packages) {
- if (pkg.getName().startsWith(packageFilter)
- && pkg.getTotalMethods() > 0) {
+ if (packageFilter.accept(pkg.getName()) && pkg.getTotalMethods() > 0) {
int pkgTotal = pkg.getTotalMethods();
totalMethods += pkgTotal;
int pkgTotalCovered = pkg.getNumCoveredMethods();
diff --git a/tools/cts-api-coverage/src/res/api-coverage.xsl b/tools/cts-api-coverage/src/res/api-coverage.xsl
index 1ac3402..b11a8c4 100644
--- a/tools/cts-api-coverage/src/res/api-coverage.xsl
+++ b/tools/cts-api-coverage/src/res/api-coverage.xsl
@@ -21,6 +21,7 @@
<xsl:template match="/">
<html>
<head>
+ <title><xsl:value-of select="api-coverage/@title" /></title>
<script type="text/javascript">
function toggleVisibility(id) {
element = document.getElementById(id);
@@ -87,7 +88,7 @@
(<xsl:value-of select="api-coverage/total/@numCovered" />/<xsl:value-of select="api-coverage/total/@numTotal" />)
</div>
<div class="apks" onclick="toggleVisibility('sourceApks')">
- Source APKs (<xsl:value-of select="count(api-coverage/debug/sources/apk)" />)
+ Source Modules (<xsl:value-of select="count(api-coverage/debug/sources/apk)" />)
</div>
<div id="sourceApks" style="display: none">
<ul>