OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.native_test; | |
6 | |
7 import android.app.Activity; | |
8 import android.app.Instrumentation; | |
9 import android.content.ComponentName; | |
10 import android.content.Intent; | |
11 import android.os.Bundle; | |
12 import android.os.Environment; | |
13 import android.util.Log; | |
14 | |
15 import java.io.BufferedInputStream; | |
16 import java.io.BufferedReader; | |
17 import java.io.File; | |
18 import java.io.FileInputStream; | |
19 import java.io.FileNotFoundException; | |
20 import java.io.IOException; | |
21 import java.io.InputStreamReader; | |
22 import java.util.HashMap; | |
23 import java.util.Map; | |
24 import java.util.regex.Matcher; | |
25 import java.util.regex.Pattern; | |
26 | |
27 /** | |
28 * An Instrumentation that runs tests based on ChromeNativeTestActivity. | |
29 */ | |
30 public class ChromeNativeTestInstrumentationTestRunner extends Instrumentation { | |
31 // TODO(jbudorick): Remove this extra when b/18981674 is fixed. | |
32 public static final String EXTRA_ONLY_OUTPUT_FAILURES = | |
33 "org.chromium.native_test.ChromeNativeTestInstrumentationTestRunner.
" | |
34 + "OnlyOutputFailures"; | |
35 | |
36 private static final String TAG = "ChromeNativeTestInstrumentationTestRunner
"; | |
37 | |
38 private static final int ACCEPT_TIMEOUT_MS = 5000; | |
39 private static final Pattern RE_TEST_OUTPUT = Pattern.compile("\\[ *([^ ]*)
*\\] ?([^ ]+) .*"); | |
40 | |
41 private static interface ResultsBundleGenerator { | |
42 public Bundle generate(Map<String, TestResult> rawResults); | |
43 } | |
44 | |
45 private String mCommandLineFile; | |
46 private String mCommandLineFlags; | |
47 private File mStdoutFile; | |
48 private Bundle mLogBundle; | |
49 private ResultsBundleGenerator mBundleGenerator; | |
50 private boolean mOnlyOutputFailures; | |
51 | |
52 @Override | |
53 public void onCreate(Bundle arguments) { | |
54 mCommandLineFile = arguments.getString(ChromeNativeTestActivity.EXTRA_CO
MMAND_LINE_FILE); | |
55 mCommandLineFlags = arguments.getString(ChromeNativeTestActivity.EXTRA_C
OMMAND_LINE_FLAGS); | |
56 try { | |
57 mStdoutFile = File.createTempFile( | |
58 ".temp_stdout_", ".txt", Environment.getExternalStorageDirec
tory()); | |
59 Log.i(TAG, "stdout file created: " + mStdoutFile.getAbsolutePath()); | |
60 } catch (IOException e) { | |
61 Log.e(TAG, "Unable to create temporary stdout file." + e.toString())
; | |
62 finish(Activity.RESULT_CANCELED, new Bundle()); | |
63 return; | |
64 } | |
65 mLogBundle = new Bundle(); | |
66 mBundleGenerator = new RobotiumBundleGenerator(); | |
67 mOnlyOutputFailures = arguments.containsKey(EXTRA_ONLY_OUTPUT_FAILURES); | |
68 start(); | |
69 } | |
70 | |
71 @Override | |
72 public void onStart() { | |
73 super.onStart(); | |
74 Bundle results = runTests(); | |
75 finish(Activity.RESULT_OK, results); | |
76 } | |
77 | |
78 /** Runs the tests in the ChromeNativeTestActivity and returns a Bundle cont
aining the results. | |
79 */ | |
80 private Bundle runTests() { | |
81 Log.i(TAG, "Creating activity."); | |
82 Activity activityUnderTest = startNativeTestActivity(); | |
83 | |
84 Log.i(TAG, "Waiting for tests to finish."); | |
85 try { | |
86 while (!activityUnderTest.isFinishing()) { | |
87 Thread.sleep(100); | |
88 } | |
89 } catch (InterruptedException e) { | |
90 Log.e(TAG, "Interrupted while waiting for activity to be destroyed:
" + e.toString()); | |
91 } | |
92 | |
93 Log.i(TAG, "Getting results."); | |
94 Map<String, TestResult> results = parseResults(activityUnderTest); | |
95 | |
96 Log.i(TAG, "Parsing results and generating output."); | |
97 return mBundleGenerator.generate(results); | |
98 } | |
99 | |
100 /** Starts the ChromeNativeTestActivty. | |
101 */ | |
102 private Activity startNativeTestActivity() { | |
103 Intent i = new Intent(Intent.ACTION_MAIN); | |
104 i.setComponent(new ComponentName( | |
105 "org.chromium.native_test", | |
106 "org.chromium.native_test.ChromeNativeTestActivity")); | |
107 i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
108 if (mCommandLineFile != null) { | |
109 Log.i(TAG, "Passing command line file extra: " + mCommandLineFile); | |
110 i.putExtra(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FILE, mComman
dLineFile); | |
111 } | |
112 if (mCommandLineFlags != null) { | |
113 Log.i(TAG, "Passing command line flag extra: " + mCommandLineFlags); | |
114 i.putExtra(ChromeNativeTestActivity.EXTRA_COMMAND_LINE_FLAGS, mComma
ndLineFlags); | |
115 } | |
116 i.putExtra(ChromeNativeTestActivity.EXTRA_STDOUT_FILE, mStdoutFile.getAb
solutePath()); | |
117 return startActivitySync(i); | |
118 } | |
119 | |
120 private static enum TestResult { | |
121 PASSED, FAILED, ERROR, UNKNOWN | |
122 } | |
123 | |
124 /** | |
125 * Generates a map between test names and test results from the instrumente
d Activity's | |
126 * output. | |
127 */ | |
128 private Map<String, TestResult> parseResults(Activity activityUnderTest) { | |
129 Map<String, TestResult> results = new HashMap<String, TestResult>(); | |
130 | |
131 BufferedReader r = null; | |
132 | |
133 try { | |
134 if (mStdoutFile == null || !mStdoutFile.exists()) { | |
135 Log.e(TAG, "Unable to find stdout file."); | |
136 return results; | |
137 } | |
138 | |
139 r = new BufferedReader(new InputStreamReader( | |
140 new BufferedInputStream(new FileInputStream(mStdoutFile)))); | |
141 | |
142 for (String l = r.readLine(); l != null && !l.equals("<<ScopedMainEn
tryLogger"); | |
143 l = r.readLine()) { | |
144 Matcher m = RE_TEST_OUTPUT.matcher(l); | |
145 boolean isFailure = false; | |
146 if (m.matches()) { | |
147 if (m.group(1).equals("RUN")) { | |
148 results.put(m.group(2), TestResult.UNKNOWN); | |
149 } else if (m.group(1).equals("FAILED")) { | |
150 results.put(m.group(2), TestResult.FAILED); | |
151 isFailure = true; | |
152 mLogBundle.putString(Instrumentation.REPORT_KEY_STREAMRE
SULT, l + "\n"); | |
153 sendStatus(0, mLogBundle); | |
154 } else if (m.group(1).equals("OK")) { | |
155 results.put(m.group(2), TestResult.PASSED); | |
156 } | |
157 } | |
158 | |
159 // TODO(jbudorick): mOnlyOutputFailures is a workaround for b/18
981674. Remove it | |
160 // once that issue is fixed. | |
161 if (!mOnlyOutputFailures || isFailure) { | |
162 mLogBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT
, l + "\n"); | |
163 sendStatus(0, mLogBundle); | |
164 } | |
165 Log.i(TAG, l); | |
166 } | |
167 } catch (FileNotFoundException e) { | |
168 Log.e(TAG, "Couldn't find stdout file file: " + e.toString()); | |
169 } catch (IOException e) { | |
170 Log.e(TAG, "Error handling stdout file: " + e.toString()); | |
171 } finally { | |
172 if (r != null) { | |
173 try { | |
174 r.close(); | |
175 } catch (IOException e) { | |
176 Log.e(TAG, "Error while closing stdout reader."); | |
177 } | |
178 } | |
179 if (mStdoutFile != null) { | |
180 if (!mStdoutFile.delete()) { | |
181 Log.e(TAG, "Unable to delete " + mStdoutFile.getAbsolutePath
()); | |
182 } | |
183 } | |
184 } | |
185 return results; | |
186 } | |
187 | |
188 /** | |
189 * Creates a results bundle that emulates the one created by Robotium. | |
190 */ | |
191 private static class RobotiumBundleGenerator implements ResultsBundleGenerat
or { | |
192 public Bundle generate(Map<String, TestResult> rawResults) { | |
193 Bundle resultsBundle = new Bundle(); | |
194 | |
195 int testsPassed = 0; | |
196 int testsFailed = 0; | |
197 | |
198 for (Map.Entry<String, TestResult> entry : rawResults.entrySet()) { | |
199 switch (entry.getValue()) { | |
200 case PASSED: | |
201 ++testsPassed; | |
202 break; | |
203 case FAILED: | |
204 // TODO(jbudorick): Remove this log message once AMP exe
cution and | |
205 // results handling has been stabilized. | |
206 Log.d(TAG, "FAILED: " + entry.getKey()); | |
207 ++testsFailed; | |
208 break; | |
209 default: | |
210 Log.w(TAG, "Unhandled: " + entry.getKey() + ", " | |
211 + entry.getValue().toString()); | |
212 break; | |
213 } | |
214 } | |
215 | |
216 StringBuilder resultBuilder = new StringBuilder(); | |
217 if (testsFailed > 0) { | |
218 resultBuilder.append( | |
219 "\nFAILURES!!! Tests run: " + Integer.toString(rawResult
s.size()) | |
220 + ", Failures: " + Integer.toString(testsFailed) + ", Er
rors: 0"); | |
221 } else { | |
222 resultBuilder.append("\nOK (" + Integer.toString(testsPassed) +
" tests)"); | |
223 } | |
224 resultsBundle.putString(Instrumentation.REPORT_KEY_STREAMRESULT, | |
225 resultBuilder.toString()); | |
226 return resultsBundle; | |
227 } | |
228 } | |
229 | |
230 } | |
OLD | NEW |