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