blob: b53043bd6afd035f7efcb0e0e4e4aa524da0ac45 [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.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
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.VariationsSeedLoader;
import org.chromium.android_webview.VariationsUtils;
import org.chromium.android_webview.services.ServiceInit;
import org.chromium.android_webview.test.services.MockVariationsSeedServer;
import org.chromium.android_webview.test.util.VariationsTestUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.util.CallbackHelper;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Test VariationsSeedLoader.
*/
@RunWith(AwJUnit4ClassRunner.class)
@OnlyRunIn(SINGLE_PROCESS)
public class VariationsSeedLoaderTest {
private static final long TIMEOUT_MILLIS = 10000;
private static class TestLoaderResult extends CallbackHelper {
private boolean mSeedRequested;
public boolean wasSeedRequested() {
assert getCallCount() > 0;
return mSeedRequested;
}
public void notifyCalled(boolean seedRequested) {
mSeedRequested = seedRequested;
super.notifyCalled();
}
}
private static class TestLoader extends VariationsSeedLoader {
private boolean mSeedRequested;
private TestLoaderResult mResult;
public TestLoader(TestLoaderResult result) {
mResult = result;
}
// Bind to the MockVariationsSeedServer built in to the instrumentation test app, rather
// than the real server in the WebView provider.
@Override
protected Intent getServerIntent() {
return new Intent(ContextUtils.getApplicationContext(), MockVariationsSeedServer.class);
}
@Override
protected void requestSeedFromService(long oldSeedDate) {
super.requestSeedFromService(oldSeedDate);
mSeedRequested = true;
}
@Override
protected void onBackgroundWorkFinished() {
mResult.notifyCalled(mSeedRequested);
}
}
private Handler mMainHandler;
// Create a TestLoader, run it on the UI thread, and block until it's finished. The return value
// indicates whether the loader decided to request a new seed.
private boolean runTestLoaderBlocking() throws InterruptedException, TimeoutException {
final TestLoaderResult result = new TestLoaderResult();
Runnable run = () -> {
TestLoader loader = new TestLoader(result);
loader.startVariationsInit();
loader.finishVariationsInit();
};
CallbackHelper onRequestReceived = MockVariationsSeedServer.getRequestHelper();
int requestsReceived = onRequestReceived.getCallCount();
Assert.assertTrue("Failed to post seed loader Runnable", mMainHandler.post(run));
result.waitForCallback("Timed out waiting for loader to finish background work.", 0);
if (result.wasSeedRequested()) {
onRequestReceived.waitForCallback("Seed requested, but timed out waiting for request" +
" to arrive in MockVariationsSeedServer", requestsReceived);
return true;
}
return false;
}
@Before
public void setUp() throws IOException {
mMainHandler = new Handler(Looper.getMainLooper());
ContextUtils.initApplicationContextForTests(
InstrumentationRegistry.getInstrumentation()
.getTargetContext().getApplicationContext());
ServiceInit.setPrivateDataDirectorySuffix();
RecordHistogram.setDisabledForTests(true);
VariationsTestUtils.deleteSeeds();
}
@After
public void tearDown() throws IOException {
RecordHistogram.setDisabledForTests(false);
VariationsTestUtils.deleteSeeds();
}
// Test the case that:
// VariationsUtils.getSeedFile() - doesn't exist
// VariationsUtils.getNewSeedFile() - doesn't exist
@Test
@MediumTest
public void testHaveNoSeed() throws Exception {
try {
boolean seedRequested = runTestLoaderBlocking();
// Since there was no seed, another seed should be requested.
Assert.assertTrue("No seed requested", seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test the case that:
// VariationsUtils.getSeedFile() - exists, timestamp = now
// VariationsUtils.getNewSeedFile() - doesn't exist
@Test
@MediumTest
public void testHaveFreshSeed() throws Exception {
try {
File oldFile = VariationsUtils.getSeedFile();
Assert.assertTrue("Seed file already exists", oldFile.createNewFile());
VariationsTestUtils.writeMockSeed(oldFile);
boolean seedRequested = runTestLoaderBlocking();
// Since there was a fresh seed, we should not request another seed.
Assert.assertFalse("New seed was requested when it should not have been",
seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test the case that:
// VariationsUtils.getSeedFile() - exists, timestamp = epoch
// VariationsUtils.getNewSeedFile() - doesn't exist
@Test
@MediumTest
public void testHaveExpiredSeed() throws Exception {
try {
File oldFile = VariationsUtils.getSeedFile();
Assert.assertTrue("Seed file already exists", oldFile.createNewFile());
VariationsTestUtils.writeMockSeed(oldFile);
oldFile.setLastModified(0);
boolean seedRequested = runTestLoaderBlocking();
// Since the seed was expired, another seed should be requested.
Assert.assertTrue("No seed requested", seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test the case that:
// VariationsUtils.getSeedFile() - doesn't exist
// VariationsUtils.getNewSeedFile() - exists, timestamp = now
@Test
@MediumTest
public void testHaveFreshNewSeed() throws Exception {
try {
File oldFile = VariationsUtils.getSeedFile();
File newFile = VariationsUtils.getNewSeedFile();
Assert.assertTrue("New seed file already exists", newFile.createNewFile());
VariationsTestUtils.writeMockSeed(newFile);
boolean seedRequested = runTestLoaderBlocking();
// The "new" seed should have been renamed to the "old" seed.
Assert.assertTrue("Old seed not found", oldFile.exists());
Assert.assertFalse("New seed still exists", newFile.exists());
// Since the "new" seed was fresh, we should not request another seed.
Assert.assertFalse("New seed was requested when it should not have been",
seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test the case that:
// VariationsUtils.getSeedFile() - doesn't exist
// VariationsUtils.getNewSeedFile() - exists, timestamp = epoch
@Test
@MediumTest
public void testHaveExpiredNewSeed() throws Exception {
try {
File oldFile = VariationsUtils.getSeedFile();
File newFile = VariationsUtils.getNewSeedFile();
Assert.assertTrue("Seed file already exists", newFile.createNewFile());
VariationsTestUtils.writeMockSeed(newFile);
newFile.setLastModified(0);
boolean seedRequested = runTestLoaderBlocking();
// The "new" seed should have been renamed to the "old" seed. Another empty "new" seed
// should have been created as a destination for the request.
Assert.assertTrue("Old seed not found", oldFile.exists());
Assert.assertTrue("New seed not found", newFile.exists());
Assert.assertTrue("New seed is not empty", newFile.length() == 0L);
// Since the "new" seed was expired, another seed should be requested.
Assert.assertTrue("No seed requested", seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test the case that:
// VariationsUtils.getSeedFile() - exists, timestamp = epoch
// VariationsUtils.getNewSeedFile() - exists, timestamp = epoch + 1 day
@Test
@MediumTest
public void testHaveBothExpiredSeeds() throws Exception {
try {
File oldFile = VariationsUtils.getSeedFile();
Assert.assertTrue("Old seed file already exists", oldFile.createNewFile());
VariationsTestUtils.writeMockSeed(oldFile);
oldFile.setLastModified(0);
File newFile = VariationsUtils.getNewSeedFile();
Assert.assertTrue("New seed file already exists", newFile.createNewFile());
VariationsTestUtils.writeMockSeed(newFile);
newFile.setLastModified(TimeUnit.DAYS.toMillis(1));
boolean seedRequested = runTestLoaderBlocking();
// The "new" seed should have been renamed to the "old" seed. Another empty "new" seed
// should have been created as a destination for the request.
Assert.assertTrue("Old seed not found", oldFile.exists());
Assert.assertTrue("New seed not found", newFile.exists());
Assert.assertTrue("New seed is not empty", newFile.length() == 0L);
// Since the "new" seed was expired, another seed should be requested.
Assert.assertTrue("No seed requested", seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
// Test loading twice. The first load should trigger a request, but the second should not,
// because requests should be rate-limited.
// VariationsUtils.getSeedFile() - doesn't exist
// VariationsUtils.getNewSeedFile() - doesn't exist
@Test
@MediumTest
public void testDoubleLoad() throws Exception {
try {
boolean seedRequested = runTestLoaderBlocking();
Assert.assertTrue("No seed requested", seedRequested);
seedRequested = runTestLoaderBlocking();
Assert.assertFalse("New seed was requested when it should not have been",
seedRequested);
} finally {
VariationsTestUtils.deleteSeeds();
}
}
}