Index: testing/android/java/src/org/chromium/native_test/ChromiumNativeTestInstrumentationTestRunner.java |
diff --git a/testing/android/java/src/org/chromium/native_test/ChromiumNativeTestInstrumentationTestRunner.java b/testing/android/java/src/org/chromium/native_test/ChromiumNativeTestInstrumentationTestRunner.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5e8d8e5b72aca064748c87f49fb98b2c3c88387a |
--- /dev/null |
+++ b/testing/android/java/src/org/chromium/native_test/ChromiumNativeTestInstrumentationTestRunner.java |
@@ -0,0 +1,196 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.native_test; |
+ |
+import android.app.Activity; |
+import android.app.Instrumentation; |
+import android.content.ComponentName; |
+import android.content.Intent; |
+import android.os.Bundle; |
+import android.util.Log; |
+ |
+import java.io.BufferedInputStream; |
+import java.io.BufferedReader; |
+import java.io.File; |
+import java.io.FileInputStream; |
+import java.io.FileNotFoundException; |
+import java.io.IOException; |
+import java.io.InputStreamReader; |
+import java.util.HashMap; |
+import java.util.Map; |
+import java.util.regex.Matcher; |
+import java.util.regex.Pattern; |
+ |
+/** |
+ * An Instrumentation that runs tests based on ChromeNativeTestActivity. |
+ */ |
+public class ChromiumNativeTestInstrumentationTestRunner extends Instrumentation { |
+ |
+ private static final String TAG = "ChromiumNativeTestInstrumentationTestRunner"; |
+ private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*) *\\] ?([^ ]*) .*"); |
+ |
+ private static interface ResultsBundleGenerator { |
+ public Bundle generate(Map<String, TestResult> rawResults); |
+ } |
+ |
+ private String mCommandLineFile; |
+ private String mCommandLineFlags; |
+ private Bundle mLogBundle; |
+ private ResultsBundleGenerator mBundleGenerator; |
+ |
+ @Override |
+ public void onCreate(Bundle arguments) { |
+ mCommandLineFile = arguments.getString(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FILE); |
+ mCommandLineFlags = arguments.getString(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FLAGS); |
+ mLogBundle = new Bundle(); |
+ mBundleGenerator = new RobotiumBundleGenerator(); |
+ start(); |
+ } |
+ |
+ @Override |
+ public void onStart() { |
+ super.onStart(); |
+ Bundle results = runTests(); |
+ finish(Activity.RESULT_OK, results); |
+ } |
+ |
+ /** Runs the tests in the ChromeNativeTestActivity and returns a Bundle containing the results. |
+ */ |
+ private Bundle runTests() { |
+ Log.i(TAG, "Creating activity."); |
+ Activity activityUnderTest = startNativeTestActivity(); |
+ |
+ Log.i(TAG, "Getting results from FIFO."); |
+ Map<String, TestResult> results = parseResultsFromFifo(activityUnderTest); |
+ |
+ Log.i(TAG, "Finishing activity."); |
+ activityUnderTest.finish(); |
+ |
+ Log.i(TAG, "Parsing results and generating output."); |
+ return mBundleGenerator.generate(results); |
+ } |
+ |
+ /** Starts the ChromeNativeTestActivty. |
+ */ |
+ private Activity startNativeTestActivity() { |
+ Intent i = new Intent(Intent.ACTION_MAIN); |
+ i.setComponent(new ComponentName( |
+ "org.chromium.native_test", |
+ "org.chromium.native_test.ChromeNativeTestActivity")); |
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
+ if (mCommandLineFile != null) { |
+ Log.i(TAG, "Passing command line file extra: " + mCommandLineFile); |
+ i.putExtra(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FILE, mCommandLineFile); |
+ } |
+ if (mCommandLineFlags != null) { |
+ Log.i(TAG, "Passing command line flag extra: " + mCommandLineFlags); |
+ i.putExtra(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FLAGS, mCommandLineFlags); |
+ } |
+ return startActivitySync(i); |
+ } |
+ |
+ private static enum TestResult { |
+ PASSED, FAILED, ERROR, UNKNOWN |
+ } |
+ |
+ /** |
+ * Generates a map between test names and test results from the instrumented Activity's FIFO. |
+ */ |
+ private Map<String, TestResult> parseResultsFromFifo(Activity activityUnderTest) { |
+ Map<String, TestResult> results = new HashMap<String, TestResult>(); |
+ |
+ File fifo = null; |
+ BufferedReader r = null; |
+ |
+ try { |
+ // Wait for the test to create the FIFO. |
+ fifo = new File(getTargetContext().getFilesDir().getAbsolutePath(), "test.fifo"); |
+ while (!fifo.exists()) { |
+ Thread.sleep(1000); |
+ } |
+ |
+ r = new BufferedReader( |
+ new InputStreamReader(new BufferedInputStream(new FileInputStream(fifo)))); |
+ |
+ StringBuilder resultsStr = new StringBuilder(); |
+ for (String l = r.readLine(); l != null && !l.equals("<<ScopedMainEntryLogger"); |
+ l = r.readLine()) { |
+ Matcher m = RE_TEST_OUTPUT.matcher(l); |
+ if (m.matches()) { |
+ if (m.group(1).equals("RUN")) { |
+ results.put(m.group(2), TestResult.UNKNOWN); |
+ } else if (m.group(1).equals("FAILED")) { |
+ results.put(m.group(2), TestResult.FAILED); |
+ } else if (m.group(1).equals("OK")) { |
+ results.put(m.group(2), TestResult.PASSED); |
+ } |
+ } |
+ resultsStr.append(l); |
+ resultsStr.append("\n"); |
+ } |
+ mLogBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, resultsStr.toString()); |
+ sendStatus(0, mLogBundle); |
+ } catch (InterruptedException e) { |
+ Log.e(TAG, "Interrupted while waiting for FIFO file creation: " + e.toString()); |
+ } catch (FileNotFoundException e) { |
+ Log.e(TAG, "Couldn't find FIFO file: " + e.toString()); |
+ } catch (IOException e) { |
+ Log.e(TAG, "Error handling FIFO file: " + e.toString()); |
+ } finally { |
+ if (r != null) { |
+ try { |
+ r.close(); |
+ } catch (IOException e) { |
+ Log.e(TAG, "Error while closing FIFO reader."); |
+ } |
+ } |
+ if (fifo != null) { |
+ if (!fifo.delete()) { |
+ Log.e(TAG, "Unable to delete " + fifo.getAbsolutePath()); |
+ } |
+ } |
+ } |
+ return results; |
+ } |
+ |
+ /** |
+ * Creates a results bundle that emulates the one created by Robotium. |
+ */ |
+ private static class RobotiumBundleGenerator implements ResultsBundleGenerator { |
+ public Bundle generate(Map<String, TestResult> rawResults) { |
+ Bundle resultsBundle = new Bundle(); |
+ |
+ int testsPassed = 0; |
+ int testsFailed = 0; |
+ |
+ for (Map.Entry<String, TestResult> entry : rawResults.entrySet()) { |
+ switch (entry.getValue()) { |
+ case PASSED: |
+ ++testsPassed; |
+ break; |
+ case FAILED: |
+ ++testsFailed; |
+ break; |
+ default: |
+ Log.w(TAG, "Unhandled: " + entry.getKey() + ", " |
+ + entry.getValue().toString()); |
+ break; |
+ } |
+ } |
+ |
+ StringBuilder resultBuilder = new StringBuilder(); |
+ resultBuilder.append("\nOK (" + Integer.toString(testsPassed) + " tests)"); |
+ if (testsFailed > 0) { |
+ resultBuilder.append( |
+ "\nFAILURES!!! Tests run: " + Integer.toString(rawResults.size()) |
+ + ", Failures: " + Integer.toString(testsFailed) + ", Errors: 0"); |
+ } |
+ resultsBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, |
+ resultBuilder.toString()); |
+ return resultsBundle; |
+ } |
+ } |
+ |
+} |