mobile/android/tests/background/junit3/src/sync/TestConfigurationMigrator.java

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mobile/android/tests/background/junit3/src/sync/TestConfigurationMigrator.java	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,286 @@
     1.4 +/* Any copyright is dedicated to the Public Domain.
     1.5 +   http://creativecommons.org/publicdomain/zero/1.0/ */
     1.6 +
     1.7 +package org.mozilla.gecko.background.sync;
     1.8 +
     1.9 +import java.util.Map;
    1.10 +
    1.11 +import org.mozilla.gecko.background.common.GlobalConstants;
    1.12 +import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
    1.13 +import org.mozilla.gecko.background.testhelpers.MockSharedPreferences;
    1.14 +import org.mozilla.gecko.sync.ExtendedJSONObject;
    1.15 +import org.mozilla.gecko.sync.PrefsBackoffHandler;
    1.16 +import org.mozilla.gecko.sync.SyncConfiguration;
    1.17 +import org.mozilla.gecko.sync.SyncConstants;
    1.18 +import org.mozilla.gecko.sync.Utils;
    1.19 +import org.mozilla.gecko.sync.config.ConfigurationMigrator;
    1.20 +import org.mozilla.gecko.sync.setup.SyncAccounts;
    1.21 +import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
    1.22 +
    1.23 +import android.accounts.Account;
    1.24 +import android.accounts.AccountManager;
    1.25 +import android.content.Context;
    1.26 +import android.content.SharedPreferences;
    1.27 +import android.content.SharedPreferences.Editor;
    1.28 +
    1.29 +public class TestConfigurationMigrator extends AndroidSyncTestCase {
    1.30 +  /**
    1.31 +   * A migrator that makes public certain protected static functions for testing.
    1.32 +   */
    1.33 +  protected static class PublicMigrator extends ConfigurationMigrator {
    1.34 +    public static int upgradeGlobals0to1(final SharedPreferences from, final SharedPreferences to) throws Exception {
    1.35 +      return ConfigurationMigrator.upgradeGlobals0to1(from, to);
    1.36 +    }
    1.37 +
    1.38 +    public static int downgradeGlobals1to0(final SharedPreferences from, final SharedPreferences to) throws Exception {
    1.39 +      return ConfigurationMigrator.downgradeGlobals1to0(from, to);
    1.40 +    }
    1.41 +
    1.42 +    public static int upgradeShared0to1(final SharedPreferences from, final SharedPreferences to) {
    1.43 +      return ConfigurationMigrator.upgradeShared0to1(from, to);
    1.44 +    }
    1.45 +
    1.46 +    public static int downgradeShared1to0(final SharedPreferences from, final SharedPreferences to) {
    1.47 +      return ConfigurationMigrator.downgradeShared1to0(from, to);
    1.48 +    }
    1.49 +
    1.50 +    public static int upgradeAndroidAccount0to1(final AccountManager accountManager, final Account account, final SharedPreferences to) throws Exception {
    1.51 +      return ConfigurationMigrator.upgradeAndroidAccount0to1(accountManager, account, to);
    1.52 +    }
    1.53 +
    1.54 +    public static int downgradeAndroidAccount1to0(final SharedPreferences from, final AccountManager accountManager, final Account account) throws Exception {
    1.55 +      return ConfigurationMigrator.downgradeAndroidAccount1to0(from, accountManager, account);
    1.56 +    }
    1.57 +  };
    1.58 +
    1.59 +  public static final String TEST_USERNAME   = "test@mozilla.com";
    1.60 +  public static final String TEST_SYNCKEY    = "testSyncKey";
    1.61 +  public static final String TEST_PASSWORD   = "testPassword";
    1.62 +  public static final String TEST_SERVERURL = null;
    1.63 +  public static final String TEST_PROFILE   = "default";
    1.64 +  public static final String TEST_PRODUCT   = GlobalConstants.BROWSER_INTENT_PACKAGE;
    1.65 +
    1.66 +  public static final String TEST_GUID = "testGuid";
    1.67 +  public static final String TEST_CLIENT_NAME = "test's Nightly on test";
    1.68 +  public static final long TEST_NUM_CLIENTS = 2;
    1.69 +
    1.70 +  protected static void putJSON(final Editor editor, final String name, final String JSON) throws Exception {
    1.71 +    editor.putString(name, ExtendedJSONObject.parseJSONObject(JSON).toJSONString());
    1.72 +  }
    1.73 +
    1.74 +  /**
    1.75 +   * Write a complete set of unversioned account prefs suitable for testing forward migration.
    1.76 +   * @throws Exception
    1.77 +   */
    1.78 +  public void populateAccountSharedPrefs(final SharedPreferences to) throws Exception {
    1.79 +    final Editor editor = to.edit();
    1.80 +
    1.81 +    putJSON(editor, "forms.remote", "{\"timestamp\":1340402010180}");
    1.82 +    putJSON(editor, "forms.local",  "{\"timestamp\":1340402018565}");
    1.83 +    editor.putString("forms.syncID", "JKAkk-wUEUpX");
    1.84 +
    1.85 +    putJSON(editor, "tabs.remote", "{\"timestamp\":1340401964300}");
    1.86 +    putJSON(editor, "tabs.local",  "{\"timestamp\":1340401970533}");
    1.87 +    editor.putString("tabs.syncID", "604bXkw7dnUq");
    1.88 +
    1.89 +    putJSON(editor, "passwords.remote", "{\"timestamp\":1340401965150}");
    1.90 +    putJSON(editor, "passwords.local",  "{\"timestamp\":1340402005243}");
    1.91 +    editor.putString("passwords.syncID", "VkTH0QiVj6dD");
    1.92 +
    1.93 +    putJSON(editor, "history.remote", "{\"timestamp\":1340402003640}");
    1.94 +    putJSON(editor, "history.local",  "{\"timestamp\":1340402015381}");
    1.95 +    editor.putString("history.syncID", "fs1241n-JyWh");
    1.96 +
    1.97 +    putJSON(editor, "bookmarks.remote", "{\"timestamp\":1340402003370}");
    1.98 +    putJSON(editor, "bookmarks.local",  "{\"timestamp\":1340402008397}");
    1.99 +    editor.putString("bookmarks.syncID", "P8gG8ERuJ4H1");
   1.100 +
   1.101 +    editor.putLong("metaGlobalLastModified", 1340401961960L);
   1.102 +    putJSON(editor, "metaGlobalServerResponseBody", "{\"ttl\":31536000,\"id\":\"global\",\"payload\":\"{\\\"storageVersion\\\":5,\\\"syncID\\\":\\\"Z2RopSDg-0bE\\\",\\\"engines\\\":{\\\"history\\\":{\\\"syncID\\\":\\\"fs1241n-JyWh\\\",\\\"version\\\":1},\\\"bookmarks\\\":{\\\"syncID\\\":\\\"P8gG8ERuJ4H1\\\",\\\"version\\\":2},\\\"passwords\\\":{\\\"syncID\\\":\\\"VkTH0QiVj6dD\\\",\\\"version\\\":1},\\\"prefs\\\":{\\\"syncID\\\":\\\"4lESgyoYPXYI\\\",\\\"version\\\":2},\\\"addons\\\":{\\\"syncID\\\":\\\"yCkJKkH-okoS\\\",\\\"version\\\":1},\\\"forms\\\":{\\\"syncID\\\":\\\"JKAkk-wUEUpX\\\",\\\"version\\\":1},\\\"clients\\\":{\\\"syncID\\\":\\\"KfANCdkZNOFJ\\\",\\\"version\\\":1},\\\"tabs\\\":{\\\"syncID\\\":\\\"604bXkw7dnUq\\\",\\\"version\\\":1}}}\"}");
   1.103 +
   1.104 +    editor.putLong("crypto5KeysLastModified", 1340401962760L);
   1.105 +    putJSON(editor, "crypto5KeysServerResponseBody", "{\"ttl\":31536000,\"id\":\"keys\",\"payload\":\"{\\\"ciphertext\\\":\\\"+ZH6AaMhnKOWS7OzpdMfT5X2C7AYgax5JRd2HY4BHAFNPDv8\\\\\\/TwQIJgFDuNjASo0WEujjdkFot39qeQ24RLAz4D11rG\\\\\\/FZwo8FEUB9aSfec1N6sao6KzWkSamdqiJSRjpsUKexp2it1HvwqRDEBH\\\\\\/lgue11axv51u1MAV3ZfX2fdzVIiGTqF1YJAvENZtol3pyEh2HI4FZlv+oLW250nV4w1vAfDNGLVbbjXbdR+kec=\\\",\\\"IV\\\":\\\"bHqF\\\\\\/4PshKt2GQ\\\\\\/njGj2Jw==\\\",\\\"hmac\\\":\\\"f97c20d5c0a141f62a1571a108de1bad4b854b29c8d4b2b0d36da73421e4becc\\\"}\"}");
   1.106 +
   1.107 +    editor.putString("syncID", "Z2RopSDg-0bE");
   1.108 +    editor.putString("clusterURL", "https://scl2-sync3.services.mozilla.com/");
   1.109 +    putJSON(editor, "enabledEngineNames", "{\"history\":0,\"bookmarks\":0,\"passwords\":0,\"prefs\":0,\"addons\":0,\"forms\":0,\"clients\":0,\"tabs\":0}");
   1.110 +
   1.111 +    editor.putLong("serverClientsTimestamp", 1340401963950L);
   1.112 +    editor.putLong("serverClientRecordTimestamp", 1340401963950L);
   1.113 +
   1.114 +    editor.commit();
   1.115 +  }
   1.116 +
   1.117 +  /**
   1.118 +   * Write a complete set of unversioned global prefs suitable for testing forward migration.
   1.119 +   * @throws Exception
   1.120 +   */
   1.121 +  public void populateGlobalSharedPrefs(final SharedPreferences to) throws Exception {
   1.122 +    final Editor editor = to.edit();
   1.123 +
   1.124 +    editor.putLong("earliestnextsync", 1340402318649L);
   1.125 +    editor.putBoolean("clusterurlisstale", false);
   1.126 +
   1.127 +    editor.commit();
   1.128 +  }
   1.129 +
   1.130 +  /**
   1.131 +   * Write a complete set of unversioned Account data suitable for testing forward migration.
   1.132 +   * @throws Exception
   1.133 +   */
   1.134 +  public void populateAccountData(final AccountManager accountManager, final Account account) throws Exception {
   1.135 +    accountManager.setUserData(account, "account.guid", TEST_GUID);
   1.136 +    accountManager.setUserData(account, "account.clientName", TEST_CLIENT_NAME);
   1.137 +    accountManager.setUserData(account, "account.numClients", Long.valueOf(TEST_NUM_CLIENTS).toString());
   1.138 +  }
   1.139 +
   1.140 +  public void testMigrateGlobals0and1() throws Exception {
   1.141 +    final SharedPreferences v0a = new MockSharedPreferences();
   1.142 +    final SharedPreferences v1a = new MockSharedPreferences();
   1.143 +    final SharedPreferences v0b = new MockSharedPreferences();
   1.144 +    final SharedPreferences v1b = new MockSharedPreferences();
   1.145 +
   1.146 +    populateGlobalSharedPrefs(v0a);
   1.147 +
   1.148 +    final int NUM_GLOBALS = 2;
   1.149 +    assertEquals(NUM_GLOBALS, v0a.getAll().size());
   1.150 +    assertEquals(NUM_GLOBALS, PublicMigrator.upgradeGlobals0to1(v0a, v1a));
   1.151 +    assertEquals(NUM_GLOBALS, PublicMigrator.downgradeGlobals1to0(v1a, v0b));
   1.152 +    assertEquals(NUM_GLOBALS, PublicMigrator.upgradeGlobals0to1(v0b, v1b));
   1.153 +    assertEquals(v0a.getAll(), v0b.getAll());
   1.154 +    assertEquals(v1a.getAll(), v1b.getAll());
   1.155 +  }
   1.156 +
   1.157 +  public void testMigrateShared0and1() throws Exception {
   1.158 +    final SharedPreferences v0a = new MockSharedPreferences();
   1.159 +    final SharedPreferences v1a = new MockSharedPreferences();
   1.160 +    final SharedPreferences v0b = new MockSharedPreferences();
   1.161 +    final SharedPreferences v1b = new MockSharedPreferences();
   1.162 +
   1.163 +    populateAccountSharedPrefs(v0a);
   1.164 +
   1.165 +    final int NUM_GLOBALS = 24;
   1.166 +    assertEquals(NUM_GLOBALS, v0a.getAll().size());
   1.167 +    assertEquals(NUM_GLOBALS, PublicMigrator.upgradeShared0to1(v0a, v1a));
   1.168 +    assertEquals(NUM_GLOBALS, PublicMigrator.downgradeShared1to0(v1a, v0b));
   1.169 +    assertEquals(NUM_GLOBALS, PublicMigrator.upgradeShared0to1(v0b, v1b));
   1.170 +    assertEquals(v0a.getAll(), v0b.getAll());
   1.171 +    assertEquals(v1a.getAll(), v1b.getAll());
   1.172 +  }
   1.173 +
   1.174 +  public void testMigrateAccount0and1() throws Exception {
   1.175 +    final Context context = getApplicationContext();
   1.176 +    final AccountManager accountManager = AccountManager.get(context);
   1.177 +    final SyncAccountParameters syncAccount = new SyncAccountParameters(context, null,
   1.178 +        TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null);
   1.179 +
   1.180 +    Account account = null;
   1.181 +    try {
   1.182 +      account = SyncAccounts.createSyncAccount(syncAccount, false);
   1.183 +      populateAccountData(accountManager, account);
   1.184 +
   1.185 +      final int NUM_ACCOUNTS = 3;
   1.186 +      final SharedPreferences a = new MockSharedPreferences();
   1.187 +      final SharedPreferences b = new MockSharedPreferences();
   1.188 +
   1.189 +      assertEquals(NUM_ACCOUNTS, PublicMigrator.upgradeAndroidAccount0to1(accountManager, account, a));
   1.190 +      assertEquals(NUM_ACCOUNTS, a.getAll().size());
   1.191 +      assertEquals(NUM_ACCOUNTS, PublicMigrator.downgradeAndroidAccount1to0(a, accountManager, account));
   1.192 +
   1.193 +      TestSyncAccounts.deleteAccount(this, accountManager, account);
   1.194 +      account = SyncAccounts.createSyncAccount(syncAccount, false);
   1.195 +
   1.196 +      assertEquals(NUM_ACCOUNTS, PublicMigrator.downgradeAndroidAccount1to0(a, accountManager, account));
   1.197 +      assertEquals(NUM_ACCOUNTS, PublicMigrator.upgradeAndroidAccount0to1(accountManager, account, b));
   1.198 +      assertEquals(a.getAll(), b.getAll());
   1.199 +    } finally {
   1.200 +      if (account != null) {
   1.201 +        TestSyncAccounts.deleteAccount(this, accountManager, account);
   1.202 +      }
   1.203 +    }
   1.204 +  }
   1.205 +
   1.206 +  public void testMigrate0to1() throws Exception {
   1.207 +    final Context context = getApplicationContext();
   1.208 +
   1.209 +    final String ACCOUNT_SHARED_PREFS_NAME = "sync.prefs.3qyu5zoqpuu4zhdiv5l2qthsiter3vop";
   1.210 +    final String GLOBAL_SHARED_PREFS_NAME = "sync.prefs.global";
   1.211 +
   1.212 +    final String path = Utils.getPrefsPath(TEST_PRODUCT, TEST_USERNAME, TEST_SERVERURL, TEST_PROFILE, 0);
   1.213 +    assertEquals(ACCOUNT_SHARED_PREFS_NAME, path);
   1.214 +    final SharedPreferences accountPrefs = context.getSharedPreferences(ACCOUNT_SHARED_PREFS_NAME, Utils.SHARED_PREFERENCES_MODE);
   1.215 +    final SharedPreferences globalPrefs = context.getSharedPreferences(GLOBAL_SHARED_PREFS_NAME, Utils.SHARED_PREFERENCES_MODE);
   1.216 +
   1.217 +    accountPrefs.edit().clear().commit();
   1.218 +    globalPrefs.edit().clear().commit();
   1.219 +    // Clear prefs we're about to write into.
   1.220 +    final SharedPreferences existingPrefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME, TEST_SERVERURL, TEST_PROFILE, 1);
   1.221 +    existingPrefs.edit().clear().commit();
   1.222 +
   1.223 +    final AccountManager accountManager = AccountManager.get(context);
   1.224 +    final SyncAccountParameters syncAccount = new SyncAccountParameters(context, null,
   1.225 +        TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null);
   1.226 +
   1.227 +    Account account = null;
   1.228 +    try {
   1.229 +      account = SyncAccounts.createSyncAccount(syncAccount, false); // Wipes prefs.
   1.230 +
   1.231 +      populateAccountSharedPrefs(accountPrefs);
   1.232 +      populateGlobalSharedPrefs(globalPrefs);
   1.233 +      populateAccountData(accountManager, account);
   1.234 +
   1.235 +      ConfigurationMigrator.upgrade0to1(context, accountManager, account, TEST_PRODUCT, TEST_USERNAME, TEST_SERVERURL, TEST_PROFILE);
   1.236 +    } finally {
   1.237 +      if (account != null) {
   1.238 +        TestSyncAccounts.deleteAccount(this, accountManager, account);
   1.239 +      }
   1.240 +    }
   1.241 +
   1.242 +    Map<String, ?> origAccountPrefs = accountPrefs.getAll();
   1.243 +    Map<String, ?> origGlobalPrefs = globalPrefs.getAll();
   1.244 +    assertFalse(origAccountPrefs.isEmpty());
   1.245 +    assertFalse(origGlobalPrefs.isEmpty());
   1.246 +
   1.247 +    final SharedPreferences newPrefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME, TEST_SERVERURL, TEST_PROFILE, 1);
   1.248 +
   1.249 +    // Some global stuff.
   1.250 +    assertEquals(false, newPrefs.getBoolean(SyncConfiguration.PREF_CLUSTER_URL_IS_STALE, true));
   1.251 +    assertEquals(1340402318649L, newPrefs.getLong(PrefsBackoffHandler.PREF_EARLIEST_NEXT + SyncConstants.BACKOFF_PREF_SUFFIX_11, 111));
   1.252 +    // Some per-Sync account stuff.
   1.253 +    assertEquals("{\"timestamp\":1340402003370}", newPrefs.getString("bookmarks.remote", null));
   1.254 +    assertEquals("{\"timestamp\":1340402008397}", newPrefs.getString("bookmarks.local", null));
   1.255 +    assertEquals("P8gG8ERuJ4H1", newPrefs.getString("bookmarks.syncID", null));
   1.256 +    assertEquals(1340401961960L, newPrefs.getLong("metaGlobalLastModified", 0));
   1.257 +    // Some per-Android account stuff.
   1.258 +    assertEquals(TEST_GUID, newPrefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null));
   1.259 +    assertEquals(TEST_CLIENT_NAME, newPrefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null));
   1.260 +    assertEquals(TEST_NUM_CLIENTS, newPrefs.getLong(SyncConfiguration.PREF_NUM_CLIENTS, -1L));
   1.261 +
   1.262 +    // Now try to downgrade.
   1.263 +    accountPrefs.edit().clear().commit();
   1.264 +    globalPrefs.edit().clear().commit();
   1.265 +
   1.266 +    account = null;
   1.267 +    try {
   1.268 +      account = SyncAccounts.createSyncAccount(syncAccount, false);
   1.269 +
   1.270 +      ConfigurationMigrator.downgrade1to0(context, accountManager, account, TEST_PRODUCT, TEST_USERNAME, TEST_SERVERURL, TEST_PROFILE);
   1.271 +
   1.272 +      final String V0_PREF_ACCOUNT_GUID = "account.guid";
   1.273 +      final String V0_PREF_CLIENT_NAME = "account.clientName";
   1.274 +      final String V0_PREF_NUM_CLIENTS = "account.numClients";
   1.275 +
   1.276 +      assertEquals(TEST_GUID, accountManager.getUserData(account, V0_PREF_ACCOUNT_GUID));
   1.277 +      assertEquals(TEST_CLIENT_NAME, accountManager.getUserData(account, V0_PREF_CLIENT_NAME));
   1.278 +      assertEquals(Long.valueOf(TEST_NUM_CLIENTS).toString(), accountManager.getUserData(account, V0_PREF_NUM_CLIENTS));
   1.279 +    } finally {
   1.280 +      if (account != null) {
   1.281 +        TestSyncAccounts.deleteAccount(this, accountManager, account);
   1.282 +      }
   1.283 +    }
   1.284 +
   1.285 +    // Check re-constituted prefs against old prefs.
   1.286 +    assertEquals(origAccountPrefs, accountPrefs.getAll());
   1.287 +    assertEquals(origGlobalPrefs, globalPrefs.getAll());
   1.288 +  }
   1.289 +}

mercurial