Notify hotwording extension of microphone state change.
[chromium-blink-merge.git] / components / invalidation / sync_invalidation_listener_unittest.cc
blob29fd0b2c25d1a57811dff4fbd9027b246ab308d0
1 // Copyright 2014 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 <map>
7 #include <set>
8 #include <string>
9 #include <vector>
11 #include "base/compiler_specific.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "components/invalidation/fake_invalidation_state_tracker.h"
15 #include "components/invalidation/invalidation_util.h"
16 #include "components/invalidation/object_id_invalidation_map.h"
17 #include "components/invalidation/push_client_channel.h"
18 #include "components/invalidation/sync_invalidation_listener.h"
19 #include "components/invalidation/unacked_invalidation_set_test_util.h"
20 #include "google/cacheinvalidation/include/invalidation-client.h"
21 #include "google/cacheinvalidation/include/types.h"
22 #include "jingle/notifier/listener/fake_push_client.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 kVersion1 = 1LL;
42 const int64 kVersion2 = 2LL;
44 const int kChromeSyncSourceId = 1004;
46 struct AckHandleLessThan {
47 bool operator()(const AckHandle& lhs, const AckHandle& rhs) const {
48 return lhs.handle_data() < rhs.handle_data();
52 typedef std::set<AckHandle, AckHandleLessThan> AckHandleSet;
54 // Fake invalidation::InvalidationClient implementation that keeps
55 // track of registered IDs and acked handles.
56 class FakeInvalidationClient : public invalidation::InvalidationClient {
57 public:
58 FakeInvalidationClient() : started_(false) {}
59 ~FakeInvalidationClient() override {}
61 const ObjectIdSet& GetRegisteredIds() const {
62 return registered_ids_;
65 void ClearAckedHandles() {
66 acked_handles_.clear();
69 bool IsAckedHandle(const AckHandle& ack_handle) const {
70 return (acked_handles_.find(ack_handle) != acked_handles_.end());
73 // invalidation::InvalidationClient implementation.
75 void Start() override { started_ = true; }
77 void Stop() override { started_ = false; }
79 void Register(const ObjectId& object_id) override {
80 if (!started_) {
81 ADD_FAILURE();
82 return;
84 registered_ids_.insert(object_id);
87 void Register(const invalidation::vector<ObjectId>& object_ids) override {
88 if (!started_) {
89 ADD_FAILURE();
90 return;
92 registered_ids_.insert(object_ids.begin(), object_ids.end());
95 void Unregister(const ObjectId& object_id) override {
96 if (!started_) {
97 ADD_FAILURE();
98 return;
100 registered_ids_.erase(object_id);
103 void Unregister(const invalidation::vector<ObjectId>& object_ids) override {
104 if (!started_) {
105 ADD_FAILURE();
106 return;
108 for (invalidation::vector<ObjectId>::const_iterator
109 it = object_ids.begin(); it != object_ids.end(); ++it) {
110 registered_ids_.erase(*it);
114 void Acknowledge(const AckHandle& ack_handle) override {
115 if (!started_) {
116 ADD_FAILURE();
117 return;
119 acked_handles_.insert(ack_handle);
122 private:
123 bool started_;
124 ObjectIdSet registered_ids_;
125 AckHandleSet acked_handles_;
128 // Fake delegate tkat keeps track of invalidation counts, payloads,
129 // and state.
130 class FakeDelegate : public SyncInvalidationListener::Delegate {
131 public:
132 explicit FakeDelegate(SyncInvalidationListener* listener)
133 : state_(TRANSIENT_INVALIDATION_ERROR) {}
134 ~FakeDelegate() override {}
136 size_t GetInvalidationCount(const ObjectId& id) const {
137 Map::const_iterator it = invalidations_.find(id);
138 if (it == invalidations_.end()) {
139 return 0;
140 } else {
141 return it->second.size();
145 int64 GetVersion(const ObjectId& id) const {
146 Map::const_iterator it = invalidations_.find(id);
147 if (it == invalidations_.end()) {
148 ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
149 return 0;
150 } else {
151 return it->second.back().version();
155 std::string GetPayload(const ObjectId& id) const {
156 Map::const_iterator it = invalidations_.find(id);
157 if (it == invalidations_.end()) {
158 ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
159 return 0;
160 } else {
161 return it->second.back().payload();
165 bool IsUnknownVersion(const ObjectId& id) const {
166 Map::const_iterator it = invalidations_.find(id);
167 if (it == invalidations_.end()) {
168 ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
169 return false;
170 } else {
171 return it->second.back().is_unknown_version();
175 bool StartsWithUnknownVersion(const ObjectId& id) const {
176 Map::const_iterator it = invalidations_.find(id);
177 if (it == invalidations_.end()) {
178 ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
179 return false;
180 } else {
181 return it->second.front().is_unknown_version();
185 InvalidatorState GetInvalidatorState() const {
186 return state_;
189 void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) {
190 List& list = invalidations_[id];
191 List::iterator it = list.begin() + n;
192 it->Acknowledge();
195 void AcknowledgeAll(const ObjectId& id) {
196 List& list = invalidations_[id];
197 for (List::iterator it = list.begin(); it != list.end(); ++it) {
198 it->Acknowledge();
202 void DropNthInvalidation(const ObjectId& id, size_t n) {
203 List& list = invalidations_[id];
204 List::iterator it = list.begin() + n;
205 it->Drop();
206 dropped_invalidations_map_.erase(id);
207 dropped_invalidations_map_.insert(std::make_pair(id, *it));
210 void RecoverFromDropEvent(const ObjectId& id) {
211 DropMap::iterator it = dropped_invalidations_map_.find(id);
212 if (it != dropped_invalidations_map_.end()) {
213 it->second.Acknowledge();
214 dropped_invalidations_map_.erase(it);
218 // SyncInvalidationListener::Delegate implementation.
219 void OnInvalidate(const ObjectIdInvalidationMap& invalidation_map) override {
220 ObjectIdSet ids = invalidation_map.GetObjectIds();
221 for (ObjectIdSet::iterator it = ids.begin(); it != ids.end(); ++it) {
222 const SingleObjectInvalidationSet& incoming =
223 invalidation_map.ForObject(*it);
224 List& list = invalidations_[*it];
225 list.insert(list.end(), incoming.begin(), incoming.end());
229 void OnInvalidatorStateChange(InvalidatorState state) override {
230 state_ = state;
233 private:
234 typedef std::vector<Invalidation> List;
235 typedef std::map<ObjectId, List, ObjectIdLessThan> Map;
236 typedef std::map<ObjectId, Invalidation, ObjectIdLessThan> DropMap;
238 Map invalidations_;
239 InvalidatorState state_;
240 DropMap dropped_invalidations_map_;
243 invalidation::InvalidationClient* CreateFakeInvalidationClient(
244 FakeInvalidationClient** fake_invalidation_client,
245 invalidation::SystemResources* resources,
246 int client_type,
247 const invalidation::string& client_name,
248 const invalidation::string& application_name,
249 invalidation::InvalidationListener* listener) {
250 *fake_invalidation_client = new FakeInvalidationClient();
251 return *fake_invalidation_client;
254 class SyncInvalidationListenerTest : public testing::Test {
255 protected:
256 SyncInvalidationListenerTest()
257 : kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"),
258 kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"),
259 kExtensionsId_(kChromeSyncSourceId, "EXTENSION"),
260 kAppsId_(kChromeSyncSourceId, "APP"),
261 fake_push_client_(new notifier::FakePushClient()),
262 fake_invalidation_client_(NULL),
263 listener_(scoped_ptr<SyncNetworkChannel>(new PushClientChannel(
264 scoped_ptr<notifier::PushClient>(fake_push_client_)))),
265 fake_delegate_(&listener_) {}
267 void SetUp() override {
268 StartClient();
270 registered_ids_.insert(kBookmarksId_);
271 registered_ids_.insert(kPreferencesId_);
272 listener_.UpdateRegisteredIds(registered_ids_);
275 void TearDown() override { StopClient(); }
277 // Restart client without re-registering IDs.
278 void RestartClient() {
279 StopClient();
280 StartClient();
283 void StartClient() {
284 fake_invalidation_client_ = NULL;
285 listener_.Start(
286 base::Bind(&CreateFakeInvalidationClient, &fake_invalidation_client_),
287 kClientId,
288 kClientInfo,
289 kState,
290 fake_tracker_.GetSavedInvalidations(),
291 fake_tracker_.AsWeakPtr(),
292 base::MessageLoopProxy::current(),
293 &fake_delegate_);
294 DCHECK(fake_invalidation_client_);
297 void StopClient() {
298 // listener_.StopForTest() stops the invalidation scheduler, which
299 // deletes any pending tasks without running them. Some tasks
300 // "run and delete" another task, so they must be run in order to
301 // avoid leaking the inner task. listener_.StopForTest() does not
302 // schedule any tasks, so it's both necessary and sufficient to
303 // drain the task queue before calling it.
304 FlushPendingWrites();
305 fake_invalidation_client_ = NULL;
306 listener_.StopForTest();
309 size_t GetInvalidationCount(const ObjectId& id) const {
310 return fake_delegate_.GetInvalidationCount(id);
313 int64 GetVersion(const ObjectId& id) const {
314 return fake_delegate_.GetVersion(id);
317 std::string GetPayload(const ObjectId& id) const {
318 return fake_delegate_.GetPayload(id);
321 bool IsUnknownVersion(const ObjectId& id) const {
322 return fake_delegate_.IsUnknownVersion(id);
325 bool StartsWithUnknownVersion(const ObjectId& id) const {
326 return fake_delegate_.StartsWithUnknownVersion(id);
329 void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) {
330 fake_delegate_.AcknowledgeNthInvalidation(id, n);
333 void DropNthInvalidation(const ObjectId& id, size_t n) {
334 return fake_delegate_.DropNthInvalidation(id, n);
337 void RecoverFromDropEvent(const ObjectId& id) {
338 return fake_delegate_.RecoverFromDropEvent(id);
341 void AcknowledgeAll(const ObjectId& id) {
342 fake_delegate_.AcknowledgeAll(id);
345 InvalidatorState GetInvalidatorState() const {
346 return fake_delegate_.GetInvalidatorState();
349 std::string GetInvalidatorClientId() const {
350 return fake_tracker_.GetInvalidatorClientId();
353 std::string GetBootstrapData() const {
354 return fake_tracker_.GetBootstrapData();
357 UnackedInvalidationsMap GetSavedInvalidations() {
358 // Allow any queued writes to go through first.
359 FlushPendingWrites();
360 return fake_tracker_.GetSavedInvalidations();
363 SingleObjectInvalidationSet GetSavedInvalidationsForType(const ObjectId& id) {
364 const UnackedInvalidationsMap& saved_state = GetSavedInvalidations();
365 UnackedInvalidationsMap::const_iterator it =
366 saved_state.find(kBookmarksId_);
367 if (it == saved_state.end()) {
368 ADD_FAILURE() << "No state saved for ID " << ObjectIdToString(id);
369 return SingleObjectInvalidationSet();
371 ObjectIdInvalidationMap map;
372 it->second.ExportInvalidations(
373 base::WeakPtr<AckHandler>(),
374 scoped_refptr<base::SingleThreadTaskRunner>(),
375 &map);
376 if (map.Empty()) {
377 return SingleObjectInvalidationSet();
378 } else {
379 return map.ForObject(id);
383 ObjectIdSet GetRegisteredIds() const {
384 return fake_invalidation_client_->GetRegisteredIds();
387 // |payload| can be NULL.
388 void FireInvalidate(const ObjectId& object_id,
389 int64 version, const char* payload) {
390 invalidation::Invalidation inv;
391 if (payload) {
392 inv = invalidation::Invalidation(object_id, version, payload);
393 } else {
394 inv = invalidation::Invalidation(object_id, version);
396 const AckHandle ack_handle("fakedata");
397 fake_invalidation_client_->ClearAckedHandles();
398 listener_.Invalidate(fake_invalidation_client_, inv, ack_handle);
399 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
402 // |payload| can be NULL, but not |type_name|.
403 void FireInvalidateUnknownVersion(const ObjectId& object_id) {
404 const AckHandle ack_handle("fakedata_unknown");
405 fake_invalidation_client_->ClearAckedHandles();
406 listener_.InvalidateUnknownVersion(fake_invalidation_client_,
407 object_id,
408 ack_handle);
409 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
412 void FireInvalidateAll() {
413 const AckHandle ack_handle("fakedata_all");
414 fake_invalidation_client_->ClearAckedHandles();
415 listener_.InvalidateAll(fake_invalidation_client_, ack_handle);
416 EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
419 void WriteState(const std::string& new_state) {
420 listener_.WriteState(new_state);
422 // Pump message loop to trigger
423 // InvalidationStateTracker::WriteState().
424 FlushPendingWrites();
427 void FlushPendingWrites() {
428 message_loop_.RunUntilIdle();
431 void EnableNotifications() {
432 fake_push_client_->EnableNotifications();
435 void DisableNotifications(notifier::NotificationsDisabledReason reason) {
436 fake_push_client_->DisableNotifications(reason);
439 const ObjectId kBookmarksId_;
440 const ObjectId kPreferencesId_;
441 const ObjectId kExtensionsId_;
442 const ObjectId kAppsId_;
444 ObjectIdSet registered_ids_;
446 private:
447 base::MessageLoop message_loop_;
448 notifier::FakePushClient* const fake_push_client_;
450 protected:
451 // A derrived test needs direct access to this.
452 FakeInvalidationStateTracker fake_tracker_;
454 // Tests need to access these directly.
455 FakeInvalidationClient* fake_invalidation_client_;
456 SyncInvalidationListener listener_;
458 private:
459 FakeDelegate fake_delegate_;
462 // Write a new state to the client. It should propagate to the
463 // tracker.
464 TEST_F(SyncInvalidationListenerTest, WriteState) {
465 WriteState(kNewState);
467 EXPECT_EQ(kNewState, GetBootstrapData());
470 // Invalidation tests.
472 // Fire an invalidation without a payload. It should be processed,
473 // the payload should remain empty, and the version should be updated.
474 TEST_F(SyncInvalidationListenerTest, InvalidateNoPayload) {
475 const ObjectId& id = kBookmarksId_;
477 FireInvalidate(id, kVersion1, NULL);
479 ASSERT_EQ(1U, GetInvalidationCount(id));
480 ASSERT_FALSE(IsUnknownVersion(id));
481 EXPECT_EQ(kVersion1, GetVersion(id));
482 EXPECT_EQ("", GetPayload(id));
485 // Fire an invalidation with an empty payload. It should be
486 // processed, the payload should remain empty, and the version should
487 // be updated.
488 TEST_F(SyncInvalidationListenerTest, InvalidateEmptyPayload) {
489 const ObjectId& id = kBookmarksId_;
491 FireInvalidate(id, kVersion1, "");
493 ASSERT_EQ(1U, GetInvalidationCount(id));
494 ASSERT_FALSE(IsUnknownVersion(id));
495 EXPECT_EQ(kVersion1, GetVersion(id));
496 EXPECT_EQ("", GetPayload(id));
499 // Fire an invalidation with a payload. It should be processed, and
500 // both the payload and the version should be updated.
501 TEST_F(SyncInvalidationListenerTest, InvalidateWithPayload) {
502 const ObjectId& id = kPreferencesId_;
504 FireInvalidate(id, kVersion1, kPayload1);
506 ASSERT_EQ(1U, GetInvalidationCount(id));
507 ASSERT_FALSE(IsUnknownVersion(id));
508 EXPECT_EQ(kVersion1, GetVersion(id));
509 EXPECT_EQ(kPayload1, GetPayload(id));
512 // Fire ten invalidations in a row. All should be received.
513 TEST_F(SyncInvalidationListenerTest, ManyInvalidations_NoDrop) {
514 const int kRepeatCount = 10;
515 const ObjectId& id = kPreferencesId_;
516 int64 initial_version = kVersion1;
517 for (int64 i = initial_version; i < initial_version + kRepeatCount; ++i) {
518 FireInvalidate(id, i, kPayload1);
520 ASSERT_EQ(static_cast<size_t>(kRepeatCount), GetInvalidationCount(id));
521 ASSERT_FALSE(IsUnknownVersion(id));
522 EXPECT_EQ(kPayload1, GetPayload(id));
523 EXPECT_EQ(initial_version + kRepeatCount - 1, GetVersion(id));
526 // Fire an invalidation for an unregistered object ID with a payload. It should
527 // still be processed, and both the payload and the version should be updated.
528 TEST_F(SyncInvalidationListenerTest, InvalidateBeforeRegistration_Simple) {
529 const ObjectId kUnregisteredId(kChromeSyncSourceId, "unregistered");
530 const ObjectId& id = kUnregisteredId;
531 ObjectIdSet ids;
532 ids.insert(id);
534 EXPECT_EQ(0U, GetInvalidationCount(id));
536 FireInvalidate(id, kVersion1, kPayload1);
538 ASSERT_EQ(0U, GetInvalidationCount(id));
540 EnableNotifications();
541 listener_.Ready(fake_invalidation_client_);
542 listener_.UpdateRegisteredIds(ids);
544 ASSERT_EQ(1U, GetInvalidationCount(id));
545 ASSERT_FALSE(IsUnknownVersion(id));
546 EXPECT_EQ(kVersion1, GetVersion(id));
547 EXPECT_EQ(kPayload1, GetPayload(id));
550 // Fire ten invalidations before an object registers. Some invalidations will
551 // be dropped an replaced with an unknown version invalidation.
552 TEST_F(SyncInvalidationListenerTest, InvalidateBeforeRegistration_Drop) {
553 const int kRepeatCount =
554 UnackedInvalidationSet::kMaxBufferedInvalidations + 1;
555 const ObjectId kUnregisteredId(kChromeSyncSourceId, "unregistered");
556 const ObjectId& id = kUnregisteredId;
557 ObjectIdSet ids;
558 ids.insert(id);
560 EXPECT_EQ(0U, GetInvalidationCount(id));
562 int64 initial_version = kVersion1;
563 for (int64 i = initial_version; i < initial_version + kRepeatCount; ++i) {
564 FireInvalidate(id, i, kPayload1);
567 EnableNotifications();
568 listener_.Ready(fake_invalidation_client_);
569 listener_.UpdateRegisteredIds(ids);
571 ASSERT_EQ(UnackedInvalidationSet::kMaxBufferedInvalidations,
572 GetInvalidationCount(id));
573 ASSERT_FALSE(IsUnknownVersion(id));
574 EXPECT_EQ(initial_version + kRepeatCount - 1, GetVersion(id));
575 EXPECT_EQ(kPayload1, GetPayload(id));
576 EXPECT_TRUE(StartsWithUnknownVersion(id));
579 // Fire an invalidation, then fire another one with a lower version. Both
580 // should be received.
581 TEST_F(SyncInvalidationListenerTest, InvalidateVersion) {
582 const ObjectId& id = kPreferencesId_;
584 FireInvalidate(id, kVersion2, kPayload2);
586 ASSERT_EQ(1U, GetInvalidationCount(id));
587 ASSERT_FALSE(IsUnknownVersion(id));
588 EXPECT_EQ(kVersion2, GetVersion(id));
589 EXPECT_EQ(kPayload2, GetPayload(id));
591 FireInvalidate(id, kVersion1, kPayload1);
593 ASSERT_EQ(2U, GetInvalidationCount(id));
594 ASSERT_FALSE(IsUnknownVersion(id));
596 EXPECT_EQ(kVersion1, GetVersion(id));
597 EXPECT_EQ(kPayload1, GetPayload(id));
600 // Fire an invalidation with an unknown version.
601 TEST_F(SyncInvalidationListenerTest, InvalidateUnknownVersion) {
602 const ObjectId& id = kBookmarksId_;
604 FireInvalidateUnknownVersion(id);
606 ASSERT_EQ(1U, GetInvalidationCount(id));
607 EXPECT_TRUE(IsUnknownVersion(id));
610 // Fire an invalidation for all enabled IDs.
611 TEST_F(SyncInvalidationListenerTest, InvalidateAll) {
612 FireInvalidateAll();
614 for (ObjectIdSet::const_iterator it = registered_ids_.begin();
615 it != registered_ids_.end(); ++it) {
616 ASSERT_EQ(1U, GetInvalidationCount(*it));
617 EXPECT_TRUE(IsUnknownVersion(*it));
621 // Test a simple scenario for multiple IDs.
622 TEST_F(SyncInvalidationListenerTest, InvalidateMultipleIds) {
623 FireInvalidate(kBookmarksId_, 3, NULL);
625 ASSERT_EQ(1U, GetInvalidationCount(kBookmarksId_));
626 ASSERT_FALSE(IsUnknownVersion(kBookmarksId_));
627 EXPECT_EQ(3, GetVersion(kBookmarksId_));
628 EXPECT_EQ("", GetPayload(kBookmarksId_));
630 // kExtensionId is not registered, so the invalidation should not get through.
631 FireInvalidate(kExtensionsId_, 2, NULL);
632 ASSERT_EQ(0U, GetInvalidationCount(kExtensionsId_));
635 // Registration tests.
637 // With IDs already registered, enable notifications then ready the
638 // client. The IDs should be registered only after the client is
639 // readied.
640 TEST_F(SyncInvalidationListenerTest, RegisterEnableReady) {
641 EXPECT_TRUE(GetRegisteredIds().empty());
643 EnableNotifications();
645 EXPECT_TRUE(GetRegisteredIds().empty());
647 listener_.Ready(fake_invalidation_client_);
649 EXPECT_EQ(registered_ids_, GetRegisteredIds());
652 // With IDs already registered, ready the client then enable
653 // notifications. The IDs should be registered after the client is
654 // readied.
655 TEST_F(SyncInvalidationListenerTest, RegisterReadyEnable) {
656 EXPECT_TRUE(GetRegisteredIds().empty());
658 listener_.Ready(fake_invalidation_client_);
660 EXPECT_EQ(registered_ids_, GetRegisteredIds());
662 EnableNotifications();
664 EXPECT_EQ(registered_ids_, GetRegisteredIds());
667 // Unregister the IDs, enable notifications, re-register the IDs, then
668 // ready the client. The IDs should be registered only after the
669 // client is readied.
670 TEST_F(SyncInvalidationListenerTest, EnableRegisterReady) {
671 listener_.UpdateRegisteredIds(ObjectIdSet());
673 EXPECT_TRUE(GetRegisteredIds().empty());
675 EnableNotifications();
677 EXPECT_TRUE(GetRegisteredIds().empty());
679 listener_.UpdateRegisteredIds(registered_ids_);
681 EXPECT_TRUE(GetRegisteredIds().empty());
683 listener_.Ready(fake_invalidation_client_);
685 EXPECT_EQ(registered_ids_, GetRegisteredIds());
688 // Unregister the IDs, enable notifications, ready the client, then
689 // re-register the IDs. The IDs should be registered only after the
690 // client is readied.
691 TEST_F(SyncInvalidationListenerTest, EnableReadyRegister) {
692 listener_.UpdateRegisteredIds(ObjectIdSet());
694 EXPECT_TRUE(GetRegisteredIds().empty());
696 EnableNotifications();
698 EXPECT_TRUE(GetRegisteredIds().empty());
700 listener_.Ready(fake_invalidation_client_);
702 EXPECT_TRUE(GetRegisteredIds().empty());
704 listener_.UpdateRegisteredIds(registered_ids_);
706 EXPECT_EQ(registered_ids_, GetRegisteredIds());
709 // Unregister the IDs, ready the client, enable notifications, then
710 // re-register the IDs. The IDs should be registered only after the
711 // client is readied.
712 TEST_F(SyncInvalidationListenerTest, ReadyEnableRegister) {
713 listener_.UpdateRegisteredIds(ObjectIdSet());
715 EXPECT_TRUE(GetRegisteredIds().empty());
717 EnableNotifications();
719 EXPECT_TRUE(GetRegisteredIds().empty());
721 listener_.Ready(fake_invalidation_client_);
723 EXPECT_TRUE(GetRegisteredIds().empty());
725 listener_.UpdateRegisteredIds(registered_ids_);
727 EXPECT_EQ(registered_ids_, GetRegisteredIds());
730 // Unregister the IDs, ready the client, re-register the IDs, then
731 // enable notifications. The IDs should be registered only after the
732 // client is readied.
734 // This test is important: see http://crbug.com/139424.
735 TEST_F(SyncInvalidationListenerTest, ReadyRegisterEnable) {
736 listener_.UpdateRegisteredIds(ObjectIdSet());
738 EXPECT_TRUE(GetRegisteredIds().empty());
740 listener_.Ready(fake_invalidation_client_);
742 EXPECT_TRUE(GetRegisteredIds().empty());
744 listener_.UpdateRegisteredIds(registered_ids_);
746 EXPECT_EQ(registered_ids_, GetRegisteredIds());
748 EnableNotifications();
750 EXPECT_EQ(registered_ids_, GetRegisteredIds());
753 // With IDs already registered, ready the client, restart the client,
754 // then re-ready it. The IDs should still be registered.
755 TEST_F(SyncInvalidationListenerTest, RegisterTypesPreserved) {
756 EXPECT_TRUE(GetRegisteredIds().empty());
758 listener_.Ready(fake_invalidation_client_);
760 EXPECT_EQ(registered_ids_, GetRegisteredIds());
762 RestartClient();
764 EXPECT_TRUE(GetRegisteredIds().empty());
766 listener_.Ready(fake_invalidation_client_);
768 EXPECT_EQ(registered_ids_, GetRegisteredIds());
771 // Make sure that state is correctly purged from the local invalidation state
772 // map cache when an ID is unregistered.
773 TEST_F(SyncInvalidationListenerTest, UnregisterCleansUpStateMapCache) {
774 const ObjectId& id = kBookmarksId_;
775 listener_.Ready(fake_invalidation_client_);
777 EXPECT_TRUE(GetSavedInvalidations().empty());
778 FireInvalidate(id, 1, "hello");
779 EXPECT_EQ(1U, GetSavedInvalidations().size());
780 EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
781 FireInvalidate(kPreferencesId_, 2, "world");
782 EXPECT_EQ(2U, GetSavedInvalidations().size());
784 EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
785 EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), kPreferencesId_));
787 ObjectIdSet ids;
788 ids.insert(id);
789 listener_.UpdateRegisteredIds(ids);
790 EXPECT_EQ(1U, GetSavedInvalidations().size());
791 EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
794 TEST_F(SyncInvalidationListenerTest, DuplicateInvaldiations_Simple) {
795 const ObjectId& id = kBookmarksId_;
796 listener_.Ready(fake_invalidation_client_);
798 // Send a stream of invalidations, including two copies of the second.
799 FireInvalidate(id, 1, "one");
800 FireInvalidate(id, 2, "two");
801 FireInvalidate(id, 3, "three");
802 FireInvalidate(id, 2, "two");
804 // Expect that the duplicate was discarded.
805 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
806 EXPECT_EQ(3U, list.GetSize());
807 SingleObjectInvalidationSet::const_iterator it = list.begin();
808 EXPECT_EQ(1, it->version());
809 it++;
810 EXPECT_EQ(2, it->version());
811 it++;
812 EXPECT_EQ(3, it->version());
815 TEST_F(SyncInvalidationListenerTest, DuplicateInvalidations_NearBufferLimit) {
816 const size_t kPairsToSend = UnackedInvalidationSet::kMaxBufferedInvalidations;
817 const ObjectId& id = kBookmarksId_;
818 listener_.Ready(fake_invalidation_client_);
820 // We will have enough buffer space in the state tracker for all these
821 // invalidations only if duplicates are ignored.
822 for (size_t i = 0; i < kPairsToSend; ++i) {
823 FireInvalidate(id, i, "payload");
824 FireInvalidate(id, i, "payload");
827 // Expect that the state map ignored duplicates.
828 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
829 EXPECT_EQ(kPairsToSend, list.GetSize());
830 EXPECT_FALSE(list.begin()->is_unknown_version());
832 // Expect that all invalidations (including duplicates) were emitted.
833 EXPECT_EQ(kPairsToSend*2, GetInvalidationCount(id));
835 // Acknowledge all invalidations to clear the internal state.
836 AcknowledgeAll(id);
837 EXPECT_TRUE(GetSavedInvalidationsForType(id).IsEmpty());
840 TEST_F(SyncInvalidationListenerTest, DuplicateInvalidations_UnknownVersion) {
841 const ObjectId& id = kBookmarksId_;
842 listener_.Ready(fake_invalidation_client_);
844 FireInvalidateUnknownVersion(id);
845 FireInvalidateUnknownVersion(id);
848 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
849 EXPECT_EQ(1U, list.GetSize());
852 // Acknowledge the second. There should be no effect on the stored list.
853 ASSERT_EQ(2U, GetInvalidationCount(id));
854 AcknowledgeNthInvalidation(id, 1);
856 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
857 EXPECT_EQ(1U, list.GetSize());
860 // Acknowledge the first. This should remove the invalidation from the list.
861 ASSERT_EQ(2U, GetInvalidationCount(id));
862 AcknowledgeNthInvalidation(id, 0);
864 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
865 EXPECT_EQ(0U, list.GetSize());
869 // Make sure that acknowledgements erase items from the local store.
870 TEST_F(SyncInvalidationListenerTest, AcknowledgementsCleanUpStateMapCache) {
871 const ObjectId& id = kBookmarksId_;
872 listener_.Ready(fake_invalidation_client_);
874 EXPECT_TRUE(GetSavedInvalidations().empty());
875 FireInvalidate(id, 10, "hello");
876 FireInvalidate(id, 20, "world");
877 FireInvalidateUnknownVersion(id);
879 // Expect that all three invalidations have been saved to permanent storage.
881 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
882 ASSERT_EQ(3U, list.GetSize());
883 EXPECT_TRUE(list.begin()->is_unknown_version());
884 EXPECT_EQ(20, list.back().version());
887 // Acknowledge the second sent invaldiation (version 20) and verify it was
888 // removed from storage.
889 AcknowledgeNthInvalidation(id, 1);
891 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
892 ASSERT_EQ(2U, list.GetSize());
893 EXPECT_TRUE(list.begin()->is_unknown_version());
894 EXPECT_EQ(10, list.back().version());
897 // Acknowledge the last sent invalidation (unknown version) and verify it was
898 // removed from storage.
899 AcknowledgeNthInvalidation(id, 2);
901 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
902 ASSERT_EQ(1U, list.GetSize());
903 EXPECT_FALSE(list.begin()->is_unknown_version());
904 EXPECT_EQ(10, list.back().version());
908 // Make sure that drops erase items from the local store.
909 TEST_F(SyncInvalidationListenerTest, DropsCleanUpStateMapCache) {
910 const ObjectId& id = kBookmarksId_;
911 listener_.Ready(fake_invalidation_client_);
913 EXPECT_TRUE(GetSavedInvalidations().empty());
914 FireInvalidate(id, 10, "hello");
915 FireInvalidate(id, 20, "world");
916 FireInvalidateUnknownVersion(id);
918 // Expect that all three invalidations have been saved to permanent storage.
920 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
921 ASSERT_EQ(3U, list.GetSize());
922 EXPECT_TRUE(list.begin()->is_unknown_version());
923 EXPECT_EQ(20, list.back().version());
926 // Drop the second sent invalidation (version 20) and verify it was removed
927 // from storage. Also verify we still have an unknown version invalidation.
928 DropNthInvalidation(id, 1);
930 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
931 ASSERT_EQ(2U, list.GetSize());
932 EXPECT_TRUE(list.begin()->is_unknown_version());
933 EXPECT_EQ(10, list.back().version());
936 // Drop the remaining invalidation. Verify an unknown version is all that
937 // remains.
938 DropNthInvalidation(id, 0);
940 SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
941 ASSERT_EQ(1U, list.GetSize());
942 EXPECT_TRUE(list.begin()->is_unknown_version());
945 // Announce that the delegate has recovered from the drop. Verify no
946 // invalidations remain saved.
947 RecoverFromDropEvent(id);
948 EXPECT_TRUE(GetSavedInvalidationsForType(id).IsEmpty());
950 RecoverFromDropEvent(id);
953 // Without readying the client, disable notifications, then enable
954 // them. The listener should still think notifications are disabled.
955 TEST_F(SyncInvalidationListenerTest, EnableNotificationsNotReady) {
956 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR,
957 GetInvalidatorState());
959 DisableNotifications(
960 notifier::TRANSIENT_NOTIFICATION_ERROR);
962 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
964 DisableNotifications(notifier::NOTIFICATION_CREDENTIALS_REJECTED);
966 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
968 EnableNotifications();
970 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
973 // Enable notifications then Ready the invalidation client. The
974 // delegate should then be ready.
975 TEST_F(SyncInvalidationListenerTest, EnableNotificationsThenReady) {
976 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
978 EnableNotifications();
980 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
982 listener_.Ready(fake_invalidation_client_);
984 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
987 // Ready the invalidation client then enable notifications. The
988 // delegate should then be ready.
989 TEST_F(SyncInvalidationListenerTest, ReadyThenEnableNotifications) {
990 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
992 listener_.Ready(fake_invalidation_client_);
994 EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
996 EnableNotifications();
998 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
1001 // Enable notifications and ready the client. Then disable
1002 // notifications with an auth error and re-enable notifications. The
1003 // delegate should go into an auth error mode and then back out.
1004 TEST_F(SyncInvalidationListenerTest, PushClientAuthError) {
1005 EnableNotifications();
1006 listener_.Ready(fake_invalidation_client_);
1008 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
1010 DisableNotifications(
1011 notifier::NOTIFICATION_CREDENTIALS_REJECTED);
1013 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
1015 EnableNotifications();
1017 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
1020 // Enable notifications and ready the client. Then simulate an auth
1021 // error from the invalidation client. Simulate some notification
1022 // events, then re-ready the client. The delegate should go into an
1023 // auth error mode and come out of it only after the client is ready.
1024 TEST_F(SyncInvalidationListenerTest, InvalidationClientAuthError) {
1025 EnableNotifications();
1026 listener_.Ready(fake_invalidation_client_);
1028 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
1030 listener_.InformError(
1031 fake_invalidation_client_,
1032 invalidation::ErrorInfo(
1033 invalidation::ErrorReason::AUTH_FAILURE,
1034 false /* is_transient */,
1035 "auth error",
1036 invalidation::ErrorContext()));
1038 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
1040 DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR);
1042 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
1044 DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR);
1046 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
1048 EnableNotifications();
1050 EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
1052 listener_.Ready(fake_invalidation_client_);
1054 EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
1057 // A variant of SyncInvalidationListenerTest that starts with some initial
1058 // state. We make not attempt to abstract away the contents of this state. The
1059 // tests that make use of this harness depend on its implementation details.
1060 class SyncInvalidationListenerTest_WithInitialState
1061 : public SyncInvalidationListenerTest {
1062 public:
1063 void SetUp() override {
1064 UnackedInvalidationSet bm_state(kBookmarksId_);
1065 UnackedInvalidationSet ext_state(kExtensionsId_);
1067 Invalidation bm_unknown = Invalidation::InitUnknownVersion(kBookmarksId_);
1068 Invalidation bm_v100 = Invalidation::Init(kBookmarksId_, 100, "hundred");
1069 bm_state.Add(bm_unknown);
1070 bm_state.Add(bm_v100);
1072 Invalidation ext_v10 = Invalidation::Init(kExtensionsId_, 10, "ten");
1073 Invalidation ext_v20 = Invalidation::Init(kExtensionsId_, 20, "twenty");
1074 ext_state.Add(ext_v10);
1075 ext_state.Add(ext_v20);
1077 initial_state.insert(std::make_pair(kBookmarksId_, bm_state));
1078 initial_state.insert(std::make_pair(kExtensionsId_, ext_state));
1080 fake_tracker_.SetSavedInvalidations(initial_state);
1082 SyncInvalidationListenerTest::SetUp();
1085 UnackedInvalidationsMap initial_state;
1088 // Verify that saved invalidations are forwarded when handlers register.
1089 TEST_F(SyncInvalidationListenerTest_WithInitialState,
1090 ReceiveSavedInvalidations) {
1091 EnableNotifications();
1092 listener_.Ready(fake_invalidation_client_);
1094 EXPECT_THAT(initial_state, test_util::Eq(GetSavedInvalidations()));
1096 ASSERT_EQ(2U, GetInvalidationCount(kBookmarksId_));
1097 EXPECT_EQ(100, GetVersion(kBookmarksId_));
1099 ASSERT_EQ(0U, GetInvalidationCount(kExtensionsId_));
1101 FireInvalidate(kExtensionsId_, 30, "thirty");
1103 ObjectIdSet ids = GetRegisteredIds();
1104 ids.insert(kExtensionsId_);
1105 listener_.UpdateRegisteredIds(ids);
1107 ASSERT_EQ(3U, GetInvalidationCount(kExtensionsId_));
1108 EXPECT_EQ(30, GetVersion(kExtensionsId_));
1111 } // namespace
1113 } // namespace syncer