OLD | NEW |
(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.chrome.browser.background_task_scheduler; |
| 6 |
| 7 import static org.junit.Assert.assertEquals; |
| 8 import static org.junit.Assert.assertFalse; |
| 9 import static org.junit.Assert.assertTrue; |
| 10 import static org.mockito.Mockito.any; |
| 11 import static org.mockito.Mockito.doAnswer; |
| 12 import static org.mockito.Mockito.doNothing; |
| 13 import static org.mockito.Mockito.doReturn; |
| 14 import static org.mockito.Mockito.doThrow; |
| 15 import static org.mockito.Mockito.eq; |
| 16 import static org.mockito.Mockito.times; |
| 17 import static org.mockito.Mockito.verify; |
| 18 |
| 19 import android.content.Context; |
| 20 |
| 21 import org.junit.Before; |
| 22 import org.junit.Test; |
| 23 import org.junit.runner.RunWith; |
| 24 import org.mockito.ArgumentCaptor; |
| 25 import org.mockito.Captor; |
| 26 import org.mockito.Mock; |
| 27 import org.mockito.MockitoAnnotations; |
| 28 import org.mockito.invocation.InvocationOnMock; |
| 29 import org.mockito.stubbing.Answer; |
| 30 import org.robolectric.RuntimeEnvironment; |
| 31 import org.robolectric.annotation.Config; |
| 32 import org.robolectric.util.ReflectionHelpers; |
| 33 |
| 34 import org.chromium.base.library_loader.LibraryProcessType; |
| 35 import org.chromium.base.library_loader.LoaderErrors; |
| 36 import org.chromium.base.library_loader.ProcessInitException; |
| 37 import org.chromium.base.test.util.Feature; |
| 38 import org.chromium.chrome.browser.init.BrowserParts; |
| 39 import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
| 40 import org.chromium.components.background_task_scheduler.BackgroundTask; |
| 41 import org.chromium.components.background_task_scheduler.TaskIds; |
| 42 import org.chromium.components.background_task_scheduler.TaskParameters; |
| 43 import org.chromium.content.browser.BrowserStartupController; |
| 44 import org.chromium.testing.local.LocalRobolectricTestRunner; |
| 45 |
| 46 import java.util.concurrent.CountDownLatch; |
| 47 import java.util.concurrent.TimeUnit; |
| 48 |
| 49 /** Unit tests for {@link BackgroundTaskScheduler}. */ |
| 50 @RunWith(LocalRobolectricTestRunner.class) |
| 51 @Config(manifest = Config.NONE) |
| 52 public class NativeBackgroundTaskTest { |
| 53 private enum InitializerSetup { |
| 54 SUCCESS, |
| 55 FAILURE, |
| 56 EXCEPTION, |
| 57 } |
| 58 |
| 59 private static final TaskParameters TASK_PARAMETERS = |
| 60 TaskParameters.create(TaskIds.TEST).build(); |
| 61 |
| 62 @Mock |
| 63 private BrowserStartupController mBrowserStartupController; |
| 64 @Mock |
| 65 private ChromeBrowserInitializer mChromeBrowserInitializer; |
| 66 @Captor |
| 67 ArgumentCaptor<BrowserParts> mBrowserParts; |
| 68 |
| 69 private static class TaskFinishedCallback implements BackgroundTask.TaskFini
shedCallback { |
| 70 private boolean mWasCalled; |
| 71 private boolean mNeedsReschedule; |
| 72 private CountDownLatch mCallbackLatch; |
| 73 |
| 74 TaskFinishedCallback() { |
| 75 mCallbackLatch = new CountDownLatch(1); |
| 76 } |
| 77 |
| 78 @Override |
| 79 public void taskFinished(boolean needsReschedule) { |
| 80 mNeedsReschedule = needsReschedule; |
| 81 mWasCalled = true; |
| 82 mCallbackLatch.countDown(); |
| 83 } |
| 84 |
| 85 boolean wasCalled() { |
| 86 return mWasCalled; |
| 87 } |
| 88 |
| 89 boolean needsRescheduling() { |
| 90 return mNeedsReschedule; |
| 91 } |
| 92 |
| 93 boolean waitOnCallback() { |
| 94 return waitOnLatch(mCallbackLatch); |
| 95 } |
| 96 } |
| 97 |
| 98 private static class TestNativeBackgroundTask extends NativeBackgroundTask { |
| 99 @StartBeforeNativeResult |
| 100 private int mStartBeforeNativeResult; |
| 101 private boolean mWasOnStartTaskWithNativeCalled; |
| 102 private boolean mNeedsReschedulingAfterStop; |
| 103 private CountDownLatch mStartWithNativeLatch; |
| 104 private boolean mWasOnStopTaskWithNativeCalled; |
| 105 private boolean mWasOnStopTaskBeforeNativeLoadedCalled; |
| 106 |
| 107 public TestNativeBackgroundTask() { |
| 108 mWasOnStartTaskWithNativeCalled = false; |
| 109 mStartBeforeNativeResult = LOAD_NATIVE; |
| 110 mNeedsReschedulingAfterStop = false; |
| 111 mStartWithNativeLatch = new CountDownLatch(1); |
| 112 } |
| 113 |
| 114 @Override |
| 115 protected int onStartTaskBeforeNativeLoaded( |
| 116 Context context, TaskParameters taskParameters, TaskFinishedCall
back callback) { |
| 117 return mStartBeforeNativeResult; |
| 118 } |
| 119 |
| 120 @Override |
| 121 protected void onStartTaskWithNative( |
| 122 Context context, TaskParameters taskParameters, TaskFinishedCall
back callback) { |
| 123 assertEquals(RuntimeEnvironment.application, context); |
| 124 assertEquals(TASK_PARAMETERS, taskParameters); |
| 125 mWasOnStartTaskWithNativeCalled = true; |
| 126 mStartWithNativeLatch.countDown(); |
| 127 } |
| 128 |
| 129 @Override |
| 130 protected boolean onStopTaskBeforeNativeLoaded( |
| 131 Context context, TaskParameters taskParameters) { |
| 132 mWasOnStopTaskBeforeNativeLoadedCalled = true; |
| 133 return mNeedsReschedulingAfterStop; |
| 134 } |
| 135 |
| 136 @Override |
| 137 protected boolean onStopTaskWithNative(Context context, TaskParameters t
askParameters) { |
| 138 mWasOnStopTaskWithNativeCalled = true; |
| 139 return mNeedsReschedulingAfterStop; |
| 140 } |
| 141 |
| 142 @Override |
| 143 public void reschedule(Context context) {} |
| 144 |
| 145 boolean waitOnStartWithNativeCallback() { |
| 146 return waitOnLatch(mStartWithNativeLatch); |
| 147 } |
| 148 |
| 149 boolean wasOnStartTaskWithNativeCalled() { |
| 150 return mWasOnStartTaskWithNativeCalled; |
| 151 } |
| 152 |
| 153 boolean wasOnStopTaskWithNativeCalled() { |
| 154 return mWasOnStopTaskWithNativeCalled; |
| 155 } |
| 156 |
| 157 boolean wasOnStopTaskBeforeNativeLoadedCalled() { |
| 158 return mWasOnStopTaskBeforeNativeLoadedCalled; |
| 159 } |
| 160 |
| 161 void setStartTaskBeforeNativeResult(@StartBeforeNativeResult int result)
{ |
| 162 mStartBeforeNativeResult = result; |
| 163 } |
| 164 |
| 165 void setNeedsReschedulingAfterStop(boolean needsReschedulingAfterStop) { |
| 166 mNeedsReschedulingAfterStop = needsReschedulingAfterStop; |
| 167 } |
| 168 } |
| 169 |
| 170 @Before |
| 171 public void setUp() { |
| 172 MockitoAnnotations.initMocks(this); |
| 173 ReflectionHelpers.setField(mBrowserStartupController, "mLibraryProcessTy
pe", |
| 174 LibraryProcessType.PROCESS_BROWSER); |
| 175 BrowserStartupController.overrideInstanceForTest(mBrowserStartupControll
er); |
| 176 ChromeBrowserInitializer.setForTesting(mChromeBrowserInitializer); |
| 177 } |
| 178 |
| 179 private void setUpChromeBrowserInitializer(InitializerSetup setup) { |
| 180 doNothing().when(mChromeBrowserInitializer).handlePreNativeStartup(any(B
rowserParts.class)); |
| 181 try { |
| 182 switch (setup) { |
| 183 case SUCCESS: |
| 184 doAnswer(new Answer<Void>() { |
| 185 @Override |
| 186 public Void answer(InvocationOnMock invocation) { |
| 187 mBrowserParts.getValue().finishNativeInitialization(
); |
| 188 return null; |
| 189 } |
| 190 }) |
| 191 .when(mChromeBrowserInitializer) |
| 192 .handlePostNativeStartup(eq(true), mBrowserParts.cap
ture()); |
| 193 break; |
| 194 case FAILURE: |
| 195 doAnswer(new Answer<Void>() { |
| 196 @Override |
| 197 public Void answer(InvocationOnMock invocation) { |
| 198 mBrowserParts.getValue().onStartupFailure(); |
| 199 return null; |
| 200 } |
| 201 }) |
| 202 .when(mChromeBrowserInitializer) |
| 203 .handlePostNativeStartup(eq(true), mBrowserParts.cap
ture()); |
| 204 break; |
| 205 case EXCEPTION: |
| 206 doThrow(new ProcessInitException( |
| 207 LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOA
D_FAILED)) |
| 208 .when(mChromeBrowserInitializer) |
| 209 .handlePostNativeStartup(eq(true), any(BrowserParts.
class)); |
| 210 break; |
| 211 default: |
| 212 assert false; |
| 213 } |
| 214 } catch (ProcessInitException e) { |
| 215 // Exception ignored, as try-catch is required by language. |
| 216 } |
| 217 } |
| 218 |
| 219 private void verifyStartupCalls(int expectedPreNativeCalls, int expectedPost
NativeCalls) { |
| 220 try { |
| 221 verify(mChromeBrowserInitializer, times(expectedPreNativeCalls)) |
| 222 .handlePreNativeStartup(any(BrowserParts.class)); |
| 223 verify(mChromeBrowserInitializer, times(expectedPostNativeCalls)) |
| 224 .handlePostNativeStartup(eq(true), any(BrowserParts.class)); |
| 225 } catch (ProcessInitException e) { |
| 226 // Exception ignored, as try-catch is required by language. |
| 227 } |
| 228 } |
| 229 |
| 230 private static boolean waitOnLatch(CountDownLatch latch) { |
| 231 try { |
| 232 // All tests are expected to get it done much faster |
| 233 return latch.await(5, TimeUnit.SECONDS); |
| 234 } catch (InterruptedException e) { |
| 235 return false; |
| 236 } |
| 237 } |
| 238 |
| 239 @Test |
| 240 @Feature("BackgroundTaskScheduler") |
| 241 public void testOnStartTask_Done_BeforeNativeLoaded() { |
| 242 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 243 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 244 task.setStartTaskBeforeNativeResult(NativeBackgroundTask.DONE); |
| 245 assertFalse(task.onStartTask(RuntimeEnvironment.application, TASK_PARAME
TERS, callback)); |
| 246 |
| 247 verify(mBrowserStartupController, times(0)).isStartupSuccessfullyComplet
ed(); |
| 248 verifyStartupCalls(0, 0); |
| 249 assertFalse(task.wasOnStartTaskWithNativeCalled()); |
| 250 assertFalse(callback.wasCalled()); |
| 251 } |
| 252 |
| 253 @Test |
| 254 @Feature("BackgroundTaskScheduler") |
| 255 public void testOnStartTask_Reschedule_BeforeNativeLoaded() { |
| 256 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 257 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 258 task.setStartTaskBeforeNativeResult(NativeBackgroundTask.RESCHEDULE); |
| 259 assertTrue(task.onStartTask(RuntimeEnvironment.application, TASK_PARAMET
ERS, callback)); |
| 260 |
| 261 assertTrue(callback.waitOnCallback()); |
| 262 verify(mBrowserStartupController, times(0)).isStartupSuccessfullyComplet
ed(); |
| 263 verifyStartupCalls(0, 0); |
| 264 assertFalse(task.wasOnStartTaskWithNativeCalled()); |
| 265 assertTrue(callback.wasCalled()); |
| 266 assertTrue(callback.needsRescheduling()); |
| 267 } |
| 268 |
| 269 @Test |
| 270 @Feature("BackgroundTaskScheduler") |
| 271 public void testOnStartTask_NativeAlreadyLoaded() { |
| 272 doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyComp
leted(); |
| 273 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 274 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 275 task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callba
ck); |
| 276 |
| 277 assertTrue(task.waitOnStartWithNativeCallback()); |
| 278 verify(mBrowserStartupController, times(1)).isStartupSuccessfullyComplet
ed(); |
| 279 verifyStartupCalls(0, 0); |
| 280 assertTrue(task.wasOnStartTaskWithNativeCalled()); |
| 281 assertFalse(callback.wasCalled()); |
| 282 } |
| 283 |
| 284 @Test |
| 285 @Feature("BackgroundTaskScheduler") |
| 286 public void testOnStartTask_NativeInitialization_Success() { |
| 287 doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCom
pleted(); |
| 288 setUpChromeBrowserInitializer(InitializerSetup.SUCCESS); |
| 289 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 290 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 291 task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callba
ck); |
| 292 |
| 293 assertTrue(task.waitOnStartWithNativeCallback()); |
| 294 verify(mBrowserStartupController, times(1)).isStartupSuccessfullyComplet
ed(); |
| 295 verifyStartupCalls(1, 1); |
| 296 assertTrue(task.wasOnStartTaskWithNativeCalled()); |
| 297 assertFalse(callback.wasCalled()); |
| 298 } |
| 299 |
| 300 @Test |
| 301 @Feature("BackgroundTaskScheduler") |
| 302 public void testOnStartTask_NativeInitialization_Failure() { |
| 303 doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCom
pleted(); |
| 304 setUpChromeBrowserInitializer(InitializerSetup.FAILURE); |
| 305 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 306 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 307 task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callba
ck); |
| 308 |
| 309 assertTrue(callback.waitOnCallback()); |
| 310 verify(mBrowserStartupController, times(1)).isStartupSuccessfullyComplet
ed(); |
| 311 verifyStartupCalls(1, 1); |
| 312 assertFalse(task.wasOnStartTaskWithNativeCalled()); |
| 313 assertTrue(callback.wasCalled()); |
| 314 assertTrue(callback.needsRescheduling()); |
| 315 } |
| 316 |
| 317 @Test |
| 318 @Feature("BackgroundTaskScheduler") |
| 319 public void testOnStartTask_NativeInitialization_Throws() { |
| 320 doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCom
pleted(); |
| 321 setUpChromeBrowserInitializer(InitializerSetup.EXCEPTION); |
| 322 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 323 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 324 task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callba
ck); |
| 325 |
| 326 assertTrue(callback.waitOnCallback()); |
| 327 verify(mBrowserStartupController, times(1)).isStartupSuccessfullyComplet
ed(); |
| 328 verifyStartupCalls(1, 1); |
| 329 assertFalse(task.wasOnStartTaskWithNativeCalled()); |
| 330 assertTrue(callback.wasCalled()); |
| 331 assertTrue(callback.needsRescheduling()); |
| 332 } |
| 333 |
| 334 @Test |
| 335 @Feature("BackgroundTaskScheduler") |
| 336 public void testOnStopTask_BeforeNativeLoaded_NeedsRescheduling() { |
| 337 doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCom
pleted(); |
| 338 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 339 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 340 task.setNeedsReschedulingAfterStop(true); |
| 341 |
| 342 assertTrue(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETE
RS)); |
| 343 assertTrue(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
| 344 assertFalse(task.wasOnStopTaskWithNativeCalled()); |
| 345 } |
| 346 |
| 347 @Test |
| 348 @Feature("BackgroundTaskScheduler") |
| 349 public void testOnStopTask_BeforeNativeLoaded_DoesntNeedRescheduling() { |
| 350 doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCom
pleted(); |
| 351 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 352 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 353 task.setNeedsReschedulingAfterStop(false); |
| 354 |
| 355 assertFalse(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMET
ERS)); |
| 356 assertTrue(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
| 357 assertFalse(task.wasOnStopTaskWithNativeCalled()); |
| 358 } |
| 359 |
| 360 @Test |
| 361 @Feature("BackgroundTaskScheduler") |
| 362 public void testOnStopTask_NativeLoaded_NeedsRescheduling() { |
| 363 doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyComp
leted(); |
| 364 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 365 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 366 task.setNeedsReschedulingAfterStop(true); |
| 367 |
| 368 assertTrue(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETE
RS)); |
| 369 assertFalse(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
| 370 assertTrue(task.wasOnStopTaskWithNativeCalled()); |
| 371 } |
| 372 |
| 373 @Test |
| 374 @Feature("BackgroundTaskScheduler") |
| 375 public void testOnStopTask_NativeLoaded_DoesntNeedRescheduling() { |
| 376 doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyComp
leted(); |
| 377 TaskFinishedCallback callback = new TaskFinishedCallback(); |
| 378 TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
| 379 task.setNeedsReschedulingAfterStop(false); |
| 380 |
| 381 assertFalse(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMET
ERS)); |
| 382 assertFalse(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
| 383 assertTrue(task.wasOnStopTaskWithNativeCalled()); |
| 384 } |
| 385 } |
OLD | NEW |