Chromium Code Reviews| Index: chrome/browser/power/process_power_collector_unittest.cc |
| diff --git a/chrome/browser/power/process_power_collector_unittest.cc b/chrome/browser/power/process_power_collector_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..eff81b367df95c7fb3d6e2675258aa99178cf9ff |
| --- /dev/null |
| +++ b/chrome/browser/power/process_power_collector_unittest.cc |
| @@ -0,0 +1,356 @@ |
| +// 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 "chrome/browser/power/process_power_collector.h" |
| + |
| +#include "apps/app_window_contents.h" |
| +#include "apps/app_window_registry.h" |
| +#include "chrome/browser/profiles/profile_manager.h" |
| +#include "chrome/browser/ui/apps/chrome_app_delegate.h" |
| +#include "chrome/browser/ui/browser_commands.h" |
| +#include "chrome/browser/ui/tabs/tab_strip_model.h" |
| +#include "chrome/test/base/browser_with_test_window_test.h" |
| +#include "chrome/test/base/testing_browser_process.h" |
| +#include "chrome/test/base/testing_profile_manager.h" |
| +#include "components/power/origin_power_map.h" |
| +#include "components/power/origin_power_map_factory.h" |
| +#include "content/public/browser/site_instance.h" |
| +#include "content/public/test/browser_test_utils.h" |
| +#include "content/public/test/mock_render_process_host.h" |
| +#include "extensions/browser/app_window/native_app_window.h" |
| +#include "extensions/common/extension.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| +#include "url/gurl.h" |
| + |
| +#if defined(OS_CHROMEOS) |
| +#include "chrome/browser/chromeos/power/power_data_collector.h" |
| +#include "chromeos/dbus/dbus_thread_manager.h" |
| +#include "chromeos/dbus/fake_dbus_thread_manager.h" |
| +#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" |
| +#endif |
| + |
| +using power::OriginPowerMap; |
| +using power::OriginPowerMapFactory; |
| + |
| +class BrowserProcessPowerTest : public BrowserWithTestWindowTest { |
| + public: |
| + BrowserProcessPowerTest() {} |
| + virtual ~BrowserProcessPowerTest() {} |
| + |
| + virtual void SetUp() OVERRIDE { |
| + BrowserWithTestWindowTest::SetUp(); |
| +#if defined(OS_CHROMEOS) |
| + chromeos::DBusThreadManager::Shutdown(); |
|
Daniel Erat
2014/08/20 19:55:08
this is weird; adding stevenjb@ for advice. should
|
| + chromeos::FakeDBusThreadManager* fake_dbus_thread_manager = |
| + new chromeos::FakeDBusThreadManager; |
| + fake_dbus_thread_manager->SetFakeClients(); |
| + chromeos::DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); |
| + chromeos::PowerDataCollector::InitializeForTesting(); |
| + |
| + power_manager::PowerSupplyProperties prop1; |
| + prop1.set_external_power( |
| + power_manager::PowerSupplyProperties::DISCONNECTED); |
| + prop1.set_battery_percent(20.00); |
| + prop1.set_battery_discharge_rate(1); |
| + chromeos::PowerDataCollector::Get()->PowerChanged(prop1); |
| +#endif |
| + |
| + profile_manager_.reset( |
| + new TestingProfileManager(TestingBrowserProcess::GetGlobal())); |
| + ASSERT_TRUE(profile_manager_->SetUp()); |
| + } |
| + |
| + virtual void TearDown() OVERRIDE { |
| +#if defined(OS_CHROMEOS) |
| + chromeos::PowerDataCollector::Shutdown(); |
| +#endif |
| + BrowserWithTestWindowTest::TearDown(); |
| + } |
| + |
| + protected: |
| + scoped_ptr<TestingProfileManager> profile_manager_; |
| + |
| + content::MockRenderProcessHost* process(Browser* browser) { |
| + return static_cast<content::MockRenderProcessHost*>( |
| + browser->tab_strip_model() |
| + ->GetActiveWebContents() |
| + ->GetRenderViewHost() |
| + ->GetProcess()); |
| + } |
| + |
| + scoped_ptr<base::ProcessHandle> MakeProcessHandle(int process_id) { |
| + scoped_ptr<base::ProcessHandle> proc_handle(new base::ProcessHandle( |
| +#if defined(OS_WIN) |
| + reinterpret_cast<HANDLE>(process_id)) |
| +#else |
| + process_id) |
| +#endif |
| + ); |
| + return proc_handle.Pass(); |
| + } |
| +}; |
| + |
| +class TestAppWindowContents : public apps::AppWindowContents { |
| + public: |
| + explicit TestAppWindowContents(content::WebContents* web_contents) { |
| + web_contents_.reset(web_contents); |
| + } |
| + // apps:AppWindowContents |
| + virtual void Initialize(content::BrowserContext* context, |
| + const GURL& url) OVERRIDE{}; |
| + virtual void LoadContents(int32 creator_process_id) OVERRIDE{}; |
| + virtual void NativeWindowChanged( |
| + extensions::NativeAppWindow* native_app_window) OVERRIDE{}; |
| + virtual void NativeWindowClosed() OVERRIDE{}; |
| + virtual void DispatchWindowShownForTests() const OVERRIDE{}; |
| + virtual content::WebContents* GetWebContents() const OVERRIDE { |
| + return web_contents_.get(); |
| + } |
| + |
| + private: |
| + scoped_ptr<content::WebContents> web_contents_; |
| +}; |
| + |
| +TEST_F(BrowserProcessPowerTest, NoSite) { |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + EXPECT_EQ(size_t(0), collector.metrics_map_for_testing()->size()); |
| +} |
| + |
| +TEST_F(BrowserProcessPowerTest, OneSite) { |
| + GURL url("http://www.google.com"); |
| + AddTab(browser(), url); |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + ProcessPowerCollector::ProcessMetricsMap* metrics_map = |
| + collector.metrics_map_for_testing(); |
| + EXPECT_EQ(size_t(1), metrics_map->size()); |
| + collector.RecordCpuUsageByOrigin(0); |
| + |
| + // Create fake process numbers. |
| + content::MockRenderProcessHost* rph = process(browser()); |
| + rph->SetProcessHandle(MakeProcessHandle(1).Pass()); |
| + |
| + OriginPowerMap* origin_power_map = |
| + OriginPowerMapFactory::GetForBrowserContext(profile()); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url)); |
| + |
| + collector.SynchronizeProcesses(); |
| + // Manually update the map to make the CPU usage work. |
|
Daniel Erat
2014/08/20 19:55:08
please add a way to fake the cpu usage so that the
Daniel Nishi
2014/08/20 20:56:35
Added a way to set a cpu usage getting callback fo
|
| + for (ProcessPowerCollector::ProcessMetricsMap::iterator it = |
| + metrics_map->begin(); |
| + it != metrics_map->end(); |
| + ++it) { |
| + it->second->set_last_cpu_percent(5); |
| + } |
| + collector.RecordCpuUsageByOrigin(5); |
| + EXPECT_EQ(100, origin_power_map->GetPowerForOrigin(url)); |
| +} |
| + |
| +TEST_F(BrowserProcessPowerTest, MultipleSites) { |
| + Browser::CreateParams native_params(profile(), |
| + chrome::HOST_DESKTOP_TYPE_NATIVE); |
| + GURL url1("http://www.google.com"); |
| + GURL url2("http://www.example.com"); |
| + GURL url3("https://www.google.com"); |
| + scoped_ptr<Browser> browser2( |
| + chrome::CreateBrowserWithTestWindowForParams(&native_params)); |
| + scoped_ptr<Browser> browser3( |
| + chrome::CreateBrowserWithTestWindowForParams(&native_params)); |
| + AddTab(browser(), url1); |
| + AddTab(browser2.get(), url2); |
| + AddTab(browser3.get(), url3); |
| + |
| + // Create fake process numbers. |
| + content::MockRenderProcessHost* rph = process(browser()); |
| + rph->SetProcessHandle(MakeProcessHandle(1).Pass()); |
|
Daniel Erat
2014/08/20 19:55:08
nit: condense these to e.g.
process(browser())-
Daniel Nishi
2014/08/20 20:56:35
Done.
|
| + rph = process(browser2.get()); |
| + rph->SetProcessHandle(MakeProcessHandle(2).Pass()); |
| + rph = process(browser3.get()); |
| + rph->SetProcessHandle(MakeProcessHandle(3).Pass()); |
| + |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + ProcessPowerCollector::ProcessMetricsMap* metrics_map = |
| + collector.metrics_map_for_testing(); |
| + EXPECT_EQ(size_t(3), metrics_map->size()); |
|
Daniel Erat
2014/08/20 19:55:08
nit: static_cast<size_t>(3) or just do 3U
Daniel Nishi
2014/08/20 20:56:34
Done.
|
| + |
| + // Since all handlers are uninitialized, this should be 0. |
| + EXPECT_EQ(0, collector.SynchronizeProcesses()); |
| + collector.RecordCpuUsageByOrigin(0); |
| + OriginPowerMap* origin_power_map = |
| + OriginPowerMapFactory::GetForBrowserContext(profile()); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url1)); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url2)); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url3)); |
| + |
| + collector.SynchronizeProcesses(); |
| + // Manually update the map to make the CPU usage work. |
| + for (ProcessPowerCollector::ProcessMetricsMap::iterator it = |
| + metrics_map->begin(); |
| + it != metrics_map->end(); |
| + ++it) { |
| + it->second->set_last_cpu_percent(5); |
| + } |
| + collector.RecordCpuUsageByOrigin(15); |
| + EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url1)); |
| + EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url2)); |
| + EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url3)); |
| + |
| + // Close some tabs and verify that they are removed from the metrics map. |
| + chrome::CloseTab(browser2.get()); |
| + chrome::CloseTab(browser3.get()); |
| + |
| + collector.SynchronizeProcesses(); |
| + collector.RecordCpuUsageByOrigin(0); |
| + EXPECT_EQ(size_t(1), metrics_map->size()); |
| +} |
| + |
| +TEST_F(BrowserProcessPowerTest, IncognitoDoesntRecordPowerUsage) { |
| + Browser::CreateParams native_params(profile()->GetOffTheRecordProfile(), |
| + chrome::HOST_DESKTOP_TYPE_NATIVE); |
| + scoped_ptr<Browser> incognito_browser( |
| + chrome::CreateBrowserWithTestWindowForParams(&native_params)); |
| + GURL url("http://www.google.com"); |
| + AddTab(browser(), url); |
| + |
| + GURL hidden_url("http://foo.com"); |
| + AddTab(incognito_browser.get(), hidden_url); |
| + |
| + // Create fake process numbers. |
| + content::MockRenderProcessHost* rph = process(browser()); |
| + rph->SetProcessHandle(MakeProcessHandle(1).Pass()); |
| + rph = process(incognito_browser.get()); |
| + rph->SetProcessHandle(MakeProcessHandle(2).Pass()); |
| + |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + ProcessPowerCollector::ProcessMetricsMap* metrics_map = |
| + collector.metrics_map_for_testing(); |
| + EXPECT_EQ(size_t(1), metrics_map->size()); |
| + collector.RecordCpuUsageByOrigin(0); |
| + |
| + OriginPowerMap* origin_power_map = |
| + OriginPowerMapFactory::GetForBrowserContext(profile()); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url)); |
| + |
| + collector.SynchronizeProcesses(); |
| + // Manually update the map to make the CPU usage work. |
| + for (ProcessPowerCollector::ProcessMetricsMap::iterator it = |
| + metrics_map->begin(); |
| + it != metrics_map->end(); |
| + ++it) { |
| + it->second->set_last_cpu_percent(5); |
| + } |
| + collector.RecordCpuUsageByOrigin(5); |
| + |
| + // Verify that the incognito data was not stored. |
| + EXPECT_EQ(100, origin_power_map->GetPowerForOrigin(url)); |
| + EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(hidden_url)); |
| + |
| + chrome::CloseTab(incognito_browser.get()); |
| +} |
| + |
| +TEST_F(BrowserProcessPowerTest, MultipleProfilesRecordSeparately) { |
| + scoped_ptr<Profile> other_profile(CreateProfile()); |
| + Browser::CreateParams native_params(other_profile.get(), |
| + chrome::HOST_DESKTOP_TYPE_NATIVE); |
| + scoped_ptr<Browser> other_user( |
| + chrome::CreateBrowserWithTestWindowForParams(&native_params)); |
| + |
| + GURL url("http://www.google.com"); |
| + AddTab(browser(), url); |
| + |
| + GURL hidden_url("http://foo.com"); |
| + AddTab(other_user.get(), hidden_url); |
| + |
| + // Create fake process numbers. |
| + content::MockRenderProcessHost* rph = process(browser()); |
| + rph->SetProcessHandle(MakeProcessHandle(1).Pass()); |
| + rph = process(other_user.get()); |
| + rph->SetProcessHandle(MakeProcessHandle(2).Pass()); |
| + |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + |
| + EXPECT_EQ(size_t(2), collector.metrics_map_for_testing()->size()); |
| + collector.RecordCpuUsageByOrigin(0); |
| + |
| + // Manually update the map to make the CPU usage work. |
| + ProcessPowerCollector::ProcessMetricsMap* metrics_map = |
| + collector.metrics_map_for_testing(); |
| + for (ProcessPowerCollector::ProcessMetricsMap::iterator it = |
| + metrics_map->begin(); |
| + it != metrics_map->end(); |
| + ++it) { |
| + it->second->set_last_cpu_percent(5); |
| + } |
| + collector.RecordCpuUsageByOrigin(5); |
| + |
| + // profile() should have an entry for |url| but not |hidden_url|. |
| + OriginPowerMap* origin_power_map_first = |
| + OriginPowerMapFactory::GetForBrowserContext(profile()); |
| + EXPECT_EQ(100, origin_power_map_first->GetPowerForOrigin(url)); |
| + EXPECT_EQ(0, origin_power_map_first->GetPowerForOrigin(hidden_url)); |
| + |
| + // |other_profile| should have an entry for |hidden_url| but not |url|. |
| + OriginPowerMap* origin_power_map_second = |
| + OriginPowerMapFactory::GetForBrowserContext(other_profile.get()); |
| + EXPECT_EQ(0, origin_power_map_second->GetPowerForOrigin(url)); |
| + EXPECT_EQ(100, origin_power_map_second->GetPowerForOrigin(hidden_url)); |
| + |
| + // Clean up |
| + chrome::CloseTab(other_user.get()); |
| +} |
| + |
| +const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; |
|
Daniel Erat
2014/08/20 19:55:08
nit: move this inside of the test that uses it
Daniel Nishi
2014/08/20 20:56:35
Done.
|
| + |
| +TEST_F(BrowserProcessPowerTest, AppsRecordPowerUsage) { |
| + Profile* current_profile = |
| + profile_manager_->CreateTestingProfile("Test user"); |
| + |
| +// Install an app (an extension*). |
|
Daniel Erat
2014/08/20 19:55:08
this should be indented two spaces
Daniel Nishi
2014/08/20 20:56:35
Done.
|
| +#if defined(OS_WIN) |
| + base::FilePath extension_path(FILE_PATH_LITERAL("c:\\foo")); |
|
Daniel Erat
2014/08/20 19:55:08
probably there's some other way of creating a fake
|
| +#elif defined(OS_POSIX) |
| + base::FilePath extension_path(FILE_PATH_LITERAL("/foo")); |
| +#endif |
| + base::DictionaryValue manifest; |
| + manifest.SetString("name", "Fake Name"); |
| + manifest.SetString("version", "1"); |
| + std::string error; |
| + scoped_refptr<extensions::Extension> extension( |
| + extensions::Extension::Create(extension_path, |
| + extensions::Manifest::INTERNAL, |
| + manifest, |
| + extensions::Extension::NO_FLAGS, |
| + kTestAppId, |
| + &error)); |
| + EXPECT_TRUE(extension.get()) << error; |
| + |
| + GURL url("chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); |
|
Daniel Erat
2014/08/20 19:55:08
use the above constant here
Daniel Nishi
2014/08/20 20:56:35
I think the standard way to do this is with hardco
|
| + // Use that to create a new AppWindow -- hopefully that can avoid |
| + // dependencies. |
|
Daniel Erat
2014/08/20 19:55:08
i don't fully understand this comment (partially t
Daniel Nishi
2014/08/20 20:56:35
Oh, whoops. That comment was one I left as a note
Daniel Nishi
2014/08/20 20:57:40
FWIW, it was a comment left from when this was ori
|
| + apps::AppWindow* window = |
| + new apps::AppWindow(current_profile, new ChromeAppDelegate(), extension); |
| + scoped_ptr<content::WebContents> web_contents( |
| + content::WebContents::Create(content::WebContents::CreateParams( |
| + current_profile, |
| + content::SiteInstance::CreateForURL(current_profile, url)))); |
| + window->SetAppWindowContentsForTesting(scoped_ptr<apps::AppWindowContents>( |
| + new TestAppWindowContents(web_contents.get()))); |
| + apps::AppWindowRegistry* app_registry = |
| + apps::AppWindowRegistry::Get(current_profile); |
| + app_registry->AddAppWindow(window); |
| + |
| + ProcessPowerCollector collector; |
| + collector.SynchronizeProcesses(); |
| + EXPECT_EQ(size_t(1), collector.metrics_map_for_testing()->size()); |
| + collector.RecordCpuUsageByOrigin(0); |
| + |
| + app_registry->RemoveAppWindow(window); |
| + collector.SynchronizeProcesses(); |
| + EXPECT_EQ(size_t(0), collector.metrics_map_for_testing()->size()); |
| + collector.RecordCpuUsageByOrigin(0); |
| +} |