Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: sync/android/javatests/src/org/chromium/sync/notifier/InvalidationServiceTest.java

Issue 459513002: Massive refactor of the Android invalidation code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments. Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.sync.notifier;
6
7 import android.accounts.Account;
8 import android.content.ComponentName;
9 import android.content.Intent;
10 import android.os.Bundle;
11 import android.test.ServiceTestCase;
12 import android.test.suitebuilder.annotation.SmallTest;
13
14 import com.google.ipc.invalidation.external.client.InvalidationListener.Registra tionState;
15 import com.google.ipc.invalidation.external.client.contrib.AndroidListener;
16 import com.google.ipc.invalidation.external.client.types.ErrorInfo;
17 import com.google.ipc.invalidation.external.client.types.Invalidation;
18 import com.google.ipc.invalidation.external.client.types.ObjectId;
19
20 import org.chromium.base.CollectionUtil;
21 import org.chromium.base.test.util.AdvancedMockContext;
22 import org.chromium.base.test.util.Feature;
23 import org.chromium.sync.internal_api.pub.base.ModelType;
24 import org.chromium.sync.notifier.InvalidationPreferences.EditContext;
25 import org.chromium.sync.signin.AccountManagerHelper;
26
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.EnumSet;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 /**
35 * Tests for the {@link InvalidationService}.
36 *
37 * @author dsmyers@google.com (Daniel Myers)
38 */
39 public class InvalidationServiceTest extends ServiceTestCase<TestableInvalidatio nService> {
40 /** Id used when creating clients. */
41 private static final byte[] CLIENT_ID = new byte[]{0, 4, 7};
42
43 /** Intents provided to {@link #startService}. */
44 private List<Intent> mStartServiceIntents;
45
46 public InvalidationServiceTest() {
47 super(TestableInvalidationService.class);
48 }
49
50 @Override
51 public void setUp() throws Exception {
52 super.setUp();
53 mStartServiceIntents = new ArrayList<Intent>();
54 setContext(new AdvancedMockContext(getContext()) {
55 @Override
56 public ComponentName startService(Intent intent) {
57 mStartServiceIntents.add(intent);
58 return new ComponentName(this, InvalidationServiceTest.class);
59 }
60 });
61 setupService();
62 }
63
64 @Override
65 public void tearDown() throws Exception {
66 if (InvalidationService.getIsClientStartedForTest()) {
67 Intent stopIntent = createStopIntent();
68 getService().onHandleIntent(stopIntent);
69 }
70 assertFalse(InvalidationService.getIsClientStartedForTest());
71 super.tearDown();
72 }
73
74 @SmallTest
75 @Feature({"Sync"})
76 public void testComputeRegistrationOps() {
77 /*
78 * Test plan: compute the set of registration operations resulting from various combinations
79 * of existing and desired registrations. Verifying that they are correc t.
80 */
81 Set<ObjectId> regAccumulator = new HashSet<ObjectId>();
82 Set<ObjectId> unregAccumulator = new HashSet<ObjectId>();
83
84 // Empty existing and desired registrations should yield empty operation sets.
85 InvalidationService.computeRegistrationOps(
86 ModelType.modelTypesToObjectIds(
87 CollectionUtil.newHashSet(ModelType.BOOKMARK, ModelType. SESSION)),
88 ModelType.modelTypesToObjectIds(
89 CollectionUtil.newHashSet(ModelType.BOOKMARK, ModelType. SESSION)),
90 regAccumulator, unregAccumulator);
91 assertEquals(0, regAccumulator.size());
92 assertEquals(0, unregAccumulator.size());
93
94 // Equal existing and desired registrations should yield empty operation sets.
95 InvalidationService.computeRegistrationOps(new HashSet<ObjectId>(),
96 new HashSet<ObjectId>(), regAccumulator, unregAccumulator);
97 assertEquals(0, regAccumulator.size());
98 assertEquals(0, unregAccumulator.size());
99
100 // Empty existing and non-empty desired registrations should yield desir ed registrations
101 // as the registration operations to do and no unregistrations.
102 Set<ObjectId> desiredTypes =
103 CollectionUtil.newHashSet(
104 ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObj ectId());
105 InvalidationService.computeRegistrationOps(
106 new HashSet<ObjectId>(),
107 desiredTypes,
108 regAccumulator, unregAccumulator);
109 assertEquals(
110 CollectionUtil.newHashSet(
111 ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObj ectId()),
112 new HashSet<ObjectId>(regAccumulator));
113 assertEquals(0, unregAccumulator.size());
114 regAccumulator.clear();
115
116 // Unequal existing and desired registrations should yield both registra tions and
117 // unregistrations. We should unregister TYPED_URL and register BOOKMARK , keeping SESSION.
118 InvalidationService.computeRegistrationOps(
119 CollectionUtil.newHashSet(
120 ModelType.SESSION.toObjectId(), ModelType.TYPED_URL.toOb jectId()),
121 CollectionUtil.newHashSet(
122 ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObj ectId()),
123 regAccumulator, unregAccumulator);
124 assertEquals(CollectionUtil.newHashSet(ModelType.BOOKMARK.toObjectId()), regAccumulator);
125 assertEquals(CollectionUtil.newHashSet(ModelType.TYPED_URL.toObjectId()) ,
126 unregAccumulator);
127 regAccumulator.clear();
128 unregAccumulator.clear();
129 }
130
131 @SmallTest
132 @Feature({"Sync"})
133 public void testReady() {
134 /**
135 * Test plan: call ready. Verify that the service sets the client id corr ectly and reissues
136 * pending registrations.
137 */
138
139 // Persist some registrations.
140 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
141 EditContext editContext = invPrefs.edit();
142 invPrefs.setSyncTypes(editContext, CollectionUtil.newArrayList("BOOKMARK ", "SESSION"));
143 ObjectId objectId = ObjectId.newInstance(1, "obj".getBytes());
144 invPrefs.setObjectIds(editContext, CollectionUtil.newArrayList(objectId) );
145 assertTrue(invPrefs.commit(editContext));
146
147 // Issue ready.
148 getService().ready(CLIENT_ID);
149 assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTe st()));
150 byte[] otherCid = "otherCid".getBytes();
151 getService().ready(otherCid);
152 assertTrue(Arrays.equals(otherCid, InvalidationService.getClientIdForTes t()));
153
154 // Verify registrations issued.
155 assertEquals(CollectionUtil.newHashSet(
156 ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObjectId(), objectId),
157 new HashSet<ObjectId>(getService().mRegistrations.get(0)));
158 }
159
160 @SmallTest
161 @Feature({"Sync"})
162 public void testReissueRegistrations() {
163 /*
164 * Test plan: call the reissueRegistrations method of the listener with both empty and
165 * non-empty sets of desired registrations stored in preferences. Verify that no register
166 * intent is set in the first case and that the appropriate register int ent is sent in
167 * the second.
168 */
169
170 // No persisted registrations.
171 getService().reissueRegistrations(CLIENT_ID);
172 assertTrue(getService().mRegistrations.isEmpty());
173
174 // Persist some registrations.
175 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
176 EditContext editContext = invPrefs.edit();
177 invPrefs.setSyncTypes(editContext, CollectionUtil.newArrayList("BOOKMARK ", "SESSION"));
178 ObjectId objectId = ObjectId.newInstance(1, "obj".getBytes());
179 invPrefs.setObjectIds(editContext, CollectionUtil.newArrayList(objectId) );
180 assertTrue(invPrefs.commit(editContext));
181
182 // Reissue registrations and verify that the appropriate registrations a re issued.
183 getService().reissueRegistrations(CLIENT_ID);
184 assertEquals(1, getService().mRegistrations.size());
185 assertEquals(CollectionUtil.newHashSet(
186 ModelType.BOOKMARK.toObjectId(), ModelType.SESSION.toObjectId(), objectId),
187 new HashSet<ObjectId>(getService().mRegistrations.get(0)));
188 }
189
190 @SmallTest
191 @Feature({"Sync"})
192 public void testInformRegistrationStatus() {
193 /*
194 * Test plan: call inform registration status under a variety of circums tances and verify
195 * that the appropriate (un)register calls are issued.
196 *
197 * 1. Registration of desired object. No calls issued.
198 * 2. Unregistration of undesired object. No calls issued.
199 * 3. Registration of undesired object. Unregistration issued.
200 * 4. Unregistration of desired object. Registration issued.
201 */
202 // Initial test setup: persist a single registration into preferences.
203 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
204 EditContext editContext = invPrefs.edit();
205 invPrefs.setSyncTypes(editContext, CollectionUtil.newArrayList("SESSION" ));
206 ObjectId desiredObjectId = ObjectId.newInstance(1, "obj1".getBytes());
207 ObjectId undesiredObjectId = ObjectId.newInstance(1, "obj2".getBytes());
208 invPrefs.setObjectIds(editContext, CollectionUtil.newArrayList(desiredOb jectId));
209 assertTrue(invPrefs.commit(editContext));
210
211 // Cases 1 and 2: calls matching desired state cause no actions.
212 getService().informRegistrationStatus(CLIENT_ID, ModelType.SESSION.toObj ectId(),
213 RegistrationState.REGISTERED);
214 getService().informRegistrationStatus(CLIENT_ID, desiredObjectId,
215 RegistrationState.REGISTERED);
216 getService().informRegistrationStatus(CLIENT_ID, ModelType.BOOKMARK.toOb jectId(),
217 RegistrationState.UNREGISTERED);
218 getService().informRegistrationStatus(CLIENT_ID, undesiredObjectId,
219 RegistrationState.UNREGISTERED);
220 assertTrue(getService().mRegistrations.isEmpty());
221 assertTrue(getService().mUnregistrations.isEmpty());
222
223 // Case 3: registration of undesired object triggers an unregistration.
224 getService().informRegistrationStatus(CLIENT_ID, ModelType.BOOKMARK.toOb jectId(),
225 RegistrationState.REGISTERED);
226 getService().informRegistrationStatus(CLIENT_ID, undesiredObjectId,
227 RegistrationState.REGISTERED);
228 assertEquals(2, getService().mUnregistrations.size());
229 assertEquals(0, getService().mRegistrations.size());
230 assertEquals(CollectionUtil.newArrayList(ModelType.BOOKMARK.toObjectId() ),
231 getService().mUnregistrations.get(0));
232 assertEquals(CollectionUtil.newArrayList(undesiredObjectId),
233 getService().mUnregistrations.get(1));
234
235 // Case 4: unregistration of a desired object triggers a registration.
236 getService().informRegistrationStatus(CLIENT_ID, ModelType.SESSION.toObj ectId(),
237 RegistrationState.UNREGISTERED);
238 getService().informRegistrationStatus(CLIENT_ID, desiredObjectId,
239 RegistrationState.UNREGISTERED);
240 assertEquals(2, getService().mUnregistrations.size());
241 assertEquals(2, getService().mRegistrations.size());
242 assertEquals(CollectionUtil.newArrayList(ModelType.SESSION.toObjectId()) ,
243 getService().mRegistrations.get(0));
244 assertEquals(CollectionUtil.newArrayList(desiredObjectId),
245 getService().mRegistrations.get(1));
246 }
247
248 @SmallTest
249 @Feature({"Sync"})
250 public void testInformRegistrationFailure() {
251 /*
252 * Test plan: call inform registration failure under a variety of circum stances and verify
253 * that the appropriate (un)register calls are issued.
254 *
255 * 1. Transient registration failure for an object that should be regist ered. Register
256 * should be called.
257 * 2. Permanent registration failure for an object that should be regist ered. No calls.
258 * 3. Transient registration failure for an object that should not be re gistered. Unregister
259 * should be called.
260 * 4. Permanent registration failure for an object should not be registe red. No calls.
261 */
262
263 // Initial test setup: persist a single registration into preferences.
264 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
265 EditContext editContext = invPrefs.edit();
266 invPrefs.setSyncTypes(editContext, CollectionUtil.newArrayList("SESSION" ));
267 ObjectId desiredObjectId = ObjectId.newInstance(1, "obj1".getBytes());
268 ObjectId undesiredObjectId = ObjectId.newInstance(1, "obj2".getBytes());
269 invPrefs.setObjectIds(editContext, CollectionUtil.newArrayList(desiredOb jectId));
270 assertTrue(invPrefs.commit(editContext));
271
272 // Cases 2 and 4: permanent registration failures never cause calls to b e made.
273 getService().informRegistrationFailure(CLIENT_ID, ModelType.SESSION.toOb jectId(), false,
274 "");
275 getService().informRegistrationFailure(CLIENT_ID, ModelType.BOOKMARK.toO bjectId(), false,
276 "");
277 getService().informRegistrationFailure(CLIENT_ID, desiredObjectId, false , "");
278 getService().informRegistrationFailure(CLIENT_ID, undesiredObjectId, fal se, "");
279 assertTrue(getService().mRegistrations.isEmpty());
280 assertTrue(getService().mUnregistrations.isEmpty());
281
282 // Case 1: transient failure of a desired registration results in re-reg istration.
283 getService().informRegistrationFailure(CLIENT_ID, ModelType.SESSION.toOb jectId(), true, "");
284 getService().informRegistrationFailure(CLIENT_ID, desiredObjectId, true, "");
285 assertEquals(2, getService().mRegistrations.size());
286 assertTrue(getService().mUnregistrations.isEmpty());
287 assertEquals(CollectionUtil.newArrayList(ModelType.SESSION.toObjectId()) ,
288 getService().mRegistrations.get(0));
289 assertEquals(CollectionUtil.newArrayList(desiredObjectId),
290 getService().mRegistrations.get(1));
291
292 // Case 3: transient failure of an undesired registration results in unr egistration.
293 getService().informRegistrationFailure(CLIENT_ID, ModelType.BOOKMARK.toO bjectId(), true,
294 "");
295 getService().informRegistrationFailure(CLIENT_ID, undesiredObjectId, tru e, "");
296 assertEquals(2, getService().mRegistrations.size());
297 assertEquals(2, getService().mUnregistrations.size());
298 assertEquals(CollectionUtil.newArrayList(ModelType.BOOKMARK.toObjectId() ),
299 getService().mUnregistrations.get(0));
300 assertEquals(CollectionUtil.newArrayList(undesiredObjectId),
301 getService().mUnregistrations.get(1));
302 }
303
304 @SmallTest
305 @Feature({"Sync"})
306 public void testInformError() {
307 /*
308 * Test plan: call informError with both permanent and transient errors. Verify that
309 * the transient error causes no action to be taken and that the permane nt error causes
310 * the client to be stopped.
311 */
312
313 // Client needs to be started for the permament error to trigger and sto p.
314 getService().setShouldRunStates(true, true);
315 getService().onCreate();
316 getService().onHandleIntent(createStartIntent());
317 getService().mStartedServices.clear(); // Discard start intent.
318
319 // Transient error.
320 getService().informError(ErrorInfo.newInstance(0, true, "transient", nul l));
321 assertTrue(getService().mStartedServices.isEmpty());
322
323 // Permanent error.
324 getService().informError(ErrorInfo.newInstance(0, false, "permanent", nu ll));
325 assertEquals(1, getService().mStartedServices.size());
326 Intent sentIntent = getService().mStartedServices.get(0);
327 Intent stopIntent = AndroidListener.createStopIntent(getContext());
328 assertTrue(stopIntent.filterEquals(sentIntent));
329 assertEquals(stopIntent.getExtras().keySet(), sentIntent.getExtras().key Set());
330 }
331
332 @SmallTest
333 @Feature({"Sync"})
334 public void testReadWriteState() {
335 /*
336 * Test plan: read, write, and read the internal notification client per sistent state.
337 * Verify appropriate return values.
338 */
339 assertNull(getService().readState());
340 byte[] writtenState = new byte[]{7, 4, 0};
341 getService().writeState(writtenState);
342 assertTrue(Arrays.equals(writtenState, getService().readState()));
343 }
344
345 @SmallTest
346 @Feature({"Sync"})
347 public void testInvalidateWithPayload() {
348 doTestInvalidate(true);
349 }
350
351 @SmallTest
352 @Feature({"Sync"})
353 public void testInvalidateWithoutPayload() {
354 doTestInvalidate(false);
355 }
356
357 private void doTestInvalidate(boolean hasPayload) {
358 /*
359 * Test plan: call invalidate() with an invalidation that may or may not have a payload.
360 * Verify the produced bundle has the correct fields.
361 */
362 // Call invalidate.
363 int version = 4747;
364 ObjectId objectId = ObjectId.newInstance(55, "BOOKMARK".getBytes());
365 final String payload = "testInvalidate-" + hasPayload;
366 Invalidation invalidation = hasPayload ?
367 Invalidation.newInstance(objectId, version, payload.getBytes()) :
368 Invalidation.newInstance(objectId, version);
369 byte[] ackHandle = ("testInvalidate-" + hasPayload).getBytes();
370 getService().invalidate(invalidation, ackHandle);
371
372 // Validate bundle.
373 assertEquals(1, getService().mRequestedSyncs.size());
374 Bundle syncBundle = getService().mRequestedSyncs.get(0);
375 assertEquals(55, syncBundle.getInt("objectSource"));
376 assertEquals("BOOKMARK", syncBundle.getString("objectId"));
377 assertEquals(version, syncBundle.getLong("version"));
378 assertEquals(hasPayload ? payload : "", syncBundle.getString("payload")) ;
379
380 // Ensure acknowledged.
381 assertSingleAcknowledgement(ackHandle);
382 }
383
384 @SmallTest
385 @Feature({"Sync"})
386 public void testInvalidateUnknownVersion() {
387 /*
388 * Test plan: call invalidateUnknownVersion(). Verify the produced bundl e has the correct
389 * fields.
390 */
391 ObjectId objectId = ObjectId.newInstance(55, "BOOKMARK".getBytes());
392 byte[] ackHandle = "testInvalidateUV".getBytes();
393 getService().invalidateUnknownVersion(objectId, ackHandle);
394
395 // Validate bundle.
396 assertEquals(1, getService().mRequestedSyncs.size());
397 Bundle syncBundle = getService().mRequestedSyncs.get(0);
398 assertEquals(55, syncBundle.getInt("objectSource"));
399 assertEquals("BOOKMARK", syncBundle.getString("objectId"));
400 assertEquals(0, syncBundle.getLong("version"));
401 assertEquals("", syncBundle.getString("payload"));
402
403 // Ensure acknowledged.
404 assertSingleAcknowledgement(ackHandle);
405 }
406
407 @SmallTest
408 @Feature({"Sync"})
409 public void testInvalidateAll() {
410 /*
411 * Test plan: call invalidateAll(). Verify the produced bundle has the c orrect fields.
412 */
413 byte[] ackHandle = "testInvalidateAll".getBytes();
414 getService().invalidateAll(ackHandle);
415
416 // Validate bundle.
417 assertEquals(1, getService().mRequestedSyncs.size());
418 Bundle syncBundle = getService().mRequestedSyncs.get(0);
419 assertEquals(0, syncBundle.keySet().size());
420
421 // Ensure acknowledged.
422 assertSingleAcknowledgement(ackHandle);
423 }
424
425 /** Asserts that the service received a single acknowledgement with handle { @code ackHandle}. */
426 private void assertSingleAcknowledgement(byte[] ackHandle) {
427 assertEquals(1, getService().mAcknowledgements.size());
428 assertTrue(Arrays.equals(ackHandle, getService().mAcknowledgements.get(0 )));
429 }
430
431 @SmallTest
432 @Feature({"Sync"})
433 public void testShouldClientBeRunning() {
434 /*
435 * Test plan: call shouldClientBeRunning with various combinations of
436 * in-foreground/sync-enabled. Verify appropriate return values.
437 */
438 getService().setShouldRunStates(false, false);
439 assertFalse(getService().shouldClientBeRunning());
440
441 getService().setShouldRunStates(false, true);
442 assertFalse(getService().shouldClientBeRunning());
443
444 getService().setShouldRunStates(true, false);
445 assertFalse(getService().shouldClientBeRunning());
446
447 // Should only be running if both in the foreground and sync is enabled.
448 getService().setShouldRunStates(true, true);
449 assertTrue(getService().shouldClientBeRunning());
450 }
451
452 @SmallTest
453 @Feature({"Sync"})
454 public void testStartAndStopClient() {
455 /*
456 * Test plan: with Chrome configured so that the client should run, send it an empty
457 * intent. Even though no owning account is known, the client should sti ll start. Send
458 * it a stop intent and verify that it stops.
459 */
460
461 // Note: we are manipulating the service object directly, rather than th rough startService,
462 // because otherwise we would need to handle the asynchronous execution model of the
463 // underlying IntentService.
464 getService().setShouldRunStates(true, true);
465 getService().onCreate();
466
467 Intent startIntent = createStartIntent();
468 getService().onHandleIntent(startIntent);
469 assertTrue(InvalidationService.getIsClientStartedForTest());
470
471 Intent stopIntent = createStopIntent();
472 getService().onHandleIntent(stopIntent);
473 assertFalse(InvalidationService.getIsClientStartedForTest());
474
475 // The issued intents should have been an AndroidListener start intent f ollowed by an
476 // AndroidListener stop intent.
477 assertEquals(2, mStartServiceIntents.size());
478 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
479 assertTrue(isAndroidListenerStopIntent(mStartServiceIntents.get(1)));
480 }
481
482 @SmallTest
483 @Feature({"Sync"})
484 public void testClientStopsWhenShouldNotBeRunning() {
485 /*
486 * Test plan: start the client. Then, change the configuration so that C hrome should not
487 * be running. Send an intent to the service and verify that it stops.
488 */
489 getService().setShouldRunStates(true, true);
490 getService().onCreate();
491
492 // Start the service.
493 Intent startIntent = createStartIntent();
494 getService().onHandleIntent(startIntent);
495 assertTrue(InvalidationService.getIsClientStartedForTest());
496
497 // Change configuration.
498 getService().setShouldRunStates(false, false);
499
500 // Send an Intent and verify that the service stops.
501 getService().onHandleIntent(startIntent);
502 assertFalse(InvalidationService.getIsClientStartedForTest());
503
504 // The issued intents should have been an AndroidListener start intent f ollowed by an
505 // AndroidListener stop intent.
506 assertEquals(2, mStartServiceIntents.size());
507 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
508 assertTrue(isAndroidListenerStopIntent(mStartServiceIntents.get(1)));
509 }
510
511 @SmallTest
512 @Feature({"Sync"})
513 public void testRegistrationIntent() {
514 /*
515 * Test plan: send a registration-change intent. Verify that it starts t he client and
516 * sets both the account and registrations in shared preferences.
517 */
518 getService().setShouldRunStates(true, true);
519 getService().onCreate();
520
521 // Send register Intent.
522 Set<ModelType> desiredRegistrations = CollectionUtil.newHashSet(
523 ModelType.BOOKMARK, ModelType.SESSION);
524 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
525 Intent registrationIntent = createRegisterIntent(account, false, desired Registrations);
526 getService().onHandleIntent(registrationIntent);
527
528 // Verify client started and state written.
529 assertTrue(InvalidationService.getIsClientStartedForTest());
530 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
531 assertEquals(account, invPrefs.getSavedSyncedAccount());
532 assertEquals(ModelType.modelTypesToSyncTypesForTest(desiredRegistrations ),
533 invPrefs.getSavedSyncedTypes());
534 assertNull(invPrefs.getSavedObjectIds());
535 assertEquals(1, mStartServiceIntents.size());
536 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
537
538 // Send another registration-change intent, this type with all-types set to true, and
539 // verify that the on-disk state is updated and that no addition Intents are issued.
540 getService().onHandleIntent(createRegisterIntent(account, true, null));
541 assertEquals(account, invPrefs.getSavedSyncedAccount());
542 assertEquals(CollectionUtil.newHashSet(ModelType.ALL_TYPES_TYPE),
543 invPrefs.getSavedSyncedTypes());
544 assertEquals(1, mStartServiceIntents.size());
545
546 // Finally, send one more registration-change intent, this time with a d ifferent account,
547 // and verify that it both updates the account, stops thye existing clie nt, and
548 // starts a new client.
549 Account account2 = AccountManagerHelper.createAccountFromName("test2@exa mple.com");
550 getService().onHandleIntent(createRegisterIntent(account2, true, null));
551 assertEquals(account2, invPrefs.getSavedSyncedAccount());
552 assertEquals(3, mStartServiceIntents.size());
553 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
554 assertTrue(isAndroidListenerStopIntent(mStartServiceIntents.get(1)));
555 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(2)));
556 }
557
558 /**
559 * Determines if the correct object ids have been written to preferences and registered with the
560 * invalidation client.
561 *
562 * @param expectedTypes The Sync types expected to be registered.
563 * @param expectedObjectIds The additional object ids expected to be registe red.
564 * @param isReady Whether the client is ready to register/unregister.
565 */
566 private boolean expectedObjectIdsRegistered(Set<ModelType> expectedTypes,
567 Set<ObjectId> expectedObjectIds, boolean isReady) {
568 // Get synced types saved to preferences.
569 Set<String> expectedSyncTypes = ModelType.modelTypesToSyncTypesForTest(e xpectedTypes);
570 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
571 Set<String> actualSyncTypes = invPrefs.getSavedSyncedTypes();
572 if (actualSyncTypes == null) {
573 actualSyncTypes = new HashSet<String>();
574 }
575
576 // Get object ids saved to preferences.
577 Set<ObjectId> actualObjectIds = invPrefs.getSavedObjectIds();
578 if (actualObjectIds == null) {
579 actualObjectIds = new HashSet<ObjectId>();
580 }
581
582 // Get expected registered object ids.
583 Set<ObjectId> expectedRegisteredIds = new HashSet<ObjectId>();
584 if (isReady) {
585 expectedRegisteredIds.addAll(ModelType.modelTypesToObjectIds(expecte dTypes));
586 expectedRegisteredIds.addAll(expectedObjectIds);
587 }
588
589 return actualSyncTypes.equals(expectedSyncTypes) &&
590 actualObjectIds.equals(expectedObjectIds) &&
591 getService().mCurrentRegistrations.equals(expectedRegisteredIds) ;
592 }
593
594 @SmallTest
595 @Feature({"Sync"})
596 public void testRegistrationIntentWithTypesAndObjectIds() {
597 /*
598 * Test plan: send a mix of registration-change intents: some for Sync t ypes and some for
599 * object ids. Verify that registering for Sync types does not interfere with object id
600 * registration and vice-versa.
601 */
602 getService().setShouldRunStates(true, true);
603 getService().onCreate();
604
605 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
606 Set<ObjectId> objectIds = new HashSet<ObjectId>();
607 Set<ModelType> types = new HashSet<ModelType>();
608
609 // Register for some object ids.
610 objectIds.add(ObjectId.newInstance(1, "obj1".getBytes()));
611 objectIds.add(ObjectId.newInstance(2, "obj2".getBytes()));
612 Intent registrationIntent =
613 createRegisterIntent(account, new int[] {1, 2}, new String[] {"obj1" , "obj2"});
614 getService().onHandleIntent(registrationIntent);
615 assertTrue(expectedObjectIdsRegistered(types, objectIds, false /* isRead y */));
616
617 // Register for some types.
618 types.add(ModelType.BOOKMARK);
619 types.add(ModelType.SESSION);
620 registrationIntent = createRegisterIntent(account, false, types);
621 getService().onHandleIntent(registrationIntent);
622 assertTrue(expectedObjectIdsRegistered(types, objectIds, false /* isRead y */));
623
624 // Set client to be ready and verify registrations.
625 getService().ready(CLIENT_ID);
626 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
627
628 // Change object id registration with types registered.
629 objectIds.add(ObjectId.newInstance(3, "obj3".getBytes()));
630 registrationIntent = createRegisterIntent(
631 account, new int[] {1, 2, 3}, new String[] {"obj1", "obj2", "obj3"}) ;
632 getService().onHandleIntent(registrationIntent);
633 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
634
635 // Change type registration with object ids registered.
636 types.remove(ModelType.BOOKMARK);
637 registrationIntent = createRegisterIntent(account, false, types);
638 getService().onHandleIntent(registrationIntent);
639 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
640
641 // Unregister all types.
642 types.clear();
643 registrationIntent = createRegisterIntent(account, false, types);
644 getService().onHandleIntent(registrationIntent);
645 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
646
647 // Change object id registration with no types registered.
648 objectIds.remove(ObjectId.newInstance(2, "obj2".getBytes()));
649 registrationIntent = createRegisterIntent(
650 account, new int[] {1, 3}, new String[] {"obj1", "obj3"});
651 getService().onHandleIntent(registrationIntent);
652 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
653
654 // Unregister all object ids.
655 objectIds.clear();
656 registrationIntent = createRegisterIntent(account, new int[0], new Strin g[0]);
657 getService().onHandleIntent(registrationIntent);
658 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
659
660 // Change type registration with no object ids registered.
661 types.add(ModelType.BOOKMARK);
662 types.add(ModelType.PASSWORD);
663 registrationIntent = createRegisterIntent(account, false, types);
664 getService().onHandleIntent(registrationIntent);
665 assertTrue(expectedObjectIdsRegistered(types, objectIds, true /* isReady */));
666 }
667
668 @SmallTest
669 @Feature({"Sync"})
670 public void testRegistrationIntentNoProxyTabsUsingReady() {
671 getService().setShouldRunStates(true, true);
672 getService().onCreate();
673
674 // Send register Intent.
675 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
676 Intent registrationIntent = createRegisterIntent(account, true, null);
677 getService().onHandleIntent(registrationIntent);
678
679 // Verify client started and state written.
680 assertTrue(InvalidationService.getIsClientStartedForTest());
681 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
682 assertEquals(account, invPrefs.getSavedSyncedAccount());
683 assertEquals(CollectionUtil.newHashSet(ModelType.ALL_TYPES_TYPE),
684 invPrefs.getSavedSyncedTypes());
685 assertEquals(1, mStartServiceIntents.size());
686 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
687
688 // Set client to be ready. This triggers registrations.
689 getService().ready(CLIENT_ID);
690 assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTe st()));
691
692 // Ensure registrations are correct.
693 Set<ObjectId> expectedTypes =
694 ModelType.modelTypesToObjectIds(EnumSet.allOf(ModelType.class));
695 assertEquals(expectedTypes, new HashSet<ObjectId>(getService().mRegistra tions.get(0)));
696 }
697
698 @SmallTest
699 @Feature({"Sync"})
700 public void testRegistrationIntentNoProxyTabsAlreadyWithClientId() {
701 getService().setShouldRunStates(true, true);
702 getService().onCreate();
703
704 // Send register Intent with no desired types.
705 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
706 Intent registrationIntent = createRegisterIntent(account, false, new Has hSet<ModelType>());
707 getService().onHandleIntent(registrationIntent);
708
709 // Verify client started and state written.
710 assertTrue(InvalidationService.getIsClientStartedForTest());
711 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
712 assertEquals(account, invPrefs.getSavedSyncedAccount());
713 assertEquals(new HashSet<String>(), invPrefs.getSavedSyncedTypes());
714 assertEquals(1, mStartServiceIntents.size());
715 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
716
717 // Make sure client is ready.
718 getService().ready(CLIENT_ID);
719 assertTrue(Arrays.equals(CLIENT_ID, InvalidationService.getClientIdForTe st()));
720
721 // Choose to register for all types in an already ready client.
722 registrationIntent = createRegisterIntent(account, true, null);
723 getService().onHandleIntent(registrationIntent);
724
725 // Ensure registrations are correct.
726 assertEquals(1, getService().mRegistrations.size());
727 Set<ObjectId> expectedTypes =
728 ModelType.modelTypesToObjectIds(EnumSet.allOf(ModelType.class));
729 assertEquals(expectedTypes, new HashSet<ObjectId>(getService().mRegistra tions.get(0)));
730 }
731
732 @SmallTest
733 @Feature({"Sync"})
734 public void testRegistrationIntentWhenClientShouldNotBeRunning() {
735 /*
736 * Test plan: send a registration change event when the client should no t be running.
737 * Verify that the service updates the on-disk state but does not start the client.
738 */
739 getService().onCreate();
740
741 // Send register Intent.
742 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
743 Set<ModelType> desiredRegistrations = CollectionUtil.newHashSet(
744 ModelType.BOOKMARK, ModelType.SESSION);
745 Intent registrationIntent = createRegisterIntent(account, false, desired Registrations);
746 getService().onHandleIntent(registrationIntent);
747
748 // Verify state written but client not started.
749 assertFalse(InvalidationService.getIsClientStartedForTest());
750 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
751 assertEquals(account, invPrefs.getSavedSyncedAccount());
752 assertEquals(ModelType.modelTypesToSyncTypesForTest(desiredRegistrations ),
753 invPrefs.getSavedSyncedTypes());
754 assertEquals(0, mStartServiceIntents.size());
755 }
756
757 @SmallTest
758 @Feature({"Sync"})
759 public void testDeferredRegistrationsIssued() {
760 /*
761 * Test plan: send a registration-change intent. Verify that the client issues a start
762 * intent but makes no registration calls. Issue a reissueRegistrations call and verify
763 * that the client does issue the appropriate registrations.
764 */
765 getService().setShouldRunStates(true, true);
766 getService().onCreate();
767
768 // Send register Intent. Verify client started but no registrations issu ed.
769 Account account = AccountManagerHelper.createAccountFromName("test@examp le.com");
770 Set<ModelType> desiredRegistrations = CollectionUtil.newHashSet(
771 ModelType.BOOKMARK, ModelType.SESSION);
772 Set<ObjectId> desiredObjectIds = ModelType.modelTypesToObjectIds(desired Registrations);
773
774 Intent registrationIntent = createRegisterIntent(account, false, desired Registrations);
775 getService().onHandleIntent(registrationIntent);
776 assertTrue(InvalidationService.getIsClientStartedForTest());
777 assertEquals(1, mStartServiceIntents.size());
778 assertTrue(isAndroidListenerStartIntent(mStartServiceIntents.get(0)));
779 InvalidationPreferences invPrefs = new InvalidationPreferences(getContex t());
780 assertEquals(ModelType.modelTypesToSyncTypesForTest(desiredRegistrations ),
781 invPrefs.getSavedSyncedTypes());
782 assertEquals(desiredObjectIds, getService().readRegistrationsFromPrefs() );
783
784 // Issue reissueRegistrations; verify registration intent issues.
785 getService().reissueRegistrations(CLIENT_ID);
786 assertEquals(2, mStartServiceIntents.size());
787 Intent expectedRegisterIntent = AndroidListener.createRegisterIntent(
788 getContext(),
789 CLIENT_ID,
790 desiredObjectIds);
791 Intent actualRegisterIntent = mStartServiceIntents.get(1);
792 assertTrue(expectedRegisterIntent.filterEquals(actualRegisterIntent));
793 assertEquals(expectedRegisterIntent.getExtras().keySet(),
794 actualRegisterIntent.getExtras().keySet());
795 assertEquals(
796 desiredObjectIds,
797 new HashSet<ObjectId>(getService().mRegistrations.get(0)));
798 }
799
800 @SmallTest
801 @Feature({"Sync"})
802 public void testRegistrationRetries() {
803 /*
804 * Test plan: validate that the alarm receiver used by the AndroidListen er underlying
805 * InvalidationService is correctly configured in the manifest and retri es registrations
806 * with exponential backoff. May need to be implemented as a downstream Chrome for Android
807 * test.
808 */
809 // TODO(dsmyers): implement.
810 // Bug: https://code.google.com/p/chromium/issues/detail?id=172398
811 }
812
813 /** Creates an intent to start the InvalidationService. */
814 private Intent createStartIntent() {
815 Intent intent = new Intent();
816 return intent;
817 }
818
819 /** Creates an intent to stop the InvalidationService. */
820 private Intent createStopIntent() {
821 Intent intent = new Intent();
822 intent.putExtra(InvalidationIntentProtocol.EXTRA_STOP, true);
823 return intent;
824 }
825
826 /** Creates an intent to register some types with the InvalidationService. * /
827 private Intent createRegisterIntent(Account account, boolean allTypes, Set<M odelType> types) {
828 Intent intent = InvalidationIntentProtocol.createRegisterIntent(account, allTypes, types);
829 return intent;
830 }
831
832 /** Creates an intent to register some types with the InvalidationService. * /
833 private Intent createRegisterIntent(
834 Account account, int[] objectSources, String[] objectNames) {
835 Intent intent = InvalidationIntentProtocol.createRegisterIntent(
836 account, objectSources, objectNames);
837 return intent;
838 }
839
840 /** Returns whether {@code intent} is an {@link AndroidListener} start inten t. */
841 private boolean isAndroidListenerStartIntent(Intent intent) {
842 Intent startIntent = AndroidListener.createStartIntent(getContext(),
843 InvalidationService.CLIENT_TYPE, "unused".getBytes());
844 return intent.getExtras().keySet().equals(startIntent.getExtras().keySet ());
845 }
846
847 /** Returns whether {@code intent} is an {@link AndroidListener} stop intent . */
848 private boolean isAndroidListenerStopIntent(Intent intent) {
849 Intent stopIntent = AndroidListener.createStopIntent(getContext());
850 return intent.getExtras().keySet().equals(stopIntent.getExtras().keySet( ));
851 }
852 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698