Chromium Code Reviews| Index: chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc |
| diff --git a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc |
| index 466b6e2fb3b21cf5c9468ae4890ca4b714b86de3..367be2a16441473648fdffd86f0481edbbdf492c 100644 |
| --- a/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc |
| +++ b/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc |
| @@ -12,47 +12,84 @@ |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/browser_sync/browser_sync_switches.h" |
| #include "components/sync/driver/about_sync_util.h" |
| +#include "components/sync/driver/fake_sync_service.h" |
| #include "components/sync/driver/sync_service.h" |
| +#include "components/sync/js/js_test_util.h" |
| #include "content/public/browser/site_instance.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "content/public/test/test_web_ui.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| +using base::DictionaryValue; |
| +using base::ListValue; |
| +using base::Value; |
| +using syncer::SyncService; |
| +using syncer::SyncServiceObserver; |
| +using syncer::TypeDebugInfoObserver; |
| + |
| namespace { |
| class TestableSyncInternalsMessageHandler : public SyncInternalsMessageHandler { |
| public: |
| - explicit TestableSyncInternalsMessageHandler( |
| + TestableSyncInternalsMessageHandler( |
| content::WebUI* web_ui, |
| - std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) |
| - : SyncInternalsMessageHandler(std::move(about_sync_data_extractor)) { |
| + SyncServiceProvider sync_service_provider, |
| + AboutSyncDataDelegate about_sync_data_delegate) |
| + : SyncInternalsMessageHandler(std::move(sync_service_provider), |
| + std::move(about_sync_data_delegate)) { |
| set_web_ui(web_ui); |
| } |
| }; |
| -class FakeExtractor : public AboutSyncDataExtractor { |
| +class TestSyncService : public syncer::FakeSyncService { |
| public: |
| - std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( |
| - syncer::SyncService* service, |
| - SigninManagerBase* signin) override { |
| - call_count_++; |
| - last_service_ = service; |
| - last_signin_ = signin; |
| - std::unique_ptr<base::DictionaryValue> dictionary( |
| - new base::DictionaryValue()); |
| - dictionary->SetString("fake_key", "fake_value"); |
| - return dictionary; |
| + void AddObserver(SyncServiceObserver* observer) override { |
| + ++add_observer_count_; |
| + } |
| + |
| + void RemoveObserver(SyncServiceObserver* observer) override { |
| + ++remove_observer_count_; |
| + } |
| + |
| + void AddTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override { |
| + ++add_type_debug_info_observer_count_; |
| } |
| - int call_count() const { return call_count_; } |
| - syncer::SyncService* last_service() const { return last_service_; } |
| - SigninManagerBase* last_signin() const { return last_signin_; } |
| + void RemoveTypeDebugInfoObserver(TypeDebugInfoObserver* observer) override { |
| + ++remove_type_debug_info_observer_count_; |
| + } |
| + |
| + base::WeakPtr<syncer::JsController> GetJsController() override { |
| + return js_controller_.AsWeakPtr(); |
| + } |
| + |
| + void GetAllNodes(const base::Callback<void(std::unique_ptr<base::ListValue>)>& |
| + callback) override { |
| + get_all_nodes_callback_ = std::move(callback); |
| + } |
| + |
| + int add_observer_count() const { return add_observer_count_; } |
| + int remove_observer_count() const { return remove_observer_count_; } |
| + int add_type_debug_info_observer_count() const { |
| + return add_type_debug_info_observer_count_; |
| + } |
| + int remove_type_debug_info_observer_count() const { |
| + return remove_type_debug_info_observer_count_; |
| + } |
| + base::Callback<void(std::unique_ptr<base::ListValue>)> |
| + get_all_nodes_callback() { |
| + return std::move(get_all_nodes_callback_); |
| + } |
| private: |
| - int call_count_ = 0; |
| - syncer::SyncService* last_service_ = nullptr; |
| - SigninManagerBase* last_signin_ = nullptr; |
| + int add_observer_count_ = 0; |
| + int remove_observer_count_ = 0; |
| + int add_type_debug_info_observer_count_ = 0; |
| + int remove_type_debug_info_observer_count_ = 0; |
| + syncer::MockJsController js_controller_; |
| + base::Callback<void(std::unique_ptr<base::ListValue>)> |
| + get_all_nodes_callback_; |
| }; |
| class SyncInternalsMessageHandlerTest : public ::testing::Test { |
| @@ -62,9 +99,24 @@ class SyncInternalsMessageHandlerTest : public ::testing::Test { |
| web_contents_.reset(content::WebContents::Create( |
| content::WebContents::CreateParams(&profile_, site_instance_.get()))); |
| web_ui_.set_web_contents(web_contents_.get()); |
| - fake_extractor_ = new FakeExtractor(); |
| + test_sync_service_ = base::MakeUnique<TestSyncService>(); |
| handler_.reset(new TestableSyncInternalsMessageHandler( |
| - &web_ui_, std::unique_ptr<FakeExtractor>(fake_extractor_))); |
| + &web_ui_, |
| + base::BindRepeating(&SyncInternalsMessageHandlerTest::sync_service, |
| + base::Unretained(this)), |
| + base::BindRepeating( |
| + &SyncInternalsMessageHandlerTest::ConstructAboutInformation, |
| + base::Unretained(this)))); |
| + } |
| + |
| + std::unique_ptr<DictionaryValue> ConstructAboutInformation( |
| + SyncService* service, |
| + version_info::Channel channel) { |
| + ++about_sync_data_delegate_call_count_; |
| + last_delegate_sync_service_ = service; |
| + auto dictionary = base::MakeUnique<DictionaryValue>(); |
| + dictionary->SetString("fake_key", "fake_value"); |
| + return dictionary; |
| } |
| void ValidateAboutInfoCall() { |
| @@ -76,16 +128,16 @@ class SyncInternalsMessageHandlerTest : public ::testing::Test { |
| EXPECT_EQ(syncer::sync_ui_util::kDispatchEvent, call_data.function_name()); |
| - const base::Value* arg1 = call_data.arg1(); |
| + const Value* arg1 = call_data.arg1(); |
| ASSERT_TRUE(arg1); |
| std::string event_type; |
| EXPECT_TRUE(arg1->GetAsString(&event_type)); |
| EXPECT_EQ(syncer::sync_ui_util::kOnAboutInfoUpdated, event_type); |
| - const base::Value* arg2 = call_data.arg2(); |
| + const Value* arg2 = call_data.arg2(); |
| ASSERT_TRUE(arg2); |
| - const base::DictionaryValue* root_dictionary = nullptr; |
| + const DictionaryValue* root_dictionary = nullptr; |
| ASSERT_TRUE(arg2->GetAsDictionary(&root_dictionary)); |
| std::string fake_value; |
| @@ -93,37 +145,170 @@ class SyncInternalsMessageHandlerTest : public ::testing::Test { |
| EXPECT_EQ("fake_value", fake_value); |
| } |
| - SyncInternalsMessageHandler* handler() { return handler_.get(); } |
| - FakeExtractor* fake_extractor() { return fake_extractor_; } |
| + void ValidateEmptyAboutInfoCall() { |
| + EXPECT_TRUE(web_ui_.call_data().empty()); |
| + } |
| + |
| + TestSyncService* test_sync_service() { return test_sync_service_.get(); } |
| + |
| + TestableSyncInternalsMessageHandler* handler() { return handler_.get(); } |
| + |
| + int CallCountWithName(const std::string& function_name) { |
| + int count = 0; |
| + for (const auto& call_data : web_ui_.call_data()) { |
| + if (call_data->function_name() == function_name) { |
| + count++; |
| + } |
| + } |
| + return count; |
| + } |
| + |
| + int about_sync_data_delegate_call_count() { |
|
Dan Beam
2017/05/25 00:28:20
nit: const {
skym
2017/05/25 17:38:12
Done.
|
| + return about_sync_data_delegate_call_count_; |
| + } |
| + |
| + SyncService* last_delegate_sync_service() { |
|
Dan Beam
2017/05/25 00:28:20
const SyncService* last_delegate_sync_service() co
skym
2017/05/25 17:38:12
Done.
|
| + return last_delegate_sync_service_; |
| + } |
| + |
| + void ResetSyncService() { test_sync_service_.reset(); } |
| + |
| + void ResetHandler() { handler_.reset(); } |
| private: |
| + SyncService* sync_service() { return test_sync_service_.get(); } |
| + |
| content::TestBrowserThreadBundle thread_bundle_; |
| TestingProfile profile_; |
| content::TestWebUI web_ui_; |
| scoped_refptr<content::SiteInstance> site_instance_; |
| std::unique_ptr<content::WebContents> web_contents_; |
| - std::unique_ptr<SyncInternalsMessageHandler> handler_; |
| + std::unique_ptr<TestSyncService> test_sync_service_; |
| + std::unique_ptr<TestableSyncInternalsMessageHandler> handler_; |
| - // Non-owning pointer to the about information the handler uses. This |
| - // extractor is owned by the handler. |
| - FakeExtractor* fake_extractor_; |
| + int about_sync_data_delegate_call_count_ = 0; |
| + SyncService* last_delegate_sync_service_ = nullptr; |
| }; |
| -} // namespace |
| +TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObservers) { |
| + ListValue empty_list; |
| + |
| + EXPECT_EQ(0, test_sync_service()->add_observer_count()); |
| + handler()->HandleRegisterForEvents(&empty_list); |
| + EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| + |
| + EXPECT_EQ(0, test_sync_service()->add_type_debug_info_observer_count()); |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| + |
| + EXPECT_EQ(0, test_sync_service()->remove_observer_count()); |
| + EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| + ResetHandler(); |
| + EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| + |
| + // Add calls should never have increased since the initial subscription. |
| + EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| +} |
| + |
| +TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversDisallowJavascript) { |
| + ListValue empty_list; |
| + |
| + EXPECT_EQ(0, test_sync_service()->add_observer_count()); |
| + handler()->HandleRegisterForEvents(&empty_list); |
| + EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| + |
| + EXPECT_EQ(0, test_sync_service()->add_type_debug_info_observer_count()); |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| + |
| + EXPECT_EQ(0, test_sync_service()->remove_observer_count()); |
| + EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| + handler()->DisallowJavascript(); |
| + EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| + |
| + // Deregistration should not repeat, no counts should increase. |
| + ResetHandler(); |
| + EXPECT_EQ(1, test_sync_service()->add_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->remove_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| +} |
| + |
| +TEST_F(SyncInternalsMessageHandlerTest, AddRemoveObserversSyncDisabled) { |
| + // Simulate completely disabling sync by flag or other mechanism. |
| + ResetSyncService(); |
| -TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoWithService) { |
| + ListValue empty_list; |
| + handler()->HandleRegisterForEvents(&empty_list); |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + handler()->DisallowJavascript(); |
| + // Cannot verify observer methods on sync services were not called, because |
| + // there is no sync service. Rather, we're just making sure the handler hasn't |
| + // performed any invalid operations when the sync service is missing. |
| +} |
| + |
| +TEST_F(SyncInternalsMessageHandlerTest, |
| + RepeatedHandleRegisterForPerTypeCounters) { |
| + ListValue empty_list; |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + EXPECT_EQ(1, test_sync_service()->add_type_debug_info_observer_count()); |
| + EXPECT_EQ(0, test_sync_service()->remove_type_debug_info_observer_count()); |
| + |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + EXPECT_EQ(2, test_sync_service()->add_type_debug_info_observer_count()); |
| + EXPECT_EQ(1, test_sync_service()->remove_type_debug_info_observer_count()); |
| + |
| + handler()->HandleRegisterForPerTypeCounters(&empty_list); |
| + EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count()); |
| + EXPECT_EQ(2, test_sync_service()->remove_type_debug_info_observer_count()); |
| + |
| + ResetHandler(); |
| + EXPECT_EQ(3, test_sync_service()->add_type_debug_info_observer_count()); |
| + EXPECT_EQ(3, test_sync_service()->remove_type_debug_info_observer_count()); |
| +} |
| + |
| +TEST_F(SyncInternalsMessageHandlerTest, HandleGetAllNodes) { |
| + ListValue args; |
| + args.AppendInteger(0); |
| + handler()->HandleGetAllNodes(&args); |
| + test_sync_service()->get_all_nodes_callback().Run( |
| + base::MakeUnique<ListValue>()); |
| + EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| + |
| + handler()->HandleGetAllNodes(&args); |
| + // This breaks the weak ref the callback is hanging onto. Which results in |
| + // the call count not incrementing. |
| + handler()->DisallowJavascript(); |
| + test_sync_service()->get_all_nodes_callback().Run( |
| + base::MakeUnique<ListValue>()); |
| + EXPECT_EQ(1, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| + |
| + handler()->HandleGetAllNodes(&args); |
| + test_sync_service()->get_all_nodes_callback().Run( |
| + base::MakeUnique<ListValue>()); |
| + EXPECT_EQ(2, CallCountWithName(syncer::sync_ui_util::kGetAllNodesCallback)); |
| +} |
| + |
| +TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfo) { |
| + handler()->AllowJavascriptForTesting(); |
| handler()->OnStateChanged(nullptr); |
| - EXPECT_EQ(1, fake_extractor()->call_count()); |
| - EXPECT_NE(nullptr, fake_extractor()->last_service()); |
| - EXPECT_NE(nullptr, fake_extractor()->last_signin()); |
| + EXPECT_EQ(1, about_sync_data_delegate_call_count()); |
| + EXPECT_NE(nullptr, last_delegate_sync_service()); |
| ValidateAboutInfoCall(); |
| } |
| -TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoWithoutService) { |
| - base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync); |
| +TEST_F(SyncInternalsMessageHandlerTest, SendAboutInfoSyncDisabled) { |
| + // Simulate completely disabling sync by flag or other mechanism. |
| + ResetSyncService(); |
| + |
| + handler()->AllowJavascriptForTesting(); |
| handler()->OnStateChanged(nullptr); |
| - EXPECT_EQ(1, fake_extractor()->call_count()); |
| - EXPECT_EQ(nullptr, fake_extractor()->last_service()); |
| - EXPECT_EQ(nullptr, fake_extractor()->last_signin()); |
| + EXPECT_EQ(1, about_sync_data_delegate_call_count()); |
| + EXPECT_EQ(nullptr, last_delegate_sync_service()); |
| ValidateAboutInfoCall(); |
| } |
| + |
| +} // namespace |