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