blob: 1b5ce4a04e863cf1c09158dedd67e12c56e52c61 [file] [log] [blame]
// Copyright 2018 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.android_webview.test;
import static org.chromium.android_webview.test.OnlyRunIn.ProcessMode.SINGLE_PROCESS;
import android.annotation.SuppressLint;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobWorkItem;
import android.content.ComponentName;
import android.support.test.filters.MediumTest;
import android.support.test.filters.SmallTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.android_webview.VariationsUtils;
import org.chromium.android_webview.services.AwVariationsSeedFetcher;
import org.chromium.android_webview.services.ServiceInit;
import org.chromium.android_webview.test.util.VariationsTestUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.components.background_task_scheduler.TaskIds;
import org.chromium.components.variations.firstrun.VariationsSeedFetcher;
import org.chromium.components.variations.firstrun.VariationsSeedFetcher.SeedInfo;
import java.io.File;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;
/**
* Test AwVariationsSeedFetcher.
*/
@RunWith(AwJUnit4ClassRunner.class)
@OnlyRunIn(SINGLE_PROCESS)
public class AwVariationsSeedFetcherTest {
private static final int JOB_ID = TaskIds.WEBVIEW_VARIATIONS_SEED_FETCH_JOB_ID;
// A mock JobScheduler which only holds one job, and never does anything with it.
private class MockJobScheduler extends JobScheduler {
public JobInfo mJob;
public void clear() {
mJob = null;
}
public void assertScheduled() {
Assert.assertNotNull("No job scheduled", mJob);
}
public void assertNotScheduled() {
Assert.assertNull("Job should not have been scheduled", mJob);
}
@Override
public void cancel(int jobId) {
throw new UnsupportedOperationException();
}
@Override
public void cancelAll() {
throw new UnsupportedOperationException();
}
@Override
public int enqueue(JobInfo job, JobWorkItem work) {
throw new UnsupportedOperationException();
}
@Override
public List<JobInfo> getAllPendingJobs() {
ArrayList<JobInfo> list = new ArrayList<>();
if (mJob != null) list.add(mJob);
return list;
}
@Override
public JobInfo getPendingJob(int jobId) {
if (mJob != null && mJob.getId() == jobId) return mJob;
return null;
}
@Override
public int schedule(JobInfo job) {
Assert.assertEquals("Job scheduled with wrong ID", JOB_ID, job.getId());
Assert.assertEquals("Job scheduled with wrong network type",
JobInfo.NETWORK_TYPE_ANY, job.getNetworkType());
Assert.assertTrue("Job scheduled without charging requirement",
job.isRequireCharging());
mJob = job;
return JobScheduler.RESULT_SUCCESS;
}
}
// A mock VariationsSeedFetcher which doesn't actually download seeds, but verifies the request
// parameters.
private class MockFetcher extends VariationsSeedFetcher {
public CallbackHelper helper = new CallbackHelper();
@Override
public SeedInfo downloadContent(@VariationsSeedFetcher.VariationsPlatform int platform,
String restrictMode, String milestone, String channel)
throws SocketTimeoutException, UnknownHostException, IOException {
Assert.assertEquals(VariationsSeedFetcher.VariationsPlatform.ANDROID_WEBVIEW, platform);
Assert.assertTrue(Integer.parseInt(milestone) > 0);
helper.notifyCalled();
return null;
}
}
private MockJobScheduler mScheduler = new MockJobScheduler();
private MockFetcher mDownloader = new MockFetcher();
@Before
public void setUp() throws IOException {
ServiceInit.setPrivateDataDirectorySuffix();
AwVariationsSeedFetcher.setMocks(mScheduler, mDownloader);
VariationsTestUtils.deleteSeeds();
}
@After
public void tearDown() throws IOException {
AwVariationsSeedFetcher.setMocks(null, null);
VariationsTestUtils.deleteSeeds();
}
// Test scheduleIfNeeded(), which should schedule a job.
@Test
@SmallTest
public void testScheduleWithNoStamp() {
try {
AwVariationsSeedFetcher.scheduleIfNeeded();
mScheduler.assertScheduled();
} finally {
mScheduler.clear();
}
}
// Create a stamp file with time = epoch, indicating the download job hasn't run in a long time.
// Then test scheduleIfNeeded(), which should schedule a job.
@Test
@MediumTest
public void testScheduleWithExpiredStamp() throws IOException {
File stamp = VariationsUtils.getStampFile();
try {
Assert.assertFalse("Stamp file already exists", stamp.exists());
Assert.assertTrue("Failed to create stamp file", stamp.createNewFile());
Assert.assertTrue("Failed to set stamp time", stamp.setLastModified(0));
AwVariationsSeedFetcher.scheduleIfNeeded();
mScheduler.assertScheduled();
} finally {
mScheduler.clear();
VariationsTestUtils.deleteSeeds(); // Remove the stamp file.
}
}
// Create a stamp file with time = now, indicating the download job ran recently. Then test
// scheduleIfNeeded(), which should not schedule a job.
@Test
@MediumTest
public void testScheduleWithFreshStamp() throws IOException {
File stamp = VariationsUtils.getStampFile();
try {
Assert.assertFalse("Stamp file already exists", stamp.exists());
Assert.assertTrue("Failed to create stamp file", stamp.createNewFile());
AwVariationsSeedFetcher.scheduleIfNeeded();
mScheduler.assertNotScheduled();
} finally {
mScheduler.clear();
VariationsTestUtils.deleteSeeds(); // Remove the stamp file.
}
}
// Pretend that a job is already scheduled. Then test scheduleIfNeeded(), which should not
// schedule a job.
@Test
@SmallTest
public void testScheduleAlreadyScheduled() {
File stamp = VariationsUtils.getStampFile();
try {
@SuppressLint("JobSchedulerService")
ComponentName component = new ComponentName(
ContextUtils.getApplicationContext(), AwVariationsSeedFetcher.class);
JobInfo job = new JobInfo.Builder(JOB_ID, component)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setRequiresCharging(true)
.build();
mScheduler.schedule(job);
AwVariationsSeedFetcher.scheduleIfNeeded();
// Check that our job object hasn't been replaced (meaning that scheduleIfNeeded didn't
// schedule a job).
Assert.assertSame(job, mScheduler.getPendingJob(JOB_ID));
} finally {
mScheduler.clear();
}
}
@Test
@SmallTest
public void testFetch() throws IOException, InterruptedException, TimeoutException {
try {
AwVariationsSeedFetcher fetcher = new AwVariationsSeedFetcher() {
// p is null in this test. Don't actually call JobService.jobFinished.
@Override
protected void jobFinished(JobParameters p) {}
};
int downloads = mDownloader.helper.getCallCount();
fetcher.onStartJob(null);
mDownloader.helper.waitForCallback(
"Timeout out waiting for AwVariationsSeedFetcher to call downloadContent",
downloads);
File stamp = VariationsUtils.getStampFile();
Assert.assertTrue("AwVariationsSeedFetcher should have updated stamp file " + stamp,
stamp.exists());
} finally {
VariationsTestUtils.deleteSeeds(); // Remove the stamp file.
}
}
}