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