diff options
Diffstat (limited to 'components/invalidation/p2p_invalidator_unittest.cc')
-rw-r--r-- | components/invalidation/p2p_invalidator_unittest.cc | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/components/invalidation/p2p_invalidator_unittest.cc b/components/invalidation/p2p_invalidator_unittest.cc new file mode 100644 index 0000000..150a91a --- /dev/null +++ b/components/invalidation/p2p_invalidator_unittest.cc @@ -0,0 +1,357 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/invalidation/p2p_invalidator.h" + +#include <cstddef> + +#include "components/invalidation/fake_invalidation_handler.h" +#include "components/invalidation/invalidator_test_template.h" +#include "components/invalidation/notifier_reason_util.h" +#include "jingle/notifier/listener/fake_push_client.h" +#include "sync/internal_api/public/base/invalidator_state.h" +#include "sync/internal_api/public/base/model_type.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +class P2PInvalidatorTestDelegate { + public: + P2PInvalidatorTestDelegate() : fake_push_client_(NULL) {} + + ~P2PInvalidatorTestDelegate() { + DestroyInvalidator(); + } + + void CreateInvalidator( + const std::string& invalidator_client_id, + const std::string& initial_state, + const base::WeakPtr<InvalidationStateTracker>& + invalidation_state_tracker) { + DCHECK(!fake_push_client_); + DCHECK(!invalidator_.get()); + fake_push_client_ = new notifier::FakePushClient(); + invalidator_.reset( + new P2PInvalidator( + scoped_ptr<notifier::PushClient>(fake_push_client_), + invalidator_client_id, + NOTIFY_OTHERS)); + } + + P2PInvalidator* GetInvalidator() { + return invalidator_.get(); + } + + notifier::FakePushClient* GetPushClient() { + return fake_push_client_; + } + + void DestroyInvalidator() { + invalidator_.reset(); + fake_push_client_ = NULL; + } + + void WaitForInvalidator() { + // Do Nothing. + } + + void TriggerOnInvalidatorStateChange(InvalidatorState state) { + if (state == INVALIDATIONS_ENABLED) { + fake_push_client_->EnableNotifications(); + } else { + fake_push_client_->DisableNotifications(ToNotifierReasonForTest(state)); + } + } + + void TriggerOnIncomingInvalidation( + const ObjectIdInvalidationMap& invalidation_map) { + const P2PNotificationData notification_data( + std::string(), NOTIFY_ALL, invalidation_map); + notifier::Notification notification; + notification.channel = kSyncP2PNotificationChannel; + notification.data = notification_data.ToString(); + fake_push_client_->SimulateIncomingNotification(notification); + } + + private: + // Owned by |invalidator_|. + notifier::FakePushClient* fake_push_client_; + scoped_ptr<P2PInvalidator> invalidator_; +}; + +class P2PInvalidatorTest : public testing::Test { + protected: + P2PInvalidatorTest() + : next_sent_notification_to_reflect_(0) { + delegate_.CreateInvalidator("sender", + "fake_state", + base::WeakPtr<InvalidationStateTracker>()); + delegate_.GetInvalidator()->RegisterHandler(&fake_handler_); + } + + virtual ~P2PInvalidatorTest() { + delegate_.GetInvalidator()->UnregisterHandler(&fake_handler_); + } + + ObjectIdInvalidationMap MakeInvalidationMap(ModelTypeSet types) { + ObjectIdInvalidationMap invalidations; + ObjectIdSet ids = ModelTypeSetToObjectIdSet(types); + return ObjectIdInvalidationMap::InvalidateAll(ids); + } + + // Simulate receiving all the notifications we sent out since last + // time this was called. + void ReflectSentNotifications() { + const std::vector<notifier::Notification>& sent_notifications = + delegate_.GetPushClient()->sent_notifications(); + for(size_t i = next_sent_notification_to_reflect_; + i < sent_notifications.size(); ++i) { + delegate_.GetInvalidator()->OnIncomingNotification(sent_notifications[i]); + } + next_sent_notification_to_reflect_ = sent_notifications.size(); + } + + FakeInvalidationHandler fake_handler_; + P2PInvalidatorTestDelegate delegate_; + + private: + size_t next_sent_notification_to_reflect_; +}; + +// Make sure the P2PNotificationTarget <-> string conversions work. +TEST_F(P2PInvalidatorTest, P2PNotificationTarget) { + for (int i = FIRST_NOTIFICATION_TARGET; + i <= LAST_NOTIFICATION_TARGET; ++i) { + P2PNotificationTarget target = static_cast<P2PNotificationTarget>(i); + const std::string& target_str = P2PNotificationTargetToString(target); + EXPECT_FALSE(target_str.empty()); + EXPECT_EQ(target, P2PNotificationTargetFromString(target_str)); + } + EXPECT_EQ(NOTIFY_SELF, P2PNotificationTargetFromString("unknown")); +} + +// Make sure notification targeting works correctly. +TEST_F(P2PInvalidatorTest, P2PNotificationDataIsTargeted) { + { + const P2PNotificationData notification_data( + "sender", NOTIFY_SELF, ObjectIdInvalidationMap()); + EXPECT_TRUE(notification_data.IsTargeted("sender")); + EXPECT_FALSE(notification_data.IsTargeted("other1")); + EXPECT_FALSE(notification_data.IsTargeted("other2")); + } + { + const P2PNotificationData notification_data( + "sender", NOTIFY_OTHERS, ObjectIdInvalidationMap()); + EXPECT_FALSE(notification_data.IsTargeted("sender")); + EXPECT_TRUE(notification_data.IsTargeted("other1")); + EXPECT_TRUE(notification_data.IsTargeted("other2")); + } + { + const P2PNotificationData notification_data( + "sender", NOTIFY_ALL, ObjectIdInvalidationMap()); + EXPECT_TRUE(notification_data.IsTargeted("sender")); + EXPECT_TRUE(notification_data.IsTargeted("other1")); + EXPECT_TRUE(notification_data.IsTargeted("other2")); + } +} + +// Make sure the P2PNotificationData <-> string conversions work for a +// default-constructed P2PNotificationData. +TEST_F(P2PInvalidatorTest, P2PNotificationDataDefault) { + const P2PNotificationData notification_data; + EXPECT_TRUE(notification_data.IsTargeted(std::string())); + EXPECT_FALSE(notification_data.IsTargeted("other1")); + EXPECT_FALSE(notification_data.IsTargeted("other2")); + EXPECT_TRUE(notification_data.GetIdInvalidationMap().Empty()); + const std::string& notification_data_str = notification_data.ToString(); + EXPECT_EQ( + "{\"invalidations\":[],\"notificationType\":\"notifySelf\"," + "\"senderId\":\"\"}", notification_data_str); + + P2PNotificationData notification_data_parsed; + EXPECT_TRUE(notification_data_parsed.ResetFromString(notification_data_str)); + EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); +} + +// Make sure the P2PNotificationData <-> string conversions work for a +// non-default-constructed P2PNotificationData. +TEST_F(P2PInvalidatorTest, P2PNotificationDataNonDefault) { + ObjectIdInvalidationMap invalidation_map = + ObjectIdInvalidationMap::InvalidateAll( + ModelTypeSetToObjectIdSet(ModelTypeSet(BOOKMARKS, THEMES))); + const P2PNotificationData notification_data("sender", + NOTIFY_ALL, + invalidation_map); + EXPECT_TRUE(notification_data.IsTargeted("sender")); + EXPECT_TRUE(notification_data.IsTargeted("other1")); + EXPECT_TRUE(notification_data.IsTargeted("other2")); + EXPECT_EQ(invalidation_map, notification_data.GetIdInvalidationMap()); + const std::string& notification_data_str = notification_data.ToString(); + EXPECT_EQ( + "{\"invalidations\":[" + "{\"isUnknownVersion\":true," + "\"objectId\":{\"name\":\"BOOKMARK\",\"source\":1004}}," + "{\"isUnknownVersion\":true," + "\"objectId\":{\"name\":\"THEME\",\"source\":1004}}" + "],\"notificationType\":\"notifyAll\"," + "\"senderId\":\"sender\"}", notification_data_str); + + P2PNotificationData notification_data_parsed; + EXPECT_TRUE(notification_data_parsed.ResetFromString(notification_data_str)); + EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); +} + +// Set up the P2PInvalidator, simulate a successful connection, and send +// a notification with the default target (NOTIFY_OTHERS). The +// observer should receive only a notification from the call to +// UpdateEnabledTypes(). +TEST_F(P2PInvalidatorTest, NotificationsBasic) { + const ModelTypeSet enabled_types(BOOKMARKS, PREFERENCES); + + P2PInvalidator* const invalidator = delegate_.GetInvalidator(); + notifier::FakePushClient* const push_client = delegate_.GetPushClient(); + + invalidator->UpdateRegisteredIds(&fake_handler_, + ModelTypeSetToObjectIdSet(enabled_types)); + + const char kEmail[] = "foo@bar.com"; + const char kToken[] = "token"; + invalidator->UpdateCredentials(kEmail, kToken); + { + notifier::Subscription expected_subscription; + expected_subscription.channel = kSyncP2PNotificationChannel; + expected_subscription.from = kEmail; + EXPECT_TRUE(notifier::SubscriptionListsEqual( + push_client->subscriptions(), + notifier::SubscriptionList(1, expected_subscription))); + } + EXPECT_EQ(kEmail, push_client->email()); + EXPECT_EQ(kToken, push_client->token()); + + ReflectSentNotifications(); + push_client->EnableNotifications(); + EXPECT_EQ(INVALIDATIONS_ENABLED, fake_handler_.GetInvalidatorState()); + + ReflectSentNotifications(); + EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); + EXPECT_THAT( + MakeInvalidationMap(enabled_types), + Eq(fake_handler_.GetLastInvalidationMap())); + + // Sent with target NOTIFY_OTHERS so should not be propagated to + // |fake_handler_|. + invalidator->SendInvalidation( + ModelTypeSetToObjectIdSet(ModelTypeSet(THEMES, APPS))); + + ReflectSentNotifications(); + EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); +} + +// Set up the P2PInvalidator and send out notifications with various +// target settings. The notifications received by the observer should +// be consistent with the target settings. +TEST_F(P2PInvalidatorTest, SendNotificationData) { + const ModelTypeSet enabled_types(BOOKMARKS, PREFERENCES, THEMES); + const ModelTypeSet changed_types(THEMES, APPS); + const ModelTypeSet expected_types(THEMES); + + const ObjectIdInvalidationMap& invalidation_map = + MakeInvalidationMap(changed_types); + + P2PInvalidator* const invalidator = delegate_.GetInvalidator(); + notifier::FakePushClient* const push_client = delegate_.GetPushClient(); + + invalidator->UpdateRegisteredIds(&fake_handler_, + ModelTypeSetToObjectIdSet(enabled_types)); + + invalidator->UpdateCredentials("foo@bar.com", "fake_token"); + + ReflectSentNotifications(); + push_client->EnableNotifications(); + EXPECT_EQ(INVALIDATIONS_ENABLED, fake_handler_.GetInvalidatorState()); + + ReflectSentNotifications(); + EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); + EXPECT_EQ(ModelTypeSetToObjectIdSet(enabled_types), + fake_handler_.GetLastInvalidationMap().GetObjectIds()); + + // Should be dropped. + invalidator->SendNotificationDataForTest(P2PNotificationData()); + ReflectSentNotifications(); + EXPECT_EQ(1, fake_handler_.GetInvalidationCount()); + + const ObjectIdSet& expected_ids = ModelTypeSetToObjectIdSet(expected_types); + + // Should be propagated. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender", NOTIFY_SELF, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); + EXPECT_EQ(expected_ids, + fake_handler_.GetLastInvalidationMap().GetObjectIds()); + + // Should be dropped. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender2", NOTIFY_SELF, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); + + // Should be dropped. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender", NOTIFY_SELF, ObjectIdInvalidationMap())); + ReflectSentNotifications(); + EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); + + // Should be dropped. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender", NOTIFY_OTHERS, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(2, fake_handler_.GetInvalidationCount()); + + // Should be propagated. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender2", NOTIFY_OTHERS, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(3, fake_handler_.GetInvalidationCount()); + EXPECT_EQ(expected_ids, + fake_handler_.GetLastInvalidationMap().GetObjectIds()); + + // Should be dropped. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender2", NOTIFY_OTHERS, ObjectIdInvalidationMap())); + ReflectSentNotifications(); + EXPECT_EQ(3, fake_handler_.GetInvalidationCount()); + + // Should be propagated. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender", NOTIFY_ALL, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(4, fake_handler_.GetInvalidationCount()); + EXPECT_EQ(expected_ids, + fake_handler_.GetLastInvalidationMap().GetObjectIds()); + + // Should be propagated. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender2", NOTIFY_ALL, invalidation_map)); + ReflectSentNotifications(); + EXPECT_EQ(5, fake_handler_.GetInvalidationCount()); + EXPECT_EQ(expected_ids, + fake_handler_.GetLastInvalidationMap().GetObjectIds()); + + // Should be dropped. + invalidator->SendNotificationDataForTest( + P2PNotificationData("sender2", NOTIFY_ALL, ObjectIdInvalidationMap())); + ReflectSentNotifications(); + EXPECT_EQ(5, fake_handler_.GetInvalidationCount()); +} + +INSTANTIATE_TYPED_TEST_CASE_P( + P2PInvalidatorTest, InvalidatorTest, + P2PInvalidatorTestDelegate); + +} // namespace + +} // namespace syncer |