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

Unified Diff: chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java

Issue 2087893003: Migrate TabPersistentStore to one shared directory for multi-instance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment styling Created 4 years, 6 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/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..42e264e13ca98f8868e06d1c2f07cd9ebc570b39
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/MultiInstanceMigrationTest.java
@@ -0,0 +1,280 @@
+// 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.tabmodel;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.test.util.AdvancedMockContext;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.TabState;
+import org.chromium.chrome.test.util.ApplicationData;
+import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Test that migrating the old multi-instance tab state folder structure to the new one works.
+ * Previously each instance had its own subdirectory for storing files. Now there is one
+ * shared directory.
+ */
+public class MultiInstanceMigrationTest extends InstrumentationTestCase {
+
+ private Context mAppContext;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mAppContext = new AdvancedMockContext(
+ getInstrumentation().getTargetContext().getApplicationContext());
+ ContextUtils.initApplicationContextForTests(mAppContext);
+ ApplicationData.clearAppData(mAppContext);
+
+ // Set the shared pref stating that the legacy file migration has occurred. The
+ // multi-instance migration won't happen if the legacy path is taken.
+ ContextUtils.getAppSharedPreferences().edit().putBoolean(
+ TabPersistentStore.PREF_HAS_RUN_FILE_MIGRATION, true).apply();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ ApplicationData.clearAppData(mAppContext);
+ }
+
+ /**
+ * Tests that normal migration of multi-instance state files works.
+ */
+ @MediumTest
+ @Feature({"TabPersistentStore"})
+ public void testMigrateData() throws IOException {
+ // Write old state files.
+ File[] stateDirs = createOldStateDirs(TabWindowManager.MAX_SIMULTANEOUS_SELECTORS, true);
+ File stateFile0 = new File(stateDirs[0], TabPersistentStore.SAVED_STATE_FILE);
+ File stateFile1 = new File(stateDirs[1], TabPersistentStore.SAVED_STATE_FILE);
+ File stateFile2 = new File(stateDirs[2], TabPersistentStore.SAVED_STATE_FILE);
+ File customTabsStateFile = new File(stateDirs[3], TabPersistentStore.SAVED_STATE_FILE);
+
+ assertTrue("Could not create state file 0", stateFile0.createNewFile());
+ assertTrue("Could not create state file 1", stateFile1.createNewFile());
+ assertTrue("Could not create state file 2", stateFile2.createNewFile());
+ assertTrue("Could not create custom tabs state file", customTabsStateFile.createNewFile());
+
+ // Create a couple of tabs for each tab state subdirectory.
+ File tab0 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "0");
+ File tab1 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "1");
+ File tab2 = new File(stateDirs[1], TabState.SAVED_TAB_STATE_FILE_PREFIX + "2");
+ File tab3 = new File(stateDirs[1], TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "3");
+ File tab4 = new File(stateDirs[2], TabState.SAVED_TAB_STATE_FILE_PREFIX + "4");
+ File tab5 = new File(stateDirs[2], TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "5");
+ File tab6 = new File(stateDirs[3], TabState.SAVED_TAB_STATE_FILE_PREFIX + "6");
+
+ assertTrue("Could not create tab 0 file", tab0.createNewFile());
+ assertTrue("Could not create tab 1 file", tab1.createNewFile());
+ assertTrue("Could not create tab 2 file", tab2.createNewFile());
+ assertTrue("Could not create tab 3 file", tab3.createNewFile());
+ assertTrue("Could not create tab 4 file", tab4.createNewFile());
+ assertTrue("Could not create tab 5 file", tab5.createNewFile());
+ assertTrue("Could not create tab 6 file", tab6.createNewFile());
+
+ // Build the TabPersistentStore which will try to move the files.
+ MockTabModelSelector selector = new MockTabModelSelector(0, 0, null);
+ TabPersistentStore store = new TabPersistentStore(selector, 0, mAppContext, null, null);
+ store.waitForMigrationToFinish();
+
+ // Make sure we don't hit the migration path again.
+ assertTrue(ContextUtils.getAppSharedPreferences().getBoolean(
+ TabPersistentStore.PREF_HAS_RUN_MULTI_INSTANCE_FILE_MIGRATION, false));
+
+ // Check that all metadata files moved.
+ File newStateFile0 = new File(stateDirs[0], TabPersistentStore.getStateFileName(0));
+ File newStateFile1 = new File(stateDirs[0], TabPersistentStore.getStateFileName(1));
+ File newStateFile2 = new File(stateDirs[0], TabPersistentStore.getStateFileName(2));
+ File newCustomTabsStateFile = new File(stateDirs[0], TabPersistentStore.getStateFileName(
+ TabModelSelectorImpl.CUSTOM_TABS_SELECTOR_INDEX));
+ assertTrue("Could not find new state file 0", newStateFile0.exists());
+ assertTrue("Could not find new state file 1", newStateFile1.exists());
+ assertTrue("Could not find new state file 2", newStateFile2.exists());
+ assertTrue("Could not find new custom tabs state file", newCustomTabsStateFile.exists());
+ assertFalse("Could still find old state file 0", stateFile0.exists());
+ assertFalse("Could still find old state file 1", stateFile1.exists());
+ assertFalse("Could still find old state file 2", stateFile2.exists());
+ assertFalse("Could still find old custom tabs state file", customTabsStateFile.exists());
+
+ // Check that tab 0 and 1 did not move.
+ assertTrue("Could not find tab 0 file", tab0.exists());
+ assertTrue("Could not find tab 1 file", tab1.exists());
+
+ // Check that tabs 2-5 did move.
+ File newTab2 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "2");
+ File newTab3 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "3");
+ File newTab4 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "4");
+ File newTab5 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "5");
+ assertTrue("Could not find new tab 2 file", newTab2.exists());
+ assertTrue("Could not find new tab 3 file", newTab3.exists());
+ assertTrue("Could not find new tab 4 file", newTab4.exists());
+ assertTrue("Could not find new tab 5 file", newTab5.exists());
+ assertFalse("Could still find old tab 2 file", tab2.exists());
+ assertFalse("Could still find old tab 3 file", tab3.exists());
+ assertFalse("Could still find old tab 4 file", tab4.exists());
+ assertFalse("Could still find old tab 5 file", tab5.exists());
+
+ // Check that the custom tab (tab 6) was deleted.
+ File newTab6 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "6");
+ assertFalse("Could still find old tab 6 file", tab6.exists());
+ assertFalse("Found new tab 6 file. It should have been deleted.", newTab6.exists());
+
+ // Check that old directories were deleted.
+ assertFalse("Could still find old state dir 1", stateDirs[1].exists());
+ assertFalse("Could still find old state dir 2", stateDirs[2].exists());
+ assertFalse("Could still find old custom tabs state dir", stateDirs[3].exists());
+ }
+
+ /**
+ * Tests that the state file migration skips unrelated files. Also tests that migration works
+ * if the number of tab state subdirectories to migrate is less than
+ * {@code TabWindowManager.MAX_SIMULTANEOUS_SELECTORS}
+ */
+ @MediumTest
+ @Feature({"TabPersistentStore"})
+ public void testMigrationLeavesOtherFilesAlone() throws IOException {
+ // Write old state files and an extra file.
+ File[] stateDirs = createOldStateDirs(2, false);
+ File stateFile0 = new File(stateDirs[0], TabPersistentStore.SAVED_STATE_FILE);
+ File stateFile1 = new File(stateDirs[1], TabPersistentStore.SAVED_STATE_FILE);
+ File tab0 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "0");
+ File tab1 = new File(stateDirs[1], TabState.SAVED_TAB_STATE_FILE_PREFIX + "1");
+ File otherFile = new File(stateDirs[1], "other.file");
+
+ assertTrue("Could not create state file 0", stateFile0.createNewFile());
+ assertTrue("Could not create state file 1", stateFile1.createNewFile());
+ assertTrue("Could not create tab 0 file", tab0.createNewFile());
+ assertTrue("Could not create tab 1 file", tab1.createNewFile());
+ assertTrue("Could not create other file", otherFile.createNewFile());
+
+ // Build the TabPersistentStore which will try to move the files.
+ MockTabModelSelector selector = new MockTabModelSelector(0, 0, null);
+ TabPersistentStore store = new TabPersistentStore(selector, 0, mAppContext, null, null);
+ store.waitForMigrationToFinish();
+
+ // Check that the other file wasn't moved.
+ File newOtherFile = new File(stateDirs[0], "other.file");
+ assertFalse("Could find new other file", newOtherFile.exists());
+ assertTrue("Could not find original other file", otherFile.exists());
+
+ // Check that the metadata files were renamed and/or moved.
+ File newStateFile0 = new File(stateDirs[0], TabPersistentStore.getStateFileName(0));
+ File newStateFile1 = new File(stateDirs[0], TabPersistentStore.getStateFileName(1));
+ assertTrue("Could not find new state file 0", newStateFile0.exists());
+ assertTrue("Could not find new state file 1", newStateFile1.exists());
+ assertFalse("Could still find old state file 0", stateFile0.exists());
+ assertFalse("Could still find old state file 1", stateFile1.exists());
+
+ // Check that tab 0 did not move.
+ assertTrue("Could not find tab 0 file", tab0.exists());
+
+ // Check that tab 1 did move.
+ File newTab1 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "1");
+ assertTrue("Could not find tab 1 file", newTab1.exists());
+ assertFalse("Could still find old tab 1 file", tab1.exists());
+ }
+
+ /**
+ * Tests that migration of multi-instance state files works when tab files with the same name
+ * exists in both directories.
+ */
+ @MediumTest
+ @Feature({"TabPersistentStore"})
+ public void testMigrateDataDuplicateTabFiles() throws IOException {
+ // Write old state files.
+ File[] stateDirs = createOldStateDirs(2, false);
+ File stateFile0 = new File(stateDirs[0], TabPersistentStore.SAVED_STATE_FILE);
+ File stateFile1 = new File(stateDirs[1], TabPersistentStore.SAVED_STATE_FILE);
+
+ assertTrue("Could not create state file 0", stateFile0.createNewFile());
+ assertTrue("Could not create state file 1", stateFile1.createNewFile());
+
+ // Create duplicate "tab0" files and ensure tab0Dir1 has been modified more recently so that
+ // it overwrites tab0Dir0.
+ File tab0Dir0 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "0");
+ File tab0Dir1 = new File(stateDirs[1], TabState.SAVED_TAB_STATE_FILE_PREFIX + "0");
+ assertTrue("Could not create tab 0-0 file", tab0Dir0.createNewFile());
+ assertTrue("Could not create tab 0-1 file", tab0Dir1.createNewFile());
+ long expectedTab0LastModifiedTime = tab0Dir0.lastModified() + 1000;
+ if (!tab0Dir1.setLastModified(expectedTab0LastModifiedTime)) {
+ fail("Failed to set last modified time.");
+ }
+
+ // Create duplicate "tab1" files and ensure tab1Dir0 has been modified more recently so that
+ // it does not get overwritten.
+ File tab1Dir0 = new File(stateDirs[0], TabState.SAVED_TAB_STATE_FILE_PREFIX + "1");
+ File tab1Dir1 = new File(stateDirs[1], TabState.SAVED_TAB_STATE_FILE_PREFIX + "1");
+ assertTrue("Could not create tab 1-0 file", tab1Dir0.createNewFile());
+ assertTrue("Could not create tab 1-1 file", tab1Dir1.createNewFile());
+ long expectedTab1LastModifiedTime = tab1Dir1.lastModified() + 1000;
+ if (!tab1Dir0.setLastModified(expectedTab1LastModifiedTime)) {
+ fail("Failed to set last modified time.");
+ }
+
+ // Build the TabPersistentStore which will try to move the files.
+ MockTabModelSelector selector = new MockTabModelSelector(0, 0, null);
+ TabPersistentStore store = new TabPersistentStore(selector, 0, mAppContext, null, null);
+ store.waitForMigrationToFinish();
+
+ // Check that "tab0" still exists and has the expected last modified time.
+ assertTrue("Could not find tab 0 file", tab0Dir0.exists());
+ assertFalse("Could still find old tab 0 file", tab0Dir1.exists());
+ assertEquals("tab 0 file not overwritten properly",
+ expectedTab0LastModifiedTime,
+ tab0Dir0.lastModified());
+
+ // Check that "tab1" still exists and has the expected last modified time.
+ assertTrue("Could not find tab 1 file", tab1Dir0.exists());
+ assertFalse("Could still find old tab 1 file", tab1Dir1.exists());
+ assertEquals("tab 1 file unexpectedly overwritten",
+ expectedTab1LastModifiedTime,
+ tab1Dir0.lastModified());
+
+ // Check that old directory was deleted.
+ assertFalse("Could still find old state dir 1", stateDirs[1].exists());
+ }
+
+ /**
+ * Creates tab state directories using the old pre-multi-instance migration file paths where
+ * each tab model had its own state directory.
+ *
+ * @param numRegularDirsToCreate The number of regular tab state directories to create.
+ * @param createCustomTabsDir Whether a custom tabs directory should be created.
+ * @return An array containing the tab state directories. If createCustomTabsDir is true,
+ * a directory for custom tabs will be added to the end of the array.
+ */
+ private File[] createOldStateDirs(int numRegularDirsToCreate, boolean createCustomTabsDir) {
+ int numDirsToCreate =
+ createCustomTabsDir ? numRegularDirsToCreate + 1 : numRegularDirsToCreate;
+ File[] stateDirs = new File[numDirsToCreate];
+ for (int i = 0; i < numRegularDirsToCreate; i++) {
+ stateDirs[i] = new File(TabPersistentStore.getOrCreateBaseStateDirectory(),
+ Integer.toString(i));
+ if (!stateDirs[i].exists()) {
+ assertTrue("Could not create state dir " + i, stateDirs[i].mkdir());
+ }
+ }
+
+ if (createCustomTabsDir) {
+ stateDirs[numDirsToCreate - 1] = new File(
+ TabPersistentStore.getOrCreateBaseStateDirectory(),
+ Integer.toString(TabModelSelectorImpl.CUSTOM_TABS_SELECTOR_INDEX));
+ if (!stateDirs[numDirsToCreate - 1].exists()) {
+ assertTrue("Could not create custom tab state dir",
+ stateDirs[numDirsToCreate - 1].mkdir());
+ }
+ }
+
+ return stateDirs;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698