browser_test_base.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright (c) 2011 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 "content/public/test/browser_test_base.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/debug/stack_trace.h" 10#include "base/message_loop/message_loop.h" 11#include "content/browser/renderer_host/render_process_host_impl.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/common/content_switches.h" 14#include "content/public/common/main_function_params.h" 15#include "content/public/test/test_utils.h" 16#include "net/base/net_errors.h" 17#include "net/dns/mock_host_resolver.h" 18#include "net/test/embedded_test_server/embedded_test_server.h" 19#include "ui/compositor/compositor_switches.h" 20#include "ui/gl/gl_implementation.h" 21#include "ui/gl/gl_switches.h" 22 23#if defined(OS_POSIX) 24#include "base/process/process_handle.h" 25#endif 26 27#if defined(OS_MACOSX) 28#include "base/mac/mac_util.h" 29#include "base/power_monitor/power_monitor_device_source.h" 30#endif 31 32#if defined(OS_ANDROID) 33#include "base/threading/thread_restrictions.h" 34#include "content/public/browser/browser_main_runner.h" 35#include "content/public/browser/browser_thread.h" 36#endif 37 38#if defined(OS_CHROMEOS) 39#include "base/chromeos/chromeos_version.h" 40#endif 41 42namespace content { 43namespace { 44 45#if defined(OS_POSIX) 46// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make 47// debugging easier) and also exit with a known error code (so that the test 48// framework considers this a failure -- http://crbug.com/57578). 49// Note: We only want to do this in the browser process, and not forked 50// processes. That might lead to hangs because of locks inside tcmalloc or the 51// OS. See http://crbug.com/141302. 52static int g_browser_process_pid; 53static void DumpStackTraceSignalHandler(int signal) { 54 if (g_browser_process_pid == base::GetCurrentProcId()) { 55 logging::RawLog(logging::LOG_ERROR, 56 "BrowserTestBase signal handler received SIGTERM. " 57 "Backtrace:\n"); 58 base::debug::StackTrace().Print(); 59 } 60 _exit(128 + signal); 61} 62#endif // defined(OS_POSIX) 63 64void RunTaskOnRendererThread(const base::Closure& task, 65 const base::Closure& quit_task) { 66 task.Run(); 67 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task); 68} 69 70// In many cases it may be not obvious that a test makes a real DNS lookup. 71// We generally don't want to rely on external DNS servers for our tests, 72// so this host resolver procedure catches external queries and returns a failed 73// lookup result. 74class LocalHostResolverProc : public net::HostResolverProc { 75 public: 76 LocalHostResolverProc() : HostResolverProc(NULL) {} 77 78 virtual int Resolve(const std::string& host, 79 net::AddressFamily address_family, 80 net::HostResolverFlags host_resolver_flags, 81 net::AddressList* addrlist, 82 int* os_error) OVERRIDE { 83 const char* kLocalHostNames[] = {"localhost", "127.0.0.1", "::1"}; 84 bool local = false; 85 86 if (host == net::GetHostName()) { 87 local = true; 88 } else { 89 for (size_t i = 0; i < arraysize(kLocalHostNames); i++) 90 if (host == kLocalHostNames[i]) { 91 local = true; 92 break; 93 } 94 } 95 96 // To avoid depending on external resources and to reduce (if not preclude) 97 // network interactions from tests, we simulate failure for non-local DNS 98 // queries, rather than perform them. 99 // If you really need to make an external DNS query, use 100 // net::RuleBasedHostResolverProc and its AllowDirectLookup method. 101 if (!local) { 102 DVLOG(1) << "To avoid external dependencies, simulating failure for " 103 "external DNS lookup of " << host; 104 return net::ERR_NOT_IMPLEMENTED; 105 } 106 107 return ResolveUsingPrevious(host, address_family, host_resolver_flags, 108 addrlist, os_error); 109 } 110 111 private: 112 virtual ~LocalHostResolverProc() {} 113}; 114 115} // namespace 116 117extern int BrowserMain(const MainFunctionParams&); 118 119BrowserTestBase::BrowserTestBase() 120 : embedded_test_server_io_thread_("EmbeddedTestServer io thread"), 121 allow_test_contexts_(true), 122 allow_osmesa_(true) { 123#if defined(OS_MACOSX) 124 base::mac::SetOverrideAmIBundled(true); 125 base::PowerMonitorDeviceSource::AllocateSystemIOPorts(); 126#endif 127 128#if defined(OS_POSIX) 129 handle_sigterm_ = true; 130#endif 131 132 // Create a separate thread for the test server to run on. It's tempting to 133 // use actual browser threads, but that doesn't work for cases where the test 134 // server needs to be started before the browser, for example when the server 135 // URL should be passed in command-line parameters. 136 base::Thread::Options thread_options; 137 thread_options.message_loop_type = base::MessageLoop::TYPE_IO; 138 CHECK(embedded_test_server_io_thread_.StartWithOptions(thread_options)); 139 embedded_test_server_.reset(new net::test_server::EmbeddedTestServer( 140 embedded_test_server_io_thread_.message_loop_proxy())); 141} 142 143BrowserTestBase::~BrowserTestBase() { 144#if defined(OS_ANDROID) 145 // RemoteTestServer can cause wait on the UI thread. 146 base::ThreadRestrictions::ScopedAllowWait allow_wait; 147 test_server_.reset(NULL); 148#endif 149} 150 151void BrowserTestBase::SetUp() { 152 CommandLine* command_line = CommandLine::ForCurrentProcess(); 153 154 // The tests assume that file:// URIs can freely access other file:// URIs. 155 command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); 156 157 command_line->AppendSwitch(switches::kDomAutomationController); 158 159 command_line->AppendSwitch(switches::kSkipGpuDataLoading); 160 161#if defined(USE_AURA) 162 // Use test contexts for browser tests unless they override and force us to 163 // use a real context. 164 if (allow_test_contexts_) 165 command_line->AppendSwitch(switches::kTestCompositor); 166#endif 167 168 // When using real GL contexts, we usually use OSMesa as this works on all 169 // bots. The command line can override this behaviour to use a real GPU. 170 if (command_line->HasSwitch(switches::kUseGpuInTests)) 171 allow_osmesa_ = false; 172 173 // Some bots pass this flag when they want to use a real GPU. 174 if (command_line->HasSwitch("enable-gpu")) 175 allow_osmesa_ = false; 176 177#if defined(OS_MACOSX) 178 // On Mac we always use a real GPU. 179 allow_osmesa_ = false; 180#endif 181 182#if defined(OS_ANDROID) 183 // On Android we always use a real GPU. 184 allow_osmesa_ = false; 185#endif 186 187#if defined(OS_CHROMEOS) 188 // If the test is running on the chromeos envrionment (such as 189 // device or vm bots), the compositor will use real GL contexts, and 190 // we should use real GL bindings with it. 191 if (base::chromeos::IsRunningOnChromeOS()) 192 allow_osmesa_ = false; 193#endif 194 195 if (command_line->HasSwitch(switches::kUseGL)) { 196 NOTREACHED() << 197 "kUseGL should not be used with tests. Try kUseGpuInTests instead."; 198 } 199 200 if (allow_osmesa_) { 201 command_line->AppendSwitchASCII( 202 switches::kUseGL, gfx::kGLImplementationOSMesaName); 203 } 204 205 scoped_refptr<net::HostResolverProc> local_resolver = 206 new LocalHostResolverProc(); 207 rule_based_resolver_ = 208 new net::RuleBasedHostResolverProc(local_resolver.get()); 209 rule_based_resolver_->AddSimulatedFailure("wpad"); 210 net::ScopedDefaultHostResolverProc scoped_local_host_resolver_proc( 211 rule_based_resolver_.get()); 212 213 SetUpInProcessBrowserTestFixture(); 214 215 MainFunctionParams params(*command_line); 216 params.ui_task = 217 new base::Closure( 218 base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this)); 219 220#if defined(OS_ANDROID) 221 BrowserMainRunner::Create()->Initialize(params); 222 // We are done running the test by now. During teardown we 223 // need to be able to perform IO. 224 base::ThreadRestrictions::SetIOAllowed(true); 225 BrowserThread::PostTask( 226 BrowserThread::IO, FROM_HERE, 227 base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), 228 true)); 229#else 230 BrowserMain(params); 231#endif 232 TearDownInProcessBrowserTestFixture(); 233} 234 235void BrowserTestBase::TearDown() { 236} 237 238void BrowserTestBase::ProxyRunTestOnMainThreadLoop() { 239#if defined(OS_POSIX) 240 if (handle_sigterm_) { 241 g_browser_process_pid = base::GetCurrentProcId(); 242 signal(SIGTERM, DumpStackTraceSignalHandler); 243 } 244#endif // defined(OS_POSIX) 245 RunTestOnMainThreadLoop(); 246} 247 248void BrowserTestBase::CreateTestServer(const base::FilePath& test_server_base) { 249 CHECK(!test_server_.get()); 250 test_server_.reset(new net::SpawnedTestServer( 251 net::SpawnedTestServer::TYPE_HTTP, 252 net::SpawnedTestServer::kLocalhost, 253 test_server_base)); 254} 255 256void BrowserTestBase::PostTaskToInProcessRendererAndWait( 257 const base::Closure& task) { 258 CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess)); 259 260 scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner; 261 262 base::MessageLoop* renderer_loop = 263 RenderProcessHostImpl::GetInProcessRendererThreadForTesting(); 264 CHECK(renderer_loop); 265 266 renderer_loop->PostTask( 267 FROM_HERE, 268 base::Bind(&RunTaskOnRendererThread, task, runner->QuitClosure())); 269 runner->Run(); 270} 271 272} // namespace content 273