SyncStorageEngineTest.java revision 632515b9d0960749ddb1636677d7f12f196d73f7
194b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov/*
29aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * Copyright (C) 2007 The Android Open Source Project
39aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany *
49aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * Licensed under the Apache License, Version 2.0 (the "License");
59aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * you may not use this file except in compliance with the License.
69aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * You may obtain a copy of the License at
79aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany *
89aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany *      http://www.apache.org/licenses/LICENSE-2.0
99aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany *
109aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * Unless required by applicable law or agreed to in writing, software
110a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov * distributed under the License is distributed on an "AS IS" BASIS,
129aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * See the License for the specific language governing permissions and
149aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany * limitations under the License.
159aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany */
16d865fecddccebf898ceed24d096fc58fb29a6e57Chandler Carruth
170a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovpackage com.android.server.content;
189aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany
199aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyimport android.accounts.Account;
209aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryanyimport android.content.ContentResolver;
210a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.content.Context;
220a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.content.ContextWrapper;
230a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.content.Intent;
240a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.content.PeriodicSync;
250a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.content.res.Resources;
260a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.os.Bundle;
27bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukovimport android.test.AndroidTestCase;
280a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.test.RenamingDelegatingContext;
29d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukovimport android.test.mock.MockContentResolver;
300a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.test.mock.MockContext;
310a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.test.suitebuilder.annotation.LargeTest;
320a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport android.test.suitebuilder.annotation.MediumTest;
3315503b0a4331c7f27f9cebc25e25c2e494f61cb9Alexey Samsonovimport android.test.suitebuilder.annotation.SmallTest;
340a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov
350a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovimport com.android.internal.os.AtomicFile;
360a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov
37d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukovimport java.io.File;
38bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukovimport java.io.FileOutputStream;
39d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukovimport java.util.List;
400a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov
410a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovpublic class SyncStorageEngineTest extends AndroidTestCase {
4215503b0a4331c7f27f9cebc25e25c2e494f61cb9Alexey Samsonov
430a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    protected Account account1;
440a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    protected String authority1 = "testprovider";
450a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    protected Bundle defaultBundle;
4697daee89b35f6141db09aee612f0f377f754092fDmitry Vyukov    protected final int DEFAULT_USER = 0;
47d51a1a10cba87be50e9ada9fa21337c387edb237Dmitry Vyukov
48bfa45e11e52081c55294355f36fa547f163dcc67Dmitry Vyukov    MockContentResolver mockResolver;
490a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    SyncStorageEngine engine;
500a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov
510a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    private File getSyncDir() {
520a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov        return new File(new File(getContext().getFilesDir(), "system"), "sync");
530a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    }
542ea978704a794e536d2801affcc7f301092d75daAlexey Samsonov
550a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    @Override
569aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany    public void setUp() {
579aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany        account1 = new Account("a@example.com", "example.type");
58dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        // Default bundle.
59dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        defaultBundle = new Bundle();
60dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        defaultBundle.putInt("int_key", 0);
61dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        defaultBundle.putString("string_key", "hello");
62dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        // Set up storage engine.
63dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        mockResolver = new MockContentResolver();
64dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov        engine = SyncStorageEngine.newTestInstance(
65dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov                new TestContext(mockResolver, getContext()));
66dd3a911e46b3f0416d60d9be5c84ccfc4b1c3aa8Alexey Samsonov    }
670a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov
680a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    /**
690a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov     * Test that we handle the case of a history row being old enough to purge before the
700a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov     * corresponding sync is finished. This can happen if the clock changes while we are syncing.
710a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov     *
720a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov     */
730a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    // TODO: this test causes AidlTest to fail. Omit for now
740a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    // @SmallTest
750a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonov    public void testPurgeActiveSync() throws Exception {
769aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany        final Account account = new Account("a@example.com", "example.type");
7715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        final String authority = "testprovider";
7815a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov
7915a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        MockContentResolver mockResolver = new MockContentResolver();
8015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov
8115a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
8215a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov                new TestContext(mockResolver, getContext()));
8315a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov
8415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        long time0 = 1000;
85230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov        long historyId = engine.insertStartSyncEvent(
86230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov                account, 0, SyncOperation.REASON_PERIODIC, authority, time0,
87230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov                SyncStorageEngine.SOURCE_LOCAL, false /* initialization */, null /* extras */);
88230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov        long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
89230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov        engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
90230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov    }
91230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov
92230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov    /**
93230c3be6cdd094a187f48e27ba0961dbeee70344Alexey Samsonov     * Test persistence of pending operations.
9415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov     */
9515a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov    @MediumTest
9615a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov    public void testPending() throws Exception {
9715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        SyncStorageEngine.PendingOperation pop =
9815a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov                new SyncStorageEngine.PendingOperation(account1, DEFAULT_USER,
9915a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov                        SyncOperation.REASON_PERIODIC, SyncStorageEngine.SOURCE_LOCAL,
10015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov                        authority1, defaultBundle, false);
10115a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov
10215a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        engine.insertIntoPending(pop);
10315a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        // Force engine to read from disk.
10415a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        engine.clearAndReadState();
10515a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov
10615a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        assert(engine.getPendingOperationCount() == 1);
10715a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        List<SyncStorageEngine.PendingOperation> pops = engine.getPendingOperations();
10815a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        SyncStorageEngine.PendingOperation popRetrieved = pops.get(0);
10915a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        assertEquals(pop.account, popRetrieved.account);
11015a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        assertEquals(pop.reason, popRetrieved.reason);
11115a77612e0a89c1df444a2034e531c8968d0cedfAlexey Samsonov        assertEquals(pop.userId, popRetrieved.userId);
112fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        assertEquals(pop.syncSource, popRetrieved.syncSource);
113fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        assertEquals(pop.authority, popRetrieved.authority);
114fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        assertEquals(pop.expedited, popRetrieved.expedited);
115fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        assertEquals(pop.serviceName, popRetrieved.serviceName);
116fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        assert(android.content.PeriodicSync.syncExtrasEquals(pop.extras, popRetrieved.extras));
117fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov
118fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov    }
119fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov
120fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov    /**
121fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov     * Test that we can create, remove and retrieve periodic syncs. Backwards compatibility -
122fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov     * periodic syncs with no flex time are no longer used.
123fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov     */
124fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov    @MediumTest
125fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov    public void testPeriodics() throws Exception {
126fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        final Account account1 = new Account("a@example.com", "example.type");
127fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        final Account account2 = new Account("b@example.com", "example.type.2");
128fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        final String authority = "testprovider";
129fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov        final Bundle extras1 = new Bundle();
13045418d1ccb083cad3cb84e0b8184adfb85876fc5Alexey Samsonov        extras1.putString("a", "1");
13145418d1ccb083cad3cb84e0b8184adfb85876fc5Alexey Samsonov        final Bundle extras2 = new Bundle();
13245418d1ccb083cad3cb84e0b8184adfb85876fc5Alexey Samsonov        extras2.putString("a", "2");
1335759d92e99e2b7adcc46a8729f16023208dd8f37Kostya Serebryany        final int period1 = 200;
13445418d1ccb083cad3cb84e0b8184adfb85876fc5Alexey Samsonov        final int period2 = 1000;
13545418d1ccb083cad3cb84e0b8184adfb85876fc5Alexey Samsonov
1368c53e54ef9e713953ec9495e82e5c330b96e49f3Alexey Samsonov        PeriodicSync sync1 = new PeriodicSync(account1, authority, extras1, period1);
137c375657778e8a72d566e29951060b7eadc749b0dKostya Serebryany        PeriodicSync sync2 = new PeriodicSync(account1, authority, extras2, period1);
138c375657778e8a72d566e29951060b7eadc749b0dKostya Serebryany        PeriodicSync sync3 = new PeriodicSync(account1, authority, extras2, period2);
1394c2ddda9ac80f94782b2b040208831233db578afKostya Serebryany        PeriodicSync sync4 = new PeriodicSync(account2, authority, extras2, period2);
1404c2ddda9ac80f94782b2b040208831233db578afKostya Serebryany
141c375657778e8a72d566e29951060b7eadc749b0dKostya Serebryany
142c375657778e8a72d566e29951060b7eadc749b0dKostya Serebryany
143d7ed1f09f316628b2d981a1d8c2cf0f5af30e90eAlexey Samsonov        removePeriodicSyncs(engine, account1, 0, authority);
144c375657778e8a72d566e29951060b7eadc749b0dKostya Serebryany        removePeriodicSyncs(engine, account2, 0, authority);
145c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        removePeriodicSyncs(engine, account1, 1, authority);
146c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
147b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov        // this should add two distinct periodic syncs for account1 and one for account2
148b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov        engine.addPeriodicSync(sync1, 0);
149c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        engine.addPeriodicSync(sync2, 0);
150c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        engine.addPeriodicSync(sync3, 0);
151c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        engine.addPeriodicSync(sync4, 0);
152c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        // add a second user
153c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        engine.addPeriodicSync(sync2, 1);
154c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
155c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        List<PeriodicSync> syncs = engine.getPeriodicSyncs(account1, 0, authority);
156c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
157c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        assertEquals(2, syncs.size());
158c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
159c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        assertEquals(sync1, syncs.get(0));
160c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        assertEquals(sync3, syncs.get(1));
161c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
162c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        engine.removePeriodicSync(sync1, 0);
163c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
164c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        syncs = engine.getPeriodicSyncs(account1, 0, authority);
165c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        assertEquals(1, syncs.size());
166c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        assertEquals(sync3, syncs.get(0));
167c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov
168c925697df6626bb0ea27ea96539bf0580f8f3d3dAlexey Samsonov        syncs = engine.getPeriodicSyncs(account2, 0, authority);
16970e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov        assertEquals(1, syncs.size());
17070e177e29c6f9ac987b65a79f6b4f3ebdabc75ccAlexey Samsonov        assertEquals(sync4, syncs.get(0));
171b46941a1d23012491a7a8a52718cacbde3c19ba1Alexey Samsonov
1721b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany        syncs = engine.getPeriodicSyncs(sync2.account, 1, sync2.authority);
1731b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany        assertEquals(1, syncs.size());
1741b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany        assertEquals(sync2, syncs.get(0));
17580acccf4647c3482c3e3e6ae21e757ba580a5956Kostya Serebryany    }
17680acccf4647c3482c3e3e6ae21e757ba580a5956Kostya Serebryany
1771b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany    /**
1781b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany     * Test that we can create, remove and retrieve periodic syncs with a provided flex time.
1791b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany     */
1801b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany    @MediumTest
1811b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany    public void testPeriodicsV2() throws Exception {
1821b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany        final Account account1 = new Account("a@example.com", "example.type");
1831b5ea8fbbef73f5d9b41dbb26a21b9a0f4d1445eKostya Serebryany        final Account account2 = new Account("b@example.com", "example.type.2");
1843334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        final String authority = "testprovider";
1853334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        final Bundle extras1 = new Bundle();
1863334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        extras1.putString("a", "1");
1873334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        final Bundle extras2 = new Bundle();
1883334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        extras2.putString("a", "2");
1893334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov        final int period1 = 200;
1909aead37421a6e4bf43265e5195c6ac31fc519982Kostya Serebryany        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