1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file. 4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <mach/mach.h> 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <vector> 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/ref_counted.h" 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/strings/string_util.h" 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/strings/stringprintf.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/ui/browser.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/ui/browser_window.h" 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/ui/tabs/tab_strip_model.h" 15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/test/base/in_process_browser_test.h" 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "net/test/spawned_test_server/spawned_test_server.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "testing/perf/perf_test.h" 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace { 20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This test spawns a new browser and counts the number of open Mach ports in 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// the browser process. It navigates tabs and closes them, repeatedly measuring 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// the number of open ports. This is used to protect against leaking Mach ports, 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// which was the source of <http://crbug.com/105513>. 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass MachPortsTest : public InProcessBrowserTest { 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public: 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MachPortsTest() 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : server_(net::SpawnedTestServer::TYPE_HTTP, 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch net::SpawnedTestServer::kLocalhost, 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::FilePath(FILE_PATH_LITERAL("data/mach_ports/moz"))) { 31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual void SetUp() OVERRIDE { 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InProcessBrowserTest::SetUp(); 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ASSERT_TRUE(server_.Start()); 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual void TearDown() OVERRIDE { 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::string ports; 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::vector<int>::iterator it = port_counts_.begin(); 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != port_counts_.end(); ++it) { 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::StringAppendF(&ports, "%d,", *it); 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch perf_test::PrintResultList("mach_ports", "", "", ports, "ports", true); 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InProcessBrowserTest::TearDown(); 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Gets the browser's current number of Mach ports and records it. 51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void RecordPortCount() { 52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mach_port_name_array_t names; 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mach_msg_type_number_t names_count = 0; 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mach_port_type_array_t types; 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mach_msg_type_number_t types_count = 0; 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mach_port_t self = mach_task_self(); 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // A friendlier interface would allow NULL buffers to only get the counts. 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kern_return_t kr = mach_port_names(self, 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &names, &names_count, 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &types, &types_count); 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ASSERT_EQ(KERN_SUCCESS, kr) << "Failed to get mach_port_names(): " 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch << mach_error_string(kr); 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ASSERT_EQ(names_count, types_count); // Documented kernel invariant. 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch port_counts_.push_back(names_count); 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch vm_deallocate(self, reinterpret_cast<vm_address_t>(names), 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch names_count * sizeof(mach_port_name_array_t)); 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch vm_deallocate(self, reinterpret_cast<vm_address_t>(types), 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch types_count * sizeof(mach_port_type_array_t)); 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Adds a tab from the page cycler data at the specified domain. 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void AddTab(const std::string& domain) { 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GURL url = server_.GetURL("files/" + domain + "/").Resolve("?skip"); 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AddTabAtIndex(0, url, content::PageTransition::PAGE_TRANSITION_TYPED); 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch private: 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch net::SpawnedTestServer server_; 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<int> port_counts_; 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 86effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochIN_PROC_BROWSER_TEST_F(MachPortsTest, GetCounts) { 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch browser()->window()->Show(); 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Record startup number. 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordPortCount(); 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Create a browser and open a few tabs. 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AddTab("www.google.com"); 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordPortCount(); 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AddTab("www.cnn.com"); 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordPortCount(); 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AddTab("www.nytimes.com"); 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordPortCount(); 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch TabStripModel* tab_strip_model = browser()->tab_strip_model(); 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int tab_count = tab_strip_model->count(); 104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ASSERT_EQ(4, tab_count); // Also count about:blank. 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Close each tab, recording the number of ports after each. Do not close the 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // last tab, which is about:blank. 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (int i = 0; i < tab_count - 1; ++i) { 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_TRUE( 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tab_strip_model->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE)); 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RecordPortCount(); 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace 116