OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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.base.test; | |
6 | |
7 import android.app.Instrumentation; | |
8 import android.content.Context; | |
9 import android.os.Bundle; | |
10 import android.os.SystemClock; | |
11 | |
12 import junit.framework.AssertionFailedError; | |
13 import junit.framework.TestCase; | |
14 import junit.framework.TestResult; | |
15 | |
16 import org.chromium.base.Log; | |
17 import org.chromium.base.test.util.CommandLineFlags; | |
18 import org.chromium.base.test.util.parameters.BaseParameter; | |
19 import org.chromium.base.test.util.parameters.Parameter; | |
20 import org.chromium.base.test.util.parameters.Parameterizable; | |
21 import org.chromium.base.test.util.parameters.ParameterizedTest; | |
22 | |
23 import java.io.PrintWriter; | |
24 import java.io.StringWriter; | |
25 import java.util.ArrayList; | |
26 import java.util.Arrays; | |
27 import java.util.List; | |
28 | |
29 /** | |
30 * A test result that can skip tests. | |
31 */ | |
32 public class BaseTestResult extends TestResult { | |
33 private static final String TAG = "cr.base.test"; | |
34 | |
35 private static final int SLEEP_INTERVAL = 50; // milliseconds | |
36 private static final int WAIT_DURATION = 5000; // milliseconds | |
37 | |
38 | |
39 private List<BaseParameter> mAvailableParameters; | |
40 private Instrumentation mInstrumentation; | |
41 private final List<SkipCheck> mSkipChecks; | |
42 | |
43 /** | |
44 * Creates an instance of BaseTestResult. | |
45 */ | |
46 public BaseTestResult(Instrumentation instrumentation) { | |
47 mSkipChecks = new ArrayList<SkipCheck>(); | |
48 mInstrumentation = instrumentation; | |
49 mAvailableParameters = new ArrayList<>(); | |
50 } | |
51 | |
52 /** | |
53 * An interface for classes that check whether a test case should be skipped . | |
54 */ | |
55 public interface SkipCheck { | |
56 /** | |
57 * | |
58 * Checks whether the given test case should be skipped. | |
59 * | |
60 * @param testCase The test case to check. | |
61 * @return Whether the test case should be skipped. | |
62 */ | |
63 public boolean shouldSkip(TestCase testCase); | |
64 } | |
65 | |
66 /** | |
67 * Adds a check for whether a test should run. | |
68 * | |
69 * @param skipCheck The check to add. | |
70 */ | |
71 public void addSkipCheck(SkipCheck skipCheck) { | |
72 mSkipChecks.add(skipCheck); | |
73 } | |
74 | |
75 protected boolean shouldSkip(final TestCase test) { | |
76 for (SkipCheck s : mSkipChecks) { | |
77 if (s.shouldSkip(test)) return true; | |
78 } | |
79 return false; | |
80 } | |
81 | |
82 @Override | |
83 protected void run(final TestCase test) { | |
84 if (shouldSkip(test)) { | |
85 startTest(test); | |
86 | |
87 Bundle skipResult = new Bundle(); | |
88 skipResult.putString("class", test.getClass().getName()); | |
89 skipResult.putString("test", test.getName()); | |
90 skipResult.putBoolean("test_skipped", true); | |
91 mInstrumentation.sendStatus(0, skipResult); | |
92 | |
93 endTest(test); | |
94 } else { | |
95 try { | |
96 CommandLineFlags.setUp( | |
97 getTargetContext(), | |
98 test.getClass().getMethod(test.getName())); | |
99 } catch (NoSuchMethodException e) { | |
100 Log.e(TAG, "Unable to set up CommandLineFlags", e); | |
101 } | |
102 | |
103 if (test instanceof Parameterizable) { | |
104 try { | |
105 runParameterized(test); | |
106 } catch (ThreadDeath e) { | |
107 Log.e(TAG, "Parameterized test run failed: %s", e); | |
108 } | |
109 } else { | |
110 super.run(test); | |
111 } | |
112 } | |
113 } | |
114 | |
115 @SuppressWarnings("unchecked") | |
116 private <T extends TestCase & Parameterizable> void runParameterized(final T estCase test) | |
117 throws ThreadDeath { | |
118 final T testCase = (T) test; | |
119 | |
120 Parameter.Reader parameterReader = new Parameter.Reader(test); | |
121 testCase.setParameterReader(parameterReader); | |
122 List<ParameterizedTest> parameterizedTests = parameterReader.getParamete rizedTests(); | |
123 if (!parameterizedTests.isEmpty()) { | |
124 | |
125 // Start and prepare test. | |
126 startTest(testCase); | |
127 List<ParameterError> errors = new ArrayList<>(); | |
128 List<ParameterError> failures = new ArrayList<>(); | |
129 mAvailableParameters.addAll(testCase.getAvailableParameters()); | |
jbudorick
2015/08/06 16:48:17
Make mAvailableParameters local to this function &
Sean Kirmani
2015/08/06 17:16:58
Done.
| |
130 | |
131 // Run the actual tests. | |
132 for (final ParameterizedTest parameterizedTest : parameterizedTests) { | |
133 parameterReader.setCurrentParameterizedTest(parameterizedTest); | |
134 try { | |
135 setUpParameters(testCase); | |
136 testCase.runBare(); | |
137 tearDownParameters(testCase); | |
138 } catch (AssertionFailedError e) { | |
139 failures.add(new ParameterError(e, parameterizedTest)); | |
140 } catch (ThreadDeath e) { | |
141 throw e; | |
142 } catch (Throwable e) { | |
143 errors.add(new ParameterError(e, parameterizedTest)); | |
144 } | |
145 } | |
146 | |
147 // Generate failures and errors. | |
148 if (!failures.isEmpty()) { | |
149 addFailure(test, new ParameterizedTestFailure(failures)); | |
150 } | |
151 if (!errors.isEmpty()) { | |
152 addError(test, new ParameterizedTestError(errors)); | |
153 } | |
154 | |
155 // End test. | |
156 mAvailableParameters = new ArrayList<>(); | |
157 endTest(testCase); | |
158 } else { | |
159 super.run(test); | |
160 } | |
161 } | |
162 | |
163 private <T extends TestCase & Parameterizable> void setUpParameters(final T test) | |
164 throws Exception { | |
165 Parameter.Reader parameterReader = new Parameter.Reader(test); | |
166 for (BaseParameter parameter : mAvailableParameters) { | |
167 if (parameterReader.getParameter(parameter.getTag()) != null) { | |
168 parameter.setUp(); | |
169 } | |
170 } | |
171 } | |
172 | |
173 private <T extends TestCase & Parameterizable> void tearDownParameters(final T test) | |
174 throws Exception { | |
175 Parameter.Reader parameterReader = new Parameter.Reader(test); | |
176 for (BaseParameter parameter : mAvailableParameters) { | |
177 if (parameterReader.getParameter(parameter.getTag()) != null) { | |
178 parameter.tearDown(); | |
179 } | |
180 } | |
181 } | |
182 | |
183 private static class ParameterError { | |
184 private Throwable mThrowable; | |
185 private ParameterizedTest mParameterizedTest; | |
186 | |
187 public ParameterError(Throwable throwable, ParameterizedTest parameteriz edTest) { | |
188 mThrowable = throwable; | |
189 mParameterizedTest = parameterizedTest; | |
190 } | |
191 | |
192 private Throwable getThrowable() { | |
193 return mThrowable; | |
194 } | |
195 | |
196 private ParameterizedTest getParameterizedTest() { | |
197 return mParameterizedTest; | |
198 } | |
199 } | |
200 | |
201 private static class ParameterizedTestFailure extends AssertionFailedError { | |
202 public ParameterizedTestFailure(List<ParameterError> failures) { | |
203 super(new ParameterizedTestError(failures).toString()); | |
204 } | |
205 } | |
206 | |
207 private static class ParameterizedTestError extends Exception { | |
208 public List<ParameterError> mErrors; | |
209 | |
210 public ParameterizedTestError(List<ParameterError> errors) { | |
211 mErrors = errors; | |
212 } | |
213 | |
214 @Override | |
215 public String toString() { | |
216 StringBuffer buffer = new StringBuffer(); | |
217 buffer.append('\n'); | |
jbudorick
2015/08/06 16:48:17
nit: collapse this line into the ctor above
Sean Kirmani
2015/08/06 17:16:58
Done.
| |
218 for (ParameterError error : mErrors) { | |
219 List<Parameter> parameters = | |
220 Arrays.asList(error.getParameterizedTest().parameters()) ; | |
221 if (!parameters.isEmpty()) { | |
222 StringBuffer parametersString = new StringBuffer(); | |
223 for (int i = 0; i < parameters.size(); i++) { | |
224 parametersString.append(parameters.get(i).tag()); | |
225 if (i != parameters.size() - 1) { | |
226 parametersString.append(','); | |
227 } | |
228 } | |
229 buffer.append(String.format("%s (with parameters %s)%n", | |
230 error.getThrowable().toString(), parametersString.to String())); | |
231 } else { | |
232 buffer.append(String.format("%s (with no parameters)%n", | |
233 error.getThrowable().toString())); | |
234 } | |
235 buffer.append(trace(error) + '\n'); | |
236 } | |
237 return buffer.toString(); | |
238 } | |
239 | |
240 /** | |
241 * @return the trace without the error message | |
242 */ | |
243 private String trace(ParameterError error) { | |
244 StringWriter stringWriter = new StringWriter(); | |
245 PrintWriter writer = new PrintWriter(stringWriter); | |
246 error.getThrowable().printStackTrace(writer); | |
247 StringBuffer buffer = stringWriter.getBuffer(); | |
248 return buffer.toString().substring(buffer.toString().indexOf('\n') + 1); | |
249 } | |
250 } | |
251 | |
252 /** | |
253 * Gets the target context. | |
254 * | |
255 * On older versions of Android, getTargetContext() may initially return nul l, so we have to | |
256 * wait for it to become available. | |
257 * | |
258 * @return The target {@link android.content.Context} if available; null oth erwise. | |
259 */ | |
260 public Context getTargetContext() { | |
261 Context targetContext = mInstrumentation.getTargetContext(); | |
262 try { | |
263 long startTime = SystemClock.uptimeMillis(); | |
264 // TODO(jbudorick): Convert this to CriteriaHelper once that moves t o base/. | |
265 while (targetContext == null | |
266 && SystemClock.uptimeMillis() - startTime < WAIT_DURATION) { | |
267 Thread.sleep(SLEEP_INTERVAL); | |
268 targetContext = mInstrumentation.getTargetContext(); | |
269 } | |
270 } catch (InterruptedException e) { | |
271 Log.e(TAG, "Interrupted while attempting to initialize the command l ine."); | |
272 } | |
273 return targetContext; | |
274 } | |
275 } | |
OLD | NEW |