This source file includes following definitions.
- GetRegisteredIds
- ClearAckedHandles
- IsAckedHandle
- Start
- Stop
- Register
- Register
- Unregister
- Unregister
- Acknowledge
- drop_handlers_deleter_
- GetInvalidationCount
- GetVersion
- GetPayload
- IsUnknownVersion
- StartsWithUnknownVersion
- GetInvalidatorState
- GetDropTrackerForObject
- AcknowledgeNthInvalidation
- AcknowledgeAll
- DropNthInvalidation
- RecoverFromDropEvent
- OnInvalidate
- OnInvalidatorStateChange
- CreateFakeInvalidationClient
- fake_delegate_
- SetUp
- TearDown
- RestartClient
- StartClient
- StopClient
- GetInvalidationCount
- GetVersion
- GetPayload
- IsUnknownVersion
- StartsWithUnknownVersion
- AcknowledgeNthInvalidation
- DropNthInvalidation
- RecoverFromDropEvent
- AcknowledgeAll
- GetInvalidatorState
- GetInvalidatorClientId
- GetBootstrapData
- GetSavedInvalidations
- GetSavedInvalidationsForType
- GetRegisteredIds
- FireInvalidate
- FireInvalidateUnknownVersion
- FireInvalidateAll
- WriteState
- FlushPendingWrites
- EnableNotifications
- DisableNotifications
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- SetUp
- TEST_F
#include <cstddef>
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "google/cacheinvalidation/include/invalidation-client.h"
#include "google/cacheinvalidation/include/types.h"
#include "jingle/notifier/listener/fake_push_client.h"
#include "sync/internal_api/public/util/weak_handle.h"
#include "sync/notifier/dropped_invalidation_tracker.h"
#include "sync/notifier/fake_invalidation_state_tracker.h"
#include "sync/notifier/invalidation_util.h"
#include "sync/notifier/object_id_invalidation_map.h"
#include "sync/notifier/push_client_channel.h"
#include "sync/notifier/sync_invalidation_listener.h"
#include "sync/notifier/unacked_invalidation_set_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using invalidation::AckHandle;
using invalidation::ObjectId;
const char kClientId[] = "client_id";
const char kClientInfo[] = "client_info";
const char kState[] = "state";
const char kNewState[] = "new_state";
const char kPayload1[] = "payload1";
const char kPayload2[] = "payload2";
const int64 kVersion1 = 1LL;
const int64 kVersion2 = 2LL;
const int kChromeSyncSourceId = 1004;
struct AckHandleLessThan {
bool operator()(const AckHandle& lhs, const AckHandle& rhs) const {
return lhs.handle_data() < rhs.handle_data();
}
};
typedef std::set<AckHandle, AckHandleLessThan> AckHandleSet;
class FakeInvalidationClient : public invalidation::InvalidationClient {
public:
FakeInvalidationClient() : started_(false) {}
virtual ~FakeInvalidationClient() {}
const ObjectIdSet& GetRegisteredIds() const {
return registered_ids_;
}
void ClearAckedHandles() {
acked_handles_.clear();
}
bool IsAckedHandle(const AckHandle& ack_handle) const {
return (acked_handles_.find(ack_handle) != acked_handles_.end());
}
virtual void Start() OVERRIDE {
started_ = true;
}
virtual void Stop() OVERRIDE {
started_ = false;
}
virtual void Register(const ObjectId& object_id) OVERRIDE {
if (!started_) {
ADD_FAILURE();
return;
}
registered_ids_.insert(object_id);
}
virtual void Register(
const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
if (!started_) {
ADD_FAILURE();
return;
}
registered_ids_.insert(object_ids.begin(), object_ids.end());
}
virtual void Unregister(const ObjectId& object_id) OVERRIDE {
if (!started_) {
ADD_FAILURE();
return;
}
registered_ids_.erase(object_id);
}
virtual void Unregister(
const invalidation::vector<ObjectId>& object_ids) OVERRIDE {
if (!started_) {
ADD_FAILURE();
return;
}
for (invalidation::vector<ObjectId>::const_iterator
it = object_ids.begin(); it != object_ids.end(); ++it) {
registered_ids_.erase(*it);
}
}
virtual void Acknowledge(const AckHandle& ack_handle) OVERRIDE {
if (!started_) {
ADD_FAILURE();
return;
}
acked_handles_.insert(ack_handle);
}
private:
bool started_;
ObjectIdSet registered_ids_;
AckHandleSet acked_handles_;
};
class FakeDelegate : public SyncInvalidationListener::Delegate {
public:
explicit FakeDelegate(SyncInvalidationListener* listener)
: state_(TRANSIENT_INVALIDATION_ERROR),
drop_handlers_deleter_(&drop_handlers_) {}
virtual ~FakeDelegate() {}
size_t GetInvalidationCount(const ObjectId& id) const {
Map::const_iterator it = invalidations_.find(id);
if (it == invalidations_.end()) {
return 0;
} else {
return it->second.size();
}
}
int64 GetVersion(const ObjectId& id) const {
Map::const_iterator it = invalidations_.find(id);
if (it == invalidations_.end()) {
ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
return 0;
} else {
return it->second.back().version();
}
}
std::string GetPayload(const ObjectId& id) const {
Map::const_iterator it = invalidations_.find(id);
if (it == invalidations_.end()) {
ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
return 0;
} else {
return it->second.back().payload();
}
}
bool IsUnknownVersion(const ObjectId& id) const {
Map::const_iterator it = invalidations_.find(id);
if (it == invalidations_.end()) {
ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
return false;
} else {
return it->second.back().is_unknown_version();
}
}
bool StartsWithUnknownVersion(const ObjectId& id) const {
Map::const_iterator it = invalidations_.find(id);
if (it == invalidations_.end()) {
ADD_FAILURE() << "No invalidations for ID " << ObjectIdToString(id);
return false;
} else {
return it->second.front().is_unknown_version();
}
}
InvalidatorState GetInvalidatorState() const {
return state_;
}
DroppedInvalidationTracker* GetDropTrackerForObject(const ObjectId& id) {
DropHandlers::iterator it = drop_handlers_.find(id);
if (it == drop_handlers_.end()) {
drop_handlers_.insert(
std::make_pair(id, new DroppedInvalidationTracker(id)));
return drop_handlers_.find(id)->second;
} else {
return it->second;
}
}
void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) {
List& list = invalidations_[id];
List::iterator it = list.begin() + n;
it->Acknowledge();
}
void AcknowledgeAll(const ObjectId& id) {
List& list = invalidations_[id];
for (List::iterator it = list.begin(); it != list.end(); ++it) {
it->Acknowledge();
}
}
void DropNthInvalidation(const ObjectId& id, size_t n) {
DroppedInvalidationTracker* drop_tracker = GetDropTrackerForObject(id);
List& list = invalidations_[id];
List::iterator it = list.begin() + n;
it->Drop(drop_tracker);
}
void RecoverFromDropEvent(const ObjectId& id) {
DroppedInvalidationTracker* drop_tracker = GetDropTrackerForObject(id);
drop_tracker->RecordRecoveryFromDropEvent();
}
virtual void OnInvalidate(
const ObjectIdInvalidationMap& invalidation_map) OVERRIDE {
ObjectIdSet ids = invalidation_map.GetObjectIds();
for (ObjectIdSet::iterator it = ids.begin(); it != ids.end(); ++it) {
const SingleObjectInvalidationSet& incoming =
invalidation_map.ForObject(*it);
List& list = invalidations_[*it];
list.insert(list.end(), incoming.begin(), incoming.end());
}
}
virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE {
state_ = state;
}
private:
typedef std::vector<Invalidation> List;
typedef std::map<ObjectId, List, ObjectIdLessThan> Map;
typedef std::map<ObjectId,
DroppedInvalidationTracker*,
ObjectIdLessThan> DropHandlers;
Map invalidations_;
InvalidatorState state_;
DropHandlers drop_handlers_;
STLValueDeleter<DropHandlers> drop_handlers_deleter_;
};
invalidation::InvalidationClient* CreateFakeInvalidationClient(
FakeInvalidationClient** fake_invalidation_client,
invalidation::SystemResources* resources,
int client_type,
const invalidation::string& client_name,
const invalidation::string& application_name,
invalidation::InvalidationListener* listener) {
*fake_invalidation_client = new FakeInvalidationClient();
return *fake_invalidation_client;
}
class SyncInvalidationListenerTest : public testing::Test {
protected:
SyncInvalidationListenerTest()
: kBookmarksId_(kChromeSyncSourceId, "BOOKMARK"),
kPreferencesId_(kChromeSyncSourceId, "PREFERENCE"),
kExtensionsId_(kChromeSyncSourceId, "EXTENSION"),
kAppsId_(kChromeSyncSourceId, "APP"),
fake_push_client_(new notifier::FakePushClient()),
fake_invalidation_client_(NULL),
listener_(scoped_ptr<SyncNetworkChannel>(new PushClientChannel(
scoped_ptr<notifier::PushClient>(fake_push_client_)))),
fake_delegate_(&listener_) {}
virtual void SetUp() {
StartClient();
registered_ids_.insert(kBookmarksId_);
registered_ids_.insert(kPreferencesId_);
listener_.UpdateRegisteredIds(registered_ids_);
}
virtual void TearDown() {
StopClient();
}
void RestartClient() {
StopClient();
StartClient();
}
void StartClient() {
fake_invalidation_client_ = NULL;
listener_.Start(base::Bind(&CreateFakeInvalidationClient,
&fake_invalidation_client_),
kClientId, kClientInfo, kState,
fake_tracker_.GetSavedInvalidations(),
MakeWeakHandle(fake_tracker_.AsWeakPtr()),
&fake_delegate_);
DCHECK(fake_invalidation_client_);
}
void StopClient() {
FlushPendingWrites();
fake_invalidation_client_ = NULL;
listener_.StopForTest();
}
size_t GetInvalidationCount(const ObjectId& id) const {
return fake_delegate_.GetInvalidationCount(id);
}
int64 GetVersion(const ObjectId& id) const {
return fake_delegate_.GetVersion(id);
}
std::string GetPayload(const ObjectId& id) const {
return fake_delegate_.GetPayload(id);
}
bool IsUnknownVersion(const ObjectId& id) const {
return fake_delegate_.IsUnknownVersion(id);
}
bool StartsWithUnknownVersion(const ObjectId& id) const {
return fake_delegate_.StartsWithUnknownVersion(id);
}
void AcknowledgeNthInvalidation(const ObjectId& id, size_t n) {
fake_delegate_.AcknowledgeNthInvalidation(id, n);
}
void DropNthInvalidation(const ObjectId& id, size_t n) {
return fake_delegate_.DropNthInvalidation(id, n);
}
void RecoverFromDropEvent(const ObjectId& id) {
return fake_delegate_.RecoverFromDropEvent(id);
}
void AcknowledgeAll(const ObjectId& id) {
fake_delegate_.AcknowledgeAll(id);
}
InvalidatorState GetInvalidatorState() const {
return fake_delegate_.GetInvalidatorState();
}
std::string GetInvalidatorClientId() const {
return fake_tracker_.GetInvalidatorClientId();
}
std::string GetBootstrapData() const {
return fake_tracker_.GetBootstrapData();
}
UnackedInvalidationsMap GetSavedInvalidations() {
FlushPendingWrites();
return fake_tracker_.GetSavedInvalidations();
}
SingleObjectInvalidationSet GetSavedInvalidationsForType(const ObjectId& id) {
const UnackedInvalidationsMap& saved_state = GetSavedInvalidations();
UnackedInvalidationsMap::const_iterator it =
saved_state.find(kBookmarksId_);
if (it == saved_state.end()) {
ADD_FAILURE() << "No state saved for ID " << ObjectIdToString(id);
return SingleObjectInvalidationSet();
}
ObjectIdInvalidationMap map;
it->second.ExportInvalidations(WeakHandle<AckHandler>(), &map);
if (map.Empty()) {
return SingleObjectInvalidationSet();
} else {
return map.ForObject(id);
}
}
ObjectIdSet GetRegisteredIds() const {
return fake_invalidation_client_->GetRegisteredIds();
}
void FireInvalidate(const ObjectId& object_id,
int64 version, const char* payload) {
invalidation::Invalidation inv;
if (payload) {
inv = invalidation::Invalidation(object_id, version, payload);
} else {
inv = invalidation::Invalidation(object_id, version);
}
const AckHandle ack_handle("fakedata");
fake_invalidation_client_->ClearAckedHandles();
listener_.Invalidate(fake_invalidation_client_, inv, ack_handle);
EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
}
void FireInvalidateUnknownVersion(const ObjectId& object_id) {
const AckHandle ack_handle("fakedata_unknown");
fake_invalidation_client_->ClearAckedHandles();
listener_.InvalidateUnknownVersion(fake_invalidation_client_,
object_id,
ack_handle);
EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
}
void FireInvalidateAll() {
const AckHandle ack_handle("fakedata_all");
fake_invalidation_client_->ClearAckedHandles();
listener_.InvalidateAll(fake_invalidation_client_, ack_handle);
EXPECT_TRUE(fake_invalidation_client_->IsAckedHandle(ack_handle));
}
void WriteState(const std::string& new_state) {
listener_.WriteState(new_state);
FlushPendingWrites();
}
void FlushPendingWrites() {
message_loop_.RunUntilIdle();
}
void EnableNotifications() {
fake_push_client_->EnableNotifications();
}
void DisableNotifications(notifier::NotificationsDisabledReason reason) {
fake_push_client_->DisableNotifications(reason);
}
const ObjectId kBookmarksId_;
const ObjectId kPreferencesId_;
const ObjectId kExtensionsId_;
const ObjectId kAppsId_;
ObjectIdSet registered_ids_;
private:
base::MessageLoop message_loop_;
notifier::FakePushClient* const fake_push_client_;
protected:
FakeInvalidationStateTracker fake_tracker_;
FakeInvalidationClient* fake_invalidation_client_;
SyncInvalidationListener listener_;
private:
FakeDelegate fake_delegate_;
};
TEST_F(SyncInvalidationListenerTest, WriteState) {
WriteState(kNewState);
EXPECT_EQ(kNewState, GetBootstrapData());
}
TEST_F(SyncInvalidationListenerTest, InvalidateNoPayload) {
const ObjectId& id = kBookmarksId_;
FireInvalidate(id, kVersion1, NULL);
ASSERT_EQ(1U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion1, GetVersion(id));
EXPECT_EQ("", GetPayload(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateEmptyPayload) {
const ObjectId& id = kBookmarksId_;
FireInvalidate(id, kVersion1, "");
ASSERT_EQ(1U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion1, GetVersion(id));
EXPECT_EQ("", GetPayload(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateWithPayload) {
const ObjectId& id = kPreferencesId_;
FireInvalidate(id, kVersion1, kPayload1);
ASSERT_EQ(1U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion1, GetVersion(id));
EXPECT_EQ(kPayload1, GetPayload(id));
}
TEST_F(SyncInvalidationListenerTest, ManyInvalidations_NoDrop) {
const int kRepeatCount = 10;
const ObjectId& id = kPreferencesId_;
int64 initial_version = kVersion1;
for (int64 i = initial_version; i < initial_version + kRepeatCount; ++i) {
FireInvalidate(id, i, kPayload1);
}
ASSERT_EQ(static_cast<size_t>(kRepeatCount), GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kPayload1, GetPayload(id));
EXPECT_EQ(initial_version + kRepeatCount - 1, GetVersion(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateBeforeRegistration_Simple) {
const ObjectId kUnregisteredId(kChromeSyncSourceId, "unregistered");
const ObjectId& id = kUnregisteredId;
ObjectIdSet ids;
ids.insert(id);
EXPECT_EQ(0U, GetInvalidationCount(id));
FireInvalidate(id, kVersion1, kPayload1);
ASSERT_EQ(0U, GetInvalidationCount(id));
EnableNotifications();
listener_.Ready(fake_invalidation_client_);
listener_.UpdateRegisteredIds(ids);
ASSERT_EQ(1U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion1, GetVersion(id));
EXPECT_EQ(kPayload1, GetPayload(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateBeforeRegistration_Drop) {
const int kRepeatCount =
UnackedInvalidationSet::kMaxBufferedInvalidations + 1;
const ObjectId kUnregisteredId(kChromeSyncSourceId, "unregistered");
const ObjectId& id = kUnregisteredId;
ObjectIdSet ids;
ids.insert(id);
EXPECT_EQ(0U, GetInvalidationCount(id));
int64 initial_version = kVersion1;
for (int64 i = initial_version; i < initial_version + kRepeatCount; ++i) {
FireInvalidate(id, i, kPayload1);
}
EnableNotifications();
listener_.Ready(fake_invalidation_client_);
listener_.UpdateRegisteredIds(ids);
ASSERT_EQ(UnackedInvalidationSet::kMaxBufferedInvalidations,
GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(initial_version + kRepeatCount - 1, GetVersion(id));
EXPECT_EQ(kPayload1, GetPayload(id));
EXPECT_TRUE(StartsWithUnknownVersion(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateVersion) {
const ObjectId& id = kPreferencesId_;
FireInvalidate(id, kVersion2, kPayload2);
ASSERT_EQ(1U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion2, GetVersion(id));
EXPECT_EQ(kPayload2, GetPayload(id));
FireInvalidate(id, kVersion1, kPayload1);
ASSERT_EQ(2U, GetInvalidationCount(id));
ASSERT_FALSE(IsUnknownVersion(id));
EXPECT_EQ(kVersion1, GetVersion(id));
EXPECT_EQ(kPayload1, GetPayload(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateUnknownVersion) {
const ObjectId& id = kBookmarksId_;
FireInvalidateUnknownVersion(id);
ASSERT_EQ(1U, GetInvalidationCount(id));
EXPECT_TRUE(IsUnknownVersion(id));
}
TEST_F(SyncInvalidationListenerTest, InvalidateAll) {
FireInvalidateAll();
for (ObjectIdSet::const_iterator it = registered_ids_.begin();
it != registered_ids_.end(); ++it) {
ASSERT_EQ(1U, GetInvalidationCount(*it));
EXPECT_TRUE(IsUnknownVersion(*it));
}
}
TEST_F(SyncInvalidationListenerTest, InvalidateMultipleIds) {
FireInvalidate(kBookmarksId_, 3, NULL);
ASSERT_EQ(1U, GetInvalidationCount(kBookmarksId_));
ASSERT_FALSE(IsUnknownVersion(kBookmarksId_));
EXPECT_EQ(3, GetVersion(kBookmarksId_));
EXPECT_EQ("", GetPayload(kBookmarksId_));
FireInvalidate(kExtensionsId_, 2, NULL);
ASSERT_EQ(0U, GetInvalidationCount(kExtensionsId_));
}
TEST_F(SyncInvalidationListenerTest, RegisterEnableReady) {
EXPECT_TRUE(GetRegisteredIds().empty());
EnableNotifications();
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, RegisterReadyEnable) {
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
EnableNotifications();
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, EnableRegisterReady) {
listener_.UpdateRegisteredIds(ObjectIdSet());
EXPECT_TRUE(GetRegisteredIds().empty());
EnableNotifications();
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.UpdateRegisteredIds(registered_ids_);
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, EnableReadyRegister) {
listener_.UpdateRegisteredIds(ObjectIdSet());
EXPECT_TRUE(GetRegisteredIds().empty());
EnableNotifications();
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.UpdateRegisteredIds(registered_ids_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, ReadyEnableRegister) {
listener_.UpdateRegisteredIds(ObjectIdSet());
EXPECT_TRUE(GetRegisteredIds().empty());
EnableNotifications();
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.UpdateRegisteredIds(registered_ids_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, ReadyRegisterEnable) {
listener_.UpdateRegisteredIds(ObjectIdSet());
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.UpdateRegisteredIds(registered_ids_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
EnableNotifications();
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, RegisterTypesPreserved) {
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
RestartClient();
EXPECT_TRUE(GetRegisteredIds().empty());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(registered_ids_, GetRegisteredIds());
}
TEST_F(SyncInvalidationListenerTest, UnregisterCleansUpStateMapCache) {
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetSavedInvalidations().empty());
FireInvalidate(id, 1, "hello");
EXPECT_EQ(1U, GetSavedInvalidations().size());
EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
FireInvalidate(kPreferencesId_, 2, "world");
EXPECT_EQ(2U, GetSavedInvalidations().size());
EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), kPreferencesId_));
ObjectIdSet ids;
ids.insert(id);
listener_.UpdateRegisteredIds(ids);
EXPECT_EQ(1U, GetSavedInvalidations().size());
EXPECT_TRUE(ContainsKey(GetSavedInvalidations(), id));
}
TEST_F(SyncInvalidationListenerTest, DuplicateInvaldiations_Simple) {
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
FireInvalidate(id, 1, "one");
FireInvalidate(id, 2, "two");
FireInvalidate(id, 3, "three");
FireInvalidate(id, 2, "two");
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
EXPECT_EQ(3U, list.GetSize());
SingleObjectInvalidationSet::const_iterator it = list.begin();
EXPECT_EQ(1, it->version());
it++;
EXPECT_EQ(2, it->version());
it++;
EXPECT_EQ(3, it->version());
}
TEST_F(SyncInvalidationListenerTest, DuplicateInvalidations_NearBufferLimit) {
const size_t kPairsToSend = UnackedInvalidationSet::kMaxBufferedInvalidations;
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
for (size_t i = 0; i < kPairsToSend; ++i) {
FireInvalidate(id, i, "payload");
FireInvalidate(id, i, "payload");
}
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
EXPECT_EQ(kPairsToSend, list.GetSize());
EXPECT_FALSE(list.begin()->is_unknown_version());
EXPECT_EQ(kPairsToSend*2, GetInvalidationCount(id));
AcknowledgeAll(id);
EXPECT_TRUE(GetSavedInvalidationsForType(id).IsEmpty());
}
TEST_F(SyncInvalidationListenerTest, DuplicateInvalidations_UnknownVersion) {
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
FireInvalidateUnknownVersion(id);
FireInvalidateUnknownVersion(id);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
EXPECT_EQ(1U, list.GetSize());
}
ASSERT_EQ(2U, GetInvalidationCount(id));
AcknowledgeNthInvalidation(id, 1);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
EXPECT_EQ(1U, list.GetSize());
}
ASSERT_EQ(2U, GetInvalidationCount(id));
AcknowledgeNthInvalidation(id, 0);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
EXPECT_EQ(0U, list.GetSize());
}
}
TEST_F(SyncInvalidationListenerTest, AcknowledgementsCleanUpStateMapCache) {
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetSavedInvalidations().empty());
FireInvalidate(id, 10, "hello");
FireInvalidate(id, 20, "world");
FireInvalidateUnknownVersion(id);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(3U, list.GetSize());
EXPECT_TRUE(list.begin()->is_unknown_version());
EXPECT_EQ(20, list.back().version());
}
AcknowledgeNthInvalidation(id, 1);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(2U, list.GetSize());
EXPECT_TRUE(list.begin()->is_unknown_version());
EXPECT_EQ(10, list.back().version());
}
AcknowledgeNthInvalidation(id, 2);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(1U, list.GetSize());
EXPECT_FALSE(list.begin()->is_unknown_version());
EXPECT_EQ(10, list.back().version());
}
}
TEST_F(SyncInvalidationListenerTest, DropsCleanUpStateMapCache) {
const ObjectId& id = kBookmarksId_;
listener_.Ready(fake_invalidation_client_);
EXPECT_TRUE(GetSavedInvalidations().empty());
FireInvalidate(id, 10, "hello");
FireInvalidate(id, 20, "world");
FireInvalidateUnknownVersion(id);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(3U, list.GetSize());
EXPECT_TRUE(list.begin()->is_unknown_version());
EXPECT_EQ(20, list.back().version());
}
DropNthInvalidation(id, 1);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(2U, list.GetSize());
EXPECT_TRUE(list.begin()->is_unknown_version());
EXPECT_EQ(10, list.back().version());
}
DropNthInvalidation(id, 0);
{
SingleObjectInvalidationSet list = GetSavedInvalidationsForType(id);
ASSERT_EQ(1U, list.GetSize());
EXPECT_TRUE(list.begin()->is_unknown_version());
}
RecoverFromDropEvent(id);
EXPECT_TRUE(GetSavedInvalidationsForType(id).IsEmpty());
RecoverFromDropEvent(id);
}
TEST_F(SyncInvalidationListenerTest, EnableNotificationsNotReady) {
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR,
GetInvalidatorState());
DisableNotifications(
notifier::TRANSIENT_NOTIFICATION_ERROR);
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
DisableNotifications(notifier::NOTIFICATION_CREDENTIALS_REJECTED);
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
EnableNotifications();
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
}
TEST_F(SyncInvalidationListenerTest, EnableNotificationsThenReady) {
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
EnableNotifications();
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
}
TEST_F(SyncInvalidationListenerTest, ReadyThenEnableNotifications) {
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, GetInvalidatorState());
EnableNotifications();
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
}
TEST_F(SyncInvalidationListenerTest, PushClientAuthError) {
EnableNotifications();
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
DisableNotifications(
notifier::NOTIFICATION_CREDENTIALS_REJECTED);
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
EnableNotifications();
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
}
TEST_F(SyncInvalidationListenerTest, InvalidationClientAuthError) {
EnableNotifications();
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
listener_.InformError(
fake_invalidation_client_,
invalidation::ErrorInfo(
invalidation::ErrorReason::AUTH_FAILURE,
false ,
"auth error",
invalidation::ErrorContext()));
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR);
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
DisableNotifications(notifier::TRANSIENT_NOTIFICATION_ERROR);
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
EnableNotifications();
EXPECT_EQ(INVALIDATION_CREDENTIALS_REJECTED, GetInvalidatorState());
listener_.Ready(fake_invalidation_client_);
EXPECT_EQ(INVALIDATIONS_ENABLED, GetInvalidatorState());
}
class SyncInvalidationListenerTest_WithInitialState
: public SyncInvalidationListenerTest {
public:
virtual void SetUp() {
UnackedInvalidationSet bm_state(kBookmarksId_);
UnackedInvalidationSet ext_state(kExtensionsId_);
Invalidation bm_unknown = Invalidation::InitUnknownVersion(kBookmarksId_);
Invalidation bm_v100 = Invalidation::Init(kBookmarksId_, 100, "hundred");
bm_state.Add(bm_unknown);
bm_state.Add(bm_v100);
Invalidation ext_v10 = Invalidation::Init(kExtensionsId_, 10, "ten");
Invalidation ext_v20 = Invalidation::Init(kExtensionsId_, 20, "twenty");
ext_state.Add(ext_v10);
ext_state.Add(ext_v20);
initial_state.insert(std::make_pair(kBookmarksId_, bm_state));
initial_state.insert(std::make_pair(kExtensionsId_, ext_state));
fake_tracker_.SetSavedInvalidations(initial_state);
SyncInvalidationListenerTest::SetUp();
}
UnackedInvalidationsMap initial_state;
};
TEST_F(SyncInvalidationListenerTest_WithInitialState,
ReceiveSavedInvalidations) {
EnableNotifications();
listener_.Ready(fake_invalidation_client_);
EXPECT_THAT(initial_state, test_util::Eq(GetSavedInvalidations()));
ASSERT_EQ(2U, GetInvalidationCount(kBookmarksId_));
EXPECT_EQ(100, GetVersion(kBookmarksId_));
ASSERT_EQ(0U, GetInvalidationCount(kExtensionsId_));
FireInvalidate(kExtensionsId_, 30, "thirty");
ObjectIdSet ids = GetRegisteredIds();
ids.insert(kExtensionsId_);
listener_.UpdateRegisteredIds(ids);
ASSERT_EQ(3U, GetInvalidationCount(kExtensionsId_));
EXPECT_EQ(30, GetVersion(kExtensionsId_));
}
}
}