SyncStorageEngineTest.java revision 632515b9d0960749ddb1636677d7f12f196d73f7
1/* 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 17package com.android.server.content; 18 19import android.accounts.Account; 20import android.content.ContentResolver; 21import android.content.Context; 22import android.content.ContextWrapper; 23import android.content.Intent; 24import android.content.PeriodicSync; 25import android.content.res.Resources; 26import android.os.Bundle; 27import 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; 34 35import com.android.internal.os.AtomicFile; 36 37import java.io.File; 38import java.io.FileOutputStream; 39import java.util.List; 40 41public class SyncStorageEngineTest extends AndroidTestCase { 42 43 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 51 private File getSyncDir() { 52 return new File(new File(getContext().getFilesDir(), "system"), "sync"); 53 } 54 55 @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 68 /** 69 * Test that we handle the case of a history row being old enough to purge before the 70 * corresponding sync is finished. This can happen if the clock changes while we are syncing. 71 * 72 */ 73 // TODO: this test causes AidlTest to fail. Omit for now 74 // @SmallTest 75 public void testPurgeActiveSync() throws Exception { 76 final Account account = new Account("a@example.com", "example.type"); 77 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( 86 account, 0, SyncOperation.REASON_PERIODIC, authority, time0, 87 SyncStorageEngine.SOURCE_LOCAL, false /* initialization */, null /* extras */); 88 long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2; 89 engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0); 90 } 91 92 /** 93 * 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); 107 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 118 } 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. 123 */ 124 @MediumTest 125 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 141 142 143 removePeriodicSyncs(engine, account1, 0, authority); 144 removePeriodicSyncs(engine, account2, 0, authority); 145 removePeriodicSyncs(engine, account1, 1, authority); 146 147 // this should add two distinct periodic syncs for account1 and one for account2 148 engine.addPeriodicSync(sync1, 0); 149 engine.addPeriodicSync(sync2, 0); 150 engine.addPeriodicSync(sync3, 0); 151 engine.addPeriodicSync(sync4, 0); 152 // add a second user 153 engine.addPeriodicSync(sync2, 1); 154 155 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority); 156 157 assertEquals(2, syncs.size()); 158 159 assertEquals(sync1, syncs.get(0)); 160 assertEquals(sync3, syncs.get(1)); 161 162 engine.removePeriodicSync(sync1, 0); 163 164 syncs = engine.getPeriodicSyncs(account1, 0, authority); 165 assertEquals(1, syncs.size()); 166 assertEquals(sync3, syncs.get(0)); 167 168 syncs = engine.getPeriodicSyncs(account2, 0, authority); 169 assertEquals(1, syncs.size()); 170 assertEquals(sync4, syncs.get(0)); 171 172 syncs = engine.getPeriodicSyncs(sync2.account, 1, sync2.authority); 173 assertEquals(1, syncs.size()); 174 assertEquals(sync2, syncs.get(0)); 175 } 176 177 /** 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)); 240 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, userId, authority); 241 for (PeriodicSync sync : syncs) { 242 engine.removePeriodicSync(sync, userId); 243 } 244 } 245 246 @LargeTest 247 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; 264 final int flex1 = 10; 265 final int flex2 = 100; 266 267 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); 272 273 MockContentResolver mockResolver = new MockContentResolver(); 274 275 SyncStorageEngine engine = SyncStorageEngine.newTestInstance( 276 new TestContext(mockResolver, getContext())); 277 278 removePeriodicSyncs(engine, account1, 0, authority1); 279 removePeriodicSyncs(engine, account2, 0, authority1); 280 removePeriodicSyncs(engine, account1, 0, authority2); 281 removePeriodicSyncs(engine, account2, 0, authority2); 282 283 engine.setMasterSyncAutomatically(false, 0); 284 285 engine.setIsSyncable(account1, 0, authority1, 1); 286 engine.setSyncAutomatically(account1, 0, authority1, true); 287 288 engine.setIsSyncable(account2, 0, authority1, 1); 289 engine.setSyncAutomatically(account2, 0, authority1, true); 290 291 engine.setIsSyncable(account1, 0, authority2, 1); 292 engine.setSyncAutomatically(account1, 0, authority2, false); 293 294 engine.setIsSyncable(account2, 0, authority2, 0); 295 engine.setSyncAutomatically(account2, 0, authority2, true); 296 297 engine.addPeriodicSync(sync1, 0); 298 engine.addPeriodicSync(sync2, 0); 299 engine.addPeriodicSync(sync3, 0); 300 engine.addPeriodicSync(sync4, 0); 301 engine.addPeriodicSync(sync5, 0); 302 303 engine.writeAllState(); 304 engine.clearAndReadState(); 305 306 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority1); 307 assertEquals(2, syncs.size()); 308 assertEquals(sync1, syncs.get(0)); 309 assertEquals(sync2, syncs.get(1)); 310 311 syncs = engine.getPeriodicSyncs(account1, 0, authority2); 312 assertEquals(2, syncs.size()); 313 assertEquals(sync3, syncs.get(0)); 314 assertEquals(sync4, syncs.get(1)); 315 316 syncs = engine.getPeriodicSyncs(account2, 0, authority1); 317 assertEquals(1, syncs.size()); 318 assertEquals(sync5, syncs.get(0)); 319 320 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)); 324 325 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)); 329 } 330 331 @MediumTest 332 /** 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 457 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()); 473 474 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" 475 + "<accounts>\n" 476 + "<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" 480 + "</accounts>\n").getBytes(); 481 482 File syncDir = getSyncDir(); 483 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 489 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext); 490 491 List<PeriodicSync> syncs = engine.getPeriodicSyncs(account, 0, authority1); 492 assertEquals(1, syncs.size()); 493 assertEquals("expected sync1: " + sync1.toString() + " == sync 2" + syncs.get(0).toString(), sync1, syncs.get(0)); 494 495 syncs = engine.getPeriodicSyncs(account, 0, authority2); 496 assertEquals(1, syncs.size()); 497 assertEquals(sync2, syncs.get(0)); 498 499 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); 504 assertEquals(1, syncs.size()); 505 assertEquals(sync3, syncs.get(0)); 506 507 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" 508 + "<accounts version=\"2\">\n" 509 + "<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 521 syncs = engine.getPeriodicSyncs(account, 0, authority1); 522 assertEquals(0, syncs.size()); 523 524 syncs = engine.getPeriodicSyncs(account, 0, authority2); 525 assertEquals(0, syncs.size()); 526 527 syncs = engine.getPeriodicSyncs(account, 0, authority3); 528 assertEquals(0, syncs.size()); 529 530 accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" 531 + "<accounts version=\"2\">\n" 532 + "<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 550 syncs = engine.getPeriodicSyncs(account, 0, authority1); 551 assertEquals(1, syncs.size()); 552 assertEquals(sync1s, syncs.get(0)); 553 554 syncs = engine.getPeriodicSyncs(account, 0, authority2); 555 assertEquals(1, syncs.size()); 556 assertEquals(sync2s, syncs.get(0)); 557 558 syncs = engine.getPeriodicSyncs(account, 0, authority3); 559 assertEquals(1, syncs.size()); 560 assertEquals(sync3s, syncs.get(0)); 561 } 562 563 @MediumTest 564 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 592 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 628 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)); 633 634 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)); 639 } 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 668 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")); 672 } 673 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 } 728} 729 730class TestContext extends ContextWrapper { 731 732 ContentResolver mResolver; 733 734 private final Context mRealContext; 735 736 public TestContext(ContentResolver resolver, Context realContext) { 737 super(new RenamingDelegatingContext(new MockContext(), realContext, "test.")); 738 mRealContext = realContext; 739 mResolver = resolver; 740 } 741 742 @Override 743 public Resources getResources() { 744 return mRealContext.getResources(); 745 } 746 747 @Override 748 public File getFilesDir() { 749 return mRealContext.getFilesDir(); 750 } 751 752 @Override 753 public void enforceCallingOrSelfPermission(String permission, String message) { 754 } 755 756 @Override 757 public void sendBroadcast(Intent intent) { 758 } 759 760 @Override 761 public ContentResolver getContentResolver() { 762 return mResolver; 763 } 764} 765