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