Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Unified Diff: chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java

Issue 2430773002: Fix WebappDataStorage#updateDidLastWebApkUpdateRequestSucceed() corner cases (Closed)
Patch Set: Merge branch 'master' into update_fail00 Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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());
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698