Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* Any copyright is dedicated to the Public Domain.
2 http://creativecommons.org/publicdomain/zero/1.0/ */
4 package org.mozilla.gecko.background.sync;
6 import java.io.UnsupportedEncodingException;
7 import java.security.NoSuchAlgorithmException;
8 import java.util.concurrent.TimeUnit;
10 import org.mozilla.gecko.background.common.GlobalConstants;
11 import org.mozilla.gecko.background.helpers.AndroidSyncTestCase;
12 import org.mozilla.gecko.sync.ExtendedJSONObject;
13 import org.mozilla.gecko.sync.SyncConfiguration;
14 import org.mozilla.gecko.sync.SyncConstants;
15 import org.mozilla.gecko.sync.Utils;
16 import org.mozilla.gecko.sync.setup.Constants;
17 import org.mozilla.gecko.sync.setup.SyncAccounts;
18 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
20 import android.accounts.Account;
21 import android.accounts.AccountManager;
22 import android.accounts.AccountManagerCallback;
23 import android.accounts.AccountManagerFuture;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.test.InstrumentationTestCase;
29 /**
30 * We can use <code>performWait</code> and <code>performNotify</code> here if we
31 * are careful about threading issues with <code>AsyncTask</code>. We need to
32 * take some care to both create and run certain tasks on the main thread --
33 * moving the object allocation out of the UI thread causes failures!
34 * <p>
35 * @see "<a href='http://stackoverflow.com/questions/2321829/android-asynctask-testing-problem-with-android-test-framework'>
36 * http://stackoverflow.com/questions/2321829/android-asynctask-testing-problem-with-android-test-framework</a>."
37 */
38 public class TestSyncAccounts extends AndroidSyncTestCase {
39 private static final String TEST_USERNAME = "testAccount@mozilla.com";
40 private static final String TEST_SYNCKEY = "testSyncKey";
41 private static final String TEST_PASSWORD = "testPassword";
42 private static final String TEST_SERVERURL = "test.server.url/";
43 private static final String TEST_CLUSTERURL = "test.cluster.url/";
45 public static final String TEST_ACCOUNTTYPE = SyncConstants.ACCOUNTTYPE_SYNC;
47 public static final String TEST_PRODUCT = GlobalConstants.BROWSER_INTENT_PACKAGE;
48 public static final String TEST_PROFILE = Constants.DEFAULT_PROFILE;
49 public static final long TEST_VERSION = SyncConfiguration.CURRENT_PREFS_VERSION;
51 public static final String TEST_PREFERENCE = "testPreference";
52 public static final String TEST_SYNC_ID = "testSyncID";
54 private Account account;
55 private Context context;
56 private AccountManager accountManager;
57 private SyncAccountParameters syncAccount;
59 public void setUp() {
60 account = null;
61 context = getApplicationContext();
62 accountManager = AccountManager.get(context);
63 syncAccount = new SyncAccountParameters(context, null,
64 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null);
65 }
67 public static void deleteAccount(final InstrumentationTestCase test, final AccountManager accountManager, final Account account) {
68 performWait(new Runnable() {
69 @Override
70 public void run() {
71 try {
72 test.runTestOnUiThread(new Runnable() {
73 final AccountManagerCallback<Boolean> callback = new AccountManagerCallback<Boolean>() {
74 @Override
75 public void run(AccountManagerFuture<Boolean> future) {
76 try {
77 future.getResult(5L, TimeUnit.SECONDS);
78 } catch (Exception e) {
79 }
80 performNotify();
81 }
82 };
84 @Override
85 public void run() {
86 accountManager.removeAccount(account, callback, null);
87 }
88 });
89 } catch (Throwable e) {
90 performNotify(e);
91 }
92 }
93 });
94 }
96 public void tearDown() {
97 if (account == null) {
98 return;
99 }
100 deleteAccount(this, accountManager, account);
101 account = null;
102 }
104 public void testSyncAccountParameters() {
105 assertEquals(TEST_USERNAME, syncAccount.username);
106 assertNull(syncAccount.accountManager);
107 assertNull(syncAccount.serverURL);
109 try {
110 syncAccount = new SyncAccountParameters(context, null,
111 null, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
112 } catch (IllegalArgumentException e) {
113 return;
114 } catch (Exception e) {
115 fail("Did not expect exception: " + e);
116 }
117 fail("Expected IllegalArgumentException.");
118 }
120 public void testCreateAccount() {
121 int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
122 account = SyncAccounts.createSyncAccount(syncAccount, false);
123 int afterCreate = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
124 assertTrue(afterCreate > before);
125 deleteAccount(this, accountManager, account);
126 account = null;
127 int afterDelete = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
128 assertEquals(before, afterDelete);
129 }
131 public void testCreateSecondAccount() {
132 int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
133 account = SyncAccounts.createSyncAccount(syncAccount, false);
134 int afterFirst = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
135 assertTrue(afterFirst > before);
137 SyncAccountParameters secondSyncAccount = new SyncAccountParameters(context, null,
138 "second@username.com", TEST_SYNCKEY, TEST_PASSWORD, null);
140 Account second = SyncAccounts.createSyncAccount(secondSyncAccount, false);
141 assertNotNull(second);
142 int afterSecond = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
143 assertTrue(afterSecond > afterFirst);
145 deleteAccount(this, accountManager, second);
146 deleteAccount(this, accountManager, account);
147 account = null;
149 int afterDelete = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
150 assertEquals(before, afterDelete);
151 }
153 public void testCreateDuplicateAccount() {
154 int before = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
155 account = SyncAccounts.createSyncAccount(syncAccount, false);
156 int afterCreate = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length;
157 assertTrue(afterCreate > before);
159 Account dupe = SyncAccounts.createSyncAccount(syncAccount, false);
160 assertNull(dupe);
161 }
163 public void testClientRecord() throws NoSuchAlgorithmException, UnsupportedEncodingException {
164 final String TEST_NAME = "testName";
165 final String TEST_GUID = "testGuid";
166 syncAccount = new SyncAccountParameters(context, null,
167 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, null, null, TEST_NAME, TEST_GUID);
168 account = SyncAccounts.createSyncAccount(syncAccount, false);
169 assertNotNull(account);
171 SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
172 SyncConstants.DEFAULT_AUTH_SERVER, TEST_PROFILE, TEST_VERSION);
174 // Verify that client record is set.
175 assertEquals(TEST_GUID, prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null));
176 assertEquals(TEST_NAME, prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null));
178 // Let's verify that clusterURL is correctly not set.
179 String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null);
180 assertNull(clusterURL);
181 }
183 public void testClusterURL() throws NoSuchAlgorithmException, UnsupportedEncodingException {
184 syncAccount = new SyncAccountParameters(context, null,
185 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
186 account = SyncAccounts.createSyncAccount(syncAccount, false);
187 assertNotNull(account);
189 SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
190 TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
191 String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null);
192 assertNotNull(clusterURL);
193 assertEquals(TEST_CLUSTERURL, clusterURL);
195 // Let's verify that client name and GUID are not set.
196 assertNull(prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null));
197 assertNull(prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null));
198 }
200 /**
201 * Verify that creating an account wipes stale settings in Shared Preferences.
202 */
203 public void testCreatingWipesSharedPrefs() throws Exception {
204 final String TEST_PREFERENCE = "testPreference";
205 final String TEST_SYNC_ID = "testSyncID";
207 SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
208 TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
209 prefs.edit().putString(SyncConfiguration.PREF_SYNC_ID, TEST_SYNC_ID).commit();
210 prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
212 syncAccount = new SyncAccountParameters(context, null,
213 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
214 account = SyncAccounts.createSyncAccount(syncAccount, false);
215 assertNotNull(account);
217 // All values deleted (known and unknown).
218 assertNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
219 assertNull(prefs.getString(TEST_SYNC_ID, null));
220 }
222 /**
223 * Verify that creating an account preserves settings in Shared Preferences when asked.
224 */
225 public void testCreateSyncAccountWithExistingPreferences() throws Exception {
227 SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME,
228 TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
230 prefs.edit().putString(SyncConfiguration.PREF_SYNC_ID, TEST_SYNC_ID).commit();
231 prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
233 assertNotNull(prefs.getString(TEST_PREFERENCE, null));
234 assertNotNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
236 syncAccount = new SyncAccountParameters(context, null,
237 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
238 account = SyncAccounts.createSyncAccountPreservingExistingPreferences(syncAccount, false);
239 assertNotNull(account);
241 // All values remain (known and unknown).
242 assertNotNull(prefs.getString(TEST_PREFERENCE, null));
243 assertNotNull(prefs.getString(SyncConfiguration.PREF_SYNC_ID, null));
244 }
246 protected void assertParams(final SyncAccountParameters params) throws Exception {
247 assertNotNull(params);
248 assertEquals(context, params.context);
249 assertEquals(Utils.usernameFromAccount(TEST_USERNAME), params.username);
250 assertEquals(TEST_PASSWORD, params.password);
251 assertEquals(TEST_SERVERURL, params.serverURL);
252 assertEquals(TEST_SYNCKEY, params.syncKey);
253 }
255 public void testBlockingFromAndroidAccountV0() throws Throwable {
256 syncAccount = new SyncAccountParameters(context, null,
257 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
258 try {
259 account = SyncAccounts.createSyncAccount(syncAccount);
260 assertNotNull(account);
262 // Test fetching parameters multiple times. Historically, we needed to
263 // invalidate this token type every fetch; now we don't, but we'd like
264 // to ensure multiple fetches work.
265 SyncAccountParameters params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
266 assertParams(params);
268 params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
269 assertParams(params);
271 // Test this works on the main thread.
272 this.runTestOnUiThread(new Runnable() {
273 @Override
274 public void run() {
275 SyncAccountParameters params;
276 try {
277 params = SyncAccounts.blockingFromAndroidAccountV0(context, accountManager, account);
278 assertParams(params);
279 } catch (Exception e) {
280 fail("Fetching Sync account parameters failed on UI thread.");
281 }
282 }
283 });
284 } finally {
285 if (account != null) {
286 deleteAccount(this, accountManager, account);
287 account = null;
288 }
289 }
290 }
292 public void testMakeSyncAccountDeletedIntent() throws Throwable {
293 syncAccount = new SyncAccountParameters(context, null,
294 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL, TEST_CLUSTERURL, null, null);
295 try {
296 account = SyncAccounts.createSyncAccount(syncAccount);
297 assertNotNull(account);
299 Intent intent = SyncAccounts.makeSyncAccountDeletedIntent(context, accountManager, account);
300 assertEquals(SyncConstants.SYNC_ACCOUNT_DELETED_ACTION, intent.getAction());
301 assertEquals(SyncConstants.SYNC_ACCOUNT_DELETED_INTENT_VERSION, intent.getLongExtra(Constants.JSON_KEY_VERSION, 0));
302 assertEquals(TEST_USERNAME, intent.getStringExtra(Constants.JSON_KEY_ACCOUNT));
303 assertTrue(Math.abs(intent.getLongExtra(Constants.JSON_KEY_TIMESTAMP, 0) - System.currentTimeMillis()) < 1000);
305 String payload = intent.getStringExtra(Constants.JSON_KEY_PAYLOAD);
306 assertNotNull(payload);
308 SyncAccountParameters params = new SyncAccountParameters(context, accountManager, ExtendedJSONObject.parseJSONObject(payload));
309 // Can't use assertParams because Sync key is deleted.
310 assertNotNull(params);
311 assertEquals(context, params.context);
312 assertEquals(Utils.usernameFromAccount(TEST_USERNAME), params.username);
313 assertEquals(TEST_PASSWORD, params.password);
314 assertEquals(TEST_SERVERURL, params.serverURL);
315 assertEquals("", params.syncKey);
316 } finally {
317 if (account != null) {
318 deleteAccount(this, accountManager, account);
319 account = null;
320 }
321 }
322 }
324 public void testBlockingPrefsFromAndroidAccountV0() throws Exception {
325 // Create test account with prefs. We use a different username to avoid a
326 // timing issue, where the delayed clean-up of the account created by the
327 // previous test deletes the preferences for this account.
328 SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT,
329 TEST_USERNAME + "2", TEST_SERVERURL, TEST_PROFILE, TEST_VERSION);
330 prefs.edit().putString(TEST_PREFERENCE, TEST_SYNC_ID).commit();
332 syncAccount = new SyncAccountParameters(context, null,
333 TEST_USERNAME + "2", TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVERURL);
334 account = SyncAccounts.createSyncAccountPreservingExistingPreferences(syncAccount, false);
335 assertNotNull(account);
337 // Fetch account and check prefs.
338 SharedPreferences sharedPreferences = SyncAccounts.blockingPrefsFromAndroidAccountV0(context, accountManager,
339 account, TEST_PRODUCT, TEST_PROFILE, TEST_VERSION);
340 assertNotNull(sharedPreferences);
341 assertEquals(TEST_SYNC_ID, sharedPreferences.getString(TEST_PREFERENCE, null));
342 }
343 }