browser_test_base.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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
17#if defined(OS_POSIX)
18#include "base/process/process_handle.h"
19#endif
20
21#if defined(OS_MACOSX)
22#include "base/mac/mac_util.h"
23#include "base/power_monitor/power_monitor_device_source.h"
24#endif
25
26#if defined(OS_ANDROID)
27#include "base/threading/thread_restrictions.h"
28#include "content/public/browser/browser_main_runner.h"
29#include "content/public/browser/browser_thread.h"
30#endif
31
32namespace content {
33namespace {
34
35#if defined(OS_POSIX)
36// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
37// debugging easier) and also exit with a known error code (so that the test
38// framework considers this a failure -- http://crbug.com/57578).
39// Note: We only want to do this in the browser process, and not forked
40// processes. That might lead to hangs because of locks inside tcmalloc or the
41// OS. See http://crbug.com/141302.
42static int g_browser_process_pid;
43static void DumpStackTraceSignalHandler(int signal) {
44  if (g_browser_process_pid == base::GetCurrentProcId()) {
45    logging::RawLog(logging::LOG_ERROR,
46                    "BrowserTestBase signal handler received SIGTERM. "
47                    "Backtrace:\n");
48    base::debug::StackTrace().PrintBacktrace();
49  }
50  _exit(128 + signal);
51}
52#endif  // defined(OS_POSIX)
53
54void RunTaskOnRendererThread(const base::Closure& task,
55                             const base::Closure& quit_task) {
56  task.Run();
57  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
58}
59
60}  // namespace
61
62extern int BrowserMain(const MainFunctionParams&);
63
64BrowserTestBase::BrowserTestBase()
65    : embedded_test_server_(
66        new net::test_server::EmbeddedTestServer(
67            BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))) {
68#if defined(OS_MACOSX)
69  base::mac::SetOverrideAmIBundled(true);
70  base::PowerMonitorDeviceSource::AllocateSystemIOPorts();
71#endif
72
73#if defined(OS_POSIX)
74  handle_sigterm_ = true;
75#endif
76}
77
78BrowserTestBase::~BrowserTestBase() {
79#if defined(OS_ANDROID)
80  // RemoteTestServer can cause wait on the UI thread.
81  base::ThreadRestrictions::ScopedAllowWait allow_wait;
82  test_server_.reset(NULL);
83#endif
84}
85
86void BrowserTestBase::SetUp() {
87  CommandLine* command_line = CommandLine::ForCurrentProcess();
88
89  // The tests assume that file:// URIs can freely access other file:// URIs.
90  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
91
92  command_line->AppendSwitch(switches::kDomAutomationController);
93
94  command_line->AppendSwitch(switches::kSkipGpuDataLoading);
95
96  MainFunctionParams params(*command_line);
97  params.ui_task =
98      new base::Closure(
99          base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this));
100
101  SetUpInProcessBrowserTestFixture();
102#if defined(OS_ANDROID)
103  BrowserMainRunner::Create()->Initialize(params);
104  // We are done running the test by now. During teardown we
105  // need to be able to perform IO.
106  base::ThreadRestrictions::SetIOAllowed(true);
107  BrowserThread::PostTask(
108      BrowserThread::IO, FROM_HERE,
109      base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
110                 true));
111#else
112  BrowserMain(params);
113#endif
114  TearDownInProcessBrowserTestFixture();
115}
116
117void BrowserTestBase::TearDown() {
118}
119
120void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
121#if defined(OS_POSIX)
122  if (handle_sigterm_) {
123    g_browser_process_pid = base::GetCurrentProcId();
124    signal(SIGTERM, DumpStackTraceSignalHandler);
125  }
126#endif  // defined(OS_POSIX)
127  RunTestOnMainThreadLoop();
128  embedded_test_server_.reset();
129}
130
131void BrowserTestBase::CreateTestServer(const base::FilePath& test_server_base) {
132  CHECK(!test_server_.get());
133  test_server_.reset(new net::SpawnedTestServer(
134      net::SpawnedTestServer::TYPE_HTTP,
135      net::SpawnedTestServer::kLocalhost,
136      test_server_base));
137}
138
139void BrowserTestBase::PostTaskToInProcessRendererAndWait(
140    const base::Closure& task) {
141  CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
142
143  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
144
145  base::MessageLoop* renderer_loop =
146      RenderProcessHostImpl::GetInProcessRendererThreadForTesting();
147  CHECK(renderer_loop);
148
149  renderer_loop->PostTask(
150      FROM_HERE,
151      base::Bind(&RunTaskOnRendererThread, task, runner->QuitClosure()));
152  runner->Run();
153}
154
155}  // namespace content
156