blob: 85de1f1c3e8692a7ed8378841b05d960b147370a [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;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070020import android.content.ComponentName;
Amith Yamasani8ff9a152012-12-11 10:42:09 -080021import android.content.ContentResolver;
22import android.content.Context;
23import android.content.ContextWrapper;
24import android.content.Intent;
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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039
Makoto Onuki15e7a252017-06-08 17:12:05 -070040/**
41 * Test for SyncStorageEngine.
42 *
43 * bit FrameworksServicesTests:com.android.server.content.SyncStorageEngineTest
44 *
45 * TODO Broken. Fix it. b/62485315
46 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047public class SyncStorageEngineTest extends AndroidTestCase {
48
Matthew Williamsfa774182013-06-18 15:44:11 -070049 protected Account account1;
Matthew Williams06485a72013-07-26 12:56:39 -070050 protected Account account2;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070051 protected ComponentName syncService1;
Matthew Williamsfa774182013-06-18 15:44:11 -070052 protected String authority1 = "testprovider";
53 protected Bundle defaultBundle;
54 protected final int DEFAULT_USER = 0;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070055
56 /* Some default poll frequencies. */
57 final long dayPoll = (60 * 60 * 24);
58 final long dayFuzz = 60;
59 final long thousandSecs = 1000;
60 final long thousandSecsFuzz = 100;
61
Matthew Williamsfa774182013-06-18 15:44:11 -070062 MockContentResolver mockResolver;
63 SyncStorageEngine engine;
Matthew Williams56dbf8f2013-07-26 12:56:39 -070064
Amith Yamasani04e0d262012-02-14 11:50:53 -080065 private File getSyncDir() {
66 return new File(new File(getContext().getFilesDir(), "system"), "sync");
67 }
68
Matthew Williamsfa774182013-06-18 15:44:11 -070069 @Override
70 public void setUp() {
71 account1 = new Account("a@example.com", "example.type");
Matthew Williams06485a72013-07-26 12:56:39 -070072 account2 = new Account("b@example.com", "example.type");
Matthew Williams56dbf8f2013-07-26 12:56:39 -070073 syncService1 = new ComponentName("com.example", "SyncService");
Matthew Williamsfa774182013-06-18 15:44:11 -070074 // Default bundle.
75 defaultBundle = new Bundle();
76 defaultBundle.putInt("int_key", 0);
77 defaultBundle.putString("string_key", "hello");
78 // Set up storage engine.
79 mockResolver = new MockContentResolver();
80 engine = SyncStorageEngine.newTestInstance(
81 new TestContext(mockResolver, getContext()));
82 }
83
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 /**
85 * Test that we handle the case of a history row being old enough to purge before the
Matthew Williamsba352712013-08-13 15:53:31 -070086 * corresponding sync is finished. This can happen if the clock changes while we are syncing.
Fred Quintanac5d1c6d2010-01-27 12:17:49 -080087 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 */
Brett Chabot2ad24f92010-10-04 19:55:14 -070089 // TODO: this test causes AidlTest to fail. Omit for now
90 // @SmallTest
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 public void testPurgeActiveSync() throws Exception {
Fred Quintanad9d2f112009-04-23 13:36:27 -070092 final Account account = new Account("a@example.com", "example.type");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 final String authority = "testprovider";
94
95 MockContentResolver mockResolver = new MockContentResolver();
96
97 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(
98 new TestContext(mockResolver, getContext()));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 long time0 = 1000;
Dianne Hackbornbef28fe2015-10-29 17:57:11 -0700100 SyncOperation op = new SyncOperation(account, 0, 0, "foo",
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700101 SyncOperation.REASON_PERIODIC,
102 SyncStorageEngine.SOURCE_LOCAL,
103 authority,
Shreyas Basarge8c834c02016-01-07 13:53:16 +0000104 Bundle.EMPTY, true);
Matthew Williams56dbf8f2013-07-26 12:56:39 -0700105 long historyId = engine.insertStartSyncEvent(op, time0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 long time1 = time0 + SyncStorageEngine.MILLIS_IN_4WEEKS * 2;
Fred Quintana77c560f2010-03-29 22:20:26 -0700107 engine.stopSyncEvent(historyId, time1 - time0, "yay", 0, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800108 }
109
Brett Chabotf76c56b2010-07-26 17:28:17 -0700110 @LargeTest
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800111 public void testAuthorityPersistence() throws Exception {
112 final Account account1 = new Account("a@example.com", "example.type");
113 final Account account2 = new Account("b@example.com", "example.type.2");
114 final String authority1 = "testprovider1";
115 final String authority2 = "testprovider2";
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800116
Amith Yamasani04e0d262012-02-14 11:50:53 -0800117 engine.setMasterSyncAutomatically(false, 0);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800118
Amith Yamasani04e0d262012-02-14 11:50:53 -0800119 engine.setIsSyncable(account1, 0, authority1, 1);
120 engine.setSyncAutomatically(account1, 0, authority1, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800121
Amith Yamasani04e0d262012-02-14 11:50:53 -0800122 engine.setIsSyncable(account2, 0, authority1, 1);
123 engine.setSyncAutomatically(account2, 0, authority1, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800124
Amith Yamasani04e0d262012-02-14 11:50:53 -0800125 engine.setIsSyncable(account1, 0, authority2, 1);
126 engine.setSyncAutomatically(account1, 0, authority2, false);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800127
Amith Yamasani04e0d262012-02-14 11:50:53 -0800128 engine.setIsSyncable(account2, 0, authority2, 0);
129 engine.setSyncAutomatically(account2, 0, authority2, true);
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800130
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800131 engine.writeAllState();
132 engine.clearAndReadState();
133
Amith Yamasani04e0d262012-02-14 11:50:53 -0800134 assertEquals(true, engine.getSyncAutomatically(account1, 0, authority1));
135 assertEquals(true, engine.getSyncAutomatically(account2, 0, authority1));
136 assertEquals(false, engine.getSyncAutomatically(account1, 0, authority2));
137 assertEquals(true, engine.getSyncAutomatically(account2, 0, authority2));
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800138
Amith Yamasani04e0d262012-02-14 11:50:53 -0800139 assertEquals(1, engine.getIsSyncable(account1, 0, authority1));
140 assertEquals(1, engine.getIsSyncable(account2, 0, authority1));
141 assertEquals(1, engine.getIsSyncable(account1, 0, authority2));
142 assertEquals(0, engine.getIsSyncable(account2, 0, authority2));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 }
Fred Quintanac2e46912010-03-15 16:10:44 -0700144
Brett Chabotf76c56b2010-07-26 17:28:17 -0700145 @MediumTest
Amith Yamasani04e0d262012-02-14 11:50:53 -0800146 public void testListenForTicklesParsing() throws Exception {
147 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
148 + "<accounts>\n"
149 + "<listenForTickles user=\"0\" enabled=\"false\" />"
150 + "<listenForTickles user=\"1\" enabled=\"true\" />"
151 + "<authority id=\"0\" user=\"0\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
152 + "<authority id=\"1\" user=\"1\" account=\"account1\" type=\"type1\" authority=\"auth1\" />\n"
153 + "</accounts>\n").getBytes();
154
155 MockContentResolver mockResolver = new MockContentResolver();
156 final TestContext testContext = new TestContext(mockResolver, getContext());
157
158 File syncDir = getSyncDir();
159 syncDir.mkdirs();
160 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
161 FileOutputStream fos = accountInfoFile.startWrite();
162 fos.write(accountsFileData);
163 accountInfoFile.finishWrite(fos);
164
165 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
166
167 assertEquals(false, engine.getMasterSyncAutomatically(0));
168 assertEquals(true, engine.getMasterSyncAutomatically(1));
169 assertEquals(true, engine.getMasterSyncAutomatically(2));
170
171 }
172
173 @MediumTest
Fred Quintanafb084402010-03-23 17:57:03 -0700174 public void testAuthorityRenaming() throws Exception {
175 final Account account1 = new Account("acc1", "type1");
176 final Account account2 = new Account("acc2", "type2");
177 final String authorityContacts = "contacts";
178 final String authorityCalendar = "calendar";
179 final String authorityOther = "other";
180 final String authorityContactsNew = "com.android.contacts";
181 final String authorityCalendarNew = "com.android.calendar";
182
183 MockContentResolver mockResolver = new MockContentResolver();
184
185 final TestContext testContext = new TestContext(mockResolver, getContext());
186
187 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
188 + "<accounts>\n"
189 + "<authority id=\"0\" account=\"acc1\" type=\"type1\" authority=\"contacts\" />\n"
190 + "<authority id=\"1\" account=\"acc1\" type=\"type1\" authority=\"calendar\" />\n"
191 + "<authority id=\"2\" account=\"acc1\" type=\"type1\" authority=\"other\" />\n"
192 + "<authority id=\"3\" account=\"acc2\" type=\"type2\" authority=\"contacts\" />\n"
193 + "<authority id=\"4\" account=\"acc2\" type=\"type2\" authority=\"calendar\" />\n"
194 + "<authority id=\"5\" account=\"acc2\" type=\"type2\" authority=\"other\" />\n"
195 + "<authority id=\"6\" account=\"acc2\" type=\"type2\" enabled=\"false\""
196 + " authority=\"com.android.calendar\" />\n"
197 + "<authority id=\"7\" account=\"acc2\" type=\"type2\" enabled=\"false\""
198 + " authority=\"com.android.contacts\" />\n"
199 + "</accounts>\n").getBytes();
200
201 File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync");
202 syncDir.mkdirs();
203 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
204 FileOutputStream fos = accountInfoFile.startWrite();
205 fos.write(accountsFileData);
206 accountInfoFile.finishWrite(fos);
207
208 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
209
Amith Yamasani04e0d262012-02-14 11:50:53 -0800210 assertEquals(false, engine.getSyncAutomatically(account1, 0, authorityContacts));
211 assertEquals(false, engine.getSyncAutomatically(account1, 0, authorityCalendar));
212 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityOther));
213 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityContactsNew));
214 assertEquals(true, engine.getSyncAutomatically(account1, 0, authorityCalendarNew));
Fred Quintanafb084402010-03-23 17:57:03 -0700215
Amith Yamasani04e0d262012-02-14 11:50:53 -0800216 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityContacts));
217 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityCalendar));
218 assertEquals(true, engine.getSyncAutomatically(account2, 0, authorityOther));
219 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityContactsNew));
220 assertEquals(false, engine.getSyncAutomatically(account2, 0, authorityCalendarNew));
Fred Quintanafb084402010-03-23 17:57:03 -0700221 }
222
223 @SmallTest
224 public void testSyncableMigration() throws Exception {
225 final Account account = new Account("acc", "type");
226
227 MockContentResolver mockResolver = new MockContentResolver();
228
229 final TestContext testContext = new TestContext(mockResolver, getContext());
230
231 byte[] accountsFileData = ("<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
232 + "<accounts>\n"
233 + "<authority id=\"0\" account=\"acc\" authority=\"other1\" />\n"
234 + "<authority id=\"1\" account=\"acc\" type=\"type\" authority=\"other2\" />\n"
235 + "<authority id=\"2\" account=\"acc\" type=\"type\" syncable=\"false\""
236 + " authority=\"other3\" />\n"
237 + "<authority id=\"3\" account=\"acc\" type=\"type\" syncable=\"true\""
238 + " authority=\"other4\" />\n"
239 + "</accounts>\n").getBytes();
240
241 File syncDir = new File(new File(testContext.getFilesDir(), "system"), "sync");
242 syncDir.mkdirs();
243 AtomicFile accountInfoFile = new AtomicFile(new File(syncDir, "accounts.xml"));
244 FileOutputStream fos = accountInfoFile.startWrite();
245 fos.write(accountsFileData);
246 accountInfoFile.finishWrite(fos);
247
248 SyncStorageEngine engine = SyncStorageEngine.newTestInstance(testContext);
249
Amith Yamasani04e0d262012-02-14 11:50:53 -0800250 assertEquals(-1, engine.getIsSyncable(account, 0, "other1"));
251 assertEquals(1, engine.getIsSyncable(account, 0, "other2"));
252 assertEquals(0, engine.getIsSyncable(account, 0, "other3"));
253 assertEquals(1, engine.getIsSyncable(account, 0, "other4"));
Fred Quintanafb084402010-03-23 17:57:03 -0700254 }
Matthew Williams632515b2013-10-10 15:51:00 -0700255
256 /**
257 * Verify that the API cannot cause a run-time reboot by passing in the empty string as an
258 * authority. The problem here is that
259 * {@link SyncStorageEngine#getOrCreateAuthorityLocked(account, provider)} would register
260 * an empty authority which causes a RTE in {@link SyncManager#scheduleReadyPeriodicSyncs()}.
261 * This is not strictly a SSE test, but it does depend on the SSE data structures.
262 */
263 @SmallTest
264 public void testExpectedIllegalArguments() throws Exception {
265 try {
266 ContentResolver.setSyncAutomatically(account1, "", true);
267 fail("empty provider string should throw IllegalArgumentException");
268 } catch (IllegalArgumentException expected) {}
269
270 try {
271 ContentResolver.addPeriodicSync(account1, "", Bundle.EMPTY, 84000L);
272 fail("empty provider string should throw IllegalArgumentException");
273 } catch (IllegalArgumentException expected) {}
274
275 try {
276 ContentResolver.removePeriodicSync(account1, "", Bundle.EMPTY);
277 fail("empty provider string should throw IllegalArgumentException");
278 } catch (IllegalArgumentException expected) {}
279
280 try {
281 ContentResolver.cancelSync(account1, "");
282 fail("empty provider string should throw IllegalArgumentException");
283 } catch (IllegalArgumentException expected) {}
284
285 try {
286 ContentResolver.setIsSyncable(account1, "", 0);
287 fail("empty provider string should throw IllegalArgumentException");
288 } catch (IllegalArgumentException expected) {}
289
290 try {
291 ContentResolver.cancelSync(account1, "");
292 fail("empty provider string should throw IllegalArgumentException");
293 } catch (IllegalArgumentException expected) {}
294
295 try {
296 ContentResolver.requestSync(account1, "", Bundle.EMPTY);
297 fail("empty provider string should throw IllegalArgumentException");
298 } catch (IllegalArgumentException expected) {}
299
300 try {
301 ContentResolver.getSyncStatus(account1, "");
302 fail("empty provider string should throw IllegalArgumentException");
303 } catch (IllegalArgumentException expected) {}
304
305 // Make sure we aren't blocking null account/provider for those functions that use it
306 // to specify ALL accounts/providers.
307 ContentResolver.requestSync(null, null, Bundle.EMPTY);
308 ContentResolver.cancelSync(null, null);
309 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800310}
311
312class TestContext extends ContextWrapper {
313
314 ContentResolver mResolver;
315
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800316 private final Context mRealContext;
317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 public TestContext(ContentResolver resolver, Context realContext) {
319 super(new RenamingDelegatingContext(new MockContext(), realContext, "test."));
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800320 mRealContext = realContext;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 mResolver = resolver;
322 }
323
324 @Override
Matthew Williamsfa774182013-06-18 15:44:11 -0700325 public Resources getResources() {
326 return mRealContext.getResources();
327 }
328
329 @Override
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800330 public File getFilesDir() {
331 return mRealContext.getFilesDir();
332 }
333
334 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 public void enforceCallingOrSelfPermission(String permission, String message) {
336 }
337
Fred Quintanac5d1c6d2010-01-27 12:17:49 -0800338 @Override
339 public void sendBroadcast(Intent intent) {
340 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341
342 @Override
343 public ContentResolver getContentResolver() {
344 return mResolver;
345 }
346}