Chromium Code Reviews| 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(1, TimeUnit.SECONDS); | |
|
nyquist
2017/05/23 20:14:29
Our devices are sometimes incredibly slow for weir
fgorski
2017/05/23 21:35:02
Done.
| |
| 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 |