// Copyright 2016 The Chromium Authors
// 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.offlinepages;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.text.format.DateUtils;
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.robolectric.annotation.Config;
import org.chromium.base.ContextUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.background_task_scheduler.ChromeBackgroundTaskFactory;
import org.chromium.components.background_task_scheduler.BackgroundTaskScheduler;
import org.chromium.components.background_task_scheduler.BackgroundTaskSchedulerFactory;
import org.chromium.components.background_task_scheduler.TaskIds;
import org.chromium.components.background_task_scheduler.TaskInfo;
/** Unit tests for BackgroundScheduler. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class BackgroundSchedulerTest {
private TriggerConditions mConditions1 =
new TriggerConditions(
/* power= */ true, 10 /* battery percentage */, true /* requires unmetered */);
private TriggerConditions mConditions2 =
new TriggerConditions(
/* power= */ false,
0 /* battery percentage */,
false /* does not require unmetered */);
@Mock private BackgroundTaskScheduler mTaskScheduler;
@Captor ArgumentCaptor<TaskInfo> mTaskInfo;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
BackgroundTaskSchedulerFactory.setSchedulerForTesting(mTaskScheduler);
ChromeBackgroundTaskFactory.setAsDefault();
doReturn(true)
.when(mTaskScheduler)
.schedule(eq(ContextUtils.getApplicationContext()), mTaskInfo.capture());
}
private void verifyFixedTaskInfoValues(TaskInfo info) {
assertEquals(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID, info.getTaskId());
assertTrue(info.isPersisted());
assertFalse(info.isPeriodic());
assertEquals(DateUtils.WEEK_IN_MILLIS, info.getOneOffInfo().getWindowEndTimeMs());
assertTrue(info.getOneOffInfo().hasWindowStartTimeConstraint());
long scheduledTimeMillis = TaskExtrasPacker.unpackTimeFromBundle(info.getExtras());
assertTrue(scheduledTimeMillis > 0L);
}
@Test
@Feature({"OfflinePages"})
public void testScheduleUnmeteredAndCharging() {
BackgroundScheduler.getInstance().schedule(mConditions1);
verify(mTaskScheduler, times(1))
.schedule(eq(ContextUtils.getApplicationContext()), eq(mTaskInfo.getValue()));
TaskInfo info = mTaskInfo.getValue();
verifyFixedTaskInfoValues(info);
assertEquals(TaskInfo.NetworkType.UNMETERED, info.getRequiredNetworkType());
assertTrue(info.requiresCharging());
assertTrue(info.shouldUpdateCurrent());
assertEquals(BackgroundScheduler.NO_DELAY, info.getOneOffInfo().getWindowStartTimeMs());
assertEquals(
mConditions1, TaskExtrasPacker.unpackTriggerConditionsFromBundle(info.getExtras()));
}
@Test
@Feature({"OfflinePages"})
public void testScheduleMeteredAndNotCharging() {
BackgroundScheduler.getInstance().schedule(mConditions2);
verify(mTaskScheduler, times(1))
.schedule(eq(ContextUtils.getApplicationContext()), eq(mTaskInfo.getValue()));
TaskInfo info = mTaskInfo.getValue();
verifyFixedTaskInfoValues(info);
assertEquals(TaskInfo.NetworkType.ANY, info.getRequiredNetworkType());
assertFalse(info.requiresCharging());
assertTrue(info.shouldUpdateCurrent());
assertEquals(BackgroundScheduler.NO_DELAY, info.getOneOffInfo().getWindowStartTimeMs());
assertEquals(
mConditions2, TaskExtrasPacker.unpackTriggerConditionsFromBundle(info.getExtras()));
}
@Test
@Feature({"OfflinePages"})
public void testScheduleBackup() {
BackgroundScheduler.getInstance()
.scheduleBackup(mConditions1, 5 * DateUtils.MINUTE_IN_MILLIS);
verify(mTaskScheduler, times(1))
.schedule(eq(ContextUtils.getApplicationContext()), eq(mTaskInfo.getValue()));
TaskInfo info = mTaskInfo.getValue();
verifyFixedTaskInfoValues(info);
assertEquals(TaskInfo.NetworkType.UNMETERED, info.getRequiredNetworkType());
assertTrue(info.requiresCharging());
assertFalse(info.shouldUpdateCurrent());
assertEquals(5 * DateUtils.MINUTE_IN_MILLIS, info.getOneOffInfo().getWindowStartTimeMs());
assertEquals(
mConditions1, TaskExtrasPacker.unpackTriggerConditionsFromBundle(info.getExtras()));
}
@Test
@Feature({"OfflinePages"})
public void testCancel() {
BackgroundScheduler.getInstance().schedule(mConditions1);
verify(mTaskScheduler, times(1))
.schedule(eq(ContextUtils.getApplicationContext()), eq(mTaskInfo.getValue()));
doNothing()
.when(mTaskScheduler)
.cancel(
eq(ContextUtils.getApplicationContext()),
eq(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
BackgroundScheduler.getInstance().cancel();
verify(mTaskScheduler, times(1))
.cancel(
eq(ContextUtils.getApplicationContext()),
eq(TaskIds.OFFLINE_PAGES_BACKGROUND_JOB_ID));
}
}