diff --git a/astrid/src/androidTest/java/com/zutubi/android/junitreport/Compatibility.java b/astrid/src/androidTest/java/com/zutubi/android/junitreport/Compatibility.java
deleted file mode 100644
index 37703924b..000000000
--- a/astrid/src/androidTest/java/com/zutubi/android/junitreport/Compatibility.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.zutubi.android.junitreport;
-
-import android.content.Context;
-import android.os.Environment;
-import android.util.Log;
-
-import java.io.File;
-import java.lang.reflect.Method;
-
-/**
- * Utilities for backwards-compatibility with early Android versions.
- */
-public final class Compatibility {
- private static final String LOG_TAG = Compatibility.class.getSimpleName();
-
- private static final Method METHOD_GET_EXTERNAL_FILES_DIR;
- static {
- Method method = null;
- try {
- method = Context.class.getMethod("getExternalFilesDir", String.class);
- } catch (Exception e) {
- // Expected for API 7 and below. Fall back will be engaged.
- }
- METHOD_GET_EXTERNAL_FILES_DIR = method;
- }
-
- /**
- * Do not instantiate.
- */
- private Compatibility() {
- }
-
- /**
- * A backwards-compatible version of {@link Context#getExternalFilesDir(String)}
- * which falls back to using {@link Environment#getExternalStorageDirectory()}
- * on API 7 and below.
- *
- * @param context context to get the external files directory for
- * @return the path of the directory holding application files on external
- * storage, or null if external storage cannot be accessed
- */
- public static File getExternalFilesDir(final Context context) {
- if (METHOD_GET_EXTERNAL_FILES_DIR == null) {
- final File externalRoot = Environment.getExternalStorageDirectory();
- if (externalRoot == null) {
- return null;
- }
-
- final String packageName = context.getApplicationContext().getPackageName();
- return new File(externalRoot, "Android/data/" + packageName + "/files");
- } else {
- try {
- return (File) METHOD_GET_EXTERNAL_FILES_DIR.invoke(context);
- } catch (Exception e) {
- Log.e(LOG_TAG, "Could not invoke getExternalFilesDir: " + e.getMessage(), e);
- return null;
- }
- }
- }
-}
diff --git a/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportListener.java b/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportListener.java
deleted file mode 100644
index 13d534396..000000000
--- a/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportListener.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2010-2012 Zutubi Pty Ltd
- *
- * 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.zutubi.android.junitreport;
-
-import android.content.Context;
-import android.util.Log;
-import android.util.Xml;
-
-import junit.framework.AssertionFailedError;
-import junit.framework.Test;
-import junit.framework.TestCase;
-import junit.framework.TestListener;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.Locale;
-
-/**
- * Custom test listener that outputs test results to XML files. The files
- * use a similar format to the Ant JUnit task XML formatter, with a few of
- * caveats:
- *
- * -
- * By default, multiple suites are all placed in a single file under a root
- * <testsuites> element. In multiFile mode a separate file is
- * created for each suite, which may be more compatible with existing
- * tools.
- *
- * -
- * Redundant information about the number of nested cases within a suite is
- * omitted.
- *
- * -
- * Durations are omitted from suites.
- *
- * -
- * Neither standard output nor system properties are included.
- *
- *
- * The differences mainly revolve around making this reporting as lightweight as
- * possible. The report is streamed as the tests run, making it impossible to,
- * e.g. include the case count in a <testsuite> element.
- */
-public class JUnitReportListener implements TestListener {
- private static final String LOG_TAG = JUnitReportListener.class.getSimpleName();
-
- private static final String ENCODING_UTF_8 = "utf-8";
-
- public static final String TOKEN_SUITE = "__suite__";
- public static final String TOKEN_EXTERNAL = "__external__";
-
- private static final String TAG_SUITES = "testsuites";
- private static final String TAG_SUITE = "testsuite";
- private static final String TAG_CASE = "testcase";
- private static final String TAG_ERROR = "error";
- private static final String TAG_FAILURE = "failure";
-
- private static final String ATTRIBUTE_NAME = "name";
- private static final String ATTRIBUTE_CLASS = "classname";
- private static final String ATTRIBUTE_TYPE = "type";
- private static final String ATTRIBUTE_MESSAGE = "message";
- private static final String ATTRIBUTE_TIME = "time";
-
- // With thanks to org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner.
- // Trimmed some entries, added others for Android.
- private static final String[] DEFAULT_TRACE_FILTERS = new String[] {
- "junit.framework.TestCase", "junit.framework.TestResult",
- "junit.framework.TestSuite",
- "junit.framework.Assert.", // don't filter AssertionFailure
- "java.lang.reflect.Method.invoke(", "sun.reflect.",
- // JUnit 4 support:
- "org.junit.", "junit.framework.JUnit4TestAdapter", " more",
- // Added for Android
- "android.test.", "android.app.Instrumentation",
- "java.lang.reflect.Method.invokeNative",
- };
-
- private Context mTargetContext;
- private String mReportFile;
- private String mReportDir;
- private boolean mFilterTraces;
- private boolean mMultiFile;
- private FileOutputStream mOutputStream;
- private XmlSerializer mSerializer;
- private String mCurrentSuite;
-
- // simple time tracking
- private boolean mTimeAlreadyWritten = false;
- private long mTestStartTime;
-
- /**
- * Creates a new listener.
- *
- * @param targetContext context of the application under test
- * @param reportFile name of the report file(s) to create
- * @param reportDir path of the directory under which to write files
- * (may be null in which case files are written under
- * the context using {@link Context#openFileOutput(String, int)}).
- * @param filterTraces if true, stack traces will have common noise (e.g.
- * framework methods) omitted for clarity
- * @param multiFile if true, use a separate file for each test suite
- */
- public JUnitReportListener(Context targetContext, String reportFile, String reportDir, boolean filterTraces, boolean multiFile) {
- Log.i(LOG_TAG, "Listener created with arguments:\n" +
- " report file : '" + reportFile + "'\n" +
- " report dir : '" + reportDir + "'\n" +
- " filter traces: " + filterTraces + "\n" +
- " multi file : " + multiFile);
-
- this.mTargetContext = targetContext;
- this.mReportFile = reportFile;
- this.mReportDir = reportDir;
- this.mFilterTraces = filterTraces;
- this.mMultiFile = multiFile;
- }
-
- @Override
- public void startTest(Test test) {
- try {
- if (test instanceof TestCase) {
- TestCase testCase = (TestCase) test;
- checkForNewSuite(testCase);
- mSerializer.startTag("", TAG_CASE);
- mSerializer.attribute("", ATTRIBUTE_CLASS, mCurrentSuite);
- mSerializer.attribute("", ATTRIBUTE_NAME, testCase.getName());
-
- mTimeAlreadyWritten = false;
- mTestStartTime = System.currentTimeMillis();
- }
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- }
- }
-
- private void checkForNewSuite(TestCase testCase) throws IOException {
- String suiteName = testCase.getClass().getName();
- if (mCurrentSuite == null || !mCurrentSuite.equals(suiteName)) {
- if (mCurrentSuite != null) {
- if (mMultiFile) {
- close();
- } else {
- mSerializer.endTag("", TAG_SUITE);
- mSerializer.flush();
- }
- }
-
- openIfRequired(suiteName);
-
- mSerializer.startTag("", TAG_SUITE);
- mSerializer.attribute("", ATTRIBUTE_NAME, suiteName);
- mCurrentSuite = suiteName;
- }
- }
-
- private void openIfRequired(String suiteName) {
- try {
- if (mSerializer == null) {
- mOutputStream = openOutputStream(resolveFileName(suiteName));
- mSerializer = Xml.newSerializer();
- mSerializer.setOutput(mOutputStream, ENCODING_UTF_8);
- mSerializer.startDocument(ENCODING_UTF_8, true);
- if (!mMultiFile) {
- mSerializer.startTag("", TAG_SUITES);
- }
- }
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- throw new RuntimeException("Unable to open serializer: " + e.getMessage(), e);
- }
- }
-
- private String resolveFileName(String suiteName) {
- String fileName = mReportFile;
- if (mMultiFile) {
- fileName = fileName.replace(TOKEN_SUITE, suiteName);
- }
- return fileName;
- }
-
- private FileOutputStream openOutputStream(String fileName) throws IOException {
- if (mReportDir == null) {
- Log.d(LOG_TAG, "No reportDir specified. Opening report file '" + fileName + "' in internal storage of app under test");
- return mTargetContext.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
- } else {
- if (mReportDir.contains(TOKEN_EXTERNAL)) {
- File externalDir = Compatibility.getExternalFilesDir(mTargetContext);
- if (externalDir == null) {
- Log.e(LOG_TAG, "reportDir references external storage, but external storage is not available (check mounting and permissions)");
- throw new IOException("Cannot access external storage");
- }
-
- String externalPath = externalDir.getAbsolutePath();
- if (externalPath.endsWith("/")) {
- externalPath = externalPath.substring(0, externalPath.length() - 1);
- }
-
- mReportDir = mReportDir.replace(TOKEN_EXTERNAL, externalPath);
- }
-
- ensureDirectoryExists(mReportDir);
-
- File outputFile = new File(mReportDir, fileName);
- Log.d(LOG_TAG, "Opening report file '" + outputFile.getAbsolutePath() + "'");
- return new FileOutputStream(outputFile);
- }
- }
-
- private void ensureDirectoryExists(String path) throws IOException {
- File dir = new File(path);
- if (!dir.isDirectory() && !dir.mkdirs()) {
- final String message = "Cannot create directory '" + path + "'";
- Log.e(LOG_TAG, message);
- throw new IOException(message);
- }
- }
-
- @Override
- public void addError(Test test, Throwable error) {
- addProblem(TAG_ERROR, error);
- }
-
- @Override
- public void addFailure(Test test, AssertionFailedError error) {
- addProblem(TAG_FAILURE, error);
- }
-
- private void addProblem(String tag, Throwable error) {
- try {
- recordTestTime();
-
- mSerializer.startTag("", tag);
- mSerializer.attribute("", ATTRIBUTE_MESSAGE, safeMessage(error));
- mSerializer.attribute("", ATTRIBUTE_TYPE, error.getClass().getName());
- StringWriter w = new StringWriter();
- error.printStackTrace(mFilterTraces ? new FilteringWriter(w) : new PrintWriter(w));
- mSerializer.text(w.toString());
- mSerializer.endTag("", tag);
- mSerializer.flush();
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- }
- }
-
- private void recordTestTime() throws IOException {
- if (!mTimeAlreadyWritten) {
- mTimeAlreadyWritten = true;
- mSerializer.attribute("", ATTRIBUTE_TIME, String.format(Locale.ENGLISH, "%.3f",
- (System.currentTimeMillis() - mTestStartTime) / 1000.));
- }
- }
-
- @Override
- public void endTest(Test test) {
- try {
- if (test instanceof TestCase) {
- recordTestTime();
- mSerializer.endTag("", TAG_CASE);
- mSerializer.flush();
- }
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- }
- }
-
- /**
- * Releases all resources associated with this listener. Must be called
- * when the listener is finished with.
- */
- public void close() {
- if (mSerializer != null) {
- try {
- // Do this just in case endTest() was not called due to a crash in native code.
- if (TAG_CASE.equals(mSerializer.getName())) {
- mSerializer.endTag("", TAG_CASE);
- }
-
- if (mCurrentSuite != null) {
- mSerializer.endTag("", TAG_SUITE);
- }
-
- if (!mMultiFile) {
- mSerializer.endTag("", TAG_SUITES);
- }
- mSerializer.endDocument();
- mSerializer.flush();
- mSerializer = null;
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- }
- }
-
- if (mOutputStream != null) {
- try {
- mOutputStream.close();
- mOutputStream = null;
- } catch (IOException e) {
- Log.e(LOG_TAG, safeMessage(e));
- }
- }
- }
-
- private String safeMessage(Throwable error) {
- String message = error.getMessage();
- return error.getClass().getName() + ": " + (message == null ? "" : message);
- }
-
- /**
- * Wrapper around a print writer that filters out common noise from stack
- * traces, making it easier to see the actual failure.
- */
- private static class FilteringWriter extends PrintWriter {
- public FilteringWriter(Writer out) {
- super(out);
- }
-
- @Override
- public void println(String s) {
- for (String filtered : DEFAULT_TRACE_FILTERS) {
- if (s.contains(filtered)) {
- return;
- }
- }
-
- super.println(s);
- }
- }
-}
diff --git a/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportTestRunner.java b/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportTestRunner.java
deleted file mode 100644
index 87d2f395c..000000000
--- a/astrid/src/androidTest/java/com/zutubi/android/junitreport/JUnitReportTestRunner.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2010-2012 Zutubi Pty Ltd
- *
- * 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.zutubi.android.junitreport;
-
-import android.os.Bundle;
-import android.test.AndroidTestRunner;
-import android.test.InstrumentationTestRunner;
-import android.util.Log;
-
-/**
- * Custom test runner that adds a {@link JUnitReportListener} to the underlying
- * test runner in order to capture test results in an XML report. You may use
- * this class in place of {@link InstrumentationTestRunner} in your test
- * project's manifest, and/or specify it to your Ant build using the test.runner
- * property.
- *
- * This runner behaves identically to the default, with the added side-effect of
- * producing JUnit XML reports. The report format is similar to that produced
- * by the Ant JUnit task's XML formatter, making it compatible with existing
- * tools that can process that format. See {@link JUnitReportListener} for
- * further details.
- *
- * This runner accepts arguments specified by the ARG_* constants. For details
- * refer to the README.
- */
-public class JUnitReportTestRunner extends InstrumentationTestRunner {
- /**
- * Name of the report file(s) to write, may contain __suite__ in multiFile mode.
- */
- private static final String ARG_REPORT_FILE = "reportFile";
- /**
- * If specified, path of the directory to write report files to. May start with __external__.
- * If not set files are written to the internal storage directory of the app under test.
- */
- private static final String ARG_REPORT_DIR = "reportDir";
- /**
- * If true, stack traces in the report will be filtered to remove common noise (e.g. framework
- * methods).
- */
- private static final String ARG_FILTER_TRACES = "filterTraces";
- /**
- * If true, produce a separate file for each test suite. By default a single report is created
- * for all suites.
- */
- private static final String ARG_MULTI_FILE = "multiFile";
- /**
- * Default name of the single report file.
- */
- private static final String DEFAULT_SINGLE_REPORT_FILE = "junit-report.xml";
- /**
- * Default name pattern for multiple report files.
- */
- private static final String DEFAULT_MULTI_REPORT_FILE = "junit-report-" + JUnitReportListener.TOKEN_SUITE + ".xml";
-
- private static final String LOG_TAG = JUnitReportTestRunner.class.getSimpleName();
-
- private JUnitReportListener mListener;
- private String mReportFile;
- private String mReportDir;
- private boolean mFilterTraces = true;
- private boolean mMultiFile = false;
-
- @Override
- public void onCreate(Bundle arguments) {
- if (arguments != null) {
- Log.i(LOG_TAG, "Created with arguments: " + arguments.keySet());
- mReportFile = arguments.getString(ARG_REPORT_FILE);
- mReportDir = arguments.getString(ARG_REPORT_DIR);
- mFilterTraces = getBooleanArgument(arguments, ARG_FILTER_TRACES, true);
- mMultiFile = getBooleanArgument(arguments, ARG_MULTI_FILE, false);
- } else {
- Log.i(LOG_TAG, "No arguments provided");
- }
-
- if (mReportFile == null) {
- mReportFile = mMultiFile ? DEFAULT_MULTI_REPORT_FILE : DEFAULT_SINGLE_REPORT_FILE;
- Log.i(LOG_TAG, "Defaulted report file to '" + mReportFile + "'");
- }
-
- super.onCreate(arguments);
- }
-
- private boolean getBooleanArgument(Bundle arguments, String name, boolean defaultValue)
- {
- String value = arguments.getString(name);
- if (value == null) {
- return defaultValue;
- } else {
- return Boolean.parseBoolean(value);
- }
- }
-
- /**
- * Subclass and override this if you want to use a different TestRunner type.
- *
- * @return the test runner to use
- */
- protected AndroidTestRunner makeAndroidTestRunner() {
- return new AndroidTestRunner();
- }
-
- @Override
- protected AndroidTestRunner getAndroidTestRunner() {
- AndroidTestRunner runner = makeAndroidTestRunner();
- mListener = new JUnitReportListener(getTargetContext(), mReportFile, mReportDir, mFilterTraces, mMultiFile);
- runner.addTestListener(mListener);
- return runner;
- }
-
- @Override
- public void finish(int resultCode, Bundle results) {
- if (mListener != null) {
- mListener.close();
- }
-
- super.finish(resultCode, results);
- }
-}