Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(894)

Unified Diff: chrome/browser/power/process_power_collector_unittest.cc

Issue 472383002: Add ProcessPowerCollector to audit power information. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+}

Powered by Google App Engine
This is Rietveld 408576698