Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: android_webview/javatests/src/org/chromium/android_webview/test/AwTestCommon.java

Issue 2933623002: Create AwJUnit4ClassRunner AwActivityTestRule and convert AwContentsTest (Closed)
Patch Set: address bo's comments Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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.android_webview.test;
6
7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
8
9 import android.app.Instrumentation;
10 import android.content.Context;
11 import android.util.AndroidRuntimeException;
12
13 import org.junit.Assert;
14
15 import org.chromium.android_webview.AwBrowserContext;
16 import org.chromium.android_webview.AwBrowserProcess;
17 import org.chromium.android_webview.AwContents;
18 import org.chromium.android_webview.AwContentsClient;
19 import org.chromium.android_webview.AwSettings;
20 import org.chromium.android_webview.test.AwTestBase.PopupInfo;
21 import org.chromium.android_webview.test.AwTestBase.TestDependencyFactory;
22 import org.chromium.android_webview.test.util.GraphicsTestUtils;
23 import org.chromium.android_webview.test.util.JSUtils;
24 import org.chromium.base.Log;
25 import org.chromium.base.ThreadUtils;
26 import org.chromium.base.test.util.CallbackHelper;
27 import org.chromium.base.test.util.InMemorySharedPreferences;
28 import org.chromium.content.browser.test.util.Criteria;
29 import org.chromium.content.browser.test.util.CriteriaHelper;
30 import org.chromium.content.browser.test.util.TestCallbackHelperContainer.OnPage FinishedHelper;
31 import org.chromium.content_public.browser.LoadUrlParams;
32 import org.chromium.net.test.util.TestWebServer;
33
34 import java.lang.annotation.Annotation;
35 import java.util.Map;
36 import java.util.concurrent.Callable;
37 import java.util.concurrent.FutureTask;
38 import java.util.concurrent.TimeUnit;
39 import java.util.regex.Matcher;
40 import java.util.regex.Pattern;
41
42 // TODO(yolandyan): move this class to its test rule once JUnit4 migration is ov er
43 final class AwTestCommon {
44 static final long WAIT_TIMEOUT_MS = scaleTimeout(15000);
45
46 static final int CHECK_INTERVAL = 100;
47
48 private static final String TAG = "AwTestCommon";
49
50 private static final Pattern MAYBE_QUOTED_STRING = Pattern.compile("^(\"?)(. *)\\1$");
51
52 // The browser context needs to be a process-wide singleton.
53 private AwBrowserContext mBrowserContext;
54
55 private final AwTestCommonCallback mCallback;
56
57 AwTestCommon(AwTestCommonCallback callback) {
58 mCallback = callback;
59 }
60
61 void setUp() throws Exception {
62 if (needsAwBrowserContextCreated()) {
63 createAwBrowserContext();
64 }
65 if (needsBrowserProcessStarted()) {
66 startBrowserProcess();
67 }
68 }
69
70 void createAwBrowserContext() {
71 if (mBrowserContext != null) {
72 throw new AndroidRuntimeException("There should only be one browser context.");
73 }
74 mCallback.getActivity(); // The Activity must be launched in order to lo ad native code
75 final InMemorySharedPreferences prefs = new InMemorySharedPreferences();
76 final Context appContext =
77 mCallback.getInstrumentation().getTargetContext().getApplication Context();
78 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
79 @Override
80 public void run() {
81 mBrowserContext = createAwBrowserContextOnUiThread(prefs, appCon text);
82 }
83 });
84 }
85
86 AwBrowserContext createAwBrowserContextOnUiThread(
87 InMemorySharedPreferences prefs, Context appContext) {
88 return new AwBrowserContext(prefs, appContext);
89 }
90
91 void startBrowserProcess() throws Exception {
92 // The Activity must be launched in order for proper webview statics to be setup.
93 mCallback.getActivity();
94 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
95 @Override
96 public void run() {
97 AwBrowserProcess.start();
98 }
99 });
100 }
101
102 boolean needsAwBrowserContextCreated() {
103 return true;
104 }
105
106 boolean needsBrowserProcessStarted() {
107 return true;
108 }
109
110 <R> R runTestOnUiThreadAndGetResult(Callable<R> callable) throws Exception {
111 FutureTask<R> task = new FutureTask<R>(callable);
112 mCallback.getInstrumentation().runOnMainSync(task);
113 return task.get();
114 }
115
116 void enableJavaScriptOnUiThread(final AwContents awContents) {
117 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
118 @Override
119 public void run() {
120 awContents.getSettings().setJavaScriptEnabled(true);
121 }
122 });
123 }
124
125 void setNetworkAvailableOnUiThread(
126 final AwContents awContents, final boolean networkUp) {
127 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
128 @Override
129 public void run() {
130 awContents.setNetworkAvailable(networkUp);
131 }
132 });
133 }
134
135 void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedH elper,
136 final String url) throws Exception {
137 loadUrlSync(awContents, onPageFinishedHelper, url, null);
138 }
139
140 void loadUrlSync(final AwContents awContents, CallbackHelper onPageFinishedH elper,
141 final String url, final Map<String, String> extraHeaders) throws Exc eption {
142 int currentCallCount = onPageFinishedHelper.getCallCount();
143 loadUrlAsync(awContents, url, extraHeaders);
144 onPageFinishedHelper.waitForCallback(
145 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
146 }
147
148 void loadUrlSyncAndExpectError(final AwContents awContents,
149 CallbackHelper onPageFinishedHelper, CallbackHelper onReceivedErrorH elper,
150 final String url) throws Exception {
151 int onErrorCallCount = onReceivedErrorHelper.getCallCount();
152 int onFinishedCallCount = onPageFinishedHelper.getCallCount();
153 loadUrlAsync(awContents, url);
154 onReceivedErrorHelper.waitForCallback(
155 onErrorCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
156 onPageFinishedHelper.waitForCallback(
157 onFinishedCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
158 }
159
160 void loadUrlAsync(final AwContents awContents, final String url) throws Exce ption {
161 loadUrlAsync(awContents, url, null);
162 }
163
164 void loadUrlAsync(
165 final AwContents awContents, final String url, final Map<String, Str ing> extraHeaders) {
166 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
167 @Override
168 public void run() {
169 awContents.loadUrl(url, extraHeaders);
170 }
171 });
172 }
173
174 void postUrlSync(final AwContents awContents, CallbackHelper onPageFinishedH elper,
175 final String url, byte[] postData) throws Exception {
176 int currentCallCount = onPageFinishedHelper.getCallCount();
177 postUrlAsync(awContents, url, postData);
178 onPageFinishedHelper.waitForCallback(
179 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
180 }
181
182 void postUrlAsync(final AwContents awContents, final String url, byte[] post Data)
183 throws Exception {
184 class PostUrl implements Runnable {
185 byte[] mPostData;
186 public PostUrl(byte[] postData) {
187 mPostData = postData;
188 }
189 @Override
190 public void run() {
191 awContents.postUrl(url, mPostData);
192 }
193 }
194 mCallback.getInstrumentation().runOnMainSync(new PostUrl(postData));
195 }
196
197 void loadDataSync(final AwContents awContents, CallbackHelper onPageFinished Helper,
198 final String data, final String mimeType, final boolean isBase64Enco ded)
199 throws Exception {
200 int currentCallCount = onPageFinishedHelper.getCallCount();
201 loadDataAsync(awContents, data, mimeType, isBase64Encoded);
202 onPageFinishedHelper.waitForCallback(
203 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
204 }
205
206 void loadDataSyncWithCharset(final AwContents awContents,
207 CallbackHelper onPageFinishedHelper, final String data, final String mimeType,
208 final boolean isBase64Encoded, final String charset) throws Exceptio n {
209 int currentCallCount = onPageFinishedHelper.getCallCount();
210 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
211 @Override
212 public void run() {
213 awContents.loadUrl(LoadUrlParams.createLoadDataParams(
214 data, mimeType, isBase64Encoded, charset));
215 }
216 });
217 onPageFinishedHelper.waitForCallback(
218 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
219 }
220
221 void loadDataAsync(final AwContents awContents, final String data, final Str ing mimeType,
222 final boolean isBase64Encoded) throws Exception {
223 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
224 @Override
225 public void run() {
226 awContents.loadData(data, mimeType, isBase64Encoded ? "base64" : null);
227 }
228 });
229 }
230
231 void loadDataWithBaseUrlSync(final AwContents awContents,
232 CallbackHelper onPageFinishedHelper, final String data, final String mimeType,
233 final boolean isBase64Encoded, final String baseUrl, final String hi storyUrl)
234 throws Throwable {
235 int currentCallCount = onPageFinishedHelper.getCallCount();
236 loadDataWithBaseUrlAsync(awContents, data, mimeType, isBase64Encoded, ba seUrl, historyUrl);
237 onPageFinishedHelper.waitForCallback(
238 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
239 }
240
241 void loadDataWithBaseUrlAsync(final AwContents awContents, final String data ,
242 final String mimeType, final boolean isBase64Encoded, final String b aseUrl,
243 final String historyUrl) throws Throwable {
244 mCallback.runOnUiThread(new Runnable() {
245 @Override
246 public void run() {
247 awContents.loadDataWithBaseURL(
248 baseUrl, data, mimeType, isBase64Encoded ? "base64" : nu ll, historyUrl);
249 }
250 });
251 }
252
253 void reloadSync(final AwContents awContents, CallbackHelper onPageFinishedHe lper)
254 throws Exception {
255 int currentCallCount = onPageFinishedHelper.getCallCount();
256 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
257 @Override
258 public void run() {
259 awContents.getNavigationController().reload(true);
260 }
261 });
262 onPageFinishedHelper.waitForCallback(
263 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
264 }
265
266 void stopLoading(final AwContents awContents) {
267 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
268 @Override
269 public void run() {
270 awContents.stopLoading();
271 }
272 });
273 }
274
275 void waitForVisualStateCallback(final AwContents awContents) throws Exceptio n {
276 final CallbackHelper ch = new CallbackHelper();
277 final int chCount = ch.getCallCount();
278 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
279 @Override
280 public void run() {
281 final long requestId = 666;
282 awContents.insertVisualStateCallback(
283 requestId, new AwContents.VisualStateCallback() {
284 @Override
285 public void onComplete(long id) {
286 Assert.assertEquals(requestId, id);
287 ch.notifyCalled();
288 }
289 });
290 }
291 });
292 ch.waitForCallback(chCount);
293 }
294
295 void insertVisualStateCallbackOnUIThread(final AwContents awContents,
296 final long requestId, final AwContents.VisualStateCallback callback) {
297 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
298 @Override
299 public void run() {
300 awContents.insertVisualStateCallback(requestId, callback);
301 }
302 });
303 }
304
305 void waitForPixelColorAtCenterOfView(final AwContents awContents,
306 final AwTestContainerView testContainerView, final int expectedColor ) throws Exception {
307 pollUiThread(new Callable<Boolean>() {
308 @Override
309 public Boolean call() throws Exception {
310 return GraphicsTestUtils.getPixelColorAtCenterOfView(awContents, testContainerView)
311 == expectedColor;
312 }
313 });
314 }
315
316 TestDependencyFactory createTestDependencyFactory() {
317 return new TestDependencyFactory();
318 }
319
320 AwTestContainerView createAwTestContainerView(final AwContentsClient awConte ntsClient) {
321 return createAwTestContainerView(awContentsClient, false, null);
322 }
323
324 AwTestContainerView createAwTestContainerView(final AwContentsClient awConte ntsClient,
325 boolean supportsLegacyQuirks, final TestDependencyFactory testDepend encyFactory) {
326 AwTestContainerView testContainerView = createDetachedAwTestContainerVie w(
327 awContentsClient, supportsLegacyQuirks, testDependencyFactory);
328 mCallback.getActivity().addView(testContainerView);
329 testContainerView.requestFocus();
330 return testContainerView;
331 }
332
333 AwBrowserContext getAwBrowserContext() {
334 return mBrowserContext;
335 }
336
337 AwTestContainerView createDetachedAwTestContainerView(
338 final AwContentsClient awContentsClient) {
339 return createDetachedAwTestContainerView(awContentsClient, false, null);
340 }
341
342 AwTestContainerView createDetachedAwTestContainerView(
343 final AwContentsClient awContentsClient, boolean supportsLegacyQuirk s,
344 TestDependencyFactory testDependencyFactory) {
345 if (testDependencyFactory == null) {
346 testDependencyFactory = createTestDependencyFactory();
347 }
348 boolean allowHardwareAcceleration = isHardwareAcceleratedTest();
349 final AwTestContainerView testContainerView =
350 testDependencyFactory.createAwTestContainerView(
351 mCallback.getActivity(), allowHardwareAcceleration);
352
353 AwSettings awSettings = testDependencyFactory.createAwSettings(
354 mCallback.getActivity(), supportsLegacyQuirks);
355 AwContents awContents = testDependencyFactory.createAwContents(mBrowserC ontext,
356 testContainerView, testContainerView.getContext(),
357 testContainerView.getInternalAccessDelegate(),
358 testContainerView.getNativeDrawGLFunctorFactory(), awContentsCli ent, awSettings,
359 testDependencyFactory);
360 testContainerView.initialize(awContents);
361 return testContainerView;
362 }
363
364 boolean isHardwareAcceleratedTest() {
365 return !mCallback.testMethodHasAnnotation(DisableHardwareAccelerationFor Test.class);
366 }
367
368 AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClie nt client)
369 throws Exception {
370 return createAwTestContainerViewOnMainSync(client, false, null);
371 }
372
373 AwTestContainerView createAwTestContainerViewOnMainSync(
374 final AwContentsClient client, final boolean supportsLegacyQuirks) {
375 return createAwTestContainerViewOnMainSync(client, supportsLegacyQuirks, null);
376 }
377
378 AwTestContainerView createAwTestContainerViewOnMainSync(final AwContentsClie nt client,
379 final boolean supportsLegacyQuirks, final TestDependencyFactory test DependencyFactory) {
380 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<AwTestC ontainerView>() {
381 @Override
382 public AwTestContainerView call() {
383 return createAwTestContainerView(
384 client, supportsLegacyQuirks, testDependencyFactory);
385 }
386 });
387 }
388
389 void destroyAwContentsOnMainSync(final AwContents awContents) {
390 if (awContents == null) return;
391 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
392 @Override
393 public void run() {
394 awContents.destroy();
395 }
396 });
397 }
398
399 String getTitleOnUiThread(final AwContents awContents) throws Exception {
400 return runTestOnUiThreadAndGetResult(new Callable<String>() {
401 @Override
402 public String call() throws Exception {
403 return awContents.getTitle();
404 }
405 });
406 }
407
408 AwSettings getAwSettingsOnUiThread(final AwContents awContents) throws Excep tion {
409 return runTestOnUiThreadAndGetResult(new Callable<AwSettings>() {
410 @Override
411 public AwSettings call() throws Exception {
412 return awContents.getSettings();
413 }
414 });
415 }
416
417 String maybeStripDoubleQuotes(String raw) {
418 Assert.assertNotNull(raw);
419 Matcher m = MAYBE_QUOTED_STRING.matcher(raw);
420 Assert.assertTrue(m.matches());
421 return m.group(2);
422 }
423
424 String executeJavaScriptAndWaitForResult(final AwContents awContents,
425 TestAwContentsClient viewClient, final String code) throws Exception {
426 return JSUtils.executeJavaScriptAndWaitForResult(mCallback.getInstrument ation(), awContents,
427 viewClient.getOnEvaluateJavaScriptResultHelper(), code);
428 }
429
430 /**
431 * Executes JavaScript code within the given ContentView to get the text con tent in
432 * document body. Returns the result string without double quotes.
433 */
434 String getJavaScriptResultBodyTextContent(
435 final AwContents awContents, final TestAwContentsClient viewClient) throws Exception {
436 String raw = executeJavaScriptAndWaitForResult(
437 awContents, viewClient, "document.body.textContent");
438 return maybeStripDoubleQuotes(raw);
439 }
440
441 static void pollInstrumentationThread(final Callable<Boolean> callable)
442 throws Exception {
443 CriteriaHelper.pollInstrumentationThread(new Criteria() {
444 @Override
445 public boolean isSatisfied() {
446 try {
447 return callable.call();
448 } catch (Throwable e) {
449 Log.e(TAG, "Exception while polling.", e);
450 return false;
451 }
452 }
453 }, WAIT_TIMEOUT_MS, CHECK_INTERVAL);
454 }
455
456 void pollUiThread(final Callable<Boolean> callable) throws Exception {
457 pollInstrumentationThread(new Callable<Boolean>() {
458 @Override
459 public Boolean call() throws Exception {
460 return runTestOnUiThreadAndGetResult(callable);
461 }
462 });
463 }
464
465 void clearCacheOnUiThread(final AwContents awContents, final boolean include DiskFiles)
466 throws Exception {
467 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
468 @Override
469 public void run() {
470 awContents.clearCache(includeDiskFiles);
471 }
472 });
473 }
474
475 float getScaleOnUiThread(final AwContents awContents) throws Exception {
476 return runTestOnUiThreadAndGetResult(new Callable<Float>() {
477 @Override
478 public Float call() throws Exception {
479 return awContents.getPageScaleFactor();
480 }
481 });
482 }
483
484 float getPixelScaleOnUiThread(final AwContents awContents) throws Exception {
485 return runTestOnUiThreadAndGetResult(new Callable<Float>() {
486 @Override
487 public Float call() throws Exception {
488 return awContents.getScale();
489 }
490 });
491 }
492
493 boolean canZoomInOnUiThread(final AwContents awContents) throws Exception {
494 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
495 @Override
496 public Boolean call() throws Exception {
497 return awContents.canZoomIn();
498 }
499 });
500 }
501
502 boolean canZoomOutOnUiThread(final AwContents awContents) throws Exception {
503 return runTestOnUiThreadAndGetResult(new Callable<Boolean>() {
504 @Override
505 public Boolean call() throws Exception {
506 return awContents.canZoomOut();
507 }
508 });
509 }
510
511 void killRenderProcessOnUiThreadAsync(final AwContents awContents) throws Ex ception {
512 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
513 @Override
514 public void run() {
515 awContents.killRenderProcess();
516 }
517 });
518 }
519
520 void triggerPopup(final AwContents parentAwContents,
521 TestAwContentsClient parentAwContentsClient, TestWebServer testWebSe rver,
522 String mainHtml, String popupHtml, String popupPath, String triggerS cript)
523 throws Exception {
524 enableJavaScriptOnUiThread(parentAwContents);
525 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
526 @Override
527 public void run() {
528 parentAwContents.getSettings().setSupportMultipleWindows(true);
529 parentAwContents.getSettings().setJavaScriptCanOpenWindowsAutoma tically(true);
530 }
531 });
532
533 final String parentUrl = testWebServer.setResponse("/popupParent.html", mainHtml, null);
534 if (popupHtml != null) {
535 testWebServer.setResponse(popupPath, popupHtml, null);
536 } else {
537 testWebServer.setResponseWithNoContentStatus(popupPath);
538 }
539
540 parentAwContentsClient.getOnCreateWindowHelper().setReturnValue(true);
541 loadUrlSync(parentAwContents, parentAwContentsClient.getOnPageFinishedHe lper(), parentUrl);
542
543 TestAwContentsClient.OnCreateWindowHelper onCreateWindowHelper =
544 parentAwContentsClient.getOnCreateWindowHelper();
545 int currentCallCount = onCreateWindowHelper.getCallCount();
546 parentAwContents.evaluateJavaScriptForTests(triggerScript, null);
547 onCreateWindowHelper.waitForCallback(
548 currentCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
549 }
550
551 PopupInfo connectPendingPopup(final AwContents parentAwContents) throws Exce ption {
552 TestAwContentsClient popupContentsClient;
553 AwTestContainerView popupContainerView;
554 final AwContents popupContents;
555 popupContentsClient = new TestAwContentsClient();
556 popupContainerView = createAwTestContainerViewOnMainSync(popupContentsCl ient);
557 popupContents = popupContainerView.getAwContents();
558 enableJavaScriptOnUiThread(popupContents);
559
560 mCallback.getInstrumentation().runOnMainSync(new Runnable() {
561 @Override
562 public void run() {
563 parentAwContents.supplyContentsForPopup(popupContents);
564 }
565 });
566
567 OnPageFinishedHelper onPageFinishedHelper = popupContentsClient.getOnPag eFinishedHelper();
568 int finishCallCount = onPageFinishedHelper.getCallCount();
569 TestAwContentsClient.OnReceivedTitleHelper onReceivedTitleHelper =
570 popupContentsClient.getOnReceivedTitleHelper();
571 int titleCallCount = onReceivedTitleHelper.getCallCount();
572
573 onPageFinishedHelper.waitForCallback(
574 finishCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
575 onReceivedTitleHelper.waitForCallback(
576 titleCallCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
577
578 return new PopupInfo(popupContentsClient, popupContainerView, popupConte nts);
579 }
580
581 interface AwTestCommonCallback {
582 Instrumentation getInstrumentation();
583 AwTestRunnerActivity getActivity();
584 void runOnUiThread(Runnable runnable) throws Throwable;
585 boolean testMethodHasAnnotation(Class<? extends Annotation> clazz);
586 }
587 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698