// Copyright (c) 2012 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 "chrome/browser/sync/glue/bridged_invalidator.h" #include <string> #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" #include "chrome/browser/sync/glue/chrome_sync_notification_bridge.h" #include "chrome/test/base/profile_mock.h" #include "content/public/test/test_browser_thread.h" #include "google/cacheinvalidation/include/types.h" #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/base/model_type_test_util.h" #include "sync/notifier/fake_invalidation_handler.h" #include "sync/notifier/fake_invalidator.h" #include "sync/notifier/invalidator_test_template.h" #include "sync/notifier/object_id_state_map_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace syncer { class InvalidationStateTracker; } // namespace syncer namespace browser_sync { // BridgedInvalidatorTestDelegate has to be visible from the syncer // namespace (where InvalidatorTest lives). class BridgedInvalidatorTestDelegate { public: BridgedInvalidatorTestDelegate() : ui_thread_(content::BrowserThread::UI, &ui_loop_), bridge_(&mock_profile_, ui_loop_.message_loop_proxy()), fake_delegate_(NULL) { // Pump |ui_loop_| to fully initialize |bridge_|. ui_loop_.RunAllPending(); } ~BridgedInvalidatorTestDelegate() { DestroyInvalidator(); } void CreateInvalidator( const std::string& /* initial_state (unused) */, const base::WeakPtr<syncer::InvalidationStateTracker>& /* invalidation_state_tracker (unused) */) { DCHECK(!fake_delegate_); DCHECK(!invalidator_.get()); fake_delegate_ = new syncer::FakeInvalidator(); invalidator_.reset(new BridgedInvalidator( &bridge_, fake_delegate_, syncer::DEFAULT_INVALIDATION_ERROR)); } BridgedInvalidator* GetInvalidator() { return invalidator_.get(); } ChromeSyncNotificationBridge* GetBridge() { return &bridge_; } syncer::FakeInvalidator* GetFakeDelegate() { return fake_delegate_; } void DestroyInvalidator() { invalidator_.reset(); fake_delegate_ = NULL; bridge_.StopForShutdown(); ui_loop_.RunAllPending(); } void WaitForInvalidator() { // Do nothing. } void TriggerOnInvalidatorStateChange(syncer::InvalidatorState state) { fake_delegate_->EmitOnInvalidatorStateChange(state); } void TriggerOnIncomingInvalidation( const syncer::ObjectIdStateMap& id_state_map, syncer::IncomingInvalidationSource source) { fake_delegate_->EmitOnIncomingInvalidation(id_state_map, source); } static bool InvalidatorHandlesDeprecatedState() { return false; } private: MessageLoop ui_loop_; content::TestBrowserThread ui_thread_; ::testing::NiceMock<ProfileMock> mock_profile_; ChromeSyncNotificationBridge bridge_; // Owned by |invalidator_|. syncer::FakeInvalidator* fake_delegate_; scoped_ptr<BridgedInvalidator> invalidator_; }; namespace { // All tests just verify that each call is passed through to the delegate, with // the exception of RegisterHandler, UnregisterHandler, and // UpdateRegisteredIds, which also verifies the call is forwarded to the // bridge. class BridgedInvalidatorTest : public testing::Test { public: BridgedInvalidatorTest() { delegate_.CreateInvalidator( "fake_state", base::WeakPtr<syncer::InvalidationStateTracker>()); } virtual ~BridgedInvalidatorTest() {} protected: BridgedInvalidatorTestDelegate delegate_; }; TEST_F(BridgedInvalidatorTest, HandlerMethods) { syncer::ObjectIdSet ids; ids.insert(invalidation::ObjectId(1, "id1")); syncer::FakeInvalidationHandler handler; delegate_.GetInvalidator()->RegisterHandler(&handler); EXPECT_TRUE(delegate_.GetFakeDelegate()->IsHandlerRegistered(&handler)); EXPECT_TRUE(delegate_.GetBridge()->IsHandlerRegisteredForTest(&handler)); delegate_.GetInvalidator()->UpdateRegisteredIds(&handler, ids); EXPECT_EQ(ids, delegate_.GetFakeDelegate()->GetRegisteredIds(&handler)); EXPECT_EQ(ids, delegate_.GetBridge()->GetRegisteredIdsForTest(&handler)); delegate_.GetInvalidator()->UnregisterHandler(&handler); EXPECT_FALSE(delegate_.GetFakeDelegate()->IsHandlerRegistered(&handler)); EXPECT_FALSE(delegate_.GetBridge()->IsHandlerRegisteredForTest(&handler)); } TEST_F(BridgedInvalidatorTest, GetInvalidatorState) { EXPECT_EQ(syncer::DEFAULT_INVALIDATION_ERROR, delegate_.GetInvalidator()->GetInvalidatorState()); } TEST_F(BridgedInvalidatorTest, SetUniqueId) { const std::string& unique_id = "unique id"; delegate_.GetInvalidator()->SetUniqueId(unique_id); EXPECT_EQ(unique_id, delegate_.GetFakeDelegate()->GetUniqueId()); } TEST_F(BridgedInvalidatorTest, SetStateDeprecated) { const std::string& state = "state"; delegate_.GetInvalidator()->SetStateDeprecated(state); EXPECT_EQ(state, delegate_.GetFakeDelegate()->GetStateDeprecated()); } TEST_F(BridgedInvalidatorTest, UpdateCredentials) { const std::string& email = "email"; const std::string& token = "token"; delegate_.GetInvalidator()->UpdateCredentials(email, token); EXPECT_EQ(email, delegate_.GetFakeDelegate()->GetCredentialsEmail()); EXPECT_EQ(token, delegate_.GetFakeDelegate()->GetCredentialsToken()); } TEST_F(BridgedInvalidatorTest, SendInvalidation) { syncer::ObjectIdSet ids; ids.insert(invalidation::ObjectId(1, "id1")); ids.insert(invalidation::ObjectId(2, "id2")); const syncer::ObjectIdStateMap& id_state_map = syncer::ObjectIdSetToStateMap(ids, "payload"); delegate_.GetInvalidator()->SendInvalidation(id_state_map); EXPECT_THAT(id_state_map, Eq(delegate_.GetFakeDelegate()->GetLastSentIdStateMap())); } } // namespace } // namespace browser_sync namespace syncer { namespace { INSTANTIATE_TYPED_TEST_CASE_P( BridgedInvalidatorTest, InvalidatorTest, ::browser_sync::BridgedInvalidatorTestDelegate); } // namespace } // namespace syncer