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

Unified Diff: chrome/test/gpu/gpu_memory_test.cc

Issue 11667030: Add GPU memory usage contents browser test (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove extraneous comments Created 7 years, 12 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/test/gpu/gpu_memory_test.cc
diff --git a/chrome/test/gpu/gpu_memory_test.cc b/chrome/test/gpu/gpu_memory_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1718c861b46f799680de0c776df4f49645a05a15
--- /dev/null
+++ b/chrome/test/gpu/gpu_memory_test.cc
@@ -0,0 +1,230 @@
+// 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 "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
+#include "chrome/browser/net/url_fixer_upper.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/test/automation/automation_proxy.h"
+#include "chrome/test/automation/browser_proxy.h"
+#include "chrome/test/automation/tab_proxy.h"
+#include "chrome/test/automation/window_proxy.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/ui/ui_test.h"
+#include "googleurl/src/gurl.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
ccameron 2013/01/03 19:07:56 Is this a layering violation -- should the switch
+#include "net/base/net_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// Run the tests with a memory limit of 256MB, and give
+// and extra 32MB of wiggle-room for over-allocation.
+const char *kMemoryLimitSwitch = "256";
+const size_t kMemoryLimit = 256 + 32;
+
+class GpuMemoryTest : public UITest {
Zhenyao Mo 2013/01/03 20:27:07 Does this truly needs to be a UI test? Will conte
ccameron 2013/01/04 21:52:35 Yes, this should have been content browser tests.
+ public:
+ GpuMemoryTest() : window_count_(1) {
+ show_window_ = true;
+ dom_automation_enabled_ = true;
+ }
+
+ ~GpuMemoryTest() {
+ }
+
+ virtual void SetUp() {
+ launch_arguments_.AppendSwitch(switches::kEnableLogging);
+ launch_arguments_.AppendSwitch(switches::kForceCompositingMode);
+ launch_arguments_.AppendSwitchASCII(switches::kForceGpuMemAvailableMb,
+ kMemoryLimitSwitch);
+ UITest::SetUp();
+ }
+
+ enum PageType {
+ PAGE_SIMPLE,
+ PAGE_CSS3D,
+ PAGE_WEBGL,
+ };
+
+ GURL GetPageGURL(PageType page_type) {
+ const FilePath kDataPath(FILE_PATH_LITERAL("gpu"));
+ const FilePath kCurrentDir(FilePath::kCurrentDirectory);
Zhenyao Mo 2013/01/03 20:27:07 kCurrentDir is never used.
ccameron 2013/01/04 21:52:35 Removed (from the new test).
+ FilePath page_path;
+ switch (page_type) {
+ case PAGE_SIMPLE:
+ page_path = ui_test_utils::GetTestFilePath(
+ kDataPath,
+ FilePath(FILE_PATH_LITERAL("mem_simple.html")));
+ break;
+ case PAGE_CSS3D:
+ page_path = ui_test_utils::GetTestFilePath(
+ kDataPath,
+ FilePath(FILE_PATH_LITERAL("mem_css3d.html")));
+ break;
+ case PAGE_WEBGL:
+ page_path = ui_test_utils::GetTestFilePath(
+ kDataPath,
+ FilePath(FILE_PATH_LITERAL("mem_webgl.html")));
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ return net::FilePathToFileURL(page_path);
+ }
+
+ BrowserProxy* GetCurrentWindow() {
+ return automation()->GetBrowserWindow(window_count_ - 1);
+ }
+
+ size_t MemoryUsageMbytes() {
+ std::string request, response, error;
ccameron 2013/01/03 19:07:56 I use JSON to get the memory values. There is not
Zhenyao Mo 2013/01/03 20:27:07 I don't see any problem doing it, but I am not an
ccameron 2013/01/04 21:52:35 Changing to browser test removes this.
+ DictionaryValue request_dict;
+ request_dict.SetString("command", "GetGpuMemoryUsage");
+ base::JSONWriter::Write(&request_dict, &request);
+
+ bool result = GetCurrentWindow()->SendJSONRequest(
+ request, -1, &response);
+ EXPECT_TRUE(result);
+
+ scoped_ptr<Value> values(base::JSONReader::ReadAndReturnError(
+ response, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
+ EXPECT_TRUE(error.empty());
+ EXPECT_EQ(values->GetType(), Value::TYPE_DICTIONARY);
+
+ DictionaryValue* values_dict = static_cast<DictionaryValue*>(values.get());
+ int mbytes_allocated = 0;
+ result = values_dict->GetInteger("gpu_memory_mbytes_allocated",
+ &mbytes_allocated);
+ EXPECT_TRUE(result);
+
+ return static_cast<size_t>(mbytes_allocated);
+ }
+
+ void NewTab() {
+ scoped_refptr<BrowserProxy> window(GetCurrentWindow());
+ ASSERT_TRUE(window.get());
+ scoped_refptr<TabProxy> tab(window->GetActiveTab());
+ EXPECT_TRUE(window->AppendTab(GetPageGURL(PAGE_SIMPLE)));
+ tab = window->GetActiveTab();
+ ASSERT_TRUE(tab.get());
+ }
+
+ void NewWindow() {
+ int actual_window_count = -1;;
+ scoped_refptr<BrowserProxy> window(GetCurrentWindow());
+ ASSERT_TRUE(window.get());
+ EXPECT_TRUE(automation()->GetBrowserWindowCount(&actual_window_count));
+ EXPECT_EQ(actual_window_count, window_count_);
+ window_count_ += 1;
+ EXPECT_TRUE(automation()->OpenNewBrowserWindow(Browser::TYPE_TABBED,
+ true));
+ EXPECT_TRUE(automation()->WaitForWindowCountToBecome(
+ window_count_));
+ EXPECT_TRUE(automation()->GetBrowserWindowCount(&actual_window_count));
+ EXPECT_EQ(actual_window_count, window_count_);
+ window = GetCurrentWindow();
+
+ // A new window will not load a url if requested too soon. The window
+ // stays on the new tab page instead.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
vangelis 2013/01/03 20:26:14 Sleep() seems like a potential source of flakiness
ccameron 2013/01/04 21:52:35 This will be a lot of work, but I've wrapped my he
+
+ ASSERT_TRUE(window.get());
+ scoped_refptr<TabProxy> tab(window->GetActiveTab());
+ ASSERT_TRUE(tab.get());
+ }
+
+ // Load a page of 3D CSS or WebGL (or a plain page), and make the page
+ // allocate |mb_to_use| MB of GPU memory.
+ void ReloadCurrentTab(PageType page_type, size_t mb_to_use) {
+ scoped_refptr<BrowserProxy> window(GetCurrentWindow());
+ ASSERT_TRUE(window.get());
+ scoped_refptr<TabProxy> tab(window->GetActiveTab());
+ ASSERT_TRUE(tab.get());
+
+ EXPECT_EQ(AUTOMATION_MSG_NAVIGATION_SUCCESS,
+ tab->NavigateToURL(GetPageGURL(page_type)));
+
+ // Execute the JS command to allocate memory (either via CSS or WebGL).
+ std::wostringstream js_call;
+ js_call << "useGpuMemory(";
+ js_call << mb_to_use;
+ js_call << ");";
+ bool result = false;
+ EXPECT_TRUE(
+ tab->ExecuteAndExtractBool(L"", js_call.str(), &result));
+ EXPECT_TRUE(result);
+
+ // Give up to a full 2 seconds for the page to load -- the WebGL
+ // and 3D CSS pages can be very slow.
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(2000));
ccameron 2013/01/03 19:07:56 Given how big the pages are (256MB for some), wait
Zhenyao Mo 2013/01/03 20:27:07 I truly think this is bad practice. It wastes tim
+ }
+
+ private:
+ int window_count_;
+};
+
+// These tests will need to be verified on Android before being enabled.
+#if !defined(OS_ANDROID)
+
+// When trying to load something that doesn't fit into our total GPU memory
+// limit, we shouldn't exceed that limit.
+TEST_F(GpuMemoryTest, Simple) {
ccameron 2013/01/03 19:07:56 These tests will explode if the GPU process is dis
Zhenyao Mo 2013/01/03 20:27:07 You can use trace events to make sure GPU process
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ EXPECT_LT(MemoryUsageMbytes(), kMemoryLimit);
+}
+
+// This should remain true if we load the same big page in three windows.
+TEST_F(GpuMemoryTest, MultiWindow) {
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ NewWindow();
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ NewWindow();
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ EXPECT_LT(MemoryUsageMbytes(), kMemoryLimit);
+}
+
+// This should remain true if we load the same big page in multiple tabs.
+TEST_F(GpuMemoryTest, MultiTab) {
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ NewTab();
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ NewTab();
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ EXPECT_LT(MemoryUsageMbytes(), kMemoryLimit);
+}
+
+// Load a page with heavy WebGL, then background it, and make sure that
+// the WebGL page's allocation causes the CSS page to use less memory
+TEST_F(GpuMemoryTest, WebGL) {
+ ReloadCurrentTab(PAGE_WEBGL, 192u);
+ NewTab();
+ ReloadCurrentTab(PAGE_SIMPLE, 1u);
+ // Make sure that we're still using <192 MB (cause we shouldn't have
+ // torched the WebGL, which uses at least that much).
+ EXPECT_GE(MemoryUsageMbytes(), 192u);
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ EXPECT_LT(MemoryUsageMbytes(), kMemoryLimit);
+}
+
+// Make sure that we don't waste memory on backgrounded tabs that can't
+// be rendered fully.
+TEST_F(GpuMemoryTest, Background) {
+ ReloadCurrentTab(PAGE_CSS3D, 256u);
+ // Make sure that the CSS page is using at least 64MB
+ EXPECT_GE(MemoryUsageMbytes(), 64u);
+ NewTab();
+ ReloadCurrentTab(PAGE_SIMPLE, 1u);
+ // Assume that the simple page will use <32 MB, and make
+ // sure that nothing remains from the hard page.
+ EXPECT_LT(MemoryUsageMbytes(), 32u);
+}
+
+#endif // !defined(OS_ANDROID)
+
+} // namespace

Powered by Google App Engine
This is Rietveld 408576698