Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / public / android / javatests / src / org / chromium / content / browser / BrowserStartupControllerTest.java
1 // Copyright 2013 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.content.browser;
6
7 import android.content.Context;
8 import android.test.InstrumentationTestCase;
9 import android.test.suitebuilder.annotation.SmallTest;
10
11 import org.chromium.base.ThreadUtils;
12 import org.chromium.base.library_loader.LoaderErrors;
13 import org.chromium.base.library_loader.ProcessInitException;
14 import org.chromium.base.test.util.AdvancedMockContext;
15
16 /**
17  * Test of BrowserStartupController
18  */
19 public class BrowserStartupControllerTest extends InstrumentationTestCase {
20
21     private TestBrowserStartupController mController;
22
23     private static class TestBrowserStartupController extends BrowserStartupController {
24
25         private int mStartupResult;
26         private boolean mLibraryLoadSucceeds;
27         private int mInitializedCounter = 0;
28
29         @Override
30         void prepareToStartBrowserProcess(boolean singleProcess) throws ProcessInitException {
31             if (!mLibraryLoadSucceeds) {
32                 throw new ProcessInitException(
33                         LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED);
34             }
35         }
36
37         private TestBrowserStartupController(Context context) {
38             super(context);
39         }
40
41         @Override
42         int contentStart() {
43             mInitializedCounter++;
44             if (BrowserStartupController.browserMayStartAsynchonously()) {
45                 // Post to the UI thread to emulate what would happen in a real scenario.
46                 ThreadUtils.postOnUiThread(new Runnable() {
47                     @Override
48                     public void run() {
49                         BrowserStartupController.browserStartupComplete(mStartupResult);
50                     }
51                 });
52             } else {
53                 BrowserStartupController.browserStartupComplete(mStartupResult);
54             }
55             return mStartupResult;
56         }
57
58         private int initializedCounter() {
59             return mInitializedCounter;
60         }
61     }
62
63     private static class TestStartupCallback implements BrowserStartupController.StartupCallback {
64         private boolean mWasSuccess;
65         private boolean mWasFailure;
66         private boolean mHasStartupResult;
67         private boolean mAlreadyStarted;
68
69         @Override
70         public void onSuccess(boolean alreadyStarted) {
71             assert !mHasStartupResult;
72             mWasSuccess = true;
73             mAlreadyStarted = alreadyStarted;
74             mHasStartupResult = true;
75         }
76
77         @Override
78         public void onFailure() {
79             assert !mHasStartupResult;
80             mWasFailure = true;
81             mHasStartupResult = true;
82         }
83     }
84
85     @Override
86     protected void setUp() throws Exception {
87         super.setUp();
88         Context context = new AdvancedMockContext(getInstrumentation().getTargetContext());
89         mController = new TestBrowserStartupController(context);
90         // Setting the static singleton instance field enables more correct testing, since it is
91         // is possible to call {@link BrowserStartupController#browserStartupComplete(int)} instead
92         // of {@link BrowserStartupController#executeEnqueuedCallbacks(int, boolean)} directly.
93         BrowserStartupController.overrideInstanceForTest(mController);
94     }
95
96     @SmallTest
97     public void testSingleAsynchronousStartupRequest() {
98         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
99         mController.mLibraryLoadSucceeds = true;
100         final TestStartupCallback callback = new TestStartupCallback();
101
102         // Kick off the asynchronous startup request.
103         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
104             @Override
105             public void run() {
106                 try {
107                     mController.startBrowserProcessesAsync(callback);
108                 } catch (Exception e) {
109                     fail("Browser should have started successfully");
110                 }
111             }
112         });
113
114         assertTrue("Asynchronous mode should have been set.",
115                 BrowserStartupController.browserMayStartAsynchonously());
116         assertEquals("The browser process should have been initialized one time.", 1,
117                 mController.initializedCounter());
118
119         // Wait for callbacks to complete.
120         getInstrumentation().waitForIdleSync();
121
122         assertTrue("Callback should have been executed.", callback.mHasStartupResult);
123         assertTrue("Callback should have been a success.", callback.mWasSuccess);
124         assertFalse("Callback should be told that the browser process was not already started.",
125                 callback.mAlreadyStarted);
126     }
127
128     @SmallTest
129     public void testMultipleAsynchronousStartupRequests() {
130         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
131         mController.mLibraryLoadSucceeds = true;
132         final TestStartupCallback callback1 = new TestStartupCallback();
133         final TestStartupCallback callback2 = new TestStartupCallback();
134         final TestStartupCallback callback3 = new TestStartupCallback();
135
136         // Kick off the asynchronous startup requests.
137         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
138             @Override
139             public void run() {
140                 try {
141                     mController.startBrowserProcessesAsync(callback1);
142                 } catch (Exception e) {
143                     fail("Browser should have started successfully");
144                 }
145             }
146         });
147         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
148             @Override
149             public void run() {
150                 try {
151                     mController.startBrowserProcessesAsync(callback2);
152                 } catch (Exception e) {
153                     fail("Browser should have started successfully");
154                 }
155             }
156         });
157         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
158             @Override
159             public void run() {
160                 mController.addStartupCompletedObserver(callback3);
161             }
162         });
163
164         assertTrue("Asynchronous mode should have been set.",
165                 BrowserStartupController.browserMayStartAsynchonously());
166         assertEquals("The browser process should have been initialized one time.", 1,
167                 mController.initializedCounter());
168
169         // Wait for callbacks to complete.
170         getInstrumentation().waitForIdleSync();
171
172         assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
173         assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
174         assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
175         assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
176         assertTrue("Callback 3 should have been executed.", callback3.mHasStartupResult);
177         assertTrue("Callback 3 should have been a success.", callback3.mWasSuccess);
178         // Some startup tasks might have been enqueued after the browser process was started, but
179         // not the first one which kicked of the startup.
180         assertFalse("Callback 1 should be told that the browser process was not already started.",
181                 callback1.mAlreadyStarted);
182     }
183
184     @SmallTest
185     public void testConsecutiveAsynchronousStartupRequests() {
186         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
187         mController.mLibraryLoadSucceeds = true;
188         final TestStartupCallback callback1 = new TestStartupCallback();
189         final TestStartupCallback callback2 = new TestStartupCallback();
190
191         // Kick off the asynchronous startup requests.
192         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
193             @Override
194             public void run() {
195                 try {
196                     mController.startBrowserProcessesAsync(callback1);
197                 } catch (Exception e) {
198                     fail("Browser should have started successfully");
199                 }
200             }
201         });
202         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
203             @Override
204             public void run() {
205                 mController.addStartupCompletedObserver(callback2);
206             }
207         });
208
209         assertTrue("Asynchronous mode should have been set.",
210                 BrowserStartupController.browserMayStartAsynchonously());
211         assertEquals("The browser process should have been initialized one time.", 1,
212                 mController.initializedCounter());
213
214         // Wait for callbacks to complete.
215         getInstrumentation().waitForIdleSync();
216
217         assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
218         assertTrue("Callback 1 should have been a success.", callback1.mWasSuccess);
219         assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
220         assertTrue("Callback 2 should have been a success.", callback2.mWasSuccess);
221
222         final TestStartupCallback callback3 = new TestStartupCallback();
223         final TestStartupCallback callback4 = new TestStartupCallback();
224
225         // Kick off more asynchronous startup requests.
226         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
227             @Override
228             public void run() {
229                 try {
230                     mController.startBrowserProcessesAsync(callback3);
231                 } catch (Exception e) {
232                     fail("Browser should have started successfully");
233                 }
234             }
235         });
236         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
237             @Override
238             public void run() {
239                 mController.addStartupCompletedObserver(callback4);
240             }
241         });
242
243         // Wait for callbacks to complete.
244         getInstrumentation().waitForIdleSync();
245
246         assertTrue("Callback 3 should have been executed.", callback3.mHasStartupResult);
247         assertTrue("Callback 3 should have been a success.", callback3.mWasSuccess);
248         assertTrue("Callback 3 should be told that the browser process was already started.",
249                 callback3.mAlreadyStarted);
250         assertTrue("Callback 4 should have been executed.", callback4.mHasStartupResult);
251         assertTrue("Callback 4 should have been a success.", callback4.mWasSuccess);
252         assertTrue("Callback 4 should be told that the browser process was already started.",
253                 callback4.mAlreadyStarted);
254     }
255
256     @SmallTest
257     public void testSingleFailedAsynchronousStartupRequest() {
258         mController.mStartupResult = BrowserStartupController.STARTUP_FAILURE;
259         mController.mLibraryLoadSucceeds = true;
260         final TestStartupCallback callback = new TestStartupCallback();
261
262         // Kick off the asynchronous startup request.
263         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
264             @Override
265             public void run() {
266                 try {
267                     mController.startBrowserProcessesAsync(callback);
268                 } catch (Exception e) {
269                     fail("Browser should have started successfully");
270                 }
271             }
272         });
273
274         assertTrue("Asynchronous mode should have been set.",
275                 BrowserStartupController.browserMayStartAsynchonously());
276         assertEquals("The browser process should have been initialized one time.", 1,
277                 mController.initializedCounter());
278
279         // Wait for callbacks to complete.
280         getInstrumentation().waitForIdleSync();
281
282         assertTrue("Callback should have been executed.", callback.mHasStartupResult);
283         assertTrue("Callback should have been a failure.", callback.mWasFailure);
284     }
285
286     @SmallTest
287     public void testConsecutiveFailedAsynchronousStartupRequests() {
288         mController.mStartupResult = BrowserStartupController.STARTUP_FAILURE;
289         mController.mLibraryLoadSucceeds = true;
290         final TestStartupCallback callback1 = new TestStartupCallback();
291         final TestStartupCallback callback2 = new TestStartupCallback();
292
293         // Kick off the asynchronous startup requests.
294         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
295             @Override
296             public void run() {
297                 try {
298                     mController.startBrowserProcessesAsync(callback1);
299                 } catch (Exception e) {
300                     fail("Browser should have started successfully");
301                 }
302             }
303         });
304         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
305             @Override
306             public void run() {
307                 mController.addStartupCompletedObserver(callback2);
308             }
309         });
310
311         assertTrue("Asynchronous mode should have been set.",
312                 BrowserStartupController.browserMayStartAsynchonously());
313         assertEquals("The browser process should have been initialized one time.", 1,
314                 mController.initializedCounter());
315
316         // Wait for callbacks to complete.
317         getInstrumentation().waitForIdleSync();
318
319         assertTrue("Callback 1 should have been executed.", callback1.mHasStartupResult);
320         assertTrue("Callback 1 should have been a failure.", callback1.mWasFailure);
321         assertTrue("Callback 2 should have been executed.", callback2.mHasStartupResult);
322         assertTrue("Callback 2 should have been a failure.", callback2.mWasFailure);
323
324         final TestStartupCallback callback3 = new TestStartupCallback();
325         final TestStartupCallback callback4 = new TestStartupCallback();
326
327         // Kick off more asynchronous startup requests.
328         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
329             @Override
330             public void run() {
331                 try {
332                     mController.startBrowserProcessesAsync(callback3);
333                 } catch (Exception e) {
334                     fail("Browser should have started successfully");
335                 }
336             }
337         });
338         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
339             @Override
340             public void run() {
341                 mController.addStartupCompletedObserver(callback4);
342             }
343         });
344
345         // Wait for callbacks to complete.
346         getInstrumentation().waitForIdleSync();
347
348         assertTrue("Callback 3 should have been executed.", callback3.mHasStartupResult);
349         assertTrue("Callback 3 should have been a failure.", callback3.mWasFailure);
350         assertTrue("Callback 4 should have been executed.", callback4.mHasStartupResult);
351         assertTrue("Callback 4 should have been a failure.", callback4.mWasFailure);
352     }
353
354     @SmallTest
355     public void testSingleSynchronousRequest() {
356         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
357         mController.mLibraryLoadSucceeds = true;
358         // Kick off the synchronous startup.
359         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
360             @Override
361             public void run() {
362                 try {
363                     mController.startBrowserProcessesSync(false);
364                 } catch (Exception e) {
365                     fail("Browser should have started successfully");
366                 }
367             }
368         });
369         assertFalse("Synchronous mode should have been set",
370                 BrowserStartupController.browserMayStartAsynchonously());
371
372         assertEquals("The browser process should have been initialized one time.", 1,
373                 mController.initializedCounter());
374     }
375
376     @SmallTest
377     public void testAsyncThenSyncRequests() {
378         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
379         mController.mLibraryLoadSucceeds = true;
380         final TestStartupCallback callback = new TestStartupCallback();
381
382         // Kick off the startups.
383         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
384             @Override
385             public void run() {
386                 try {
387                     mController.startBrowserProcessesAsync(callback);
388                 } catch (Exception e) {
389                     fail("Browser should have started successfully");
390                 }
391                 // To ensure that the async startup doesn't complete too soon we have
392                 // to do both these in a since Runnable instance. This avoids the
393                 // unpredictable race that happens in real situations.
394                 try {
395                     mController.startBrowserProcessesSync(false);
396                 } catch (Exception e) {
397                     fail("Browser should have started successfully");
398                 }
399             }
400         });
401         assertFalse("Synchronous mode should have been set",
402                 BrowserStartupController.browserMayStartAsynchonously());
403
404         assertEquals("The browser process should have been initialized twice.", 2,
405                 mController.initializedCounter());
406
407         assertTrue("Callback should have been executed.", callback.mHasStartupResult);
408         assertTrue("Callback should have been a success.", callback.mWasSuccess);
409         assertFalse("Callback should be told that the browser process was not already started.",
410                 callback.mAlreadyStarted);
411     }
412
413     @SmallTest
414     public void testSyncThenAsyncRequests() {
415         mController.mStartupResult = BrowserStartupController.STARTUP_SUCCESS;
416         mController.mLibraryLoadSucceeds = true;
417         final TestStartupCallback callback = new TestStartupCallback();
418
419         // Do a synchronous startup first.
420         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
421             @Override
422             public void run() {
423                 try {
424                     mController.startBrowserProcessesSync(false);
425                 } catch (Exception e) {
426                     fail("Browser should have started successfully");
427                 }
428             }
429         });
430
431         assertEquals("The browser process should have been initialized once.", 1,
432                 mController.initializedCounter());
433
434         assertFalse("Synchronous mode should have been set",
435                 BrowserStartupController.browserMayStartAsynchonously());
436
437         // Kick off the asynchronous startup request. This should just queue the callback.
438         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
439             @Override
440             public void run() {
441                 try {
442                     mController.startBrowserProcessesAsync(callback);
443                 } catch (Exception e) {
444                     fail("Browser should have started successfully");
445                 }
446             }
447         });
448
449         assertEquals("The browser process should not have been initialized a second time.", 1,
450                 mController.initializedCounter());
451
452         // Wait for callbacks to complete.
453         getInstrumentation().waitForIdleSync();
454
455         assertTrue("Callback should have been executed.", callback.mHasStartupResult);
456         assertTrue("Callback should have been a success.", callback.mWasSuccess);
457         assertTrue("Callback should be told that the browser process was already started.",
458                 callback.mAlreadyStarted);
459     }
460
461     @SmallTest
462     public void testLibraryLoadFails() {
463         mController.mLibraryLoadSucceeds = false;
464         final TestStartupCallback callback = new TestStartupCallback();
465
466         // Kick off the asynchronous startup request.
467         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
468             @Override
469             public void run() {
470                 try {
471                     mController.startBrowserProcessesAsync(callback);
472                     fail("Browser should not have started successfully");
473                 } catch (Exception e) {
474                     // Exception expected, ignore.
475                 }
476             }
477         });
478
479         assertEquals("The browser process should not have been initialized.", 0,
480                 mController.initializedCounter());
481
482         // Wait for callbacks to complete.
483         getInstrumentation().waitForIdleSync();
484     }
485
486 }