Index: chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java |
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..74ebeaae58b7bc3a24fa97e78bbae971dde1fdb7 |
--- /dev/null |
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java |
@@ -0,0 +1,385 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.chrome.browser.background_task_scheduler; |
+ |
+import static org.junit.Assert.assertEquals; |
+import static org.junit.Assert.assertFalse; |
+import static org.junit.Assert.assertTrue; |
+import static org.mockito.Mockito.any; |
+import static org.mockito.Mockito.doAnswer; |
+import static org.mockito.Mockito.doNothing; |
+import static org.mockito.Mockito.doReturn; |
+import static org.mockito.Mockito.doThrow; |
+import static org.mockito.Mockito.eq; |
+import static org.mockito.Mockito.times; |
+import static org.mockito.Mockito.verify; |
+ |
+import android.content.Context; |
+ |
+import org.junit.Before; |
+import org.junit.Test; |
+import org.junit.runner.RunWith; |
+import org.mockito.ArgumentCaptor; |
+import org.mockito.Captor; |
+import org.mockito.Mock; |
+import org.mockito.MockitoAnnotations; |
+import org.mockito.invocation.InvocationOnMock; |
+import org.mockito.stubbing.Answer; |
+import org.robolectric.RuntimeEnvironment; |
+import org.robolectric.annotation.Config; |
+import org.robolectric.util.ReflectionHelpers; |
+ |
+import org.chromium.base.library_loader.LibraryProcessType; |
+import org.chromium.base.library_loader.LoaderErrors; |
+import org.chromium.base.library_loader.ProcessInitException; |
+import org.chromium.base.test.util.Feature; |
+import org.chromium.chrome.browser.init.BrowserParts; |
+import org.chromium.chrome.browser.init.ChromeBrowserInitializer; |
+import org.chromium.components.background_task_scheduler.BackgroundTask; |
+import org.chromium.components.background_task_scheduler.TaskIds; |
+import org.chromium.components.background_task_scheduler.TaskParameters; |
+import org.chromium.content.browser.BrowserStartupController; |
+import org.chromium.testing.local.LocalRobolectricTestRunner; |
+ |
+import java.util.concurrent.CountDownLatch; |
+import java.util.concurrent.TimeUnit; |
+ |
+/** Unit tests for {@link BackgroundTaskScheduler}. */ |
+@RunWith(LocalRobolectricTestRunner.class) |
+@Config(manifest = Config.NONE) |
+public class NativeBackgroundTaskTest { |
+ private enum InitializerSetup { |
+ SUCCESS, |
+ FAILURE, |
+ EXCEPTION, |
+ } |
+ |
+ private static final TaskParameters TASK_PARAMETERS = |
+ TaskParameters.create(TaskIds.TEST).build(); |
+ |
+ @Mock |
+ private BrowserStartupController mBrowserStartupController; |
+ @Mock |
+ private ChromeBrowserInitializer mChromeBrowserInitializer; |
+ @Captor |
+ ArgumentCaptor<BrowserParts> mBrowserParts; |
+ |
+ private static class TaskFinishedCallback implements BackgroundTask.TaskFinishedCallback { |
+ private boolean mWasCalled; |
+ private boolean mNeedsReschedule; |
+ private CountDownLatch mCallbackLatch; |
+ |
+ TaskFinishedCallback() { |
+ mCallbackLatch = new CountDownLatch(1); |
+ } |
+ |
+ @Override |
+ public void taskFinished(boolean needsReschedule) { |
+ mNeedsReschedule = needsReschedule; |
+ mWasCalled = true; |
+ mCallbackLatch.countDown(); |
+ } |
+ |
+ boolean wasCalled() { |
+ return mWasCalled; |
+ } |
+ |
+ boolean needsRescheduling() { |
+ return mNeedsReschedule; |
+ } |
+ |
+ boolean waitOnCallback() { |
+ return waitOnLatch(mCallbackLatch); |
+ } |
+ } |
+ |
+ private static class TestNativeBackgroundTask extends NativeBackgroundTask { |
+ @StartBeforeNativeResult |
+ private int mStartBeforeNativeResult; |
+ private boolean mWasOnStartTaskWithNativeCalled; |
+ private boolean mNeedsReschedulingAfterStop; |
+ private CountDownLatch mStartWithNativeLatch; |
+ private boolean mWasOnStopTaskWithNativeCalled; |
+ private boolean mWasOnStopTaskBeforeNativeLoadedCalled; |
+ |
+ public TestNativeBackgroundTask() { |
+ mWasOnStartTaskWithNativeCalled = false; |
+ mStartBeforeNativeResult = LOAD_NATIVE; |
+ mNeedsReschedulingAfterStop = false; |
+ mStartWithNativeLatch = new CountDownLatch(1); |
+ } |
+ |
+ @Override |
+ protected int onStartTaskBeforeNativeLoaded( |
+ Context context, TaskParameters taskParameters, TaskFinishedCallback callback) { |
+ return mStartBeforeNativeResult; |
+ } |
+ |
+ @Override |
+ protected void onStartTaskWithNative( |
+ Context context, TaskParameters taskParameters, TaskFinishedCallback callback) { |
+ assertEquals(RuntimeEnvironment.application, context); |
+ assertEquals(TASK_PARAMETERS, taskParameters); |
+ mWasOnStartTaskWithNativeCalled = true; |
+ mStartWithNativeLatch.countDown(); |
+ } |
+ |
+ @Override |
+ protected boolean onStopTaskBeforeNativeLoaded( |
+ Context context, TaskParameters taskParameters) { |
+ mWasOnStopTaskBeforeNativeLoadedCalled = true; |
+ return mNeedsReschedulingAfterStop; |
+ } |
+ |
+ @Override |
+ protected boolean onStopTaskWithNative(Context context, TaskParameters taskParameters) { |
+ mWasOnStopTaskWithNativeCalled = true; |
+ return mNeedsReschedulingAfterStop; |
+ } |
+ |
+ @Override |
+ public void reschedule(Context context) {} |
+ |
+ boolean waitOnStartWithNativeCallback() { |
+ return waitOnLatch(mStartWithNativeLatch); |
+ } |
+ |
+ boolean wasOnStartTaskWithNativeCalled() { |
+ return mWasOnStartTaskWithNativeCalled; |
+ } |
+ |
+ boolean wasOnStopTaskWithNativeCalled() { |
+ return mWasOnStopTaskWithNativeCalled; |
+ } |
+ |
+ boolean wasOnStopTaskBeforeNativeLoadedCalled() { |
+ return mWasOnStopTaskBeforeNativeLoadedCalled; |
+ } |
+ |
+ void setStartTaskBeforeNativeResult(@StartBeforeNativeResult int result) { |
+ mStartBeforeNativeResult = result; |
+ } |
+ |
+ void setNeedsReschedulingAfterStop(boolean needsReschedulingAfterStop) { |
+ mNeedsReschedulingAfterStop = needsReschedulingAfterStop; |
+ } |
+ } |
+ |
+ @Before |
+ public void setUp() { |
+ MockitoAnnotations.initMocks(this); |
+ ReflectionHelpers.setField(mBrowserStartupController, "mLibraryProcessType", |
+ LibraryProcessType.PROCESS_BROWSER); |
+ BrowserStartupController.overrideInstanceForTest(mBrowserStartupController); |
+ ChromeBrowserInitializer.setForTesting(mChromeBrowserInitializer); |
+ } |
+ |
+ private void setUpChromeBrowserInitializer(InitializerSetup setup) { |
+ doNothing().when(mChromeBrowserInitializer).handlePreNativeStartup(any(BrowserParts.class)); |
+ try { |
+ switch (setup) { |
+ case SUCCESS: |
+ doAnswer(new Answer<Void>() { |
+ @Override |
+ public Void answer(InvocationOnMock invocation) { |
+ mBrowserParts.getValue().finishNativeInitialization(); |
+ return null; |
+ } |
+ }) |
+ .when(mChromeBrowserInitializer) |
+ .handlePostNativeStartup(eq(true), mBrowserParts.capture()); |
+ break; |
+ case FAILURE: |
+ doAnswer(new Answer<Void>() { |
+ @Override |
+ public Void answer(InvocationOnMock invocation) { |
+ mBrowserParts.getValue().onStartupFailure(); |
+ return null; |
+ } |
+ }) |
+ .when(mChromeBrowserInitializer) |
+ .handlePostNativeStartup(eq(true), mBrowserParts.capture()); |
+ break; |
+ case EXCEPTION: |
+ doThrow(new ProcessInitException( |
+ LoaderErrors.LOADER_ERROR_NATIVE_LIBRARY_LOAD_FAILED)) |
+ .when(mChromeBrowserInitializer) |
+ .handlePostNativeStartup(eq(true), any(BrowserParts.class)); |
+ break; |
+ default: |
+ assert false; |
+ } |
+ } catch (ProcessInitException e) { |
+ // Exception ignored, as try-catch is required by language. |
+ } |
+ } |
+ |
+ private void verifyStartupCalls(int expectedPreNativeCalls, int expectedPostNativeCalls) { |
+ try { |
+ verify(mChromeBrowserInitializer, times(expectedPreNativeCalls)) |
+ .handlePreNativeStartup(any(BrowserParts.class)); |
+ verify(mChromeBrowserInitializer, times(expectedPostNativeCalls)) |
+ .handlePostNativeStartup(eq(true), any(BrowserParts.class)); |
+ } catch (ProcessInitException e) { |
+ // Exception ignored, as try-catch is required by language. |
+ } |
+ } |
+ |
+ private static boolean waitOnLatch(CountDownLatch latch) { |
+ try { |
+ // All tests are expected to get it done much faster |
+ return latch.await(5, TimeUnit.SECONDS); |
+ } catch (InterruptedException e) { |
+ return false; |
+ } |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_Done_BeforeNativeLoaded() { |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setStartTaskBeforeNativeResult(NativeBackgroundTask.DONE); |
+ assertFalse(task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback)); |
+ |
+ verify(mBrowserStartupController, times(0)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(0, 0); |
+ assertFalse(task.wasOnStartTaskWithNativeCalled()); |
+ assertFalse(callback.wasCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_Reschedule_BeforeNativeLoaded() { |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setStartTaskBeforeNativeResult(NativeBackgroundTask.RESCHEDULE); |
+ assertTrue(task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback)); |
+ |
+ assertTrue(callback.waitOnCallback()); |
+ verify(mBrowserStartupController, times(0)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(0, 0); |
+ assertFalse(task.wasOnStartTaskWithNativeCalled()); |
+ assertTrue(callback.wasCalled()); |
+ assertTrue(callback.needsRescheduling()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_NativeAlreadyLoaded() { |
+ doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback); |
+ |
+ assertTrue(task.waitOnStartWithNativeCallback()); |
+ verify(mBrowserStartupController, times(1)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(0, 0); |
+ assertTrue(task.wasOnStartTaskWithNativeCalled()); |
+ assertFalse(callback.wasCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_NativeInitialization_Success() { |
+ doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ setUpChromeBrowserInitializer(InitializerSetup.SUCCESS); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback); |
+ |
+ assertTrue(task.waitOnStartWithNativeCallback()); |
+ verify(mBrowserStartupController, times(1)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(1, 1); |
+ assertTrue(task.wasOnStartTaskWithNativeCalled()); |
+ assertFalse(callback.wasCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_NativeInitialization_Failure() { |
+ doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ setUpChromeBrowserInitializer(InitializerSetup.FAILURE); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback); |
+ |
+ assertTrue(callback.waitOnCallback()); |
+ verify(mBrowserStartupController, times(1)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(1, 1); |
+ assertFalse(task.wasOnStartTaskWithNativeCalled()); |
+ assertTrue(callback.wasCalled()); |
+ assertTrue(callback.needsRescheduling()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStartTask_NativeInitialization_Throws() { |
+ doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ setUpChromeBrowserInitializer(InitializerSetup.EXCEPTION); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.onStartTask(RuntimeEnvironment.application, TASK_PARAMETERS, callback); |
+ |
+ assertTrue(callback.waitOnCallback()); |
+ verify(mBrowserStartupController, times(1)).isStartupSuccessfullyCompleted(); |
+ verifyStartupCalls(1, 1); |
+ assertFalse(task.wasOnStartTaskWithNativeCalled()); |
+ assertTrue(callback.wasCalled()); |
+ assertTrue(callback.needsRescheduling()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStopTask_BeforeNativeLoaded_NeedsRescheduling() { |
+ doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setNeedsReschedulingAfterStop(true); |
+ |
+ assertTrue(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETERS)); |
+ assertTrue(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
+ assertFalse(task.wasOnStopTaskWithNativeCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStopTask_BeforeNativeLoaded_DoesntNeedRescheduling() { |
+ doReturn(false).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setNeedsReschedulingAfterStop(false); |
+ |
+ assertFalse(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETERS)); |
+ assertTrue(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
+ assertFalse(task.wasOnStopTaskWithNativeCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStopTask_NativeLoaded_NeedsRescheduling() { |
+ doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setNeedsReschedulingAfterStop(true); |
+ |
+ assertTrue(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETERS)); |
+ assertFalse(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
+ assertTrue(task.wasOnStopTaskWithNativeCalled()); |
+ } |
+ |
+ @Test |
+ @Feature("BackgroundTaskScheduler") |
+ public void testOnStopTask_NativeLoaded_DoesntNeedRescheduling() { |
+ doReturn(true).when(mBrowserStartupController).isStartupSuccessfullyCompleted(); |
+ TaskFinishedCallback callback = new TaskFinishedCallback(); |
+ TestNativeBackgroundTask task = new TestNativeBackgroundTask(); |
+ task.setNeedsReschedulingAfterStop(false); |
+ |
+ assertFalse(task.onStopTask(RuntimeEnvironment.application, TASK_PARAMETERS)); |
+ assertFalse(task.wasOnStopTaskBeforeNativeLoadedCalled()); |
+ assertTrue(task.wasOnStopTaskWithNativeCalled()); |
+ } |
+} |