summaryrefslogtreecommitdiffstats
path: root/tools/dalvik_jtreg
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dalvik_jtreg')
-rw-r--r--tools/dalvik_jtreg/Android.mk3
-rw-r--r--tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java7
-rw-r--r--tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java67
-rw-r--r--tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java21
-rw-r--r--tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java197
5 files changed, 259 insertions, 36 deletions
diff --git a/tools/dalvik_jtreg/Android.mk b/tools/dalvik_jtreg/Android.mk
index f32312a..7da7212 100644
--- a/tools/dalvik_jtreg/Android.mk
+++ b/tools/dalvik_jtreg/Android.mk
@@ -16,9 +16,10 @@ LOCAL_SRC_FILES := \
java/dalvik/jtreg/TestDescriptions.java \
java/dalvik/jtreg/TestRunner.java \
java/dalvik/jtreg/TestToDex.java \
+ java/dalvik/jtreg/XmlReportPrinter.java \
LOCAL_MODULE:= dalvik_jtreg
-LOCAL_STATIC_JAVA_LIBRARIES := javatest jh jtreg
+LOCAL_STATIC_JAVA_LIBRARIES := javatest jh jtreg kxml2-2.3.0
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java b/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java
index b7813d8..ef8508e 100644
--- a/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/Adb.java
@@ -24,8 +24,11 @@ import java.io.File;
final class Adb {
public void mkdir(File name) {
- new Command("adb", "shell", "mkdir", name.toString())
- .execute();
+ new Command("adb", "shell", "mkdir", name.toString()).execute();
+ }
+
+ public void rm(File name) {
+ new Command("adb", "shell", "rm", "-r", name.toString()).execute();
}
public void push(File local, File remote) {
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java b/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java
index 0ef24b2..bfe2908 100644
--- a/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/JtregRunner.java
@@ -20,6 +20,7 @@ import com.sun.javatest.TestDescription;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
@@ -57,6 +58,7 @@ public final class JtregRunner {
private Integer debugPort;
private Set<File> expectationDirs = new LinkedHashSet<File>();
private long timeoutSeconds = 10 * 60; // default is ten minutes
+ private File xmlReportsDirectory;
private File deviceTestRunner;
@@ -78,17 +80,14 @@ public final class JtregRunner {
// threads helps for packages that contain many unsupported tests
ExecutorService builders = Executors.newFixedThreadPool(8);
for (final TestDescription testDescription : tests) {
- builders.submit(new Runnable() {
- public void run() {
- try {
- String qualifiedName = TestDescriptions.qualifiedName(testDescription);
- ExpectedResult expectedResult = ExpectedResult.forRun(expectationDirs, qualifiedName);
- TestRun testRun = new TestRun(qualifiedName, testDescription, expectedResult);
- buildAndInstall(testRun);
- readyToRun.put(testRun);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ builders.submit(new Callable<Void>() {
+ public Void call() throws Exception {
+ String qualifiedName = TestDescriptions.qualifiedName(testDescription);
+ ExpectedResult expectedResult = ExpectedResult.forRun(expectationDirs, qualifiedName);
+ TestRun testRun = new TestRun(qualifiedName, testDescription, expectedResult);
+ buildAndInstall(testRun);
+ readyToRun.put(testRun);
+ return null;
}
});
}
@@ -98,8 +97,10 @@ public final class JtregRunner {
int unsupportedTests = 0;
+ List<TestRun> runs = new ArrayList<TestRun>(tests.size());
while (!builders.isTerminated() || !readyToRun.isEmpty()) {
TestRun testRun = readyToRun.take();
+ runs.add(testRun);
if (testRun.getResult() == Result.UNSUPPORTED) {
logger.fine("skipping " + testRun.getQualifiedName());
@@ -117,6 +118,12 @@ public final class JtregRunner {
if (unsupportedTests > 0) {
logger.info("Skipped " + unsupportedTests + " unsupported tests.");
}
+
+ if (xmlReportsDirectory != null) {
+ logger.info("Printing XML Reports... ");
+ int numFiles = new XmlReportPrinter().generateReports(xmlReportsDirectory, runs);
+ logger.info(numFiles + " XML files written.");
+ }
}
/**
@@ -253,16 +260,21 @@ public final class JtregRunner {
}
}
+ private void shutdown() {
+ adb.rm(deviceTemp);
+ outputReaders.shutdown();
+ }
+
public static void main(String[] args) throws Exception {
if (args.length < 2) {
- System.out.println("Usage: JTRegRunner [options]... <android_jar> <directoryWithTests>");
+ System.out.println("Usage: JTRegRunner [options]... <android jar> <tests directory>");
System.out.println();
- System.out.println(" android_jar: the API jar file to compile against. Usually");
+ System.out.println(" <android jar>: the API jar file to compile against. Usually");
System.out.println(" this is <SDK>/platforms/android-<X.X>/android.jar where");
System.out.println(" <SDK> is the path to an Android SDK path and <X.X> is a");
System.out.println(" release version like 1.5.");
System.out.println();
- System.out.println(" directoryWithTests: a directory to scan for test cases;");
+ System.out.println(" <tests directory>: a directory to scan for test cases;");
System.out.println(" typically this is 'platform_v6/jdk/test' if 'platform_v6'");
System.out.println(" contains the sources of a platform implementation.");
System.out.println();
@@ -276,8 +288,11 @@ public final class JtregRunner {
System.out.println(" looking for test expectations. The directory should include");
System.out.println(" <test>.expected files describing expected results.");
System.out.println();
- System.out.println(" --timeoutSeconds <seconds>: maximum execution time of each test");
- System.out.println(" before the runner aborts it.");
+ System.out.println(" --timeout-seconds <seconds>: maximum execution time of each");
+ System.out.println(" test before the runner aborts it.");
+ System.out.println();
+ System.out.println(" --xml-reports-directory <path>: directory to emit JUnit-style");
+ System.out.println(" XML test results.");
System.out.println();
System.out.println(" --verbose: turn on verbose output");
System.out.println();
@@ -302,12 +317,6 @@ public final class JtregRunner {
if ("--debug".equals(args[i])) {
jtregRunner.debugPort = Integer.valueOf(args[++i]);
- } else if ("--timeoutSeconds".equals(args[i])) {
- jtregRunner.timeoutSeconds = Long.valueOf(args[++i]);
-
- } else if ("--verbose".equals(args[i])) {
- Logger.getLogger("dalvik.jtreg").setLevel(Level.FINE);
-
} else if ("--expectations".equals(args[i])) {
File expectationDir = new File(args[++i]);
if (!expectationDir.isDirectory()) {
@@ -315,12 +324,26 @@ public final class JtregRunner {
}
jtregRunner.expectationDirs.add(expectationDir);
+ } else if ("--timeout-seconds".equals(args[i])) {
+ jtregRunner.timeoutSeconds = Long.valueOf(args[++i]);
+
+ } else if ("--verbose".equals(args[i])) {
+ Logger.getLogger("dalvik.jtreg").setLevel(Level.FINE);
+
+ } else if ("--xml-reports-directory".equals(args[i])) {
+ jtregRunner.xmlReportsDirectory = new File(args[++i]);
+ if (!jtregRunner.xmlReportsDirectory.isDirectory()) {
+ throw new RuntimeException("Invalid XML reports directory: "
+ + jtregRunner.xmlReportsDirectory);
+ }
+
} else {
throw new RuntimeException("Unrecognized option: " + args[i]);
}
}
jtregRunner.buildAndRunAllTests();
+ jtregRunner.shutdown();
}
private static void prepareLogging() {
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java b/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java
index d0be8d2..c7ffe7f 100644
--- a/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/TestDescriptions.java
@@ -44,23 +44,22 @@ class TestDescriptions {
/**
* Returns a fully qualified name of the form {@code
- * java_lang_Math_PowTests} from the given test description. The returned
+ * java.lang.Math.PowTests} from the given test description. The returned
* name is appropriate for use in a filename.
*/
static String qualifiedName(TestDescription testDescription) {
- StringBuilder result = new StringBuilder();
+ return className(testDescription) + "." + escape(testDescription.getName());
+ }
+ /**
+ * Returns the name of the class under test, such as {@code java.lang.Math}.
+ */
+ static String className(TestDescription testDescription) {
String dir = testDescription.getDir().toString();
int separatorIndex = dir.indexOf(TEST_ROOT);
- if (separatorIndex != -1) {
- result.append(escape(dir.substring(separatorIndex + TEST_ROOT.length())));
- } else {
- result.append(escape(dir));
- }
-
- result.append(".");
- result.append(escape(testDescription.getName()));
- return result.toString();
+ return separatorIndex != -1
+ ? escape(dir.substring(separatorIndex + TEST_ROOT.length()))
+ : escape(dir);
}
/**
diff --git a/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java b/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java
new file mode 100644
index 0000000..bc3c507
--- /dev/null
+++ b/tools/dalvik_jtreg/java/dalvik/jtreg/XmlReportPrinter.java
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+package dalvik.jtreg;
+
+import org.kxml2.io.KXmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+
+/**
+ * Writes JUnit results to a series of XML files in a format consistent with
+ * Ant's XMLJUnitResultFormatter.
+ *
+ * <p>Unlike Ant's formatter, this class does not report the execution time of
+ * tests.
+ *
+ * TODO: unify this and com.google.coretests.XmlReportPrinter
+ */
+public class XmlReportPrinter {
+
+ /**
+ * Test results of these types are omitted from the report, as if the tests
+ * never existed. Equivalent to the core test runner's @BrokenTest.
+ */
+ private static final EnumSet<Result> IGNORED_RESULTS
+ = EnumSet.of(Result.COMPILE_FAILED);
+
+ private static final EnumSet<Result> FAILED_RESULTS
+ = EnumSet.of(Result.EXEC_FAILED);
+ private static final EnumSet<Result> ERROR_RESULTS
+ = EnumSet.complementOf(EnumSet.of(Result.EXEC_FAILED, Result.SUCCESS));
+
+ private static final String TESTSUITE = "testsuite";
+ private static final String TESTCASE = "testcase";
+ private static final String ERROR = "error";
+ private static final String FAILURE = "failure";
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_TIME = "time";
+ private static final String ATTR_ERRORS = "errors";
+ private static final String ATTR_FAILURES = "failures";
+ private static final String ATTR_TESTS = "tests";
+ private static final String ATTR_TYPE = "type";
+ private static final String ATTR_MESSAGE = "message";
+ private static final String PROPERTIES = "properties";
+ private static final String ATTR_CLASSNAME = "classname";
+ private static final String TIMESTAMP = "timestamp";
+ private static final String HOSTNAME = "hostname";
+
+ /** the XML namespace */
+ private static final String ns = null;
+
+ /**
+ * Populates the directory with the report data from the completed tests.
+ */
+ public int generateReports(File directory, Collection<TestRun> results) {
+ Map<String, Suite> suites = testsToSuites(results);
+
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ TimeZone gmt = TimeZone.getTimeZone("GMT");
+ dateFormat.setTimeZone(gmt);
+ dateFormat.setLenient(true);
+ String timestamp = dateFormat.format(new Date());
+
+ for (Suite suite : suites.values()) {
+ FileOutputStream stream = null;
+ try {
+ stream = new FileOutputStream(new File(directory, "TEST-" + suite.name + ".xml"));
+
+ KXmlSerializer serializer = new KXmlSerializer();
+ serializer.setOutput(stream, "UTF-8");
+ serializer.startDocument("UTF-8", null);
+ serializer.setFeature(
+ "http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ suite.print(serializer, timestamp);
+ serializer.endDocument();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+
+ return suites.size();
+ }
+
+ private Map<String, Suite> testsToSuites(Collection<TestRun> testRuns) {
+ Map<String, Suite> result = new LinkedHashMap<String, Suite>();
+ for (TestRun testRun : testRuns) {
+ if (IGNORED_RESULTS.contains(testRun.getResult())) {
+ continue;
+ }
+
+ String suiteName = suiteName(testRun);
+ Suite suite = result.get(suiteName);
+ if (suite == null) {
+ suite = new Suite(suiteName);
+ result.put(suiteName, suite);
+ }
+
+ suite.tests.add(testRun);
+ if (FAILED_RESULTS.contains(testRun.getResult())) {
+ suite.failuresCount++;
+ } else if (ERROR_RESULTS.contains(testRun.getResult())) {
+ suite.errorsCount++;
+ }
+ }
+ return result;
+ }
+
+ private static String suiteName(TestRun testRun) {
+ return TestDescriptions.className(testRun.getTestDescription());
+ }
+
+ static class Suite {
+ private final String name;
+ private final List<TestRun> tests = new ArrayList<TestRun>();
+ private int failuresCount;
+ private int errorsCount;
+
+ Suite(String name) {
+ this.name = name;
+ }
+
+ void print(KXmlSerializer serializer, String timestamp) throws IOException {
+ serializer.startTag(ns, TESTSUITE);
+ serializer.attribute(ns, ATTR_NAME, name);
+ serializer.attribute(ns, ATTR_TESTS, Integer.toString(tests.size()));
+ serializer.attribute(ns, ATTR_FAILURES, Integer.toString(failuresCount));
+ serializer.attribute(ns, ATTR_ERRORS, Integer.toString(errorsCount));
+ serializer.attribute(ns, ATTR_TIME, "0");
+ serializer.attribute(ns, TIMESTAMP, timestamp);
+ serializer.attribute(ns, HOSTNAME, "localhost");
+ serializer.startTag(ns, PROPERTIES);
+ serializer.endTag(ns, PROPERTIES);
+
+ for (TestRun testRun : tests) {
+ print(serializer, testRun);
+ }
+
+ serializer.endTag(ns, TESTSUITE);
+ }
+
+ void print(KXmlSerializer serializer, TestRun testRun) throws IOException {
+ serializer.startTag(ns, TESTCASE);
+ serializer.attribute(ns, ATTR_NAME, testRun.getTestDescription().getName());
+ serializer.attribute(ns, ATTR_CLASSNAME, suiteName(testRun));
+ serializer.attribute(ns, ATTR_TIME, "0");
+
+ String result = ERROR_RESULTS.contains(testRun.getResult()) ? ERROR
+ : FAILED_RESULTS.contains(testRun.getResult()) ? FAILURE
+ : null;
+
+ if (result != null) {
+ serializer.startTag(ns, result);
+ String title = testRun.getTestDescription().getTitle();
+ if (title != null && title.length() > 0) {
+ serializer.attribute(ns, ATTR_MESSAGE, title);
+ }
+ serializer.attribute(ns, ATTR_TYPE, testRun.getResult().toString());
+ serializer.text(Strings.join(testRun.getOutputLines(), "\n"));
+ serializer.endTag(ns, result);
+ }
+
+ serializer.endTag(ns, TESTCASE);
+ }
+ }
+} \ No newline at end of file