| Index: chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
|
| diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..29ab626f14286fedc2a2beab7565bd4c1cc13b23
|
| --- /dev/null
|
| +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
|
| @@ -0,0 +1,290 @@
|
| +// Copyright 2016 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.webapps;
|
| +
|
| +import android.os.Bundle;
|
| +
|
| +import static org.junit.Assert.assertEquals;
|
| +import static org.junit.Assert.assertFalse;
|
| +import static org.junit.Assert.assertTrue;
|
| +
|
| +import org.junit.Before;
|
| +import org.junit.Test;
|
| +import org.junit.runner.RunWith;
|
| +import org.robolectric.RuntimeEnvironment;
|
| +import org.robolectric.annotation.Config;
|
| +import org.robolectric.shadows.ShadowApplication;
|
| +
|
| +import org.chromium.base.CommandLine;
|
| +import org.chromium.base.ContextUtils;
|
| +import org.chromium.blink_public.platform.WebDisplayMode;
|
| +import org.chromium.chrome.browser.ShortcutHelper;
|
| +import org.chromium.chrome.browser.ShortcutSource;
|
| +import org.chromium.chrome.browser.tab.Tab;
|
| +import org.chromium.content_public.common.ScreenOrientationValues;
|
| +import org.chromium.testing.local.LocalRobolectricTestRunner;
|
| +import org.chromium.webapk.lib.client.WebApkVersion;
|
| +import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
|
| +import org.chromium.webapk.test.WebApkTestHelper;
|
| +
|
| +/**
|
| + * Unit tests for WebApkUpdateManager.
|
| + */
|
| +@RunWith(LocalRobolectricTestRunner.class)
|
| +@Config(manifest = Config.NONE)
|
| +public class WebApkUpdateManagerTest {
|
| + /** WebAPK's id in {@link WebAppDataStorage}. */
|
| + private static final String WEBAPK_ID = "id";
|
| +
|
| + /** WebAPK's start URL. */
|
| + private static final String WEBAPK_START_URL = "https://www.unicode.party";
|
| +
|
| + /** {@link WebappDataStorage#Clock} subclass which enables time to be manually advanced. */
|
| + private static class MockClock extends WebappDataStorage.Clock {
|
| + // 0 has a special meaning: {@link WebappDataStorage#LAST_USED_UNSET}.
|
| + private long mTimeMillis = 1;
|
| +
|
| + public void advance(long millis) {
|
| + mTimeMillis += millis;
|
| + }
|
| +
|
| + @Override
|
| + public long currentTimeMillis() {
|
| + return mTimeMillis;
|
| + }
|
| + }
|
| +
|
| + /** Mock {@link ManifestUpgradeDetector}. */
|
| + private static class TestManifestUpgradeDetector extends ManifestUpgradeDetector {
|
| + private boolean mStarted;
|
| +
|
| + public TestManifestUpgradeDetector(Tab tab, WebappInfo info, Bundle metaData,
|
| + ManifestUpgradeDetector.Callback callback) {
|
| + super(tab, info, metaData, callback);
|
| + }
|
| +
|
| + public boolean wasStarted() {
|
| + return mStarted;
|
| + }
|
| +
|
| + @Override
|
| + public boolean start() {
|
| + mStarted = true;
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + private static class TestWebApkUpdateManager extends WebApkUpdateManager {
|
| + private WebappDataStorage.Clock mClock;
|
| + private TestManifestUpgradeDetector mUpgradeDetector;
|
| + private boolean mUpdateRequested;
|
| +
|
| + public TestWebApkUpdateManager(WebappDataStorage.Clock clock) {
|
| + mClock = clock;
|
| + }
|
| +
|
| + /**
|
| + * Returns whether the is-update-needed check has been triggered.
|
| + */
|
| + public boolean updateCheckStarted() {
|
| + return mUpgradeDetector != null && mUpgradeDetector.wasStarted();
|
| + }
|
| +
|
| + /**
|
| + * Returns whether an update has been requested.
|
| + */
|
| + public boolean updateRequested() {
|
| + return mUpdateRequested;
|
| + }
|
| +
|
| + @Override
|
| + protected ManifestUpgradeDetector buildManifestUpgradeDetector(
|
| + Tab tab, WebappInfo info, Bundle metaData) {
|
| + mUpgradeDetector = new TestManifestUpgradeDetector(tab, info, metaData, this);
|
| + return mUpgradeDetector;
|
| + }
|
| +
|
| + @Override
|
| + public void updateAsync(ManifestUpgradeDetector.FetchedManifestData data) {
|
| + mUpdateRequested = true;
|
| + }
|
| +
|
| + @Override
|
| + protected long currentTimeMillis() {
|
| + return mClock.currentTimeMillis();
|
| + }
|
| + }
|
| +
|
| + private MockClock mClock;
|
| +
|
| + private WebappDataStorage getStorage() {
|
| + return WebappRegistry.getInstance().getWebappDataStorage(WEBAPK_ID);
|
| + }
|
| +
|
| + private void updateIfNeeded(WebApkUpdateManager updateManager) {
|
| + WebappInfo info = WebappInfo.create(WEBAPK_ID, WEBAPK_START_URL, null, null, null, null,
|
| + WebDisplayMode.Standalone, ScreenOrientationValues.DEFAULT, ShortcutSource.UNKNOWN,
|
| + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING,
|
| + ShortcutHelper.MANIFEST_COLOR_INVALID_OR_MISSING, false,
|
| + WebApkTestHelper.WEBAPK_PACKAGE_NAME);
|
| + updateManager.updateIfNeeded(null, info);
|
| + }
|
| +
|
| + /**
|
| + * Runs {@link WebApkUpdateManager#updateIfNeeded()} and returns whether an
|
| + * is-update-needed check has been triggered.
|
| + */
|
| + private boolean updateIfNeededChecksForUpdatedWebManifest() {
|
| + TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(mClock);
|
| + updateIfNeeded(updateManager);
|
| + return updateManager.updateCheckStarted();
|
| + }
|
| +
|
| + @Before
|
| + public void setUp() {
|
| + ContextUtils.initApplicationContextForTests(RuntimeEnvironment.application);
|
| + CommandLine.init(null);
|
| +
|
| + mClock = new MockClock();
|
| + WebappDataStorage.setClockForTests(mClock);
|
| +
|
| + Bundle metaData = new Bundle();
|
| + metaData.putInt(
|
| + WebApkMetaDataKeys.SHELL_APK_VERSION, WebApkVersion.CURRENT_SHELL_APK_VERSION);
|
| + WebApkTestHelper.registerWebApkWithMetaData(metaData);
|
| +
|
| + WebappRegistry.getInstance().register(
|
| + WEBAPK_ID, new WebappRegistry.FetchWebappDataStorageCallback() {
|
| + @Override
|
| + public void onWebappDataStorageRetrieved(WebappDataStorage storage) {}
|
| + });
|
| + ShadowApplication.getInstance().runBackgroundTasks();
|
| +
|
| + WebappDataStorage storage = getStorage();
|
| + storage.updateTimeOfLastCheckForUpdatedWebManifest();
|
| + storage.updateTimeOfLastWebApkUpdateRequestCompletion();
|
| + storage.updateDidLastWebApkUpdateRequestSucceed(true);
|
| + }
|
| +
|
| + /**
|
| + * Test that if the WebAPK update failed (e.g. because the WebAPK server is not reachable) that
|
| + * the is-update-needed check is retried after less time than if the WebAPK update had
|
| + * succeeded.
|
| + * The is-update-needed check is the first step in retrying to update the WebAPK.
|
| + */
|
| + @Test
|
| + public void testCheckUpdateMoreFrequentlyIfUpdateFails() {
|
| + assertTrue(WebApkUpdateManager.FULL_CHECK_UPDATE_INTERVAL
|
| + > WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| +
|
| + WebappDataStorage storage = getStorage();
|
| +
|
| + assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
|
| + assertFalse(updateIfNeededChecksForUpdatedWebManifest());
|
| + mClock.advance(WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| + assertFalse(updateIfNeededChecksForUpdatedWebManifest());
|
| +
|
| + // Advance all of the time stamps.
|
| + storage.updateTimeOfLastCheckForUpdatedWebManifest();
|
| + storage.updateTimeOfLastWebApkUpdateRequestCompletion();
|
| +
|
| + storage.updateDidLastWebApkUpdateRequestSucceed(false);
|
| + assertFalse(updateIfNeededChecksForUpdatedWebManifest());
|
| + mClock.advance(WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| + assertTrue(updateIfNeededChecksForUpdatedWebManifest());
|
| + }
|
| +
|
| + /**
|
| + * Test that if there was no previous WebAPK update attempt that the is-update-needed check is
|
| + * done after the usual delay (as opposed to the shorter delay if the previous WebAPK update
|
| + * failed.)
|
| + */
|
| + @Test
|
| + public void testRegularCheckIntervalIfNoPriorWebApkUpdate() {
|
| + assertTrue(WebApkUpdateManager.FULL_CHECK_UPDATE_INTERVAL
|
| + > WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| +
|
| + getStorage().delete();
|
| + WebappDataStorage storage = getStorage();
|
| +
|
| + // Done when WebAPK is registered in {@link WebApkActivity}.
|
| + storage.updateTimeOfLastCheckForUpdatedWebManifest();
|
| +
|
| + assertFalse(updateIfNeededChecksForUpdatedWebManifest());
|
| + mClock.advance(WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| + assertFalse(updateIfNeededChecksForUpdatedWebManifest());
|
| + mClock.advance(WebApkUpdateManager.FULL_CHECK_UPDATE_INTERVAL
|
| + - WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| + assertTrue(updateIfNeededChecksForUpdatedWebManifest());
|
| + }
|
| +
|
| + /**
|
| + * Test that the completion time of the previous WebAPK update is not modified if:
|
| + * - The previous WebAPK update succeeded.
|
| + * AND
|
| + * - A WebAPK update is not required.
|
| + */
|
| + @Test
|
| + public void testUpdateNotNeeded() {
|
| + long initialTime = mClock.currentTimeMillis();
|
| + mClock.advance(WebApkUpdateManager.FULL_CHECK_UPDATE_INTERVAL);
|
| +
|
| + TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(mClock);
|
| + updateIfNeeded(updateManager);
|
| + assertTrue(updateManager.updateCheckStarted());
|
| + updateManager.onUpgradeNeededCheckFinished(false, null);
|
| + assertFalse(updateManager.updateRequested());
|
| +
|
| + WebappDataStorage storage = getStorage();
|
| + assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
|
| + assertEquals(initialTime, storage.getLastWebApkUpdateRequestCompletionTime());
|
| + }
|
| +
|
| + /**
|
| + * Test that the last WebAPK update is marked as having succeeded if:
|
| + * - The previous WebAPK update failed.
|
| + * AND
|
| + * - A WebAPK update is no longer required.
|
| + */
|
| + @Test
|
| + public void testMarkUpdateAsSucceededIfUpdateNoLongerNeeded() {
|
| + WebappDataStorage storage = getStorage();
|
| + storage.updateDidLastWebApkUpdateRequestSucceed(false);
|
| + mClock.advance(WebApkUpdateManager.RETRY_UPDATE_DURATION);
|
| +
|
| + TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(mClock);
|
| + updateIfNeeded(updateManager);
|
| + assertTrue(updateManager.updateCheckStarted());
|
| + updateManager.onUpgradeNeededCheckFinished(false, null);
|
| + assertFalse(updateManager.updateRequested());
|
| +
|
| + assertTrue(storage.getDidLastWebApkUpdateRequestSucceed());
|
| + assertEquals(
|
| + mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
|
| + }
|
| +
|
| + /**
|
| + * Test that the WebAPK update is marked as having failed if Chrome is killed prior to the
|
| + * WebAPK update completing.
|
| + */
|
| + @Test
|
| + public void testMarkUpdateAsFailedIfClosePriorToUpdateCompleting() {
|
| + mClock.advance(WebApkUpdateManager.FULL_CHECK_UPDATE_INTERVAL);
|
| +
|
| + TestWebApkUpdateManager updateManager = new TestWebApkUpdateManager(mClock);
|
| + updateIfNeeded(updateManager);
|
| + assertTrue(updateManager.updateCheckStarted());
|
| + updateManager.onUpgradeNeededCheckFinished(true, null);
|
| + assertTrue(updateManager.updateRequested());
|
| +
|
| + // Chrome is killed. {@link WebApkUpdateManager#onBuiltWebApk} is never called.
|
| +
|
| + // Check {@link WebappDataStorage} state.
|
| + WebappDataStorage storage = getStorage();
|
| + assertFalse(storage.getDidLastWebApkUpdateRequestSucceed());
|
| + assertEquals(
|
| + mClock.currentTimeMillis(), storage.getLastWebApkUpdateRequestCompletionTime());
|
| + }
|
| +}
|
|
|