1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <vector> 6 7 #include "base/memory/ref_counted.h" 8 #include "base/strings/string_util.h" 9 #include "chrome/common/automation_constants.h" 10 #include "chrome/common/automation_messages.h" 11 #include "chrome/test/automation/automation_proxy.h" 12 #include "chrome/test/automation/browser_proxy.h" 13 #include "chrome/test/automation/tab_proxy.h" 14 #include "chrome/test/perf/perf_test.h" 15 #include "chrome/test/ui/ui_perf_test.h" 16 #include "net/test/spawned_test_server/spawned_test_server.h" 17 18 namespace { 19 20 // This test spawns a new browser and counts the number of open Mach ports in 21 // the browser process. It navigates tabs and closes them, repeatedly measuring 22 // the number of open ports. This is used to protect against leaking Mach ports, 23 // which was the source of <http://crbug.com/105513>. 24 class MachPortsTest : public UIPerfTest { 25 public: 26 MachPortsTest() 27 : server_(net::SpawnedTestServer::TYPE_HTTP, 28 net::SpawnedTestServer::kLocalhost, 29 base::FilePath(FILE_PATH_LITERAL("data/mach_ports/moz"))) { 30 } 31 32 virtual void SetUp() OVERRIDE { 33 UIPerfTest::SetUp(); 34 35 ASSERT_TRUE(server_.Start()); 36 } 37 38 virtual void TearDown() OVERRIDE { 39 std::string ports; 40 for (std::vector<int>::iterator it = port_counts_.begin(); 41 it != port_counts_.end(); ++it) { 42 base::StringAppendF(&ports, "%d,", *it); 43 } 44 perf_test::PrintResultList("mach_ports", "", "", ports, "ports", true); 45 46 UIPerfTest::TearDown(); 47 } 48 49 // Gets the browser's current number of Mach ports and records it. 50 void RecordPortCount() { 51 int port_count = 0; 52 ASSERT_TRUE(automation()->Send( 53 new AutomationMsg_GetMachPortCount(&port_count))); 54 port_counts_.push_back(port_count); 55 } 56 57 // Adds a tab from the page cycler data at the specified domain. 58 bool AddTab(scoped_refptr<BrowserProxy> browser, const std::string& domain) { 59 GURL url = server_.GetURL("files/" + domain + "/").Resolve("?skip"); 60 return browser->AppendTab(url); 61 } 62 63 private: 64 net::SpawnedTestServer server_; 65 std::vector<int> port_counts_; 66 }; 67 68 TEST_F(MachPortsTest, GetCounts) { 69 ASSERT_EQ(AUTOMATION_SUCCESS, automation()->WaitForAppLaunch()); 70 71 // Record startup number. 72 RecordPortCount(); 73 74 // Create a browser and open a few tabs. 75 scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); 76 ASSERT_TRUE(browser.get()); 77 78 EXPECT_TRUE(AddTab(browser, "www.google.com")); 79 RecordPortCount(); 80 81 EXPECT_TRUE(AddTab(browser, "www.cnn.com")); 82 RecordPortCount(); 83 84 EXPECT_TRUE(AddTab(browser, "www.nytimes.com")); 85 RecordPortCount(); 86 87 int tab_count = 0; 88 ASSERT_TRUE(browser->GetTabCount(&tab_count)); 89 EXPECT_EQ(4, tab_count); // Also count about:blank. 90 91 // Close each tab, recording the number of ports after each. Do not close the 92 // last tab, which is about:blank because it will be closed by the proxy. 93 for (int i = 0; i < tab_count - 1; ++i) { 94 scoped_refptr<TabProxy> tab(browser->GetActiveTab()); 95 ASSERT_TRUE(tab.get()); 96 97 EXPECT_TRUE(tab->Close(true)); 98 RecordPortCount(); 99 } 100 } 101 102 } // namespace 103