Home | History | Annotate | Download | only in test
      1 // Copyright (c) 2012 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 "base/test/test_suite.h"
      6 
      7 #include "base/at_exit.h"
      8 #include "base/base_paths.h"
      9 #include "base/base_switches.h"
     10 #include "base/command_line.h"
     11 #include "base/debug/debug_on_start_win.h"
     12 #include "base/debug/debugger.h"
     13 #include "base/debug/stack_trace.h"
     14 #include "base/files/file_path.h"
     15 #include "base/i18n/icu_util.h"
     16 #include "base/logging.h"
     17 #include "base/memory/scoped_ptr.h"
     18 #include "base/path_service.h"
     19 #include "base/process/memory.h"
     20 #include "base/test/multiprocess_test.h"
     21 #include "base/test/test_timeouts.h"
     22 #include "base/time/time.h"
     23 #include "testing/gtest/include/gtest/gtest.h"
     24 #include "testing/multiprocess_func_list.h"
     25 
     26 #if defined(OS_MACOSX)
     27 #include "base/mac/scoped_nsautorelease_pool.h"
     28 #if defined(OS_IOS)
     29 #include "base/test/test_listener_ios.h"
     30 #else
     31 #include "base/test/mock_chrome_application_mac.h"
     32 #endif  // OS_IOS
     33 #endif  // OS_MACOSX
     34 
     35 #if defined(OS_ANDROID)
     36 #include "base/test/test_support_android.h"
     37 #endif
     38 
     39 #if defined(OS_IOS)
     40 #include "base/test/test_support_ios.h"
     41 #endif
     42 
     43 #if defined(TOOLKIT_GTK)
     44 #include <gtk/gtk.h>
     45 #endif
     46 
     47 namespace {
     48 
     49 class MaybeTestDisabler : public testing::EmptyTestEventListener {
     50  public:
     51   virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE {
     52     ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info))
     53         << "Probably the OS #ifdefs don't include all of the necessary "
     54            "platforms.\nPlease ensure that no tests have the MAYBE_ prefix "
     55            "after the code is preprocessed.";
     56   }
     57 };
     58 
     59 class TestClientInitializer : public testing::EmptyTestEventListener {
     60  public:
     61   TestClientInitializer()
     62       : old_command_line_(CommandLine::NO_PROGRAM) {
     63   }
     64 
     65   virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE {
     66     old_command_line_ = *CommandLine::ForCurrentProcess();
     67   }
     68 
     69   virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE {
     70     *CommandLine::ForCurrentProcess() = old_command_line_;
     71   }
     72 
     73  private:
     74   CommandLine old_command_line_;
     75 
     76   DISALLOW_COPY_AND_ASSIGN(TestClientInitializer);
     77 };
     78 
     79 }  // namespace
     80 
     81 TestSuite::TestSuite(int argc, char** argv) : initialized_command_line_(false) {
     82   PreInitialize(argc, argv, true);
     83 }
     84 
     85 TestSuite::TestSuite(int argc, char** argv, bool create_at_exit_manager)
     86     : initialized_command_line_(false) {
     87   PreInitialize(argc, argv, create_at_exit_manager);
     88 }
     89 
     90 TestSuite::~TestSuite() {
     91   if (initialized_command_line_)
     92     CommandLine::Reset();
     93 }
     94 
     95 void TestSuite::PreInitialize(int argc, char** argv,
     96                               bool create_at_exit_manager) {
     97 #if defined(OS_WIN)
     98   testing::GTEST_FLAG(catch_exceptions) = false;
     99 #endif
    100   base::EnableTerminationOnHeapCorruption();
    101   initialized_command_line_ = CommandLine::Init(argc, argv);
    102   testing::InitGoogleTest(&argc, argv);
    103 #if defined(OS_LINUX) && defined(USE_AURA)
    104   // When calling native char conversion functions (e.g wrctomb) we need to
    105   // have the locale set. In the absence of such a call the "C" locale is the
    106   // default. In the gtk code (below) gtk_init() implicitly sets a locale.
    107   setlocale(LC_ALL, "");
    108 #elif defined(TOOLKIT_GTK)
    109   gtk_init_check(&argc, &argv);
    110 #endif  // defined(TOOLKIT_GTK)
    111 
    112   // On Android, AtExitManager is created in
    113   // testing/android/native_test_wrapper.cc before main() is called.
    114 #if !defined(OS_ANDROID)
    115   if (create_at_exit_manager)
    116     at_exit_manager_.reset(new base::AtExitManager);
    117 #endif
    118 
    119 #if defined(OS_IOS)
    120   InitIOSRunHook(this, argc, argv);
    121 #endif
    122 
    123   // Don't add additional code to this function.  Instead add it to
    124   // Initialize().  See bug 6436.
    125 }
    126 
    127 
    128 // static
    129 bool TestSuite::IsMarkedMaybe(const testing::TestInfo& test) {
    130   return strncmp(test.name(), "MAYBE_", 6) == 0;
    131 }
    132 
    133 void TestSuite::CatchMaybeTests() {
    134   testing::TestEventListeners& listeners =
    135       testing::UnitTest::GetInstance()->listeners();
    136   listeners.Append(new MaybeTestDisabler);
    137 }
    138 
    139 void TestSuite::ResetCommandLine() {
    140   testing::TestEventListeners& listeners =
    141       testing::UnitTest::GetInstance()->listeners();
    142   listeners.Append(new TestClientInitializer);
    143 }
    144 
    145 // Don't add additional code to this method.  Instead add it to
    146 // Initialize().  See bug 6436.
    147 int TestSuite::Run() {
    148 #if defined(OS_IOS)
    149   RunTestsFromIOSApp();
    150 #endif
    151 
    152 #if defined(OS_MACOSX)
    153   base::mac::ScopedNSAutoreleasePool scoped_pool;
    154 #endif
    155 
    156   Initialize();
    157   std::string client_func =
    158       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
    159           switches::kTestChildProcess);
    160 
    161   // Check to see if we are being run as a client process.
    162   if (!client_func.empty())
    163     return multi_process_function_list::InvokeChildProcessTest(client_func);
    164 #if defined(OS_IOS)
    165   base::test_listener_ios::RegisterTestEndListener();
    166 #endif
    167   int result = RUN_ALL_TESTS();
    168 
    169 #if defined(OS_MACOSX)
    170   // This MUST happen before Shutdown() since Shutdown() tears down
    171   // objects (such as NotificationService::current()) that Cocoa
    172   // objects use to remove themselves as observers.
    173   scoped_pool.Recycle();
    174 #endif
    175 
    176   Shutdown();
    177 
    178   return result;
    179 }
    180 
    181 // static
    182 void TestSuite::UnitTestAssertHandler(const std::string& str) {
    183   RAW_LOG(FATAL, str.c_str());
    184 }
    185 
    186 void TestSuite::SuppressErrorDialogs() {
    187 #if defined(OS_WIN)
    188   UINT new_flags = SEM_FAILCRITICALERRORS |
    189                    SEM_NOGPFAULTERRORBOX |
    190                    SEM_NOOPENFILEERRORBOX;
    191 
    192   // Preserve existing error mode, as discussed at
    193   // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
    194   UINT existing_flags = SetErrorMode(new_flags);
    195   SetErrorMode(existing_flags | new_flags);
    196 
    197 #if defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1)
    198   // Suppress the "Debug Assertion Failed" dialog.
    199   // TODO(hbono): remove this code when gtest has it.
    200   // http://groups.google.com/d/topic/googletestframework/OjuwNlXy5ac/discussion
    201   _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
    202   _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
    203 #endif  // defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1)
    204 #endif  // defined(OS_WIN)
    205 }
    206 
    207 void TestSuite::Initialize() {
    208 #if defined(OS_MACOSX) && !defined(OS_IOS)
    209   // Some of the app unit tests spin runloops.
    210   mock_cr_app::RegisterMockCrApp();
    211 #endif
    212 
    213 #if defined(OS_IOS)
    214   InitIOSTestMessageLoop();
    215 #endif  // OS_IOS
    216 
    217 #if defined(OS_ANDROID)
    218   InitAndroidTest();
    219 #else
    220   // Initialize logging.
    221   base::FilePath exe;
    222   PathService::Get(base::FILE_EXE, &exe);
    223   base::FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
    224   logging::LoggingSettings settings;
    225   settings.logging_dest = logging::LOG_TO_ALL;
    226   settings.log_file = log_filename.value().c_str();
    227   settings.delete_old = logging::DELETE_OLD_LOG_FILE;
    228   logging::InitLogging(settings);
    229   // We want process and thread IDs because we may have multiple processes.
    230   // Note: temporarily enabled timestamps in an effort to catch bug 6361.
    231   logging::SetLogItems(true, true, true, true);
    232 #endif  // else defined(OS_ANDROID)
    233 
    234   CHECK(base::debug::EnableInProcessStackDumping());
    235 #if defined(OS_WIN)
    236   // Make sure we run with high resolution timer to minimize differences
    237   // between production code and test code.
    238   base::Time::EnableHighResolutionTimer(true);
    239 #endif  // defined(OS_WIN)
    240 
    241   // In some cases, we do not want to see standard error dialogs.
    242   if (!base::debug::BeingDebugged() &&
    243       !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) {
    244     SuppressErrorDialogs();
    245     base::debug::SetSuppressDebugUI(true);
    246     logging::SetLogAssertHandler(UnitTestAssertHandler);
    247   }
    248 
    249   icu_util::Initialize();
    250 
    251   CatchMaybeTests();
    252   ResetCommandLine();
    253 
    254   TestTimeouts::Initialize();
    255 }
    256 
    257 void TestSuite::Shutdown() {
    258 }
    259