diff options
16 files changed, 519 insertions, 129 deletions
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index e3aa161..ed1e417 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -1735,6 +1735,12 @@ bool ProfileSyncService::IsCryptographerReady( return backend_.get() && backend_->IsCryptographerReady(trans); } +SyncBackendHost* ProfileSyncService::GetBackendForTest() { + // We don't check |backend_initialized_|; we assume the test class + // knows what it's doing. + return backend_.get(); +} + void ProfileSyncService::ConfigurePriorityDataTypes() { const syncer::ModelTypeSet priority_types = Intersection(GetPreferredDataTypes(), syncer::PriorityUserTypes()); diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index 0746981..c9bfd84 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -700,6 +700,9 @@ class ProfileSyncService browser_sync::FaviconCache* GetFaviconCache(); protected: + // Used by test classes that derive from ProfileSyncService. + virtual browser_sync::SyncBackendHost* GetBackendForTest(); + // Helper to configure the priority data types. void ConfigurePriorityDataTypes(); diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc index 0c05e3c..a3c3808 100644 --- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc @@ -21,7 +21,6 @@ #include "base/synchronization/waitable_event.h" #include "base/time/time.h" #include "chrome/browser/autofill/personal_data_manager_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/abstract_profile_sync_service_test.h" @@ -39,7 +38,6 @@ #include "chrome/browser/webdata/autocomplete_syncable_service.h" #include "chrome/browser/webdata/autofill_profile_syncable_service.h" #include "chrome/browser/webdata/web_data_service_factory.h" -#include "chrome/test/base/testing_profile.h" #include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill/core/browser/personal_data_manager.h" #include "components/autofill/core/browser/webdata/autofill_change.h" diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc index 9721a9e..fec5344 100644 --- a/chrome/browser/sync/profile_sync_service_password_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc @@ -18,8 +18,6 @@ #include "chrome/browser/password_manager/mock_password_store.h" #include "chrome/browser/password_manager/password_store.h" #include "chrome/browser/password_manager/password_store_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/abstract_profile_sync_service_test.h" @@ -34,7 +32,6 @@ #include "chrome/browser/sync/profile_sync_test_util.h" #include "chrome/browser/sync/test_profile_sync_service.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_profile.h" #include "components/autofill/core/common/password_form.h" #include "content/public/browser/notification_source.h" #include "content/public/test/mock_notification_observer.h" @@ -104,7 +101,8 @@ class PasswordTestProfileSyncService : public TestProfileSyncService { profile, signin, oauth2_token_service, - ProfileSyncService::AUTO_START) {} + ProfileSyncService::AUTO_START, + false) {} virtual ~PasswordTestProfileSyncService() {} diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc index b5a6dd1..6acbc75 100644 --- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc @@ -17,7 +17,6 @@ #include "base/strings/string_piece.h" #include "chrome/browser/invalidation/invalidation_service_factory.h" #include "chrome/browser/prefs/pref_model_associator.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/abstract_profile_sync_service_test.h" diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc index ba4dccb9..04ae92a 100644 --- a/chrome/browser/sync/profile_sync_service_session_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc @@ -19,8 +19,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/invalidation/invalidation_service_factory.h" #include "chrome/browser/sessions/session_tab_helper.h" -#include "chrome/browser/signin/profile_oauth2_token_service.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/abstract_profile_sync_service_test.h" @@ -86,12 +84,14 @@ class FakeProfileSyncService : public TestProfileSyncService { Profile* profile, SigninManagerBase* signin, ProfileOAuth2TokenService* oauth2_token_service, - ProfileSyncService::StartBehavior behavior) + ProfileSyncService::StartBehavior behavior, + bool synchronous_backend_initialization) : TestProfileSyncService(factory, profile, signin, oauth2_token_service, - behavior) {} + behavior, + synchronous_backend_initialization) {} virtual ~FakeProfileSyncService() {} virtual scoped_ptr<DeviceInfo> GetLocalDeviceInfo() const OVERRIDE { @@ -198,7 +198,8 @@ class ProfileSyncServiceSessionTest profile(), signin, oauth2_token_service, - ProfileSyncService::AUTO_START)); + ProfileSyncService::AUTO_START, + false)); sync_service_->set_backend_init_callback(callback); // Register the session data type. diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc index 9716001..4d78985 100644 --- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc @@ -23,7 +23,6 @@ #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/invalidation/invalidation_service_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/abstract_profile_sync_service_test.h" diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc index 3451c1a..e7ccdc6 100644 --- a/chrome/browser/sync/profile_sync_service_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_unittest.cc @@ -8,39 +8,136 @@ #include "base/run_loop.h" #include "base/values.h" #include "chrome/browser/invalidation/invalidation_service_factory.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/token_service.h" #include "chrome/browser/signin/token_service_factory.h" #include "chrome/browser/sync/fake_oauth2_token_service.h" -#include "chrome/browser/sync/glue/data_type_manager_impl.h" +#include "chrome/browser/sync/glue/bookmark_data_type_controller.h" +#include "chrome/browser/sync/glue/data_type_controller.h" #include "chrome/browser/sync/glue/sync_backend_host_mock.h" #include "chrome/browser/sync/profile_sync_components_factory_mock.h" +#include "chrome/browser/sync/test_profile_sync_service.h" +#include "chrome/common/chrome_version_info.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_pref_service_syncable.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_utils.h" +#include "google/cacheinvalidation/include/types.h" #include "google_apis/gaia/gaia_constants.h" +#include "sync/js/js_arg_list.h" +#include "sync/js/js_event_details.h" +#include "sync/js/js_test_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +// TODO(akalin): Add tests here that exercise the whole +// ProfileSyncService/SyncBackendHost stack while mocking out as +// little as possible. + namespace browser_sync { namespace { -ACTION(ReturnNewDataTypeManager) { - return new browser_sync::DataTypeManagerImpl(arg0, - arg1, - arg2, - arg3, - arg4, - arg5); -} - using testing::_; +using testing::AtLeast; +using testing::AtMost; +using testing::Mock; +using testing::Return; using testing::StrictMock; +void SignalDone(base::WaitableEvent* done) { + done->Signal(); +} + +class ProfileSyncServiceTest : public testing::Test { + protected: + ProfileSyncServiceTest() + : thread_bundle_(content::TestBrowserThreadBundle::REAL_DB_THREAD | + content::TestBrowserThreadBundle::REAL_FILE_THREAD | + content::TestBrowserThreadBundle::REAL_IO_THREAD) { + } + + virtual ~ProfileSyncServiceTest() {} + + virtual void SetUp() OVERRIDE { + TestingProfile::Builder builder; + builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(), + FakeOAuth2TokenService::BuildTokenService); + profile_ = builder.Build().Pass(); + invalidation::InvalidationServiceFactory::GetInstance()-> + SetBuildOnlyFakeInvalidatorsForTest(true); + } + + virtual void TearDown() OVERRIDE { + // Kill the service before the profile. + if (service_) + service_->Shutdown(); + + service_.reset(); + profile_.reset(); + + // Pump messages posted by the sync thread (which may end up + // posting on the IO thread). + base::RunLoop().RunUntilIdle(); + content::RunAllPendingInMessageLoop(content::BrowserThread::IO); + base::RunLoop().RunUntilIdle(); + } + + void StartSyncServiceAndSetInitialSyncEnded() { + if (service_) + return; + + SigninManagerBase* signin = + SigninManagerFactory::GetForProfile(profile_.get()); + signin->SetAuthenticatedUsername("test"); + ProfileOAuth2TokenService* oauth2_token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()); + ProfileSyncComponentsFactoryMock* factory = + new ProfileSyncComponentsFactoryMock(); + service_.reset(new TestProfileSyncService( + factory, + profile_.get(), + signin, + oauth2_token_service, + ProfileSyncService::AUTO_START, + true)); + + + // Register the bookmark data type. + ON_CALL(*factory, CreateDataTypeManager(_, _, _, _, _, _)). + WillByDefault(ReturnNewDataTypeManager()); + + service_->Initialize(); + } + + void WaitForBackendInitDone() { + for (int i = 0; i < 5; ++i) { + base::WaitableEvent done(false, false); + service_->GetBackendForTest()->GetSyncLoopForTesting() + ->PostTask(FROM_HERE, base::Bind(&SignalDone, &done)); + done.Wait(); + base::RunLoop().RunUntilIdle(); + if (service_->sync_initialized()) { + return; + } + } + LOG(ERROR) << "Backend not initialized."; + } + + void IssueTestTokens() { + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()) + ->UpdateCredentials("test", "oauth2_login_token"); + } + + scoped_ptr<TestProfileSyncService> service_; + scoped_ptr<TestingProfile> profile_; + + private: + content::TestBrowserThreadBundle thread_bundle_; +}; + class TestProfileSyncServiceObserver : public ProfileSyncServiceObserver { public: explicit TestProfileSyncServiceObserver(ProfileSyncService* service) @@ -83,12 +180,13 @@ ACTION(ReturnNewSyncBackendHostNoReturn) { // MockSyncBackendHost. // // This is useful if we want to test the ProfileSyncService and don't care about -// testing the SyncBackendHost. -class ProfileSyncServiceTest : public ::testing::Test { +// testing the SyncBackendHost. It's easier to use than the other tests, since +// it doesn't involve any threads. +class ProfileSyncServiceSimpleTest : public ::testing::Test { protected: - ProfileSyncServiceTest() + ProfileSyncServiceSimpleTest() : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {} - virtual ~ProfileSyncServiceTest() {} + virtual ~ProfileSyncServiceSimpleTest() {} virtual void SetUp() OVERRIDE { TestingProfile::Builder builder; @@ -178,7 +276,7 @@ class ProfileSyncServiceTest : public ::testing::Test { }; // Verify that the server URLs are sane. -TEST_F(ProfileSyncServiceTest, InitialState) { +TEST_F(ProfileSyncServiceSimpleTest, InitialState) { CreateService(ProfileSyncService::AUTO_START); Initialize(); const std::string& url = service()->sync_service_url().spec(); @@ -187,7 +285,7 @@ TEST_F(ProfileSyncServiceTest, InitialState) { } // Verify a successful initialization. -TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) { +TEST_F(ProfileSyncServiceSimpleTest, SuccessfulInitialization) { profile()->GetTestingPrefService()->SetManagedPref( prefs::kSyncManaged, Value::CreateBooleanValue(false)); @@ -203,7 +301,7 @@ TEST_F(ProfileSyncServiceTest, SuccessfulInitialization) { // Verify that the SetSetupInProgress function call updates state // and notifies observers. -TEST_F(ProfileSyncServiceTest, SetupInProgress) { +TEST_F(ProfileSyncServiceSimpleTest, SetupInProgress) { CreateService(ProfileSyncService::MANUAL_START); Initialize(); @@ -219,7 +317,7 @@ TEST_F(ProfileSyncServiceTest, SetupInProgress) { } // Verify that disable by enterprise policy works. -TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) { +TEST_F(ProfileSyncServiceSimpleTest, DisabledByPolicyBeforeInit) { profile()->GetTestingPrefService()->SetManagedPref( prefs::kSyncManaged, Value::CreateBooleanValue(true)); @@ -232,7 +330,7 @@ TEST_F(ProfileSyncServiceTest, DisabledByPolicyBeforeInit) { // Verify that disable by enterprise policy works even after the backend has // been initialized. -TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) { +TEST_F(ProfileSyncServiceSimpleTest, DisabledByPolicyAfterInit) { IssueTestTokens(); CreateService(ProfileSyncService::AUTO_START); ExpectDataTypeManagerCreation(); @@ -252,7 +350,7 @@ TEST_F(ProfileSyncServiceTest, DisabledByPolicyAfterInit) { // Exercies the ProfileSyncService's code paths related to getting shut down // before the backend initialize call returns. -TEST_F(ProfileSyncServiceTest, AbortedByShutdown) { +TEST_F(ProfileSyncServiceSimpleTest, AbortedByShutdown) { CreateService(ProfileSyncService::AUTO_START); PrepareDelayedInitSyncBackendHost(); @@ -264,7 +362,7 @@ TEST_F(ProfileSyncServiceTest, AbortedByShutdown) { } // Test StopAndSuppress() before we've initialized the backend. -TEST_F(ProfileSyncServiceTest, EarlyStopAndSuppress) { +TEST_F(ProfileSyncServiceSimpleTest, EarlyStopAndSuppress) { CreateService(ProfileSyncService::AUTO_START); IssueTestTokens(); @@ -285,7 +383,7 @@ TEST_F(ProfileSyncServiceTest, EarlyStopAndSuppress) { } // Test StopAndSuppress() after we've initialized the backend. -TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) { +TEST_F(ProfileSyncServiceSimpleTest, DisableAndEnableSyncTemporarily) { CreateService(ProfileSyncService::AUTO_START); IssueTestTokens(); ExpectDataTypeManagerCreation(); @@ -314,7 +412,7 @@ TEST_F(ProfileSyncServiceTest, DisableAndEnableSyncTemporarily) { // things that deal with concepts like "signing out" and policy. #if !defined (OS_CHROMEOS) -TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) { +TEST_F(ProfileSyncServiceSimpleTest, EnableSyncAndSignOut) { CreateService(ProfileSyncService::AUTO_START); ExpectDataTypeManagerCreation(); ExpectSyncBackendHostCreation(); @@ -330,29 +428,116 @@ TEST_F(ProfileSyncServiceTest, EnableSyncAndSignOut) { #endif // !defined(OS_CHROMEOS) -TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) { - CreateService(ProfileSyncService::AUTO_START); +TEST_F(ProfileSyncServiceTest, JsControllerHandlersBasic) { + StartSyncServiceAndSetInitialSyncEnded(); IssueTestTokens(); - ExpectDataTypeManagerCreation(); - ExpectSyncBackendHostCreation(); - Initialize(); + EXPECT_TRUE(service_->sync_initialized()); + EXPECT_TRUE(service_->GetBackendForTest() != NULL); + + base::WeakPtr<syncer::JsController> js_controller = + service_->GetJsController(); + StrictMock<syncer::MockJsEventHandler> event_handler; + js_controller->AddJsEventHandler(&event_handler); + js_controller->RemoveJsEventHandler(&event_handler); +} + +TEST_F(ProfileSyncServiceTest, + JsControllerHandlersDelayedBackendInitialization) { + StartSyncServiceAndSetInitialSyncEnded(); + + StrictMock<syncer::MockJsEventHandler> event_handler; + EXPECT_CALL(event_handler, HandleJsEvent(_, _)).Times(AtLeast(1)); + + EXPECT_EQ(NULL, service_->GetBackendForTest()); + EXPECT_FALSE(service_->sync_initialized()); - // Initial status. + base::WeakPtr<syncer::JsController> js_controller = + service_->GetJsController(); + js_controller->AddJsEventHandler(&event_handler); + // Since we're doing synchronous initialization, backend should be + // initialized by this call. + IssueTestTokens(); + EXPECT_TRUE(service_->sync_initialized()); + js_controller->RemoveJsEventHandler(&event_handler); +} + +TEST_F(ProfileSyncServiceTest, JsControllerProcessJsMessageBasic) { + StartSyncServiceAndSetInitialSyncEnded(); + IssueTestTokens(); + WaitForBackendInitDone(); + + StrictMock<syncer::MockJsReplyHandler> reply_handler; + + ListValue arg_list1; + arg_list1.Append(Value::CreateStringValue("INVALIDATIONS_ENABLED")); + syncer::JsArgList args1(&arg_list1); + EXPECT_CALL(reply_handler, + HandleJsReply("getNotificationState", HasArgs(args1))); + + { + base::WeakPtr<syncer::JsController> js_controller = + service_->GetJsController(); + js_controller->ProcessJsMessage("getNotificationState", args1, + reply_handler.AsWeakHandle()); + } + + // This forces the sync thread to process the message and reply. + base::WaitableEvent done(false, false); + service_->GetBackendForTest()->GetSyncLoopForTesting() + ->PostTask(FROM_HERE, + base::Bind(&SignalDone, &done)); + done.Wait(); + + // Call TearDown() to flush the message loops before the mock is destroyed. + // TearDown() is idempotent, so it's not a problem that it gets called by the + // test fixture again later. + TearDown(); +} + +TEST_F(ProfileSyncServiceTest, + JsControllerProcessJsMessageBasicDelayedBackendInitialization) { + StartSyncServiceAndSetInitialSyncEnded(); + + StrictMock<syncer::MockJsReplyHandler> reply_handler; + + ListValue arg_list1; + arg_list1.Append(Value::CreateStringValue("INVALIDATIONS_ENABLED")); + syncer::JsArgList args1(&arg_list1); + EXPECT_CALL(reply_handler, + HandleJsReply("getNotificationState", HasArgs(args1))); + + { + base::WeakPtr<syncer::JsController> js_controller = + service_->GetJsController(); + js_controller->ProcessJsMessage("getNotificationState", + args1, reply_handler.AsWeakHandle()); + } + + IssueTestTokens(); + WaitForBackendInitDone(); + + // This forces the sync thread to process the message and reply. + base::WaitableEvent done(false, false); + service_->GetBackendForTest()->GetSyncLoopForTesting() + ->PostTask(FROM_HERE, + base::Bind(&SignalDone, &done)); + done.Wait(); +} + +TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) { + StartSyncServiceAndSetInitialSyncEnded(); + IssueTestTokens(); ProfileSyncService::SyncTokenStatus token_status = - service()->GetSyncTokenStatus(); + service_->GetSyncTokenStatus(); EXPECT_EQ(syncer::CONNECTION_NOT_ATTEMPTED, token_status.connection_status); EXPECT_TRUE(token_status.connection_status_update_time.is_null()); EXPECT_TRUE(token_status.token_request_time.is_null()); EXPECT_TRUE(token_status.token_receive_time.is_null()); - // Simulate an auth error. - service()->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR); - - // The token request will take the form of a posted task. Run it. - base::RunLoop loop; - loop.RunUntilIdle(); - - token_status = service()->GetSyncTokenStatus(); + // Sync engine is given invalid token at initialization and will report + // auth error when trying to connect. + service_->OnConnectionStatusChange(syncer::CONNECTION_AUTH_ERROR); + token_status = service_->GetSyncTokenStatus(); EXPECT_EQ(syncer::CONNECTION_AUTH_ERROR, token_status.connection_status); EXPECT_FALSE(token_status.connection_status_update_time.is_null()); EXPECT_FALSE(token_status.token_request_time.is_null()); @@ -362,8 +547,8 @@ TEST_F(ProfileSyncServiceTest, GetSyncTokenStatus) { EXPECT_TRUE(token_status.next_token_request_time.is_null()); // Simulate successful connection. - service()->OnConnectionStatusChange(syncer::CONNECTION_OK); - token_status = service()->GetSyncTokenStatus(); + service_->OnConnectionStatusChange(syncer::CONNECTION_OK); + token_status = service_->GetSyncTokenStatus(); EXPECT_EQ(syncer::CONNECTION_OK, token_status.connection_status); } diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc index d739ded..3f2bece 100644 --- a/chrome/browser/sync/test_profile_sync_service.cc +++ b/chrome/browser/sync/test_profile_sync_service.cc @@ -5,21 +5,19 @@ #include "chrome/browser/sync/test_profile_sync_service.h" #include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/glue/sync_backend_host.h" #include "chrome/browser/sync/glue/sync_backend_host_core.h" #include "chrome/browser/sync/profile_sync_components_factory.h" -#include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/test/test_http_bridge_factory.h" #include "sync/internal_api/public/test/sync_manager_factory_for_profile_sync_test.h" -#include "sync/internal_api/public/test/test_internal_components_factory.h" #include "sync/internal_api/public/user_share.h" #include "sync/js/js_reply_handler.h" #include "sync/protocol/encryption.pb.h" using syncer::InternalComponentsFactory; +using syncer::ModelSafeRoutingInfo; using syncer::TestInternalComponentsFactory; using syncer::UserShare; @@ -28,23 +26,42 @@ namespace browser_sync { SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest( Profile* profile, const base::WeakPtr<SyncPrefs>& sync_prefs, - base::Closure& callback) + base::Closure& callback, + bool set_initial_sync_ended_on_init, + bool synchronous_init, + bool fail_initial_download, + syncer::StorageOption storage_option) : browser_sync::SyncBackendHostImpl( profile->GetDebugName(), profile, sync_prefs), - callback_(callback) {} + callback_(callback), + fail_initial_download_(fail_initial_download), + set_initial_sync_ended_on_init_(set_initial_sync_ended_on_init), + synchronous_init_(synchronous_init), + storage_option_(storage_option), + weak_ptr_factory_(this) {} SyncBackendHostForProfileSyncTest::~SyncBackendHostForProfileSyncTest() {} +namespace { + +scoped_ptr<syncer::HttpPostProviderFactory> MakeTestHttpBridgeFactory() { + return scoped_ptr<syncer::HttpPostProviderFactory>( + new browser_sync::TestHttpBridgeFactory()); +} + +} // namespace + void SyncBackendHostForProfileSyncTest::InitCore( scoped_ptr<DoInitializeOptions> options) { - options->http_bridge_factory = - scoped_ptr<syncer::HttpPostProviderFactory>( - new browser_sync::TestHttpBridgeFactory()); + options->http_bridge_factory = MakeTestHttpBridgeFactory(); options->sync_manager_factory.reset( - new syncer::SyncManagerFactoryForProfileSyncTest(callback_)); + new syncer::SyncManagerFactoryForProfileSyncTest( + callback_, + set_initial_sync_ended_on_init_)); options->credentials.email = "testuser@gmail.com"; options->credentials.sync_token = "token"; options->restored_key_for_bootstrapping = ""; + syncer::StorageOption storage = storage_option_; // It'd be nice if we avoided creating the InternalComponentsFactory in the // first place, but SyncBackendHost will have created one by now so we must @@ -52,10 +69,23 @@ void SyncBackendHostForProfileSyncTest::InitCore( InternalComponentsFactory::Switches factory_switches = options->internal_components_factory->GetSwitches(); options->internal_components_factory.reset( - new TestInternalComponentsFactory(factory_switches, - syncer::STORAGE_IN_MEMORY)); + new TestInternalComponentsFactory(factory_switches, storage)); SyncBackendHostImpl::InitCore(options.Pass()); + if (synchronous_init_ && !base::MessageLoop::current()->is_running()) { + // The SyncBackend posts a task to the current loop when + // initialization completes. + base::MessageLoop::current()->Run(); + } +} + +void SyncBackendHostForProfileSyncTest::UpdateCredentials( + const syncer::SyncCredentials& credentials) { + // If we had failed the initial download, complete initialization now. + if (!initial_download_closure_.is_null()) { + initial_download_closure_.Run(); + initial_download_closure_.Reset(); + } } void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer( @@ -70,6 +100,8 @@ void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer( syncer::ModelTypeSet)>& ready_task, const base::Closure& retry_callback) { syncer::ModelTypeSet failed_configuration_types; + if (fail_initial_download_) + failed_configuration_types = to_download; // The first parameter there should be the set of enabled types. That's not // something we have access to from this strange test harness. We'll just @@ -82,12 +114,41 @@ void SyncBackendHostForProfileSyncTest::RequestConfigureSyncer( ready_task); } +void +SyncBackendHostForProfileSyncTest::HandleInitializationSuccessOnFrontendLoop( + const syncer::WeakHandle<syncer::JsBackend> js_backend, + const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> + debug_info_listener) { + if (fail_initial_download_) { + // We interrupt this successful init to bring you a simulated failure. + initial_download_closure_ = base::Bind( + &SyncBackendHostForProfileSyncTest:: + HandleInitializationSuccessOnFrontendLoop, + weak_ptr_factory_.GetWeakPtr(), + js_backend, + debug_info_listener); + HandleControlTypesDownloadRetry(); + if (synchronous_init_) + base::MessageLoop::current()->Quit(); + } else { + SyncBackendHostImpl::HandleInitializationSuccessOnFrontendLoop( + js_backend, + debug_info_listener); + } +} + } // namespace browser_sync syncer::TestIdFactory* TestProfileSyncService::id_factory() { return &id_factory_; } +browser_sync::SyncBackendHostForProfileSyncTest* + TestProfileSyncService::GetBackendForTest() { + return static_cast<browser_sync::SyncBackendHostForProfileSyncTest*>( + ProfileSyncService::GetBackendForTest()); +} + syncer::WeakHandle<syncer::JsEventHandler> TestProfileSyncService::GetJsEventHandler() { return syncer::WeakHandle<syncer::JsEventHandler>(); @@ -98,12 +159,19 @@ TestProfileSyncService::TestProfileSyncService( Profile* profile, SigninManagerBase* signin, ProfileOAuth2TokenService* oauth2_token_service, - ProfileSyncService::StartBehavior behavior) + ProfileSyncService::StartBehavior behavior, + bool synchronous_backend_initialization) : ProfileSyncService(factory, profile, signin, oauth2_token_service, - behavior) { + behavior), + synchronous_backend_initialization_( + synchronous_backend_initialization), + synchronous_sync_configuration_(false), + set_initial_sync_ended_on_init_(true), + fail_initial_download_(false), + storage_option_(syncer::STORAGE_IN_MEMORY) { SetSyncSetupCompleted(); } @@ -124,7 +192,8 @@ BrowserContextKeyedService* TestProfileSyncService::BuildAutoStartAsyncInit( profile, signin, oauth2_token_service, - ProfileSyncService::AUTO_START); + ProfileSyncService::AUTO_START, + false); } ProfileSyncComponentsFactoryMock* @@ -133,20 +202,82 @@ TestProfileSyncService::components_factory_mock() { return static_cast<ProfileSyncComponentsFactoryMock*>(factory()); } +void TestProfileSyncService::RequestAccessToken() { + ProfileSyncService::RequestAccessToken(); + if (synchronous_backend_initialization_) { + base::MessageLoop::current()->Run(); + } +} + +void TestProfileSyncService::OnGetTokenSuccess( + const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) { + ProfileSyncService::OnGetTokenSuccess(request, access_token, + expiration_time); + if (synchronous_backend_initialization_) { + base::MessageLoop::current()->Quit(); + } +} + +void TestProfileSyncService::OnGetTokenFailure( + const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) { + ProfileSyncService::OnGetTokenFailure(request, error); + if (synchronous_backend_initialization_) { + base::MessageLoop::current()->Quit(); + } +} + + +void TestProfileSyncService::OnBackendInitialized( + const syncer::WeakHandle<syncer::JsBackend>& backend, + const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& + debug_info_listener, + bool success) { + ProfileSyncService::OnBackendInitialized(backend, + debug_info_listener, + success); + + // TODO(akalin): Figure out a better way to do this. + if (synchronous_backend_initialization_) { + base::MessageLoop::current()->Quit(); + } +} + void TestProfileSyncService::OnConfigureDone( const browser_sync::DataTypeManager::ConfigureResult& result) { ProfileSyncService::OnConfigureDone(result); - base::MessageLoop::current()->Quit(); + if (!synchronous_sync_configuration_) + base::MessageLoop::current()->Quit(); } UserShare* TestProfileSyncService::GetUserShare() const { return backend_->GetUserShare(); } +void TestProfileSyncService::dont_set_initial_sync_ended_on_init() { + set_initial_sync_ended_on_init_ = false; +} +void TestProfileSyncService::set_synchronous_sync_configuration() { + synchronous_sync_configuration_ = true; +} +void TestProfileSyncService::fail_initial_download() { + fail_initial_download_ = true; +} +void TestProfileSyncService::set_storage_option( + syncer::StorageOption storage_option) { + storage_option_ = storage_option; +} + void TestProfileSyncService::CreateBackend() { backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest( profile(), sync_prefs_.AsWeakPtr(), - callback_)); + callback_, + set_initial_sync_ended_on_init_, + synchronous_backend_initialization_, + fail_initial_download_, + storage_option_)); } diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h index 08b4262..3b72c6c 100644 --- a/chrome/browser/sync/test_profile_sync_service.h +++ b/chrome/browser/sync/test_profile_sync_service.h @@ -10,18 +10,21 @@ #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/invalidation/invalidator_storage.h" #include "chrome/browser/signin/profile_oauth2_token_service.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/sync/glue/data_type_manager_impl.h" #include "chrome/browser/sync/glue/sync_backend_host_impl.h" +#include "chrome/browser/sync/profile_sync_components_factory_mock.h" #include "chrome/browser/sync/profile_sync_service.h" #include "chrome/browser/sync/sync_prefs.h" +#include "chrome/test/base/profile_mock.h" +#include "google_apis/gaia/oauth2_token_service.h" +#include "sync/internal_api/public/test/test_internal_components_factory.h" #include "sync/test/engine/test_id_factory.h" #include "testing/gmock/include/gmock/gmock.h" class Profile; -class ProfileOAuth2TokenService; -class ProfileSyncComponentsFactory; -class ProfileSyncComponentsFactoryMock; ACTION(ReturnNewDataTypeManager) { return new browser_sync::DataTypeManagerImpl(arg0, @@ -36,12 +39,24 @@ namespace browser_sync { class SyncBackendHostForProfileSyncTest : public SyncBackendHostImpl { public: + // |synchronous_init| causes initialization to block until the syncapi has + // completed setting itself up and called us back. + // TOOD(akalin): Remove |synchronous_init| (http://crbug.com/140354). SyncBackendHostForProfileSyncTest( Profile* profile, const base::WeakPtr<SyncPrefs>& sync_prefs, - base::Closure& callback); + base::Closure& callback, + bool set_initial_sync_ended_on_init, + bool synchronous_init, + bool fail_initial_download, + syncer::StorageOption storage_option); virtual ~SyncBackendHostForProfileSyncTest(); + MOCK_METHOD1(RequestNudge, void(const tracked_objects::Location&)); + + virtual void UpdateCredentials( + const syncer::SyncCredentials& credentials) OVERRIDE; + virtual void RequestConfigureSyncer( syncer::ConfigureReason reason, syncer::ModelTypeSet to_download, @@ -54,31 +69,67 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHostImpl { syncer::ModelTypeSet)>& ready_task, const base::Closure& retry_callback) OVERRIDE; + virtual void HandleInitializationSuccessOnFrontendLoop( + const syncer::WeakHandle<syncer::JsBackend> js_backend, + const syncer::WeakHandle<syncer::DataTypeDebugInfoListener> + debug_info_listener) OVERRIDE; + protected: virtual void InitCore(scoped_ptr<DoInitializeOptions> options) OVERRIDE; private: + + // Invoked at the start of HandleSyncManagerInitializationOnFrontendLoop. // Allows extra initialization work to be performed before the backend comes // up. base::Closure& callback_; + + // Saved closure in case we failed the initial download but then received + // new credentials. Holds the results of + // HandleSyncManagerInitializationOnFrontendLoop, and if + // |fail_initial_download_| was true, finishes the initialization process + // once we receive new credentials. + base::Closure initial_download_closure_; + bool fail_initial_download_; + + bool set_initial_sync_ended_on_init_; + bool synchronous_init_; + syncer::StorageOption storage_option_; + + base::WeakPtrFactory<SyncBackendHostForProfileSyncTest> weak_ptr_factory_; }; } // namespace browser_sync class TestProfileSyncService : public ProfileSyncService { public: - // TODO(tim): Add ability to inject TokenService alongside SigninManager. + // TODO(tim): Remove |synchronous_backend_initialization|, and add ability to + // inject TokenService alongside SigninManager. // TODO(rogerta): what does above comment mean? TestProfileSyncService( ProfileSyncComponentsFactory* factory, Profile* profile, SigninManagerBase* signin, ProfileOAuth2TokenService* oauth2_token_service, - ProfileSyncService::StartBehavior behavior); + ProfileSyncService::StartBehavior behavior, + bool synchronous_backend_initialization); virtual ~TestProfileSyncService(); + virtual void RequestAccessToken() OVERRIDE; + virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) OVERRIDE; + virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) OVERRIDE; + + virtual void OnBackendInitialized( + const syncer::WeakHandle<syncer::JsBackend>& backend, + const syncer::WeakHandle<syncer::DataTypeDebugInfoListener>& + debug_info_listener, + bool success) OVERRIDE; + virtual void OnConfigureDone( const browser_sync::DataTypeManager::ConfigureResult& result) OVERRIDE; @@ -90,6 +141,16 @@ class TestProfileSyncService : public ProfileSyncService { ProfileSyncComponentsFactoryMock* components_factory_mock(); + // If this is called, configuring data types will require a syncer + // nudge. + void dont_set_initial_sync_ended_on_init(); + void set_synchronous_sync_configuration(); + + // Fails initial download until a new auth token is provided. + void fail_initial_download(); + + void set_storage_option(syncer::StorageOption option); + // |callback| can be used to populate nodes before the OnBackendInitialized // callback fires. void set_backend_init_callback(const base::Closure& callback) { @@ -98,6 +159,12 @@ class TestProfileSyncService : public ProfileSyncService { syncer::TestIdFactory* id_factory(); + // Override of ProfileSyncService::GetBackendForTest() with a more + // specific return type (since C++ supports covariant return types) + // that is made public. + virtual browser_sync::SyncBackendHostForProfileSyncTest* + GetBackendForTest() OVERRIDE; + protected: virtual void CreateBackend() OVERRIDE; @@ -110,7 +177,17 @@ class TestProfileSyncService : public ProfileSyncService { private: syncer::TestIdFactory id_factory_; + bool synchronous_backend_initialization_; + + // Set to true when a mock data type manager is being used and the configure + // step is performed synchronously. + bool synchronous_sync_configuration_; + base::Closure callback_; + bool set_initial_sync_ended_on_init_; + + bool fail_initial_download_; + syncer::StorageOption storage_option_; }; #endif // CHROME_BROWSER_SYNC_TEST_PROFILE_SYNC_SERVICE_H_ diff --git a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc index 57fed78..13b20c0 100644 --- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc +++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc @@ -196,7 +196,8 @@ class OneClickTestProfileSyncService : public TestProfileSyncService { profile, NULL, NULL, - ProfileSyncService::MANUAL_START), + ProfileSyncService::MANUAL_START, + false), // synchronous_backend_init first_setup_in_progress_(false) {} bool first_setup_in_progress_; diff --git a/sync/internal_api/public/test/sync_manager_factory_for_profile_sync_test.h b/sync/internal_api/public/test/sync_manager_factory_for_profile_sync_test.h index 76d6bef..d8615c0 100644 --- a/sync/internal_api/public/test/sync_manager_factory_for_profile_sync_test.h +++ b/sync/internal_api/public/test/sync_manager_factory_for_profile_sync_test.h @@ -15,12 +15,14 @@ namespace syncer { class SyncManagerFactoryForProfileSyncTest : public syncer::SyncManagerFactory { public: - SyncManagerFactoryForProfileSyncTest(base::Closure init_callback); + SyncManagerFactoryForProfileSyncTest(base::Closure init_callback, + bool set_initial_sync_ended); virtual ~SyncManagerFactoryForProfileSyncTest(); virtual scoped_ptr<syncer::SyncManager> CreateSyncManager( std::string name) OVERRIDE; private: base::Closure init_callback_; + bool set_initial_sync_ended_; }; } // namespace syncer diff --git a/sync/internal_api/test/sync_manager_factory_for_profile_sync_test.cc b/sync/internal_api/test/sync_manager_factory_for_profile_sync_test.cc index 34289c4..df4073b 100644 --- a/sync/internal_api/test/sync_manager_factory_for_profile_sync_test.cc +++ b/sync/internal_api/test/sync_manager_factory_for_profile_sync_test.cc @@ -9,8 +9,10 @@ namespace syncer { SyncManagerFactoryForProfileSyncTest::SyncManagerFactoryForProfileSyncTest( - base::Closure init_callback) - : init_callback_(init_callback) { + base::Closure init_callback, + bool set_initial_sync_ended) + : init_callback_(init_callback), + set_initial_sync_ended_(set_initial_sync_ended) { } SyncManagerFactoryForProfileSyncTest::~SyncManagerFactoryForProfileSyncTest() {} @@ -20,7 +22,8 @@ SyncManagerFactoryForProfileSyncTest::CreateSyncManager(std::string name) { return scoped_ptr<syncer::SyncManager>( new SyncManagerForProfileSyncTest( name, - init_callback_)); + init_callback_, + set_initial_sync_ended_)); } } // namespace syncer diff --git a/sync/internal_api/test/sync_manager_for_profile_sync_test.cc b/sync/internal_api/test/sync_manager_for_profile_sync_test.cc index e552c2f..aaa6c8d 100644 --- a/sync/internal_api/test/sync_manager_for_profile_sync_test.cc +++ b/sync/internal_api/test/sync_manager_for_profile_sync_test.cc @@ -12,9 +12,11 @@ namespace syncer { SyncManagerForProfileSyncTest::SyncManagerForProfileSyncTest( std::string name, - base::Closure init_callback) + base::Closure init_callback, + bool set_initial_sync_ended) : SyncManagerImpl(name), - init_callback_(init_callback) {} + init_callback_(init_callback), + set_initial_sync_ended_(set_initial_sync_ended) {} SyncManagerForProfileSyncTest::~SyncManagerForProfileSyncTest() {} @@ -25,14 +27,18 @@ void SyncManagerForProfileSyncTest::NotifyInitializationSuccess() { if (!init_callback_.is_null()) init_callback_.Run(); - ModelTypeSet early_download_types; - early_download_types.PutAll(ControlTypes()); - early_download_types.PutAll(PriorityUserTypes()); - for (ModelTypeSet::Iterator it = early_download_types.First(); - it.Good(); it.Inc()) { - if (!directory->InitialSyncEndedForType(it.Get())) { - syncer::TestUserShare::CreateRoot(it.Get(), user_share); + if (set_initial_sync_ended_) { + ModelTypeSet early_download_types; + early_download_types.PutAll(ControlTypes()); + early_download_types.PutAll(PriorityUserTypes()); + for (ModelTypeSet::Iterator it = early_download_types.First(); + it.Good(); it.Inc()) { + if (!directory->InitialSyncEndedForType(it.Get())) { + syncer::TestUserShare::CreateRoot(it.Get(), user_share); + } } + } else { + VLOG(2) << "Skipping directory init"; } SyncManagerImpl::NotifyInitializationSuccess(); diff --git a/sync/internal_api/test/sync_manager_for_profile_sync_test.h b/sync/internal_api/test/sync_manager_for_profile_sync_test.h index 8493386..c9af22d 100644 --- a/sync/internal_api/test/sync_manager_for_profile_sync_test.h +++ b/sync/internal_api/test/sync_manager_for_profile_sync_test.h @@ -19,12 +19,14 @@ class SyncManagerForProfileSyncTest : public syncer::SyncManagerImpl { public: SyncManagerForProfileSyncTest(std::string name, - base::Closure init_callback); + base::Closure init_callback, + bool set_initial_sync_ended); virtual ~SyncManagerForProfileSyncTest(); virtual void NotifyInitializationSuccess() OVERRIDE; private: base::Closure init_callback_; + bool set_initial_sync_ended_; }; } // namespace syncer diff --git a/sync/js/sync_js_controller_unittest.cc b/sync/js/sync_js_controller_unittest.cc index eca617c..ac46935 100644 --- a/sync/js/sync_js_controller_unittest.cc +++ b/sync/js/sync_js_controller_unittest.cc @@ -30,15 +30,10 @@ class SyncJsControllerTest : public testing::Test { base::MessageLoop message_loop_; }; -ACTION_P(ReplyToMessage, reply_name) { - arg2.Call(FROM_HERE, &JsReplyHandler::HandleJsReply, reply_name, JsArgList()); -} - TEST_F(SyncJsControllerTest, Messages) { InSequence dummy; // |mock_backend| needs to outlive |sync_js_controller|. StrictMock<MockJsBackend> mock_backend; - StrictMock<MockJsReplyHandler> mock_reply_handler; SyncJsController sync_js_controller; base::ListValue arg_list1, arg_list2; @@ -46,23 +41,17 @@ TEST_F(SyncJsControllerTest, Messages) { arg_list2.Append(new base::FundamentalValue(5)); JsArgList args1(&arg_list1), args2(&arg_list2); + // TODO(akalin): Write matchers for WeakHandle and use them here + // instead of _. EXPECT_CALL(mock_backend, SetJsEventHandler(_)); - EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) - .WillOnce(ReplyToMessage("test1_reply")); - EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) - .WillOnce(ReplyToMessage("test2_reply")); + EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)); + EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)); sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); - sync_js_controller.ProcessJsMessage("test1", - args2, - mock_reply_handler.AsWeakHandle()); - sync_js_controller.ProcessJsMessage("test2", - args1, - mock_reply_handler.AsWeakHandle()); - - // The replies should be waiting on our message loop. - EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); + sync_js_controller.ProcessJsMessage("test1", args2, + WeakHandle<JsReplyHandler>()); + sync_js_controller.ProcessJsMessage("test2", args1, + WeakHandle<JsReplyHandler>()); PumpLoop(); // Let destructor of |sync_js_controller| call RemoveBackend(). @@ -71,7 +60,6 @@ TEST_F(SyncJsControllerTest, Messages) { TEST_F(SyncJsControllerTest, QueuedMessages) { // |mock_backend| needs to outlive |sync_js_controller|. StrictMock<MockJsBackend> mock_backend; - StrictMock<MockJsReplyHandler> mock_reply_handler; SyncJsController sync_js_controller; base::ListValue arg_list1, arg_list2; @@ -80,29 +68,20 @@ TEST_F(SyncJsControllerTest, QueuedMessages) { JsArgList args1(&arg_list1), args2(&arg_list2); // Should queue messages. - sync_js_controller.ProcessJsMessage( - "test1", - args2, - mock_reply_handler.AsWeakHandle()); - sync_js_controller.ProcessJsMessage( - "test2", - args1, - mock_reply_handler.AsWeakHandle()); + sync_js_controller.ProcessJsMessage("test1", args2, + WeakHandle<JsReplyHandler>()); + sync_js_controller.ProcessJsMessage("test2", args1, + WeakHandle<JsReplyHandler>()); - // Should do nothing. - PumpLoop(); Mock::VerifyAndClearExpectations(&mock_backend); - - // Should call the queued messages. + // TODO(akalin): Write matchers for WeakHandle and use them here + // instead of _. EXPECT_CALL(mock_backend, SetJsEventHandler(_)); - EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)) - .WillOnce(ReplyToMessage("test1_reply")); - EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)) - .WillOnce(ReplyToMessage("test2_reply")); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test1_reply", _)); - EXPECT_CALL(mock_reply_handler, HandleJsReply("test2_reply", _)); + EXPECT_CALL(mock_backend, ProcessJsMessage("test1", HasArgs(args2), _)); + EXPECT_CALL(mock_backend, ProcessJsMessage("test2", HasArgs(args1), _)); + // Should call the queued messages. sync_js_controller.AttachJsBackend(mock_backend.AsWeakHandle()); PumpLoop(); |