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