browser_test_base.cc revision c2db58bd994c04d98e4ee2cd7565b71548655fe3
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 "content/browser/renderer_host/render_process_host_impl.h"
11#include "content/public/browser/browser_thread.h"
12#include "content/public/common/content_switches.h"
13#include "content/public/common/main_function_params.h"
14#include "content/public/test/test_utils.h"
15#include "net/test/embedded_test_server/embedded_test_server.h"
16#include "ui/compositor/compositor_switches.h"
17#include "ui/gl/gl_implementation.h"
18#include "ui/gl/gl_switches.h"
19
20#if defined(OS_POSIX)
21#include "base/process/process_handle.h"
22#endif
23
24#if defined(OS_MACOSX)
25#include "base/mac/mac_util.h"
26#include "base/power_monitor/power_monitor_device_source.h"
27#endif
28
29#if defined(OS_ANDROID)
30#include "base/threading/thread_restrictions.h"
31#include "content/public/browser/browser_main_runner.h"
32#include "content/public/browser/browser_thread.h"
33#endif
34
35#if defined(OS_CHROMEOS)
36#include "base/chromeos/chromeos_version.h"
37#endif
38
39namespace content {
40namespace {
41
42#if defined(OS_POSIX)
43// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
44// debugging easier) and also exit with a known error code (so that the test
45// framework considers this a failure -- http://crbug.com/57578).
46// Note: We only want to do this in the browser process, and not forked
47// processes. That might lead to hangs because of locks inside tcmalloc or the
48// OS. See http://crbug.com/141302.
49static int g_browser_process_pid;
50static void DumpStackTraceSignalHandler(int signal) {
51  if (g_browser_process_pid == base::GetCurrentProcId()) {
52    logging::RawLog(logging::LOG_ERROR,
53                    "BrowserTestBase signal handler received SIGTERM. "
54                    "Backtrace:\n");
55    base::debug::StackTrace().PrintBacktrace();
56  }
57  _exit(128 + signal);
58}
59#endif  // defined(OS_POSIX)
60
61void RunTaskOnRendererThread(const base::Closure& task,
62                             const base::Closure& quit_task) {
63  task.Run();
64  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
65}
66
67}  // namespace
68
69extern int BrowserMain(const MainFunctionParams&);
70
71BrowserTestBase::BrowserTestBase()
72    : embedded_test_server_(
73        new net::test_server::EmbeddedTestServer(
74            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))),
75      allow_test_contexts_(true),
76      allow_osmesa_(true) {
77#if defined(OS_MACOSX)
78  base::mac::SetOverrideAmIBundled(true);
79  base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
80#endif
81
82#if defined(OS_POSIX)
83  handle_sigterm_ = true;
84#endif
85}
86
87BrowserTestBase::~BrowserTestBase() {
88#if defined(OS_ANDROID)
89  // RemoteTestServer can cause wait on the UI thread.
90  base::ThreadRestrictions::ScopedAllowWait allow_wait;
91  test_server_.reset(NULL);
92#endif
93}
94
95void BrowserTestBase::SetUp() {
96  CommandLine* command_line = CommandLine::ForCurrentProcess();
97
98  // The tests assume that file:// URIs can freely access other file:// URIs.
99  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
100
101  command_line->AppendSwitch(switches::kDomAutomationController);
102
103  command_line->AppendSwitch(switches::kSkipGpuDataLoading);
104
105  MainFunctionParams params(*command_line);
106  params.ui_task =
107      new base::Closure(
108          base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this));
109
110#if defined(USE_AURA)
111  // Use test contexts for browser tests unless they override and force us to
112  // use a real context.
113  if (allow_test_contexts_)
114    command_line->AppendSwitch(switches::kTestCompositor);
115#endif
116
117  // When using real GL contexts, we usually use OSMesa as this works on all
118  // bots. The command line can override this behaviour to use a real GPU.
119  if (command_line->HasSwitch(switches::kUseGpuInTests))
120    allow_osmesa_ = false;
121
122  // Some bots pass this flag when they want to use a real GPU.
123  if (command_line->HasSwitch("enable-gpu"))
124    allow_osmesa_ = false;
125
126#if defined(OS_MACOSX)
127  // On Mac we always use a real GPU.
128  allow_osmesa_ = false;
129#endif
130
131#if defined(OS_ANDROID)
132  // On Android we always use a real GPU.
133  allow_osmesa_ = false;
134#endif
135
136#if defined(OS_CHROMEOS)
137  // If the test is running on the chromeos envrionment (such as
138  // device or vm bots), the compositor will use real GL contexts, and
139  // we should use real GL bindings with it.
140  if (base::chromeos::IsRunningOnChromeOS())
141    allow_osmesa_ = false;
142#endif
143
144  if (command_line->HasSwitch(switches::kUseGL)) {
145    NOTREACHED() <<
146        "kUseGL should not be used with tests. Try kUseGpuInTests instead.";
147  }
148
149  if (allow_osmesa_) {
150    command_line->AppendSwitchASCII(
151        switches::kUseGL, gfx::kGLImplementationOSMesaName);
152  }
153
154  SetUpInProcessBrowserTestFixture();
155#if defined(OS_ANDROID)
156  BrowserMainRunner::Create()->Initialize(params);
157  // We are done running the test by now. During teardown we
158  // need to be able to perform IO.
159  base::ThreadRestrictions::SetIOAllowed(true);
160  BrowserThread::PostTask(
161      BrowserThread::IO, FROM_HERE,
162      base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
163                 true));
164#else
165  BrowserMain(params);
166#endif
167  TearDownInProcessBrowserTestFixture();
168}
169
170void BrowserTestBase::TearDown() {
171}
172
173void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
174#if defined(OS_POSIX)
175  if (handle_sigterm_) {
176    g_browser_process_pid = base::GetCurrentProcId();
177    signal(SIGTERM, DumpStackTraceSignalHandler);
178  }
179#endif  // defined(OS_POSIX)
180  RunTestOnMainThreadLoop();
181  embedded_test_server_.reset();
182}
183
184void BrowserTestBase::CreateTestServer(const base::FilePath& test_server_base) {
185  CHECK(!test_server_.get());
186  test_server_.reset(new net::SpawnedTestServer(
187      net::SpawnedTestServer::TYPE_HTTP,
188      net::SpawnedTestServer::kLocalhost,
189      test_server_base));
190}
191
192void BrowserTestBase::PostTaskToInProcessRendererAndWait(
193    const base::Closure& task) {
194  CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
195
196  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
197
198  base::MessageLoop* renderer_loop =
199      RenderProcessHostImpl::GetInProcessRendererThreadForTesting();
200  CHECK(renderer_loop);
201
202  renderer_loop->PostTask(
203      FROM_HERE,
204      base::Bind(&RunTaskOnRendererThread, task, runner->QuitClosure()));
205  runner->Run();
206}
207
208}  // namespace content
209