Don't switch browser locale on secondary user login
[chromium-blink-merge.git] / sync / notifier / sync_invalidation_listener_unittest.cc
blobd3aa712b7d973a7e00f3362e9dcd6c10dd7c9747
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.
5 #include <cstddef>
6 #include <set>
7 #include <string>
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"
25 namespace syncer {
27 namespace {
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 {
58 public:
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 {
77 started_ = true;
80 virtual void Stop() OVERRIDE {
81 started_ = false;
84 virtual void Register(const ObjectId& object_id) OVERRIDE {
85 if (!started_) {
86 ADD_FAILURE();
87 return;
89 registered_ids_.insert(object_id);
92 virtual void Register(
93 const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
94 if (!started_) {
95 ADD_FAILURE();
96 return;
98 registered_ids_.insert(object_ids.begin(), object_ids.end());
101 virtual void Unregister(const ObjectId& object_id) OVERRIDE {
102 if (!started_) {
103 ADD_FAILURE();
104 return;
106 registered_ids_.erase(object_id);
109 virtual void Unregister(
110 const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
111 if (!started_) {
112 ADD_FAILURE();
113 return;
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 {
122 if (!started_) {
123 ADD_FAILURE();
124 return;
126 acked_handles_.insert(ack_handle);
129 private:
130 bool started_;
131 ObjectIdSet registered_ids_;
132 AckHandleSet acked_handles_;
135 // Fake delegate tkat keeps track of invalidation counts, payloads,
136 // and state.
137 class FakeDelegate : public SyncInvalidationListener::Delegate {
138 public:
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 {
160 return state_;
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 {
179 state_ = state;
182 private:
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,
193 int client_type,
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 {
204 public:
205 FakeTickClock() {}
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_;
217 private:
218 base::TimeTicks fake_now_ticks_;
220 DISALLOW_COPY_AND_ASSIGN(FakeTickClock);
223 class FakeBackoffEntry : public net::BackoffEntry {
224 public:
225 FakeBackoffEntry(const Policy *const policy, base::TickClock* tick_clock)
226 : BackoffEntry(policy), tick_clock_(tick_clock) {
229 protected:
230 virtual base::TimeTicks ImplGetTimeNow() const OVERRIDE {
231 return tick_clock_->NowTicks();
234 private:
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 {
246 protected:
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() {
259 StartClient();
261 registered_ids_.insert(kBookmarksId_);
262 registered_ids_.insert(kPreferencesId_);
263 listener_.UpdateRegisteredIds(registered_ids_);
266 virtual void TearDown() {
267 StopClient();
270 // Restart client without re-registering IDs.
271 void RestartClient() {
272 StopClient();
273 StartClient();
276 void StartClient() {
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()),
283 &fake_delegate_);
284 DCHECK(fake_invalidation_client_);
287 void StopClient() {
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;
335 if (payload) {
336 inv = invalidation::Invalidation(object_id, version, payload);
337 } else {
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,
354 ack_handle);
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_;
416 private:
417 base::MessageLoop message_loop_;
418 FakeInvalidationStateTracker fake_tracker_;
419 notifier::FakePushClient* const fake_push_client_;
421 protected:
422 // Tests need to access these directly.
423 FakeInvalidationClient* fake_invalidation_client_;
424 FakeTickClock tick_clock_;
425 SyncInvalidationListener listener_;
427 private:
428 FakeDelegate fake_delegate_;
431 // Write a new state to the client. It should propagate to the
432 // tracker.
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
457 // be updated.
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
529 // processed.
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) {
553 FireInvalidateAll();
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.
601 FireInvalidateAll();
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
616 // affect it.
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
681 // is restarted.
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
704 // on the safe side.
705 StopClient();
706 tick_clock_.LeapForward(1200);
707 StartClient();
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.
731 RestartClient();
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
739 // readied.
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
754 // readied.
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());
862 RestartClient();
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_));
885 ObjectIdSet ids;
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 */,
974 "auth error",
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());
996 } // namespace
998 } // namespace syncer