diff -r 000000000000 -r 6474c204b198 mobile/android/tests/background/junit3/src/sync/TestSyncAccounts.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mobile/android/tests/background/junit3/src/sync/TestSyncAccounts.java Wed Dec 31 06:09:35 2014 +0100
@@ -0,0 +1,343 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.gecko.background.sync;
+
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.concurrent.TimeUnit;
+
+import org.mozilla.gecko.background.common.GlobalConstants;
+import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
+import org.mozilla.gecko.sync.ExtendedJSONObject;
+import org.mozilla.gecko.sync.SyncConfiguration;
+import org.mozilla.gecko.sync.SyncConstants;
+import org.mozilla.gecko.sync.Utils;
+import org.mozilla.gecko.sync.setup.Constants;
+import org.mozilla.gecko.sync.setup.SyncAccounts;
+import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.accounts.AccountManagerCallback;
+import android.accounts.AccountManagerFuture;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.test.InstrumentationTestCase;
+
+/**
+ * We can use performWait
and performNotify
here if we
+ * are careful about threading issues with AsyncTask
. We need to
+ * take some care to both create and run certain tasks on the main thread --
+ * moving the object allocation out of the UI thread causes failures!
+ *
+ * @see "
+ * http://stackoverflow.com/questions/2321829/android-asynctask-testing-problem-with-android-test-framework."
+ */
+public class TestSyncAccounts extends AndroidSyncTestCase {
+ private static final String TEST_USERNAME = "testAccount@mozilla.com";
+ private static final String TEST_SYNCKEY = "testSyncKey";
+ private static final String TEST_PASSWORD = "testPassword";
+ private static final String TEST_SERVERURL = "test.server.url/";
+ private static final String TEST_CLUSTERURL = "test.cluster.url/";
+
+ public static final String TEST_ACCOUNTTYPE = SyncConstants.ACCOUNTTYPE_SYNC;
+
+ public static final String TEST_PRODUCT = GlobalConstants.BROWSER_INTENT_PACKAGE;
+ public static final String TEST_PROFILE = Constants.DEFAULT_PROFILE;
+ public static final long TEST_VERSION = SyncConfiguration.CURRENT_PREFS_VERSION;
+
+ public static final String TEST_PREFERENCE = "testPreference";
+ public static final String TEST_SYNC_ID = "testSyncID";
+
+ private Account account;
+ private Context context;
+ private AccountManager accountManager;
+ private SyncAccountParameters syncAccount;
+
+ public void setUp() {
+ account = null;
+ context = getApplicationContext();
+ accountManager = AccountManager.get(context);
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null);
+ }
+
+ public static void deleteAccount(final InstrumentationTestCase test, final AccountManager accountManager, final Account account) {
+ performWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ test.runTestOnUiThread(new Runnable() {
+ final AccountManagerCallback callback = new AccountManagerCallback() {
+ @Override
+ public void run(AccountManagerFuture future) {
+ try {
+ future.getResult(5L, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ }
+ performNotify();
+ }
+ };
+
+ @Override
+ public void run() {
+ accountManager.removeAccount(account, callback, null);
+ }
+ });
+ } catch (Throwable e) {
+ performNotify(e);
+ }
+ }
+ });
+ }
+
+ public void tearDown() {
+ if (account == null) {
+ return;
+ }
+ deleteAccount(this, accountManager, account);
+ account = null;
+ }
+
+ public void testSyncAccountParameters() {
+ assertEquals(TEST_USERNAME, syncAccount.username);
+ assertNull(syncAccount.accountManager);
+ assertNull(syncAccount.serverURL);
+
+ try {
+ syncAccount = new SyncAccountParameters(context, null,
+ null, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
+ } catch (IllegalArgumentException e) {
+ return;
+ } catch (Exception e) {
+ fail("Did not expect exception: " + e);
+ }
+ fail("Expected IllegalArgumentException.");
+ }
+
+ public void testCreateAccount() {
+ int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ int afterCreate = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertTrue(afterCreate > before);
+ deleteAccount(this, accountManager, account);
+ account = null;
+ int afterDelete = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertEquals(before, afterDelete);
+ }
+
+ public void testCreateSecondAccount() {
+ int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ int afterFirst = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertTrue(afterFirst > before);
+
+ SyncAccountParameters secondSyncAccount = new SyncAccountParameters(context, null,
+ "second@username.com", TEST_SYNCKEY, TEST_PASSWORD, null);
+
+ Account second = SyncAccounts.createSyncAccount(secondSyncAccount, false);
+ assertNotNull(second);
+ int afterSecond = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertTrue(afterSecond > afterFirst);
+
+ deleteAccount(this, accountManager, second);
+ deleteAccount(this, accountManager, account);
+ account = null;
+
+ int afterDelete = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertEquals(before, afterDelete);
+ }
+
+ public void testCreateDuplicateAccount() {
+ int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ int afterCreate = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
+ assertTrue(afterCreate > before);
+
+ Account dupe = SyncAccounts.createSyncAccount(syncAccount, false);
+ assertNull(dupe);
+ }
+
+ public void testClientRecord() throws NoSuchAlgorithmException, UnsupportedEncodingException {
+ final String TEST_NAME = "testName";
+ final String TEST_GUID = "testGuid";
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null, null, TEST_NAME, TEST_GUID);
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ assertNotNull(account);
+
+ SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
+ SyncConstants.DEFAULT_AUTH_SERVER, TEST_PROFILE, TEST_VERSION);
+
+ // Verify that client record is set.
+ assertEquals(TEST_GUID, prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null));
+ assertEquals(TEST_NAME, prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null));
+
+ // Let's verify that clusterURL is correctly not set.
+ String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null);
+ assertNull(clusterURL);
+ }
+
+ public void testClusterURL() throws NoSuchAlgorithmException, UnsupportedEncodingException {
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ assertNotNull(account);
+
+ SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
+ TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
+ String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null);
+ assertNotNull(clusterURL);
+ assertEquals(TEST_CLUSTERURL, clusterURL);
+
+ // Let's verify that client name and GUID are not set.
+ assertNull(prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null));
+ assertNull(prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null));
+ }
+
+ /**
+ * Verify that creating an account wipes stale settings in Shared Preferences.
+ */
+ public void testCreatingWipesSharedPrefs() throws Exception {
+ final String TEST_PREFERENCE = "testPreference";
+ final String TEST_SYNC_ID = "testSyncID";
+
+ SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
+ TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
+ prefs.edit().putString(SyncConfiguration.PREF_SYNC_ID, TEST_SYNC_ID).commit();
+ prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
+
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
+ account = SyncAccounts.createSyncAccount(syncAccount, false);
+ assertNotNull(account);
+
+ // All values deleted (known and unknown).
+ assertNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
+ assertNull(prefs.getString(TEST_SYNC_ID, null));
+ }
+
+ /**
+ * Verify that creating an account preserves settings in Shared Preferences when asked.
+ */
+ public void testCreateSyncAccountWithExistingPreferences() throws Exception {
+
+ SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
+ TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
+
+ prefs.edit().putString(SyncConfiguration.PREF_SYNC_ID, TEST_SYNC_ID).commit();
+ prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
+
+ assertNotNull(prefs.getString(TEST_PREFERENCE, null));
+ assertNotNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
+
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
+ account = SyncAccounts.createSyncAccountPreservingExistingPreferences(syncAccount, false);
+ assertNotNull(account);
+
+ // All values remain (known and unknown).
+ assertNotNull(prefs.getString(TEST_PREFERENCE, null));
+ assertNotNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
+ }
+
+ protected void assertParams(final SyncAccountParameters params) throws Exception {
+ assertNotNull(params);
+ assertEquals(context, params.context);
+ assertEquals(Utils.usernameFromAccount(TEST_USERNAME), params.username);
+ assertEquals(TEST_PASSWORD, params.password);
+ assertEquals(TEST_SERVERURL, params.serverURL);
+ assertEquals(TEST_SYNCKEY, params.syncKey);
+ }
+
+ public void testBlockingFromAndroidAccountV0() throws Throwable {
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
+ try {
+ account = SyncAccounts.createSyncAccount(syncAccount);
+ assertNotNull(account);
+
+ // Test fetching parameters multiple times. Historically, we needed to
+ // invalidate this token type every fetch; now we don't, but we'd like
+ // to ensure multiple fetches work.
+ SyncAccountParameters params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
+ assertParams(params);
+
+ params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
+ assertParams(params);
+
+ // Test this works on the main thread.
+ this.runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ SyncAccountParameters params;
+ try {
+ params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
+ assertParams(params);
+ } catch (Exception e) {
+ fail("Fetching Sync account parameters failed on UI thread.");
+ }
+ }
+ });
+ } finally {
+ if (account != null) {
+ deleteAccount(this, accountManager, account);
+ account = null;
+ }
+ }
+ }
+
+ public void testMakeSyncAccountDeletedIntent() throws Throwable {
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
+ try {
+ account = SyncAccounts.createSyncAccount(syncAccount);
+ assertNotNull(account);
+
+ Intent intent = SyncAccounts.makeSyncAccountDeletedIntent(context, accountManager, account);
+ assertEquals(SyncConstants.SYNC_ACCOUNT_DELETED_ACTION, intent.getAction());
+ assertEquals(SyncConstants.SYNC_ACCOUNT_DELETED_INTENT_VERSION, intent.getLongExtra(Constants.JSON_KEY_VERSION, 0));
+ assertEquals(TEST_USERNAME, intent.getStringExtra(Constants.JSON_KEY_ACCOUNT));
+ assertTrue(Math.abs(intent.getLongExtra(Constants.JSON_KEY_TIMESTAMP, 0) - System.currentTimeMillis()) < 1000);
+
+ String payload = intent.getStringExtra(Constants.JSON_KEY_PAYLOAD);
+ assertNotNull(payload);
+
+ SyncAccountParameters params = new SyncAccountParameters(context, accountManager, ExtendedJSONObject.parseJSONObject(payload));
+ // Can't use assertParams because Sync key is deleted.
+ assertNotNull(params);
+ assertEquals(context, params.context);
+ assertEquals(Utils.usernameFromAccount(TEST_USERNAME), params.username);
+ assertEquals(TEST_PASSWORD, params.password);
+ assertEquals(TEST_SERVERURL, params.serverURL);
+ assertEquals("", params.syncKey);
+ } finally {
+ if (account != null) {
+ deleteAccount(this, accountManager, account);
+ account = null;
+ }
+ }
+ }
+
+ public void testBlockingPrefsFromAndroidAccountV0() throws Exception {
+ // Create test account with prefs. We use a different username to avoid a
+ // timing issue, where the delayed clean-up of the account created by the
+ // previous test deletes the preferences for this account.
+ SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT,
+ TEST_USERNAME + "2", TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
+ prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
+
+ syncAccount = new SyncAccountParameters(context, null,
+ TEST_USERNAME + "2", TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
+ account = SyncAccounts.createSyncAccountPreservingExistingPreferences(syncAccount, false);
+ assertNotNull(account);
+
+ // Fetch account and check prefs.
+ SharedPreferences sharedPreferences = SyncAccounts.blockingPrefsFromAndroidAccountV0(context, accountManager,
+ account, TEST_PRODUCT, TEST_PROFILE, TEST_VERSION);
+ assertNotNull(sharedPreferences);
+ assertEquals(TEST_SYNC_ID, sharedPreferences.getString(TEST_PREFERENCE, null));
+ }
+}