blob: f870e4cc86bb7196b62232728d55a28db6ef1e65 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Amith Yamasani8ff9a152012-12-11 10:42:09 -080017package com.android.server.content;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Fred Quintanad9d2f112009-04-23 13:36:27 -070019import android.accounts.Account;
Amith Yamasani8ff9a152012-12-11 10:42:09 -080020import android.content.ContentResolver;
21import android.content.Context;
22import android.content.ContextWrapper;
23import android.content.Intent;
24import android.content.PeriodicSync;
Matthew Williamsfa774182013-06-18 15:44:11 -070025import android.content.res.Resources;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080026import android.os.Bundle;
Brett Chabotf76c56b2010-07-26 17:28:17 -070027import android.test.AndroidTestCase;
28import android.test.RenamingDelegatingContext;
29import android.test.mock.MockContentResolver;
30import android.test.mock.MockContext;
31import android.test.suitebuilder.annotation.LargeTest;
32import android.test.suitebuilder.annotation.MediumTest;
33import android.test.suitebuilder.annotation.SmallTest;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080034
Alon Albert57286f92012-10-09 14:21:38 -070035import com.android.internal.os.AtomicFile;
36
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080037import java.io.File;
Fred Quintanac2e46912010-03-15 16:10:44 -070038import java.io.FileOutputStream;
Brett Chabotf76c56b2010-07-26 17:28:17 -070039import java.util.List;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040
41public class SyncStorageEngineTest extends AndroidTestCase {
42
Matthew Williamsfa774182013-06-18 15:44:11 -070043 protected Account account1;
44 protected String authority1 = "testprovider";
45 protected Bundle defaultBundle;
46 protected final int DEFAULT_USER = 0;
47
48 MockContentResolver mockResolver;
49 SyncStorageEngine engine;
50
Amith Yamasani04e0d262012-02-14 11:50:53 -080051 private File getSyncDir() {
52 return new File(new File(getContext().getFilesDir(), "system"), "sync");
53 }
54
Matthew Williamsfa774182013-06-18 15:44:11 -070055 @Override
56 public void setUp() {
57 account1 = new Account("a@example.com", "example.type");
58 // Default bundle.
59 defaultBundle = new Bundle();
60 defaultBundle.putInt("int_key", 0);
61 defaultBundle.putString("string_key", "hello");
62 // Set up storage engine.
63 mockResolver = new MockContentResolver();
64 engine = SyncStorageEngine.newTestInstance(
65 new TestContext(mockResolver, getContext()));
66 }
67
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 /**
69 * Test that we handle the case of a history row being old enough to purge before the
Matthew Williamsba352712013-08-13 15:53:31 -070070 * corresponding sync is finished. This can happen if the clock changes while we are syncing.
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080071 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 */
Brett Chabot2ad24f92010-10-04 19:55:14 -070073 // TODO: this test causes AidlTest to fail. Omit for now
74 // @SmallTest
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 public void testPurgeActiveSync() throws Exception {
Fred Quintanad9d2f112009-04-23 13:36:27 -070076 final Account account = new Account("a@example.com", "example.type");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077 final String authority = "testprovider";
78
79 MockContentResolver mockResolver = new MockContentResolver();
80
81 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
82 new TestContext(mockResolver, getContext()));
83
84 long time0 = 1000;
85 long historyId = engine.insertStartSyncEvent(
Alon Albert57286f92012-10-09 14:21:38 -070086 account, 0, SyncOperation.REASON_PERIODIC, authority, time0,
87 SyncStorageEngine.SOURCE_LOCAL, false /* initialization */, null /* extras */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
Fred Quintana77c560f2010-03-29 22:20:26 -070089 engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080090 }
91
92 /**
Matthew Williamsfa774182013-06-18 15:44:11 -070093 * Test persistence of pending operations.
94 */
95 @MediumTest
96 public void testPending() throws Exception {
97 SyncStorageEngine.PendingOperation pop =
98 new SyncStorageEngine.PendingOperation(account1, DEFAULT_USER,
99 SyncOperation.REASON_PERIODIC, SyncStorageEngine.SOURCE_LOCAL,
100 authority1, defaultBundle, false);
101
102 engine.insertIntoPending(pop);
103 // Force engine to read from disk.
104 engine.clearAndReadState();
105
106 assert(engine.getPendingOperationCount() == 1);
Matthew Williamsba352712013-08-13 15:53:31 -0700107 List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
108 SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
109 assertEquals(pop.account, popRetrieved.account);
110 assertEquals(pop.reason, popRetrieved.reason);
111 assertEquals(pop.userId, popRetrieved.userId);
112 assertEquals(pop.syncSource, popRetrieved.syncSource);
113 assertEquals(pop.authority, popRetrieved.authority);
114 assertEquals(pop.expedited, popRetrieved.expedited);
115 assertEquals(pop.serviceName, popRetrieved.serviceName);
116 assert(android.content.PeriodicSync.syncExtrasEquals(pop.extras, popRetrieved.extras));
117
Matthew Williamsfa774182013-06-18 15:44:11 -0700118 }
119
120 /**
121 * Test that we can create, remove and retrieve periodic syncs. Backwards compatibility -
122 * periodic syncs with no flex time are no longer used.
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800123 */
Brett Chabotf76c56b2010-07-26 17:28:17 -0700124 @MediumTest
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800125 public void testPeriodics() throws Exception {
126 final Account account1 = new Account("a@example.com", "example.type");
127 final Account account2 = new Account("b@example.com", "example.type.2");
128 final String authority = "testprovider";
129 final Bundle extras1 = new Bundle();
130 extras1.putString("a", "1");
131 final Bundle extras2 = new Bundle();
132 extras2.putString("a", "2");
133 final int period1 = 200;
134 final int period2 = 1000;
135
136 PeriodicSync sync1 = new PeriodicSync(account1, authority, extras1, period1);
137 PeriodicSync sync2 = new PeriodicSync(account1, authority, extras2, period1);
138 PeriodicSync sync3 = new PeriodicSync(account1, authority, extras2, period2);
139 PeriodicSync sync4 = new PeriodicSync(account2, authority, extras2, period2);
140
Matthew Williamsfa774182013-06-18 15:44:11 -0700141
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800142
Amith Yamasani04e0d262012-02-14 11:50:53 -0800143 removePeriodicSyncs(engine, account1, 0, authority);
144 removePeriodicSyncs(engine, account2, 0, authority);
145 removePeriodicSyncs(engine, account1, 1, authority);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800146
147 // this should add two distinct periodic syncs for account1 and one for account2
Matthew Williamsfa774182013-06-18 15:44:11 -0700148 engine.addPeriodicSync(sync1, 0);
149 engine.addPeriodicSync(sync2, 0);
150 engine.addPeriodicSync(sync3, 0);
151 engine.addPeriodicSync(sync4, 0);
Amith Yamasani04e0d262012-02-14 11:50:53 -0800152 // add a second user
Matthew Williamsfa774182013-06-18 15:44:11 -0700153 engine.addPeriodicSync(sync2, 1);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800154
Amith Yamasani04e0d262012-02-14 11:50:53 -0800155 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800156
157 assertEquals(2, syncs.size());
158
159 assertEquals(sync1, syncs.get(0));
160 assertEquals(sync3, syncs.get(1));
161
Matthew Williamsfa774182013-06-18 15:44:11 -0700162 engine.removePeriodicSync(sync1, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800163
Amith Yamasani04e0d262012-02-14 11:50:53 -0800164 syncs = engine.getPeriodicSyncs(account1, 0, authority);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800165 assertEquals(1, syncs.size());
166 assertEquals(sync3, syncs.get(0));
167
Amith Yamasani04e0d262012-02-14 11:50:53 -0800168 syncs = engine.getPeriodicSyncs(account2, 0, authority);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800169 assertEquals(1, syncs.size());
170 assertEquals(sync4, syncs.get(0));
Amith Yamasani04e0d262012-02-14 11:50:53 -0800171
172 syncs = engine.getPeriodicSyncs(sync2.account, 1, sync2.authority);
173 assertEquals(1, syncs.size());
174 assertEquals(sync2, syncs.get(0));
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800175 }
176
Matthew Williamsfa774182013-06-18 15:44:11 -0700177 /**
178 * Test that we can create, remove and retrieve periodic syncs with a provided flex time.
179 */
180 @MediumTest
181 public void testPeriodicsV2() throws Exception {
182 final Account account1 = new Account("a@example.com", "example.type");
183 final Account account2 = new Account("b@example.com", "example.type.2");
184 final String authority = "testprovider";
185 final Bundle extras1 = new Bundle();
186 extras1.putString("a", "1");
187 final Bundle extras2 = new Bundle();
188 extras2.putString("a", "2");
189 final int period1 = 200;
190 final int period2 = 1000;
191 final int flex1 = 10;
192 final int flex2 = 100;
193
194 PeriodicSync sync1 = new PeriodicSync(account1, authority, extras1, period1, flex1);
195 PeriodicSync sync2 = new PeriodicSync(account1, authority, extras2, period1, flex1);
196 PeriodicSync sync3 = new PeriodicSync(account1, authority, extras2, period2, flex2);
197 PeriodicSync sync4 = new PeriodicSync(account2, authority, extras2, period2, flex2);
198
199 MockContentResolver mockResolver = new MockContentResolver();
200
201 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
202 new TestContext(mockResolver, getContext()));
203
204 removePeriodicSyncs(engine, account1, 0, authority);
205 removePeriodicSyncs(engine, account2, 0, authority);
206 removePeriodicSyncs(engine, account1, 1, authority);
207
208 // This should add two distinct periodic syncs for account1 and one for account2
209 engine.addPeriodicSync(sync1, 0);
210 engine.addPeriodicSync(sync2, 0);
211 engine.addPeriodicSync(sync3, 0); // Should edit sync2 and update the period.
212 engine.addPeriodicSync(sync4, 0);
213 // add a second user
214 engine.addPeriodicSync(sync2, 1);
215
216 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority);
217
218 assertEquals(2, syncs.size());
219
220 assertEquals(sync1, syncs.get(0));
221 assertEquals(sync3, syncs.get(1));
222
223 engine.removePeriodicSync(sync1, 0);
224
225 syncs = engine.getPeriodicSyncs(account1, 0, authority);
226 assertEquals(1, syncs.size());
227 assertEquals(sync3, syncs.get(0));
228
229 syncs = engine.getPeriodicSyncs(account2, 0, authority);
230 assertEquals(1, syncs.size());
231 assertEquals(sync4, syncs.get(0));
232
233 syncs = engine.getPeriodicSyncs(sync2.account, 1, sync2.authority);
234 assertEquals(1, syncs.size());
235 assertEquals(sync2, syncs.get(0));
236 }
237
238 private void removePeriodicSyncs(SyncStorageEngine engine, Account account, int userId, String authority) {
239 engine.setIsSyncable(account, userId, authority, engine.getIsSyncable(account, 0, authority));
Amith Yamasani04e0d262012-02-14 11:50:53 -0800240 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, userId, authority);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800241 for (PeriodicSync sync : syncs) {
Matthew Williamsfa774182013-06-18 15:44:11 -0700242 engine.removePeriodicSync(sync, userId);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800243 }
244 }
245
Brett Chabotf76c56b2010-07-26 17:28:17 -0700246 @LargeTest
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800247 public void testAuthorityPersistence() throws Exception {
248 final Account account1 = new Account("a@example.com", "example.type");
249 final Account account2 = new Account("b@example.com", "example.type.2");
250 final String authority1 = "testprovider1";
251 final String authority2 = "testprovider2";
252 final Bundle extras1 = new Bundle();
253 extras1.putString("a", "1");
254 final Bundle extras2 = new Bundle();
255 extras2.putString("a", "2");
256 extras2.putLong("b", 2);
257 extras2.putInt("c", 1);
258 extras2.putBoolean("d", true);
259 extras2.putDouble("e", 1.2);
260 extras2.putFloat("f", 4.5f);
261 extras2.putParcelable("g", account1);
262 final int period1 = 200;
263 final int period2 = 1000;
Matthew Williamsfa774182013-06-18 15:44:11 -0700264 final int flex1 = 10;
265 final int flex2 = 100;
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800266
Matthew Williamsfa774182013-06-18 15:44:11 -0700267 PeriodicSync sync1 = new PeriodicSync(account1, authority1, extras1, period1, flex1);
268 PeriodicSync sync2 = new PeriodicSync(account1, authority1, extras2, period1, flex1);
269 PeriodicSync sync3 = new PeriodicSync(account1, authority2, extras1, period1, flex1);
270 PeriodicSync sync4 = new PeriodicSync(account1, authority2, extras2, period2, flex2);
271 PeriodicSync sync5 = new PeriodicSync(account2, authority1, extras1, period1, flex1);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800272
273 MockContentResolver mockResolver = new MockContentResolver();
274
275 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
276 new TestContext(mockResolver, getContext()));
277
Amith Yamasani04e0d262012-02-14 11:50:53 -0800278 removePeriodicSyncs(engine, account1, 0, authority1);
279 removePeriodicSyncs(engine, account2, 0, authority1);
280 removePeriodicSyncs(engine, account1, 0, authority2);
281 removePeriodicSyncs(engine, account2, 0, authority2);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800282
Amith Yamasani04e0d262012-02-14 11:50:53 -0800283 engine.setMasterSyncAutomatically(false, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800284
Amith Yamasani04e0d262012-02-14 11:50:53 -0800285 engine.setIsSyncable(account1, 0, authority1, 1);
286 engine.setSyncAutomatically(account1, 0, authority1, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800287
Amith Yamasani04e0d262012-02-14 11:50:53 -0800288 engine.setIsSyncable(account2, 0, authority1, 1);
289 engine.setSyncAutomatically(account2, 0, authority1, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800290
Amith Yamasani04e0d262012-02-14 11:50:53 -0800291 engine.setIsSyncable(account1, 0, authority2, 1);
292 engine.setSyncAutomatically(account1, 0, authority2, false);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800293
Amith Yamasani04e0d262012-02-14 11:50:53 -0800294 engine.setIsSyncable(account2, 0, authority2, 0);
295 engine.setSyncAutomatically(account2, 0, authority2, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800296
Matthew Williamsfa774182013-06-18 15:44:11 -0700297 engine.addPeriodicSync(sync1, 0);
298 engine.addPeriodicSync(sync2, 0);
299 engine.addPeriodicSync(sync3, 0);
300 engine.addPeriodicSync(sync4, 0);
301 engine.addPeriodicSync(sync5, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800302
303 engine.writeAllState();
304 engine.clearAndReadState();
305
Amith Yamasani04e0d262012-02-14 11:50:53 -0800306 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority1);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800307 assertEquals(2, syncs.size());
308 assertEquals(sync1, syncs.get(0));
309 assertEquals(sync2, syncs.get(1));
310
Amith Yamasani04e0d262012-02-14 11:50:53 -0800311 syncs = engine.getPeriodicSyncs(account1, 0, authority2);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800312 assertEquals(2, syncs.size());
313 assertEquals(sync3, syncs.get(0));
314 assertEquals(sync4, syncs.get(1));
315
Amith Yamasani04e0d262012-02-14 11:50:53 -0800316 syncs = engine.getPeriodicSyncs(account2, 0, authority1);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800317 assertEquals(1, syncs.size());
318 assertEquals(sync5, syncs.get(0));
319
Amith Yamasani04e0d262012-02-14 11:50:53 -0800320 assertEquals(true, engine.getSyncAutomatically(account1, 0, authority1));
321 assertEquals(true, engine.getSyncAutomatically(account2, 0, authority1));
322 assertEquals(false, engine.getSyncAutomatically(account1, 0, authority2));
323 assertEquals(true, engine.getSyncAutomatically(account2, 0, authority2));
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800324
Amith Yamasani04e0d262012-02-14 11:50:53 -0800325 assertEquals(1, engine.getIsSyncable(account1, 0, authority1));
326 assertEquals(1, engine.getIsSyncable(account2, 0, authority1));
327 assertEquals(1, engine.getIsSyncable(account1, 0, authority2));
328 assertEquals(0, engine.getIsSyncable(account2, 0, authority2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 }
Fred Quintanac2e46912010-03-15 16:10:44 -0700330
Brett Chabotf76c56b2010-07-26 17:28:17 -0700331 @MediumTest
Matthew Williamsfa774182013-06-18 15:44:11 -0700332 /**
333 * V2 introduces flex time as well as service components.
334 * @throws Exception
335 */
336 public void testAuthorityParsingV2() throws Exception {
337 final Account account = new Account("account1", "type1");
338 final String authority1 = "auth1";
339 final String authority2 = "auth2";
340 final String authority3 = "auth3";
341
342 final long dayPoll = (60 * 60 * 24);
343 final long dayFuzz = 60;
344 final long thousandSecs = 1000;
345 final long thousandSecsFuzz = 100;
346 final Bundle extras = new Bundle();
347 PeriodicSync sync1 = new PeriodicSync(account, authority1, extras, dayPoll, dayFuzz);
348 PeriodicSync sync2 = new PeriodicSync(account, authority2, extras, dayPoll, dayFuzz);
349 PeriodicSync sync3 = new PeriodicSync(account, authority3, extras, dayPoll, dayFuzz);
350 PeriodicSync sync1s = new PeriodicSync(account, authority1, extras, thousandSecs, thousandSecsFuzz);
351 PeriodicSync sync2s = new PeriodicSync(account, authority2, extras, thousandSecs, thousandSecsFuzz);
352 PeriodicSync sync3s = new PeriodicSync(account, authority3, extras, thousandSecs, thousandSecsFuzz);
353 MockContentResolver mockResolver = new MockContentResolver();
354
355 final TestContext testContext = new TestContext(mockResolver, getContext());
356
357 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
358 + "<accounts version=\"2\" >\n"
359 + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" >"
360 + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
361 + "\n</authority>"
362 + "<authority id=\"1\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth2\" >"
363 + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
364 + "\n</authority>"
365 // No user defaults to user 0 - all users.
366 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" >"
367 + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
368 + "\n</authority>"
369 + "<authority id=\"3\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth3\" >"
370 + "\n<periodicSync period=\"" + dayPoll + "\" flex=\"" + dayFuzz + "\"/>"
371 + "\n</authority>"
372 + "</accounts>").getBytes();
373
374 File syncDir = getSyncDir();
375 syncDir.mkdirs();
376 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
377 FileOutputStream fos = accountInfoFile.startWrite();
378 fos.write(accountsFileData);
379 accountInfoFile.finishWrite(fos);
380
381 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
382
383 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, 0, authority1);
384 assertEquals("Got incorrect # of syncs", 1, syncs.size());
385 assertEquals(sync1, syncs.get(0));
386
387 syncs = engine.getPeriodicSyncs(account, 0, authority2);
388 assertEquals(1, syncs.size());
389 assertEquals(sync2, syncs.get(0));
390
391 syncs = engine.getPeriodicSyncs(account, 0, authority3);
392 assertEquals(1, syncs.size());
393 assertEquals(sync3, syncs.get(0));
394
395 syncs = engine.getPeriodicSyncs(account, 1, authority3);
396 assertEquals(1, syncs.size());
397 assertEquals(sync3, syncs.get(0));
398
399 // Test empty periodic data.
400 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
401 + "<accounts version=\"2\">\n"
402 + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
403 + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
404 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
405 + "</accounts>\n").getBytes();
406
407 accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
408 fos = accountInfoFile.startWrite();
409 fos.write(accountsFileData);
410 accountInfoFile.finishWrite(fos);
411
412 engine.clearAndReadState();
413
414 syncs = engine.getPeriodicSyncs(account, 0, authority1);
415 assertEquals(0, syncs.size());
416
417 syncs = engine.getPeriodicSyncs(account, 0, authority2);
418 assertEquals(0, syncs.size());
419
420 syncs = engine.getPeriodicSyncs(account, 0, authority3);
421 assertEquals(0, syncs.size());
422
423 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
424 + "<accounts version=\"2\">\n"
425 + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n"
426 + "<periodicSync period=\"1000\" />\n"
427 + "</authority>"
428 + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n"
429 + "<periodicSync period=\"1000\" />\n"
430 + "</authority>"
431 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n"
432 + "<periodicSync period=\"1000\" />\n"
433 + "</authority>"
434 + "</accounts>\n").getBytes();
435
436 accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
437 fos = accountInfoFile.startWrite();
438 fos.write(accountsFileData);
439 accountInfoFile.finishWrite(fos);
440
441 engine.clearAndReadState();
442
443 syncs = engine.getPeriodicSyncs(account, 0, authority1);
444 assertEquals(1, syncs.size());
445 assertEquals(sync1s, syncs.get(0));
446
447 syncs = engine.getPeriodicSyncs(account, 0, authority2);
448 assertEquals(1, syncs.size());
449 assertEquals(sync2s, syncs.get(0));
450
451 syncs = engine.getPeriodicSyncs(account, 0, authority3);
452 assertEquals(1, syncs.size());
453 assertEquals(sync3s, syncs.get(0));
454 }
455
456 @MediumTest
Fred Quintanac2e46912010-03-15 16:10:44 -0700457 public void testAuthorityParsing() throws Exception {
458 final Account account = new Account("account1", "type1");
459 final String authority1 = "auth1";
460 final String authority2 = "auth2";
461 final String authority3 = "auth3";
462 final Bundle extras = new Bundle();
463 PeriodicSync sync1 = new PeriodicSync(account, authority1, extras, (long) (60 * 60 * 24));
464 PeriodicSync sync2 = new PeriodicSync(account, authority2, extras, (long) (60 * 60 * 24));
465 PeriodicSync sync3 = new PeriodicSync(account, authority3, extras, (long) (60 * 60 * 24));
466 PeriodicSync sync1s = new PeriodicSync(account, authority1, extras, 1000);
467 PeriodicSync sync2s = new PeriodicSync(account, authority2, extras, 1000);
468 PeriodicSync sync3s = new PeriodicSync(account, authority3, extras, 1000);
469
470 MockContentResolver mockResolver = new MockContentResolver();
471
472 final TestContext testContext = new TestContext(mockResolver, getContext());
Fred Quintanac2e46912010-03-15 16:10:44 -0700473
474 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
475 + "<accounts>\n"
Amith Yamasani04e0d262012-02-14 11:50:53 -0800476 + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
477 + "<authority id=\"1\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
478 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
479 + "<authority id=\"3\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
Fred Quintanac2e46912010-03-15 16:10:44 -0700480 + "</accounts>\n").getBytes();
481
Amith Yamasani04e0d262012-02-14 11:50:53 -0800482 File syncDir = getSyncDir();
Fred Quintanac2e46912010-03-15 16:10:44 -0700483 syncDir.mkdirs();
484 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
485 FileOutputStream fos = accountInfoFile.startWrite();
486 fos.write(accountsFileData);
487 accountInfoFile.finishWrite(fos);
488
Fred Quintanafb084402010-03-23 17:57:03 -0700489 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
Fred Quintanac2e46912010-03-15 16:10:44 -0700490
Amith Yamasani04e0d262012-02-14 11:50:53 -0800491 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, 0, authority1);
Fred Quintanac2e46912010-03-15 16:10:44 -0700492 assertEquals(1, syncs.size());
Matthew Williamsfa774182013-06-18 15:44:11 -0700493 assertEquals("expected sync1: " + sync1.toString() + " == sync 2" + syncs.get(0).toString(), sync1, syncs.get(0));
Fred Quintanac2e46912010-03-15 16:10:44 -0700494
Amith Yamasani04e0d262012-02-14 11:50:53 -0800495 syncs = engine.getPeriodicSyncs(account, 0, authority2);
Fred Quintanac2e46912010-03-15 16:10:44 -0700496 assertEquals(1, syncs.size());
497 assertEquals(sync2, syncs.get(0));
498
Amith Yamasani04e0d262012-02-14 11:50:53 -0800499 syncs = engine.getPeriodicSyncs(account, 0, authority3);
500 assertEquals(1, syncs.size());
501 assertEquals(sync3, syncs.get(0));
502
503 syncs = engine.getPeriodicSyncs(account, 1, authority3);
Fred Quintanac2e46912010-03-15 16:10:44 -0700504 assertEquals(1, syncs.size());
505 assertEquals(sync3, syncs.get(0));
506
507 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
Fred Quintanafb084402010-03-23 17:57:03 -0700508 + "<accounts version=\"2\">\n"
Fred Quintanac2e46912010-03-15 16:10:44 -0700509 + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
510 + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\" />\n"
511 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\" />\n"
512 + "</accounts>\n").getBytes();
513
514 accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
515 fos = accountInfoFile.startWrite();
516 fos.write(accountsFileData);
517 accountInfoFile.finishWrite(fos);
518
519 engine.clearAndReadState();
520
Amith Yamasani04e0d262012-02-14 11:50:53 -0800521 syncs = engine.getPeriodicSyncs(account, 0, authority1);
Fred Quintanac2e46912010-03-15 16:10:44 -0700522 assertEquals(0, syncs.size());
523
Amith Yamasani04e0d262012-02-14 11:50:53 -0800524 syncs = engine.getPeriodicSyncs(account, 0, authority2);
Fred Quintanac2e46912010-03-15 16:10:44 -0700525 assertEquals(0, syncs.size());
526
Amith Yamasani04e0d262012-02-14 11:50:53 -0800527 syncs = engine.getPeriodicSyncs(account, 0, authority3);
Fred Quintanac2e46912010-03-15 16:10:44 -0700528 assertEquals(0, syncs.size());
529
530 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
Fred Quintanafb084402010-03-23 17:57:03 -0700531 + "<accounts version=\"2\">\n"
Fred Quintanac2e46912010-03-15 16:10:44 -0700532 + "<authority id=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\">\n"
533 + "<periodicSync period=\"1000\" />\n"
534 + "</authority>"
535 + "<authority id=\"1\" account=\"account1\" type=\"type1\" authority=\"auth2\">\n"
536 + "<periodicSync period=\"1000\" />\n"
537 + "</authority>"
538 + "<authority id=\"2\" account=\"account1\" type=\"type1\" authority=\"auth3\">\n"
539 + "<periodicSync period=\"1000\" />\n"
540 + "</authority>"
541 + "</accounts>\n").getBytes();
542
543 accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
544 fos = accountInfoFile.startWrite();
545 fos.write(accountsFileData);
546 accountInfoFile.finishWrite(fos);
547
548 engine.clearAndReadState();
549
Amith Yamasani04e0d262012-02-14 11:50:53 -0800550 syncs = engine.getPeriodicSyncs(account, 0, authority1);
Fred Quintanac2e46912010-03-15 16:10:44 -0700551 assertEquals(1, syncs.size());
552 assertEquals(sync1s, syncs.get(0));
553
Amith Yamasani04e0d262012-02-14 11:50:53 -0800554 syncs = engine.getPeriodicSyncs(account, 0, authority2);
Fred Quintanac2e46912010-03-15 16:10:44 -0700555 assertEquals(1, syncs.size());
556 assertEquals(sync2s, syncs.get(0));
557
Amith Yamasani04e0d262012-02-14 11:50:53 -0800558 syncs = engine.getPeriodicSyncs(account, 0, authority3);
Fred Quintanac2e46912010-03-15 16:10:44 -0700559 assertEquals(1, syncs.size());
560 assertEquals(sync3s, syncs.get(0));
561 }
Fred Quintanafb084402010-03-23 17:57:03 -0700562
Brett Chabotf76c56b2010-07-26 17:28:17 -0700563 @MediumTest
Amith Yamasani04e0d262012-02-14 11:50:53 -0800564 public void testListenForTicklesParsing() throws Exception {
565 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
566 + "<accounts>\n"
567 + "<listenForTickles user=\"0\" enabled=\"false\" />"
568 + "<listenForTickles user=\"1\" enabled=\"true\" />"
569 + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
570 + "<authority id=\"1\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
571 + "</accounts>\n").getBytes();
572
573 MockContentResolver mockResolver = new MockContentResolver();
574 final TestContext testContext = new TestContext(mockResolver, getContext());
575
576 File syncDir = getSyncDir();
577 syncDir.mkdirs();
578 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
579 FileOutputStream fos = accountInfoFile.startWrite();
580 fos.write(accountsFileData);
581 accountInfoFile.finishWrite(fos);
582
583 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
584
585 assertEquals(false, engine.getMasterSyncAutomatically(0));
586 assertEquals(true, engine.getMasterSyncAutomatically(1));
587 assertEquals(true, engine.getMasterSyncAutomatically(2));
588
589 }
590
591 @MediumTest
Fred Quintanafb084402010-03-23 17:57:03 -0700592 public void testAuthorityRenaming() throws Exception {
593 final Account account1 = new Account("acc1", "type1");
594 final Account account2 = new Account("acc2", "type2");
595 final String authorityContacts = "contacts";
596 final String authorityCalendar = "calendar";
597 final String authorityOther = "other";
598 final String authorityContactsNew = "com.android.contacts";
599 final String authorityCalendarNew = "com.android.calendar";
600
601 MockContentResolver mockResolver = new MockContentResolver();
602
603 final TestContext testContext = new TestContext(mockResolver, getContext());
604
605 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
606 + "<accounts>\n"
607 + "<authority id=\"0\" account=\"acc1\" type=\"type1\" authority=\"contacts\" />\n"
608 + "<authority id=\"1\" account=\"acc1\" type=\"type1\" authority=\"calendar\" />\n"
609 + "<authority id=\"2\" account=\"acc1\" type=\"type1\" authority=\"other\" />\n"
610 + "<authority id=\"3\" account=\"acc2\" type=\"type2\" authority=\"contacts\" />\n"
611 + "<authority id=\"4\" account=\"acc2\" type=\"type2\" authority=\"calendar\" />\n"
612 + "<authority id=\"5\" account=\"acc2\" type=\"type2\" authority=\"other\" />\n"
613 + "<authority id=\"6\" account=\"acc2\" type=\"type2\" enabled=\"false\""
614 + " authority=\"com.android.calendar\" />\n"
615 + "<authority id=\"7\" account=\"acc2\" type=\"type2\" enabled=\"false\""
616 + " authority=\"com.android.contacts\" />\n"
617 + "</accounts>\n").getBytes();
618
619 File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync");
620 syncDir.mkdirs();
621 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
622 FileOutputStream fos = accountInfoFile.startWrite();
623 fos.write(accountsFileData);
624 accountInfoFile.finishWrite(fos);
625
626 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
627
Amith Yamasani04e0d262012-02-14 11:50:53 -0800628 assertEquals(false, engine.getSyncAutomatically(account1, 0, authorityContacts));
629 assertEquals(false, engine.getSyncAutomatically(account1, 0, authorityCalendar));
630 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityOther));
631 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityContactsNew));
632 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityCalendarNew));
Fred Quintanafb084402010-03-23 17:57:03 -0700633
Amith Yamasani04e0d262012-02-14 11:50:53 -0800634 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityContacts));
635 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityCalendar));
636 assertEquals(true, engine.getSyncAutomatically(account2, 0, authorityOther));
637 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityContactsNew));
638 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityCalendarNew));
Fred Quintanafb084402010-03-23 17:57:03 -0700639 }
640
641 @SmallTest
642 public void testSyncableMigration() throws Exception {
643 final Account account = new Account("acc", "type");
644
645 MockContentResolver mockResolver = new MockContentResolver();
646
647 final TestContext testContext = new TestContext(mockResolver, getContext());
648
649 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
650 + "<accounts>\n"
651 + "<authority id=\"0\" account=\"acc\" authority=\"other1\" />\n"
652 + "<authority id=\"1\" account=\"acc\" type=\"type\" authority=\"other2\" />\n"
653 + "<authority id=\"2\" account=\"acc\" type=\"type\" syncable=\"false\""
654 + " authority=\"other3\" />\n"
655 + "<authority id=\"3\" account=\"acc\" type=\"type\" syncable=\"true\""
656 + " authority=\"other4\" />\n"
657 + "</accounts>\n").getBytes();
658
659 File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync");
660 syncDir.mkdirs();
661 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
662 FileOutputStream fos = accountInfoFile.startWrite();
663 fos.write(accountsFileData);
664 accountInfoFile.finishWrite(fos);
665
666 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
667
Amith Yamasani04e0d262012-02-14 11:50:53 -0800668 assertEquals(-1, engine.getIsSyncable(account, 0, "other1"));
669 assertEquals(1, engine.getIsSyncable(account, 0, "other2"));
670 assertEquals(0, engine.getIsSyncable(account, 0, "other3"));
671 assertEquals(1, engine.getIsSyncable(account, 0, "other4"));
Fred Quintanafb084402010-03-23 17:57:03 -0700672 }
Matthew Williams632515b2013-10-10 15:51:00 -0700673
674 /**
675 * Verify that the API cannot cause a run-time reboot by passing in the empty string as an
676 * authority. The problem here is that
677 * {@link SyncStorageEngine#getOrCreateAuthorityLocked(account, provider)} would register
678 * an empty authority which causes a RTE in {@link SyncManager#scheduleReadyPeriodicSyncs()}.
679 * This is not strictly a SSE test, but it does depend on the SSE data structures.
680 */
681 @SmallTest
682 public void testExpectedIllegalArguments() throws Exception {
683 try {
684 ContentResolver.setSyncAutomatically(account1, "", true);
685 fail("empty provider string should throw IllegalArgumentException");
686 } catch (IllegalArgumentException expected) {}
687
688 try {
689 ContentResolver.addPeriodicSync(account1, "", Bundle.EMPTY, 84000L);
690 fail("empty provider string should throw IllegalArgumentException");
691 } catch (IllegalArgumentException expected) {}
692
693 try {
694 ContentResolver.removePeriodicSync(account1, "", Bundle.EMPTY);
695 fail("empty provider string should throw IllegalArgumentException");
696 } catch (IllegalArgumentException expected) {}
697
698 try {
699 ContentResolver.cancelSync(account1, "");
700 fail("empty provider string should throw IllegalArgumentException");
701 } catch (IllegalArgumentException expected) {}
702
703 try {
704 ContentResolver.setIsSyncable(account1, "", 0);
705 fail("empty provider string should throw IllegalArgumentException");
706 } catch (IllegalArgumentException expected) {}
707
708 try {
709 ContentResolver.cancelSync(account1, "");
710 fail("empty provider string should throw IllegalArgumentException");
711 } catch (IllegalArgumentException expected) {}
712
713 try {
714 ContentResolver.requestSync(account1, "", Bundle.EMPTY);
715 fail("empty provider string should throw IllegalArgumentException");
716 } catch (IllegalArgumentException expected) {}
717
718 try {
719 ContentResolver.getSyncStatus(account1, "");
720 fail("empty provider string should throw IllegalArgumentException");
721 } catch (IllegalArgumentException expected) {}
722
723 // Make sure we aren't blocking null account/provider for those functions that use it
724 // to specify ALL accounts/providers.
725 ContentResolver.requestSync(null, null, Bundle.EMPTY);
726 ContentResolver.cancelSync(null, null);
727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728}
729
730class TestContext extends ContextWrapper {
731
732 ContentResolver mResolver;
733
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800734 private final Context mRealContext;
735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800736 public TestContext(ContentResolver resolver, Context realContext) {
737 super(new RenamingDelegatingContext(new MockContext(), realContext, "test."));
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800738 mRealContext = realContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 mResolver = resolver;
740 }
741
742 @Override
Matthew Williamsfa774182013-06-18 15:44:11 -0700743 public Resources getResources() {
744 return mRealContext.getResources();
745 }
746
747 @Override
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800748 public File getFilesDir() {
749 return mRealContext.getFilesDir();
750 }
751
752 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 public void enforceCallingOrSelfPermission(String permission, String message) {
754 }
755
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800756 @Override
757 public void sendBroadcast(Intent intent) {
758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759
760 @Override
761 public ContentResolver getContentResolver() {
762 return mResolver;
763 }
764}