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