|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 package org.mozilla.gecko.background.sync; |
|
5 |
|
6 import java.io.FileInputStream; |
|
7 import java.io.FileNotFoundException; |
|
8 import java.io.FileOutputStream; |
|
9 import java.io.PrintStream; |
|
10 import java.util.ArrayList; |
|
11 import java.util.List; |
|
12 |
|
13 import org.mozilla.gecko.background.common.GlobalConstants; |
|
14 import org.mozilla.gecko.background.helpers.AndroidSyncTestCase; |
|
15 import org.mozilla.gecko.db.BrowserContract; |
|
16 import org.mozilla.gecko.sync.ExtendedJSONObject; |
|
17 import org.mozilla.gecko.sync.SyncConfiguration; |
|
18 import org.mozilla.gecko.sync.SyncConstants; |
|
19 import org.mozilla.gecko.sync.Utils; |
|
20 import org.mozilla.gecko.sync.config.AccountPickler; |
|
21 import org.mozilla.gecko.sync.setup.Constants; |
|
22 import org.mozilla.gecko.sync.setup.SyncAccounts; |
|
23 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters; |
|
24 |
|
25 import android.accounts.Account; |
|
26 import android.accounts.AccountManager; |
|
27 import android.content.ContentResolver; |
|
28 import android.content.Context; |
|
29 import android.content.SharedPreferences; |
|
30 |
|
31 public class TestAccountPickler extends AndroidSyncTestCase { |
|
32 public static final String TEST_FILENAME = "test.json"; |
|
33 public static final String TEST_ACCOUNTTYPE = SyncConstants.ACCOUNTTYPE_SYNC; |
|
34 |
|
35 // Test account names must start with TEST_USERNAME in order to be recognized |
|
36 // as test accounts and deleted in tearDown. |
|
37 public static final String TEST_USERNAME = "testAccount@mozilla.com"; |
|
38 public static final String TEST_USERNAME2 = TEST_USERNAME + "2"; |
|
39 |
|
40 public static final String TEST_SYNCKEY = "testSyncKey"; |
|
41 public static final String TEST_PASSWORD = "testPassword"; |
|
42 public static final String TEST_SERVER_URL = "test.server.url/"; |
|
43 public static final String TEST_CLUSTER_URL = "test.cluster.url/"; |
|
44 public static final String TEST_CLIENT_NAME = "testClientName"; |
|
45 public static final String TEST_CLIENT_GUID = "testClientGuid"; |
|
46 |
|
47 public static final String TEST_PRODUCT = GlobalConstants.BROWSER_INTENT_PACKAGE; |
|
48 public static final String TEST_PROFILE = "default"; |
|
49 public static final long TEST_VERSION = SyncConfiguration.CURRENT_PREFS_VERSION; |
|
50 |
|
51 protected SyncAccountParameters params; |
|
52 protected Context context; |
|
53 protected AccountManager accountManager; |
|
54 protected int numAccounts; |
|
55 |
|
56 public void setUp() { |
|
57 context = getApplicationContext(); |
|
58 accountManager = AccountManager.get(context); |
|
59 params = new SyncAccountParameters(context, accountManager, |
|
60 TEST_USERNAME, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVER_URL, |
|
61 TEST_CLUSTER_URL, TEST_CLIENT_NAME, TEST_CLIENT_GUID); |
|
62 numAccounts = accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length; |
|
63 } |
|
64 |
|
65 public static List<Account> getTestAccounts(final AccountManager accountManager) { |
|
66 final List<Account> testAccounts = new ArrayList<Account>(); |
|
67 |
|
68 final Account[] accounts = accountManager.getAccountsByType(TEST_ACCOUNTTYPE); |
|
69 for (Account account : accounts) { |
|
70 if (account.name.startsWith(TEST_USERNAME)) { |
|
71 testAccounts.add(account); |
|
72 } |
|
73 } |
|
74 |
|
75 return testAccounts; |
|
76 } |
|
77 |
|
78 public void deleteTestAccounts() { |
|
79 for (Account account : getTestAccounts(accountManager)) { |
|
80 TestSyncAccounts.deleteAccount(this, accountManager, account); |
|
81 } |
|
82 } |
|
83 |
|
84 public void tearDown() { |
|
85 deleteTestAccounts(); |
|
86 assertEquals(numAccounts, accountManager.getAccountsByType(TEST_ACCOUNTTYPE).length); |
|
87 } |
|
88 |
|
89 public static void assertFileNotPresent(final Context context, final String filename) throws Exception { |
|
90 // Verify file is not present. |
|
91 FileInputStream fis = null; |
|
92 try { |
|
93 fis = context.openFileInput(TEST_FILENAME); |
|
94 fail("Should get FileNotFoundException."); |
|
95 } catch (FileNotFoundException e) { |
|
96 // Do nothing; file should not exist. |
|
97 } finally { |
|
98 if (fis != null) { |
|
99 fis.close(); |
|
100 } |
|
101 } |
|
102 } |
|
103 |
|
104 public void testPersist() throws Exception { |
|
105 context.deleteFile(TEST_FILENAME); |
|
106 assertFileNotPresent(context, TEST_FILENAME); |
|
107 |
|
108 AccountPickler.pickle(context, TEST_FILENAME, params, true); |
|
109 |
|
110 final String s = Utils.readFile(context, TEST_FILENAME); |
|
111 assertNotNull(s); |
|
112 |
|
113 final ExtendedJSONObject o = ExtendedJSONObject.parseJSONObject(s); |
|
114 assertEquals(TEST_USERNAME, o.getString(Constants.JSON_KEY_ACCOUNT)); |
|
115 assertEquals(TEST_PASSWORD, o.getString(Constants.JSON_KEY_PASSWORD)); |
|
116 assertEquals(TEST_SERVER_URL, o.getString(Constants.JSON_KEY_SERVER)); |
|
117 assertEquals(TEST_SYNCKEY, o.getString(Constants.JSON_KEY_SYNCKEY)); |
|
118 assertEquals(TEST_CLUSTER_URL, o.getString(Constants.JSON_KEY_CLUSTER)); |
|
119 assertEquals(TEST_CLIENT_NAME, o.getString(Constants.JSON_KEY_CLIENT_NAME)); |
|
120 assertEquals(TEST_CLIENT_GUID, o.getString(Constants.JSON_KEY_CLIENT_GUID)); |
|
121 assertEquals(Boolean.valueOf(true), o.get(Constants.JSON_KEY_SYNC_AUTOMATICALLY)); |
|
122 assertEquals(Long.valueOf(AccountPickler.VERSION), o.getLong(Constants.JSON_KEY_VERSION)); |
|
123 assertTrue(o.containsKey(Constants.JSON_KEY_TIMESTAMP)); |
|
124 } |
|
125 |
|
126 public void testDeletePickle() throws Exception { |
|
127 AccountPickler.pickle(context, TEST_FILENAME, params, false); |
|
128 |
|
129 // Verify file is present. |
|
130 final String s = Utils.readFile(context, TEST_FILENAME); |
|
131 assertNotNull(s); |
|
132 assertTrue(s.length() > 0); |
|
133 |
|
134 AccountPickler.deletePickle(context, TEST_FILENAME); |
|
135 assertFileNotPresent(context, TEST_FILENAME); |
|
136 } |
|
137 |
|
138 public Account deleteAccountsAndUnpickle(final Context context, final AccountManager accountManager, final String filename) { |
|
139 deleteTestAccounts(); |
|
140 assertEquals(0, getTestAccounts(accountManager).size()); |
|
141 |
|
142 return AccountPickler.unpickle(context, filename); |
|
143 } |
|
144 |
|
145 public void testUnpickleSuccess() throws Exception { |
|
146 AccountPickler.pickle(context, TEST_FILENAME, params, true); |
|
147 |
|
148 // Make sure we have no accounts hanging around. |
|
149 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
150 assertNotNull(account); |
|
151 |
|
152 try { |
|
153 assertEquals(1, getTestAccounts(accountManager).size()); |
|
154 assertTrue(ContentResolver.getSyncAutomatically(account, BrowserContract.AUTHORITY)); |
|
155 assertEquals(account.name, TEST_USERNAME); |
|
156 |
|
157 // Verify Account parameters are in place. Not testing clusterURL since it's stored in |
|
158 // shared prefs and it's less critical. |
|
159 final String password = accountManager.getPassword(account); |
|
160 final String serverURL = accountManager.getUserData(account, Constants.OPTION_SERVER); |
|
161 final String syncKey = accountManager.getUserData(account, Constants.OPTION_SYNCKEY); |
|
162 |
|
163 assertEquals(TEST_PASSWORD, password); |
|
164 assertEquals(TEST_SERVER_URL, serverURL); |
|
165 assertEquals(TEST_SYNCKEY, syncKey); |
|
166 |
|
167 // Verify shared prefs parameters are in place. |
|
168 final SharedPreferences prefs = Utils.getSharedPreferences(context, TEST_PRODUCT, TEST_USERNAME, TEST_SERVER_URL, TEST_PROFILE, TEST_VERSION); |
|
169 final String clusterURL = prefs.getString(SyncConfiguration.PREF_CLUSTER_URL, null); |
|
170 final String clientName = prefs.getString(SyncConfiguration.PREF_CLIENT_NAME, null); |
|
171 final String clientGuid = prefs.getString(SyncConfiguration.PREF_ACCOUNT_GUID, null); |
|
172 |
|
173 assertEquals(TEST_CLUSTER_URL, clusterURL); |
|
174 assertEquals(TEST_CLIENT_NAME, clientName); |
|
175 assertEquals(TEST_CLIENT_GUID, clientGuid); |
|
176 } finally { |
|
177 TestSyncAccounts.deleteAccount(this, accountManager, account); |
|
178 } |
|
179 } |
|
180 |
|
181 public void testUnpickleNoAutomatic() throws Exception { |
|
182 AccountPickler.pickle(context, TEST_FILENAME, params, false); |
|
183 |
|
184 // Make sure we have no accounts hanging around. |
|
185 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
186 assertNotNull(account); |
|
187 |
|
188 try { |
|
189 assertEquals(1, getTestAccounts(accountManager).size()); |
|
190 assertFalse(ContentResolver.getSyncAutomatically(account, BrowserContract.AUTHORITY)); |
|
191 } finally { |
|
192 TestSyncAccounts.deleteAccount(this, accountManager, account); |
|
193 } |
|
194 } |
|
195 |
|
196 public void testUnpickleNoFile() { |
|
197 // Just in case file is hanging around. |
|
198 context.deleteFile(TEST_FILENAME); |
|
199 |
|
200 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
201 assertNull(account); |
|
202 } |
|
203 |
|
204 public void testUnpickleIncompleteUserData() throws Exception { |
|
205 final FileOutputStream fos = context.openFileOutput(TEST_FILENAME, Context.MODE_PRIVATE); |
|
206 final PrintStream ps = (new PrintStream(fos)); |
|
207 ps.print("{}"); // Valid JSON, just missing everything. |
|
208 ps.close(); |
|
209 fos.close(); |
|
210 |
|
211 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
212 assertNull(account); |
|
213 } |
|
214 |
|
215 public void testUnpickleMalformedFile() throws Exception { |
|
216 final FileOutputStream fos = context.openFileOutput(TEST_FILENAME, Context.MODE_PRIVATE); |
|
217 final PrintStream ps = (new PrintStream(fos)); |
|
218 ps.print("{1:!}"); // Not valid JSON. |
|
219 ps.close(); |
|
220 fos.close(); |
|
221 |
|
222 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
223 assertNull(account); |
|
224 } |
|
225 |
|
226 public void testUnpickleAccountAlreadyExists() { |
|
227 AccountPickler.pickle(context, TEST_FILENAME, params, false); |
|
228 |
|
229 // Make sure we have no test accounts hanging around. |
|
230 final Account account = deleteAccountsAndUnpickle(context, accountManager, TEST_FILENAME); |
|
231 assertNotNull(account); |
|
232 assertEquals(TEST_USERNAME, account.name); |
|
233 |
|
234 // Now replace file with new username. |
|
235 params = new SyncAccountParameters(context, accountManager, |
|
236 TEST_USERNAME2, TEST_SYNCKEY, TEST_PASSWORD, TEST_SERVER_URL, null, TEST_CLIENT_NAME, TEST_CLIENT_GUID); |
|
237 AccountPickler.pickle(context, TEST_FILENAME, params, false); |
|
238 |
|
239 // Checking if sync accounts exist could try to unpickle. That unpickle |
|
240 // would load an account with a different username, so we can check that |
|
241 // nothing was unpickled by verifying that the username has not changed. |
|
242 assertTrue(SyncAccounts.syncAccountsExist(context)); |
|
243 |
|
244 for (Account a : getTestAccounts(accountManager)) { |
|
245 assertEquals(TEST_USERNAME, a.name); |
|
246 } |
|
247 } |
|
248 } |