1 // Copyright (c) 2012 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.
9 #include "base/compiler_specific.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/stl_util.h"
12 #include "base/time/tick_clock.h"
13 #include "base/time/time.h"
14 #include "google/cacheinvalidation/include/invalidation-client.h"
15 #include "google/cacheinvalidation/include/types.h"
16 #include "jingle/notifier/listener/fake_push_client.h"
17 #include "sync/internal_api/public/base/invalidation_test_util.h"
18 #include "sync/internal_api/public/util/weak_handle.h"
19 #include "sync/notifier/ack_tracker.h"
20 #include "sync/notifier/fake_invalidation_state_tracker.h"
21 #include "sync/notifier/invalidation_util.h"
22 #include "sync/notifier/sync_invalidation_listener.h"
23 #include "testing/gtest/include/gtest/gtest.h"
29 using invalidation::AckHandle
;
30 using invalidation::ObjectId
;
32 const char kClientId
[] = "client_id";
33 const char kClientInfo
[] = "client_info";
35 const char kState
[] = "state";
36 const char kNewState
[] = "new_state";
38 const char kPayload1
[] = "payload1";
39 const char kPayload2
[] = "payload2";
41 const int64 kMinVersion
= FakeInvalidationStateTracker::kMinVersion
;
42 const int64 kVersion1
= 1LL;
43 const int64 kVersion2
= 2LL;
45 const int kChromeSyncSourceId
= 1004;
47 struct AckHandleLessThan
{
48 bool operator()(const AckHandle
& lhs
, const AckHandle
& rhs
) const {
49 return lhs
.handle_data() < rhs
.handle_data();
53 typedef std::set
<AckHandle
, AckHandleLessThan
> AckHandleSet
;
55 // Fake invalidation::InvalidationClient implementation that keeps
56 // track of registered IDs and acked handles.
57 class FakeInvalidationClient
: public invalidation::InvalidationClient
{
59 FakeInvalidationClient() : started_(false) {}
60 virtual ~FakeInvalidationClient() {}
62 const ObjectIdSet
& GetRegisteredIds() const {
63 return registered_ids_
;
66 void ClearAckedHandles() {
67 acked_handles_
.clear();
70 bool IsAckedHandle(const AckHandle
& ack_handle
) const {
71 return (acked_handles_
.find(ack_handle
) != acked_handles_
.end());
74 // invalidation::InvalidationClient implementation.
76 virtual void Start() OVERRIDE
{
80 virtual void Stop() OVERRIDE
{
84 virtual void Register(const ObjectId
& object_id
) OVERRIDE
{
89 registered_ids_
.insert(object_id
);
92 virtual void Register(
93 const invalidation::vector
<ObjectId
>& object_ids
) OVERRIDE
{
98 registered_ids_
.insert(object_ids
.begin(), object_ids
.end());
101 virtual void Unregister(const ObjectId
& object_id
) OVERRIDE
{
106 registered_ids_
.erase(object_id
);
109 virtual void Unregister(
110 const invalidation::vector
<ObjectId
>& object_ids
) OVERRIDE
{
115 for (invalidation::vector
<ObjectId
>::const_iterator
116 it
= object_ids
.begin(); it
!= object_ids
.end(); ++it
) {
117 registered_ids_
.erase(*it
);
121 virtual void Acknowledge(const AckHandle
& ack_handle
) OVERRIDE
{
126 acked_handles_
.insert(ack_handle
);
131 ObjectIdSet registered_ids_
;
132 AckHandleSet acked_handles_
;
135 // Fake delegate tkat keeps track of invalidation counts, payloads,
137 class FakeDelegate
: public SyncInvalidationListener::Delegate
{
139 explicit FakeDelegate(SyncInvalidationListener
* listener
)
140 : listener_(listener
),
141 state_(TRANSIENT_INVALIDATION_ERROR
) {}
142 virtual ~FakeDelegate() {}
144 int GetInvalidationCount(const ObjectId
& id
) const {
145 ObjectIdCountMap::const_iterator it
= invalidation_counts_
.find(id
);
146 return (it
== invalidation_counts_
.end()) ? 0 : it
->second
;
149 int64
GetVersion(const ObjectId
& id
) const {
150 ObjectIdInvalidationMap::const_iterator it
= invalidations_
.find(id
);
151 return (it
== invalidations_
.end()) ? 0 : it
->second
.version
;
154 std::string
GetPayload(const ObjectId
& id
) const {
155 ObjectIdInvalidationMap::const_iterator it
= invalidations_
.find(id
);
156 return (it
== invalidations_
.end()) ? std::string() : it
->second
.payload
;
159 InvalidatorState
GetInvalidatorState() const {
163 void Acknowledge(const ObjectId
& id
) {
164 listener_
->Acknowledge(id
, invalidations_
[id
].ack_handle
);
167 // SyncInvalidationListener::Delegate implementation.
169 virtual void OnInvalidate(
170 const ObjectIdInvalidationMap
& invalidation_map
) OVERRIDE
{
171 for (ObjectIdInvalidationMap::const_iterator it
= invalidation_map
.begin();
172 it
!= invalidation_map
.end(); ++it
) {
173 ++invalidation_counts_
[it
->first
];
174 invalidations_
[it
->first
] = it
->second
;
178 virtual void OnInvalidatorStateChange(InvalidatorState state
) OVERRIDE
{
183 typedef std::map
<ObjectId
, int, ObjectIdLessThan
> ObjectIdCountMap
;
184 ObjectIdCountMap invalidation_counts_
;
185 ObjectIdInvalidationMap invalidations_
;
186 SyncInvalidationListener
* listener_
;
187 InvalidatorState state_
;
190 invalidation::InvalidationClient
* CreateFakeInvalidationClient(
191 FakeInvalidationClient
** fake_invalidation_client
,
192 invalidation::SystemResources
* resources
,
194 const invalidation::string
& client_name
,
195 const invalidation::string
& application_name
,
196 invalidation::InvalidationListener
* listener
) {
197 *fake_invalidation_client
= new FakeInvalidationClient();
198 return *fake_invalidation_client
;
201 // TODO(dcheng): FakeTickClock and FakeBackoffEntry ought to be factored out
202 // into a helpers file so it can be shared with the AckTracker unittest.
203 class FakeTickClock
: public base::TickClock
{
206 virtual ~FakeTickClock() {}
208 void LeapForward(int seconds
) {
209 ASSERT_GT(seconds
, 0);
210 fake_now_ticks_
+= base::TimeDelta::FromSeconds(seconds
);
213 virtual base::TimeTicks
NowTicks() OVERRIDE
{
214 return fake_now_ticks_
;
218 base::TimeTicks fake_now_ticks_
;
220 DISALLOW_COPY_AND_ASSIGN(FakeTickClock
);
223 class FakeBackoffEntry
: public net::BackoffEntry
{
225 FakeBackoffEntry(const Policy
*const policy
, base::TickClock
* tick_clock
)
226 : BackoffEntry(policy
), tick_clock_(tick_clock
) {
230 virtual base::TimeTicks
ImplGetTimeNow() const OVERRIDE
{
231 return tick_clock_
->NowTicks();
235 base::TickClock
* const tick_clock_
;
238 scoped_ptr
<net::BackoffEntry
> CreateMockEntry(
239 base::TickClock
* tick_clock
,
240 const net::BackoffEntry::Policy
*const policy
) {
241 return scoped_ptr
<net::BackoffEntry
>(
242 new FakeBackoffEntry(policy
, tick_clock
));
245 class SyncInvalidationListenerTest
: public testing::Test
{
247 SyncInvalidationListenerTest()
248 : kBookmarksId_(kChromeSyncSourceId
, "BOOKMARK"),
249 kPreferencesId_(kChromeSyncSourceId
, "PREFERENCE"),
250 kExtensionsId_(kChromeSyncSourceId
, "EXTENSION"),
251 kAppsId_(kChromeSyncSourceId
, "APP"),
252 fake_push_client_(new notifier::FakePushClient()),
253 fake_invalidation_client_(NULL
),
254 listener_(&tick_clock_
,
255 scoped_ptr
<notifier::PushClient
>(fake_push_client_
)),
256 fake_delegate_(&listener_
) {}
258 virtual void SetUp() {
261 registered_ids_
.insert(kBookmarksId_
);
262 registered_ids_
.insert(kPreferencesId_
);
263 listener_
.UpdateRegisteredIds(registered_ids_
);
266 virtual void TearDown() {
270 // Restart client without re-registering IDs.
271 void RestartClient() {
277 fake_invalidation_client_
= NULL
;
278 listener_
.Start(base::Bind(&CreateFakeInvalidationClient
,
279 &fake_invalidation_client_
),
280 kClientId
, kClientInfo
, kState
,
281 fake_tracker_
.GetAllInvalidationStates(),
282 MakeWeakHandle(fake_tracker_
.AsWeakPtr()),
284 DCHECK(fake_invalidation_client_
);
288 // listener_.StopForTest() stops the invalidation scheduler, which
289 // deletes any pending tasks without running them. Some tasks
290 // "run and delete" another task, so they must be run in order to
291 // avoid leaking the inner task. listener_.StopForTest() does not
292 // schedule any tasks, so it's both necessary and sufficient to
293 // drain the task queue before calling it.
294 message_loop_
.RunUntilIdle();
295 fake_invalidation_client_
= NULL
;
296 listener_
.StopForTest();
299 int GetInvalidationCount(const ObjectId
& id
) const {
300 return fake_delegate_
.GetInvalidationCount(id
);
303 int64
GetVersion(const ObjectId
& id
) const {
304 return fake_delegate_
.GetVersion(id
);
307 std::string
GetPayload(const ObjectId
& id
) const {
308 return fake_delegate_
.GetPayload(id
);
311 InvalidatorState
GetInvalidatorState() const {
312 return fake_delegate_
.GetInvalidatorState();
315 int64
GetMaxVersion(const ObjectId
& id
) const {
316 return fake_tracker_
.GetMaxVersion(id
);
319 std::string
GetInvalidatorClientId() const {
320 return fake_tracker_
.GetInvalidatorClientId();
323 std::string
GetBootstrapData() const {
324 return fake_tracker_
.GetBootstrapData();
327 ObjectIdSet
GetRegisteredIds() const {
328 return fake_invalidation_client_
->GetRegisteredIds();
331 // |payload| can be NULL.
332 void FireInvalidate(const ObjectId
& object_id
,
333 int64 version
, const char* payload
) {
334 invalidation::Invalidation inv
;
336 inv
= invalidation::Invalidation(object_id
, version
, payload
);
338 inv
= invalidation::Invalidation(object_id
, version
);
340 const AckHandle
ack_handle("fakedata");
341 fake_invalidation_client_
->ClearAckedHandles();
342 listener_
.Invalidate(fake_invalidation_client_
, inv
, ack_handle
);
343 // Pump message loop to trigger InvalidationStateTracker::SetMaxVersion()
344 // and callback from InvalidationStateTracker::GenerateAckHandles().
345 message_loop_
.RunUntilIdle();
346 EXPECT_TRUE(fake_invalidation_client_
->IsAckedHandle(ack_handle
));
349 // |payload| can be NULL, but not |type_name|.
350 void FireInvalidateUnknownVersion(const ObjectId
& object_id
) {
351 const AckHandle
ack_handle("fakedata_unknown");
352 fake_invalidation_client_
->ClearAckedHandles();
353 listener_
.InvalidateUnknownVersion(fake_invalidation_client_
, object_id
,
355 // Pump message loop to trigger callback from
356 // InvalidationStateTracker::GenerateAckHandles().
357 message_loop_
.RunUntilIdle();
358 EXPECT_TRUE(fake_invalidation_client_
->IsAckedHandle(ack_handle
));
361 void FireInvalidateAll() {
362 const AckHandle
ack_handle("fakedata_all");
363 fake_invalidation_client_
->ClearAckedHandles();
364 listener_
.InvalidateAll(fake_invalidation_client_
, ack_handle
);
365 // Pump message loop to trigger callback from
366 // InvalidationStateTracker::GenerateAckHandles().
367 message_loop_
.RunUntilIdle();
368 EXPECT_TRUE(fake_invalidation_client_
->IsAckedHandle(ack_handle
));
371 void WriteState(const std::string
& new_state
) {
372 listener_
.WriteState(new_state
);
373 // Pump message loop to trigger
374 // InvalidationStateTracker::WriteState().
375 message_loop_
.RunUntilIdle();
378 void EnableNotifications() {
379 fake_push_client_
->EnableNotifications();
382 void DisableNotifications(notifier::NotificationsDisabledReason reason
) {
383 fake_push_client_
->DisableNotifications(reason
);
386 void VerifyUnacknowledged(const ObjectId
& object_id
) {
387 InvalidationStateMap state_map
= fake_tracker_
.GetAllInvalidationStates();
388 EXPECT_THAT(state_map
[object_id
].current
,
389 Not(Eq(state_map
[object_id
].expected
)));
390 EXPECT_EQ(listener_
.GetStateMapForTest(), state_map
);
393 void VerifyAcknowledged(const ObjectId
& object_id
) {
394 InvalidationStateMap state_map
= fake_tracker_
.GetAllInvalidationStates();
395 EXPECT_THAT(state_map
[object_id
].current
,
396 Eq(state_map
[object_id
].expected
));
397 EXPECT_EQ(listener_
.GetStateMapForTest(), state_map
);
400 void AcknowledgeAndVerify(const ObjectId
& object_id
) {
401 VerifyUnacknowledged(object_id
);
402 fake_delegate_
.Acknowledge(object_id
);
403 // Pump message loop to trigger
404 // InvalidationStateTracker::Acknowledge().
405 message_loop_
.RunUntilIdle();
406 VerifyAcknowledged(object_id
);
409 const ObjectId kBookmarksId_
;
410 const ObjectId kPreferencesId_
;
411 const ObjectId kExtensionsId_
;
412 const ObjectId kAppsId_
;
414 ObjectIdSet registered_ids_
;
417 base::MessageLoop message_loop_
;
418 FakeInvalidationStateTracker fake_tracker_
;
419 notifier::FakePushClient
* const fake_push_client_
;
422 // Tests need to access these directly.
423 FakeInvalidationClient
* fake_invalidation_client_
;
424 FakeTickClock tick_clock_
;
425 SyncInvalidationListener listener_
;
428 FakeDelegate fake_delegate_
;
431 // Write a new state to the client. It should propagate to the
433 TEST_F(SyncInvalidationListenerTest
, WriteState
) {
434 WriteState(kNewState
);
436 EXPECT_EQ(kNewState
, GetBootstrapData());
439 // Invalidation tests.
441 // Fire an invalidation without a payload. It should be processed,
442 // the payload should remain empty, and the version should be updated.
443 TEST_F(SyncInvalidationListenerTest
, InvalidateNoPayload
) {
444 const ObjectId
& id
= kBookmarksId_
;
446 FireInvalidate(id
, kVersion1
, NULL
);
448 EXPECT_EQ(1, GetInvalidationCount(id
));
449 EXPECT_EQ(kVersion1
, GetVersion(id
));
450 EXPECT_EQ("", GetPayload(id
));
451 EXPECT_EQ(kVersion1
, GetMaxVersion(id
));
452 AcknowledgeAndVerify(id
);
455 // Fire an invalidation with an empty payload. It should be
456 // processed, the payload should remain empty, and the version should
458 TEST_F(SyncInvalidationListenerTest
, InvalidateEmptyPayload
) {
459 const ObjectId
& id
= kBookmarksId_
;
461 FireInvalidate(id
, kVersion1
, "");
463 EXPECT_EQ(1, GetInvalidationCount(id
));
464 EXPECT_EQ(kVersion1
, GetVersion(id
));
465 EXPECT_EQ("", GetPayload(id
));
466 EXPECT_EQ(kVersion1
, GetMaxVersion(id
));
467 AcknowledgeAndVerify(id
);
470 // Fire an invalidation with a payload. It should be processed, and
471 // both the payload and the version should be updated.
472 TEST_F(SyncInvalidationListenerTest
, InvalidateWithPayload
) {
473 const ObjectId
& id
= kPreferencesId_
;
475 FireInvalidate(id
, kVersion1
, kPayload1
);
477 EXPECT_EQ(1, GetInvalidationCount(id
));
478 EXPECT_EQ(kVersion1
, GetVersion(id
));
479 EXPECT_EQ(kPayload1
, GetPayload(id
));
480 EXPECT_EQ(kVersion1
, GetMaxVersion(id
));
481 AcknowledgeAndVerify(id
);
484 // Fire an invalidation for an unregistered object ID with a payload. It should
485 // still be processed, and both the payload and the version should be updated.
486 TEST_F(SyncInvalidationListenerTest
, InvalidateUnregisteredWithPayload
) {
487 const ObjectId
kUnregisteredId(
488 kChromeSyncSourceId
, "unregistered");
489 const ObjectId
& id
= kUnregisteredId
;
491 EXPECT_EQ(0, GetInvalidationCount(id
));
492 EXPECT_EQ("", GetPayload(id
));
493 EXPECT_EQ(kMinVersion
, GetMaxVersion(id
));
495 FireInvalidate(id
, kVersion1
, "unregistered payload");
497 EXPECT_EQ(1, GetInvalidationCount(id
));
498 EXPECT_EQ(kVersion1
, GetVersion(id
));
499 EXPECT_EQ("unregistered payload", GetPayload(id
));
500 EXPECT_EQ(kVersion1
, GetMaxVersion(id
));
501 AcknowledgeAndVerify(id
);
504 // Fire an invalidation, then fire another one with a lower version.
505 // The first one should be processed and should update the payload and
506 // version, but the second one shouldn't.
507 TEST_F(SyncInvalidationListenerTest
, InvalidateVersion
) {
508 const ObjectId
& id
= kPreferencesId_
;
510 FireInvalidate(id
, kVersion2
, kPayload2
);
512 EXPECT_EQ(1, GetInvalidationCount(id
));
513 EXPECT_EQ(kVersion2
, GetVersion(id
));
514 EXPECT_EQ(kPayload2
, GetPayload(id
));
515 EXPECT_EQ(kVersion2
, GetMaxVersion(id
));
516 AcknowledgeAndVerify(id
);
518 FireInvalidate(id
, kVersion1
, kPayload1
);
520 EXPECT_EQ(1, GetInvalidationCount(id
));
521 EXPECT_EQ(kVersion2
, GetVersion(id
));
522 EXPECT_EQ(kPayload2
, GetPayload(id
));
523 EXPECT_EQ(kVersion2
, GetMaxVersion(id
));
524 VerifyAcknowledged(id
);
527 // Fire an invalidation with an unknown version twice. It shouldn't
528 // update the payload or version either time, but it should still be
530 TEST_F(SyncInvalidationListenerTest
, InvalidateUnknownVersion
) {
531 const ObjectId
& id
= kBookmarksId_
;
533 FireInvalidateUnknownVersion(id
);
535 EXPECT_EQ(1, GetInvalidationCount(id
));
536 EXPECT_EQ(Invalidation::kUnknownVersion
, GetVersion(id
));
537 EXPECT_EQ("", GetPayload(id
));
538 EXPECT_EQ(kMinVersion
, GetMaxVersion(id
));
539 AcknowledgeAndVerify(id
);
541 FireInvalidateUnknownVersion(id
);
543 EXPECT_EQ(2, GetInvalidationCount(id
));
544 EXPECT_EQ(Invalidation::kUnknownVersion
, GetVersion(id
));
545 EXPECT_EQ("", GetPayload(id
));
546 EXPECT_EQ(kMinVersion
, GetMaxVersion(id
));
547 AcknowledgeAndVerify(id
);
550 // Fire an invalidation for all enabled IDs. It shouldn't update the
551 // payload or version, but it should still invalidate the IDs.
552 TEST_F(SyncInvalidationListenerTest
, InvalidateAll
) {
555 for (ObjectIdSet::const_iterator it
= registered_ids_
.begin();
556 it
!= registered_ids_
.end(); ++it
) {
557 EXPECT_EQ(1, GetInvalidationCount(*it
));
558 EXPECT_EQ(Invalidation::kUnknownVersion
, GetVersion(*it
));
559 EXPECT_EQ("", GetPayload(*it
));
560 EXPECT_EQ(kMinVersion
, GetMaxVersion(*it
));
561 AcknowledgeAndVerify(*it
);
565 // Comprehensive test of various scenarios for multiple IDs.
566 TEST_F(SyncInvalidationListenerTest
, InvalidateMultipleIds
) {
567 FireInvalidate(kBookmarksId_
, 3, NULL
);
569 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_
));
570 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
571 EXPECT_EQ("", GetPayload(kBookmarksId_
));
572 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
573 AcknowledgeAndVerify(kBookmarksId_
);
575 FireInvalidate(kExtensionsId_
, 2, NULL
);
577 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_
));
578 EXPECT_EQ(2, GetVersion(kExtensionsId_
));
579 EXPECT_EQ("", GetPayload(kExtensionsId_
));
580 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_
));
581 AcknowledgeAndVerify(kExtensionsId_
);
583 // Invalidations with lower version numbers should be ignored.
585 FireInvalidate(kBookmarksId_
, 1, NULL
);
587 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_
));
588 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
589 EXPECT_EQ("", GetPayload(kBookmarksId_
));
590 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
592 FireInvalidate(kExtensionsId_
, 1, NULL
);
594 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_
));
595 EXPECT_EQ(2, GetVersion(kExtensionsId_
));
596 EXPECT_EQ("", GetPayload(kExtensionsId_
));
597 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_
));
599 // InvalidateAll shouldn't change any version state.
603 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_
));
604 EXPECT_EQ(Invalidation::kUnknownVersion
, GetVersion(kBookmarksId_
));
605 EXPECT_EQ("", GetPayload(kBookmarksId_
));
606 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
607 AcknowledgeAndVerify(kBookmarksId_
);
609 EXPECT_EQ(1, GetInvalidationCount(kPreferencesId_
));
610 EXPECT_EQ(Invalidation::kUnknownVersion
, GetVersion(kPreferencesId_
));
611 EXPECT_EQ("", GetPayload(kPreferencesId_
));
612 EXPECT_EQ(kMinVersion
, GetMaxVersion(kPreferencesId_
));
613 AcknowledgeAndVerify(kPreferencesId_
);
615 // Note that kExtensionsId_ is not registered, so InvalidateAll() shouldn't
617 EXPECT_EQ(1, GetInvalidationCount(kExtensionsId_
));
618 EXPECT_EQ(2, GetVersion(kExtensionsId_
));
619 EXPECT_EQ("", GetPayload(kExtensionsId_
));
620 EXPECT_EQ(2, GetMaxVersion(kExtensionsId_
));
621 VerifyAcknowledged(kExtensionsId_
);
623 // Invalidations with higher version numbers should be processed.
625 FireInvalidate(kPreferencesId_
, 5, NULL
);
626 EXPECT_EQ(2, GetInvalidationCount(kPreferencesId_
));
627 EXPECT_EQ(5, GetVersion(kPreferencesId_
));
628 EXPECT_EQ("", GetPayload(kPreferencesId_
));
629 EXPECT_EQ(5, GetMaxVersion(kPreferencesId_
));
630 AcknowledgeAndVerify(kPreferencesId_
);
632 FireInvalidate(kExtensionsId_
, 3, NULL
);
633 EXPECT_EQ(2, GetInvalidationCount(kExtensionsId_
));
634 EXPECT_EQ(3, GetVersion(kExtensionsId_
));
635 EXPECT_EQ("", GetPayload(kExtensionsId_
));
636 EXPECT_EQ(3, GetMaxVersion(kExtensionsId_
));
637 AcknowledgeAndVerify(kExtensionsId_
);
639 FireInvalidate(kBookmarksId_
, 4, NULL
);
640 EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_
));
641 EXPECT_EQ(4, GetVersion(kBookmarksId_
));
642 EXPECT_EQ("", GetPayload(kBookmarksId_
));
643 EXPECT_EQ(4, GetMaxVersion(kBookmarksId_
));
644 AcknowledgeAndVerify(kBookmarksId_
);
647 // Various tests for the local invalidation feature.
648 // Tests a "normal" scenario. We allow one timeout period to expire by sending
649 // ack handles that are not the "latest" ack handle. Once the timeout expires,
650 // we verify that we get a second callback and then acknowledge it. Once
651 // acknowledged, no further timeouts should occur.
652 TEST_F(SyncInvalidationListenerTest
, InvalidateOneTimeout
) {
653 listener_
.GetAckTrackerForTest()->SetCreateBackoffEntryCallbackForTest(
654 base::Bind(&CreateMockEntry
, &tick_clock_
));
656 // Trigger the initial invalidation.
657 FireInvalidate(kBookmarksId_
, 3, NULL
);
658 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_
));
659 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
660 EXPECT_EQ("", GetPayload(kBookmarksId_
));
661 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
662 VerifyUnacknowledged(kBookmarksId_
);
664 // Trigger one timeout.
665 tick_clock_
.LeapForward(60);
666 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->TriggerTimeoutAtForTest(
667 tick_clock_
.NowTicks()));
668 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_
));
669 // Other properties should remain the same.
670 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
671 EXPECT_EQ("", GetPayload(kBookmarksId_
));
672 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
674 AcknowledgeAndVerify(kBookmarksId_
);
676 // No more invalidations should remain in the queue.
677 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->IsQueueEmptyForTest());
680 // Test that an unacknowledged invalidation triggers reminders if the listener
682 TEST_F(SyncInvalidationListenerTest
, InvalidationTimeoutRestart
) {
683 listener_
.GetAckTrackerForTest()->SetCreateBackoffEntryCallbackForTest(
684 base::Bind(&CreateMockEntry
, &tick_clock_
));
686 FireInvalidate(kBookmarksId_
, 3, NULL
);
687 EXPECT_EQ(1, GetInvalidationCount(kBookmarksId_
));
688 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
689 EXPECT_EQ("", GetPayload(kBookmarksId_
));
690 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
692 // Trigger one timeout.
693 tick_clock_
.LeapForward(60);
694 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->TriggerTimeoutAtForTest(
695 tick_clock_
.NowTicks()));
696 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_
));
697 // Other properties should remain the same.
698 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
699 EXPECT_EQ("", GetPayload(kBookmarksId_
));
700 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
702 // Restarting the client should reset the retry count and the timeout period
703 // (e.g. it shouldn't increase to 120 seconds). Skip ahead 1200 seconds to be
706 tick_clock_
.LeapForward(1200);
709 // The bookmark invalidation state should not have changed.
710 EXPECT_EQ(2, GetInvalidationCount(kBookmarksId_
));
711 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
712 EXPECT_EQ("", GetPayload(kBookmarksId_
));
713 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
715 // Now trigger the invalidation reminder after the client restarts.
716 tick_clock_
.LeapForward(60);
717 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->TriggerTimeoutAtForTest(
718 tick_clock_
.NowTicks()));
719 EXPECT_EQ(3, GetInvalidationCount(kBookmarksId_
));
720 // Other properties should remain the same.
721 EXPECT_EQ(3, GetVersion(kBookmarksId_
));
722 EXPECT_EQ("", GetPayload(kBookmarksId_
));
723 EXPECT_EQ(3, GetMaxVersion(kBookmarksId_
));
725 AcknowledgeAndVerify(kBookmarksId_
);
727 // No more invalidations should remain in the queue.
728 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->IsQueueEmptyForTest());
730 // The queue should remain empty when we restart now.
732 EXPECT_TRUE(listener_
.GetAckTrackerForTest()->IsQueueEmptyForTest());
735 // Registration tests.
737 // With IDs already registered, enable notifications then ready the
738 // client. The IDs should be registered only after the client is
740 TEST_F(SyncInvalidationListenerTest
, RegisterEnableReady
) {
741 EXPECT_TRUE(GetRegisteredIds().empty());
743 EnableNotifications();
745 EXPECT_TRUE(GetRegisteredIds().empty());
747 listener_
.Ready(fake_invalidation_client_
);
749 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
752 // With IDs already registered, ready the client then enable
753 // notifications. The IDs should be registered after the client is
755 TEST_F(SyncInvalidationListenerTest
, RegisterReadyEnable
) {
756 EXPECT_TRUE(GetRegisteredIds().empty());
758 listener_
.Ready(fake_invalidation_client_
);
760 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
762 EnableNotifications();
764 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
767 // Unregister the IDs, enable notifications, re-register the IDs, then
768 // ready the client. The IDs should be registered only after the
769 // client is readied.
770 TEST_F(SyncInvalidationListenerTest
, EnableRegisterReady
) {
771 listener_
.UpdateRegisteredIds(ObjectIdSet());
773 EXPECT_TRUE(GetRegisteredIds().empty());
775 EnableNotifications();
777 EXPECT_TRUE(GetRegisteredIds().empty());
779 listener_
.UpdateRegisteredIds(registered_ids_
);
781 EXPECT_TRUE(GetRegisteredIds().empty());
783 listener_
.Ready(fake_invalidation_client_
);
785 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
788 // Unregister the IDs, enable notifications, ready the client, then
789 // re-register the IDs. The IDs should be registered only after the
790 // client is readied.
791 TEST_F(SyncInvalidationListenerTest
, EnableReadyRegister
) {
792 listener_
.UpdateRegisteredIds(ObjectIdSet());
794 EXPECT_TRUE(GetRegisteredIds().empty());
796 EnableNotifications();
798 EXPECT_TRUE(GetRegisteredIds().empty());
800 listener_
.Ready(fake_invalidation_client_
);
802 EXPECT_TRUE(GetRegisteredIds().empty());
804 listener_
.UpdateRegisteredIds(registered_ids_
);
806 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
809 // Unregister the IDs, ready the client, enable notifications, then
810 // re-register the IDs. The IDs should be registered only after the
811 // client is readied.
812 TEST_F(SyncInvalidationListenerTest
, ReadyEnableRegister
) {
813 listener_
.UpdateRegisteredIds(ObjectIdSet());
815 EXPECT_TRUE(GetRegisteredIds().empty());
817 EnableNotifications();
819 EXPECT_TRUE(GetRegisteredIds().empty());
821 listener_
.Ready(fake_invalidation_client_
);
823 EXPECT_TRUE(GetRegisteredIds().empty());
825 listener_
.UpdateRegisteredIds(registered_ids_
);
827 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
830 // Unregister the IDs, ready the client, re-register the IDs, then
831 // enable notifications. The IDs should be registered only after the
832 // client is readied.
834 // This test is important: see http://crbug.com/139424.
835 TEST_F(SyncInvalidationListenerTest
, ReadyRegisterEnable
) {
836 listener_
.UpdateRegisteredIds(ObjectIdSet());
838 EXPECT_TRUE(GetRegisteredIds().empty());
840 listener_
.Ready(fake_invalidation_client_
);
842 EXPECT_TRUE(GetRegisteredIds().empty());
844 listener_
.UpdateRegisteredIds(registered_ids_
);
846 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
848 EnableNotifications();
850 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
853 // With IDs already registered, ready the client, restart the client,
854 // then re-ready it. The IDs should still be registered.
855 TEST_F(SyncInvalidationListenerTest
, RegisterTypesPreserved
) {
856 EXPECT_TRUE(GetRegisteredIds().empty());
858 listener_
.Ready(fake_invalidation_client_
);
860 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
864 EXPECT_TRUE(GetRegisteredIds().empty());
866 listener_
.Ready(fake_invalidation_client_
);
868 EXPECT_EQ(registered_ids_
, GetRegisteredIds());
871 // Make sure that state is correctly purged from the local invalidation state
872 // map cache when an ID is unregistered.
873 TEST_F(SyncInvalidationListenerTest
, UnregisterCleansUpStateMapCache
) {
874 listener_
.Ready(fake_invalidation_client_
);
876 EXPECT_TRUE(listener_
.GetStateMapForTest().empty());
877 FireInvalidate(kBookmarksId_
, 1, "hello");
878 EXPECT_EQ(1U, listener_
.GetStateMapForTest().size());
879 EXPECT_TRUE(ContainsKey(listener_
.GetStateMapForTest(), kBookmarksId_
));
880 FireInvalidate(kPreferencesId_
, 2, "world");
881 EXPECT_EQ(2U, listener_
.GetStateMapForTest().size());
882 EXPECT_TRUE(ContainsKey(listener_
.GetStateMapForTest(), kBookmarksId_
));
883 EXPECT_TRUE(ContainsKey(listener_
.GetStateMapForTest(), kPreferencesId_
));
886 ids
.insert(kBookmarksId_
);
887 listener_
.UpdateRegisteredIds(ids
);
888 EXPECT_EQ(1U, listener_
.GetStateMapForTest().size());
889 EXPECT_TRUE(ContainsKey(listener_
.GetStateMapForTest(), kBookmarksId_
));
892 // Without readying the client, disable notifications, then enable
893 // them. The listener should still think notifications are disabled.
894 TEST_F(SyncInvalidationListenerTest
, EnableNotificationsNotReady
) {
895 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
,
896 GetInvalidatorState());
898 DisableNotifications(
899 notifier::TRANSIENT_NOTIFICATION_ERROR
);
901 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
903 DisableNotifications(notifier::NOTIFICATION_CREDENTIALS_REJECTED
);
905 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
907 EnableNotifications();
909 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
912 // Enable notifications then Ready the invalidation client. The
913 // delegate should then be ready.
914 TEST_F(SyncInvalidationListenerTest
, EnableNotificationsThenReady
) {
915 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
917 EnableNotifications();
919 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
921 listener_
.Ready(fake_invalidation_client_
);
923 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
926 // Ready the invalidation client then enable notifications. The
927 // delegate should then be ready.
928 TEST_F(SyncInvalidationListenerTest
, ReadyThenEnableNotifications
) {
929 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
931 listener_
.Ready(fake_invalidation_client_
);
933 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR
, GetInvalidatorState());
935 EnableNotifications();
937 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
940 // Enable notifications and ready the client. Then disable
941 // notifications with an auth error and re-enable notifications. The
942 // delegate should go into an auth error mode and then back out.
943 TEST_F(SyncInvalidationListenerTest
, PushClientAuthError
) {
944 EnableNotifications();
945 listener_
.Ready(fake_invalidation_client_
);
947 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
949 DisableNotifications(
950 notifier::NOTIFICATION_CREDENTIALS_REJECTED
);
952 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
954 EnableNotifications();
956 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
959 // Enable notifications and ready the client. Then simulate an auth
960 // error from the invalidation client. Simulate some notification
961 // events, then re-ready the client. The delegate should go into an
962 // auth error mode and come out of it only after the client is ready.
963 TEST_F(SyncInvalidationListenerTest
, InvalidationClientAuthError
) {
964 EnableNotifications();
965 listener_
.Ready(fake_invalidation_client_
);
967 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
969 listener_
.InformError(
970 fake_invalidation_client_
,
971 invalidation::ErrorInfo(
972 invalidation::ErrorReason::AUTH_FAILURE
,
973 false /* is_transient */,
975 invalidation::ErrorContext()));
977 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
979 DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR
);
981 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
983 DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR
);
985 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
987 EnableNotifications();
989 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED
, GetInvalidatorState());
991 listener_
.Ready(fake_invalidation_client_
);
993 EXPECT_EQ(INVALIDATIONS_ENABLED
, GetInvalidatorState());
998 } // namespace syncer