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