michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: package org.mozilla.gecko.background.sync; michael@0: michael@0: import java.io.FileInputStream; michael@0: import java.io.FileNotFoundException; michael@0: import java.io.FileOutputStream; michael@0: import java.io.PrintStream; michael@0: import java.util.ArrayList; michael@0: import java.util.List; michael@0: michael@0: import org.mozilla.gecko.background.common.GlobalConstants; michael@0: import org.mozilla.gecko.background.helpers.AndroidSyncTestCase; michael@0: import org.mozilla.gecko.db.BrowserContract; michael@0: import org.mozilla.gecko.sync.ExtendedJSONObject; michael@0: import org.mozilla.gecko.sync.SyncConfiguration; michael@0: import org.mozilla.gecko.sync.SyncConstants; michael@0: import org.mozilla.gecko.sync.Utils; michael@0: import org.mozilla.gecko.sync.config.AccountPickler; michael@0: import org.mozilla.gecko.sync.setup.Constants; michael@0: import org.mozilla.gecko.sync.setup.SyncAccounts; michael@0: import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; michael@0: michael@0: import android.accounts.Account; michael@0: import android.accounts.AccountManager; michael@0: import android.content.ContentResolver; michael@0: import android.content.Context; michael@0: import android.content.SharedPreferences; michael@0: michael@0: public class TestAccountPickler extends AndroidSyncTestCase { michael@0: public static final String TEST_FILENAME = "test.json"; michael@0: public static final String TEST_ACCOUNTTYPE = SyncConstants.ACCOUNTTYPE_SYNC; michael@0: michael@0: // Test account names must start with TEST_USERNAME in order to be recognized michael@0: // as test accounts and deleted in tearDown. michael@0: public static final String TEST_USERNAME = "testAccount@mozilla.com"; michael@0: public static final String TEST_USERNAME2 = TEST_USERNAME + "2"; michael@0: michael@0: public static final String TEST_SYNCKEY = "testSyncKey"; michael@0: public static final String TEST_PASSWORD = "testPassword"; michael@0: public static final String TEST_SERVER_URL = "test.server.url/"; michael@0: public static final String TEST_CLUSTER_URL = "test.cluster.url/"; michael@0: public static final String TEST_CLIENT_NAME = "testClientName"; michael@0: public static final String TEST_CLIENT_GUID = "testClientGuid"; michael@0: michael@0: public static final String TEST_PRODUCT = GlobalConstants.BROWSER_INTENT_PACKAGE; michael@0: public static final String TEST_PROFILE = "default"; michael@0: public static final long TEST_VERSION = SyncConfiguration.CURRENT_PREFS_VERSION; michael@0: michael@0: protected SyncAccountParameters params; michael@0: protected Context context; michael@0: protected AccountManager accountManager; michael@0: protected int numAccounts; michael@0: michael@0: public void setUp() { michael@0: context = getApplicationContext(); michael@0: accountManager = AccountManager.get(context); michael@0: params = new SyncAccountParameters(context, accountManager, michael@0: TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVER_URL, michael@0: TEST_CLUSTER_URL, TEST_CLIENT_NAME, TEST_CLIENT_GUID); michael@0: numAccounts = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length; michael@0: } michael@0: michael@0: public static List getTestAccounts(final AccountManager accountManager) { michael@0: final List testAccounts = new ArrayList(); michael@0: michael@0: final Account[] accounts = accountManager.getAccountsByType(TEST_ACCOUNTTYPE); michael@0: for (Account account : accounts) { michael@0: if (account.name.startsWith(TEST_USERNAME)) { michael@0: testAccounts.add(account); michael@0: } michael@0: } michael@0: michael@0: return testAccounts; michael@0: } michael@0: michael@0: public void deleteTestAccounts() { michael@0: for (Account account : getTestAccounts(accountManager)) { michael@0: TestSyncAccounts.deleteAccount(this, accountManager, account); michael@0: } michael@0: } michael@0: michael@0: public void tearDown() { michael@0: deleteTestAccounts(); michael@0: assertEquals(numAccounts, accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length); michael@0: } michael@0: michael@0: public static void assertFileNotPresent(final Context context, final String filename) throws Exception { michael@0: // Verify file is not present. michael@0: FileInputStream fis = null; michael@0: try { michael@0: fis = context.openFileInput(TEST_FILENAME); michael@0: fail("Should get FileNotFoundException."); michael@0: } catch (FileNotFoundException e) { michael@0: // Do nothing; file should not exist. michael@0: } finally { michael@0: if (fis != null) { michael@0: fis.close(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: public void testPersist() throws Exception { michael@0: context.deleteFile(TEST_FILENAME); michael@0: assertFileNotPresent(context, TEST_FILENAME); michael@0: michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, true); michael@0: michael@0: final String s = Utils.readFile(context, TEST_FILENAME); michael@0: assertNotNull(s); michael@0: michael@0: final ExtendedJSONObject o = ExtendedJSONObject.parseJSONObject(s); michael@0: assertEquals(TEST_USERNAME, o.getString(Constants.JSON_KEY_ACCOUNT)); michael@0: assertEquals(TEST_PASSWORD, o.getString(Constants.JSON_KEY_PASSWORD)); michael@0: assertEquals(TEST_SERVER_URL, o.getString(Constants.JSON_KEY_SERVER)); michael@0: assertEquals(TEST_SYNCKEY, o.getString(Constants.JSON_KEY_SYNCKEY)); michael@0: assertEquals(TEST_CLUSTER_URL, o.getString(Constants.JSON_KEY_CLUSTER)); michael@0: assertEquals(TEST_CLIENT_NAME, o.getString(Constants.JSON_KEY_CLIENT_NAME)); michael@0: assertEquals(TEST_CLIENT_GUID, o.getString(Constants.JSON_KEY_CLIENT_GUID)); michael@0: assertEquals(Boolean.valueOf(true), o.get(Constants.JSON_KEY_SYNC_AUTOMATICALLY)); michael@0: assertEquals(Long.valueOf(AccountPickler.VERSION), o.getLong(Constants.JSON_KEY_VERSION)); michael@0: assertTrue(o.containsKey(Constants.JSON_KEY_TIMESTAMP)); michael@0: } michael@0: michael@0: public void testDeletePickle() throws Exception { michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, false); michael@0: michael@0: // Verify file is present. michael@0: final String s = Utils.readFile(context, TEST_FILENAME); michael@0: assertNotNull(s); michael@0: assertTrue(s.length() > 0); michael@0: michael@0: AccountPickler.deletePickle(context, TEST_FILENAME); michael@0: assertFileNotPresent(context, TEST_FILENAME); michael@0: } michael@0: michael@0: public Account deleteAccountsAndUnpickle(final Context context, final AccountManager accountManager, final String filename) { michael@0: deleteTestAccounts(); michael@0: assertEquals(0, getTestAccounts(accountManager).size()); michael@0: michael@0: return AccountPickler.unpickle(context, filename); michael@0: } michael@0: michael@0: public void testUnpickleSuccess() throws Exception { michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, true); michael@0: michael@0: // Make sure we have no accounts hanging around. michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNotNull(account); michael@0: michael@0: try { michael@0: assertEquals(1, getTestAccounts(accountManager).size()); michael@0: assertTrue(ContentResolver.getSyncAutomatically(account, BrowserContract.AUTHORITY)); michael@0: assertEquals(account.name, TEST_USERNAME); michael@0: michael@0: // Verify Account parameters are in place. Not testing clusterURL since it's stored in michael@0: // shared prefs and it's less critical. michael@0: final String password = accountManager.getPassword(account); michael@0: final String serverURL = accountManager.getUserData(account, Constants.OPTION_SERVER); michael@0: final String syncKey = accountManager.getUserData(account, Constants.OPTION_SYNCKEY); michael@0: michael@0: assertEquals(TEST_PASSWORD, password); michael@0: assertEquals(TEST_SERVER_URL, serverURL); michael@0: assertEquals(TEST_SYNCKEY, syncKey); michael@0: michael@0: // Verify shared prefs parameters are in place. michael@0: final SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME, TEST_SERVER_URL, TEST_PROFILE, TEST_VERSION); michael@0: final String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null); michael@0: final String clientName = prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null); michael@0: final String clientGuid = prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null); michael@0: michael@0: assertEquals(TEST_CLUSTER_URL, clusterURL); michael@0: assertEquals(TEST_CLIENT_NAME, clientName); michael@0: assertEquals(TEST_CLIENT_GUID, clientGuid); michael@0: } finally { michael@0: TestSyncAccounts.deleteAccount(this, accountManager, account); michael@0: } michael@0: } michael@0: michael@0: public void testUnpickleNoAutomatic() throws Exception { michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, false); michael@0: michael@0: // Make sure we have no accounts hanging around. michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNotNull(account); michael@0: michael@0: try { michael@0: assertEquals(1, getTestAccounts(accountManager).size()); michael@0: assertFalse(ContentResolver.getSyncAutomatically(account, BrowserContract.AUTHORITY)); michael@0: } finally { michael@0: TestSyncAccounts.deleteAccount(this, accountManager, account); michael@0: } michael@0: } michael@0: michael@0: public void testUnpickleNoFile() { michael@0: // Just in case file is hanging around. michael@0: context.deleteFile(TEST_FILENAME); michael@0: michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNull(account); michael@0: } michael@0: michael@0: public void testUnpickleIncompleteUserData() throws Exception { michael@0: final FileOutputStream fos = context.openFileOutput(TEST_FILENAME, Context.MODE_PRIVATE); michael@0: final PrintStream ps = (new PrintStream(fos)); michael@0: ps.print("{}"); // Valid JSON, just missing everything. michael@0: ps.close(); michael@0: fos.close(); michael@0: michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNull(account); michael@0: } michael@0: michael@0: public void testUnpickleMalformedFile() throws Exception { michael@0: final FileOutputStream fos = context.openFileOutput(TEST_FILENAME, Context.MODE_PRIVATE); michael@0: final PrintStream ps = (new PrintStream(fos)); michael@0: ps.print("{1:!}"); // Not valid JSON. michael@0: ps.close(); michael@0: fos.close(); michael@0: michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNull(account); michael@0: } michael@0: michael@0: public void testUnpickleAccountAlreadyExists() { michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, false); michael@0: michael@0: // Make sure we have no test accounts hanging around. michael@0: final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); michael@0: assertNotNull(account); michael@0: assertEquals(TEST_USERNAME, account.name); michael@0: michael@0: // Now replace file with new username. michael@0: params = new SyncAccountParameters(context, accountManager, michael@0: TEST_USERNAME2, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVER_URL, null, TEST_CLIENT_NAME, TEST_CLIENT_GUID); michael@0: AccountPickler.pickle(context, TEST_FILENAME, params, false); michael@0: michael@0: // Checking if sync accounts exist could try to unpickle. That unpickle michael@0: // would load an account with a different username, so we can check that michael@0: // nothing was unpickled by verifying that the username has not changed. michael@0: assertTrue(SyncAccounts.syncAccountsExist(context)); michael@0: michael@0: for (Account a : getTestAccounts(accountManager)) { michael@0: assertEquals(TEST_USERNAME, a.name); michael@0: } michael@0: } michael@0: }