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/bind.h" 11 #include "base/command_line.h" 12 #include "base/debug/debugger.h" 13 #include "base/debug/stack_trace.h" 14 #include "base/files/file_path.h" 15 #include "base/files/file_util.h" 16 #include "base/i18n/icu_util.h" 17 #include "base/logging.h" 18 #include "base/memory/scoped_ptr.h" 19 #include "base/path_service.h" 20 #include "base/process/memory.h" 21 #include "base/test/gtest_xml_util.h" 22 #include "base/test/launcher/unit_test_launcher.h" 23 #include "base/test/multiprocess_test.h" 24 #include "base/test/test_switches.h" 25 #include "base/test/test_timeouts.h" 26 #include "base/time/time.h" 27 #include "testing/gmock/include/gmock/gmock.h" 28 #include "testing/gtest/include/gtest/gtest.h" 29 #include "testing/multiprocess_func_list.h" 30 31 #if defined(OS_MACOSX) 32 #include "base/mac/scoped_nsautorelease_pool.h" 33 #if defined(OS_IOS) 34 #include "base/test/test_listener_ios.h" 35 #else 36 #include "base/test/mock_chrome_application_mac.h" 37 #endif // OS_IOS 38 #endif // OS_MACOSX 39 40 #if defined(OS_ANDROID) 41 #include "base/test/test_support_android.h" 42 #endif 43 44 #if defined(OS_IOS) 45 #include "base/test/test_support_ios.h" 46 #endif 47 48 namespace { 49 50 class MaybeTestDisabler : public testing::EmptyTestEventListener { 51 public: 52 virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE { 53 ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info)) 54 << "Probably the OS #ifdefs don't include all of the necessary " 55 "platforms.\nPlease ensure that no tests have the MAYBE_ prefix " 56 "after the code is preprocessed."; 57 } 58 }; 59 60 class TestClientInitializer : public testing::EmptyTestEventListener { 61 public: 62 TestClientInitializer() 63 : old_command_line_(CommandLine::NO_PROGRAM) { 64 } 65 66 virtual void OnTestStart(const testing::TestInfo& test_info) OVERRIDE { 67 old_command_line_ = *CommandLine::ForCurrentProcess(); 68 } 69 70 virtual void OnTestEnd(const testing::TestInfo& test_info) OVERRIDE { 71 *CommandLine::ForCurrentProcess() = old_command_line_; 72 } 73 74 private: 75 CommandLine old_command_line_; 76 77 DISALLOW_COPY_AND_ASSIGN(TestClientInitializer); 78 }; 79 80 } // namespace 81 82 namespace base { 83 84 int RunUnitTestsUsingBaseTestSuite(int argc, char **argv) { 85 TestSuite test_suite(argc, argv); 86 return base::LaunchUnitTests( 87 argc, argv, Bind(&TestSuite::Run, Unretained(&test_suite))); 88 } 89 90 } // namespace base 91 92 TestSuite::TestSuite(int argc, char** argv) : initialized_command_line_(false) { 93 PreInitialize(true); 94 InitializeFromCommandLine(argc, argv); 95 } 96 97 #if defined(OS_WIN) 98 TestSuite::TestSuite(int argc, wchar_t** argv) 99 : initialized_command_line_(false) { 100 PreInitialize(true); 101 InitializeFromCommandLine(argc, argv); 102 } 103 #endif // defined(OS_WIN) 104 105 TestSuite::TestSuite(int argc, char** argv, bool create_at_exit_manager) 106 : initialized_command_line_(false) { 107 PreInitialize(create_at_exit_manager); 108 InitializeFromCommandLine(argc, argv); 109 } 110 111 TestSuite::~TestSuite() { 112 if (initialized_command_line_) 113 CommandLine::Reset(); 114 } 115 116 void TestSuite::InitializeFromCommandLine(int argc, char** argv) { 117 initialized_command_line_ = CommandLine::Init(argc, argv); 118 testing::InitGoogleTest(&argc, argv); 119 testing::InitGoogleMock(&argc, argv); 120 121 #if defined(OS_IOS) 122 InitIOSRunHook(this, argc, argv); 123 #endif 124 } 125 126 #if defined(OS_WIN) 127 void TestSuite::InitializeFromCommandLine(int argc, wchar_t** argv) { 128 // Windows CommandLine::Init ignores argv anyway. 129 initialized_command_line_ = CommandLine::Init(argc, NULL); 130 testing::InitGoogleTest(&argc, argv); 131 testing::InitGoogleMock(&argc, argv); 132 } 133 #endif // defined(OS_WIN) 134 135 void TestSuite::PreInitialize(bool create_at_exit_manager) { 136 #if defined(OS_WIN) 137 testing::GTEST_FLAG(catch_exceptions) = false; 138 #endif 139 base::EnableTerminationOnHeapCorruption(); 140 #if defined(OS_LINUX) && defined(USE_AURA) 141 // When calling native char conversion functions (e.g wrctomb) we need to 142 // have the locale set. In the absence of such a call the "C" locale is the 143 // default. In the gtk code (below) gtk_init() implicitly sets a locale. 144 setlocale(LC_ALL, ""); 145 #endif // defined(OS_LINUX) && defined(USE_AURA) 146 147 // On Android, AtExitManager is created in 148 // testing/android/native_test_wrapper.cc before main() is called. 149 #if !defined(OS_ANDROID) 150 if (create_at_exit_manager) 151 at_exit_manager_.reset(new base::AtExitManager); 152 #endif 153 154 // Don't add additional code to this function. Instead add it to 155 // Initialize(). See bug 6436. 156 } 157 158 159 // static 160 bool TestSuite::IsMarkedMaybe(const testing::TestInfo& test) { 161 return strncmp(test.name(), "MAYBE_", 6) == 0; 162 } 163 164 void TestSuite::CatchMaybeTests() { 165 testing::TestEventListeners& listeners = 166 testing::UnitTest::GetInstance()->listeners(); 167 listeners.Append(new MaybeTestDisabler); 168 } 169 170 void TestSuite::ResetCommandLine() { 171 testing::TestEventListeners& listeners = 172 testing::UnitTest::GetInstance()->listeners(); 173 listeners.Append(new TestClientInitializer); 174 } 175 176 #if !defined(OS_IOS) 177 void TestSuite::AddTestLauncherResultPrinter() { 178 // Only add the custom printer if requested. 179 if (!CommandLine::ForCurrentProcess()->HasSwitch( 180 switches::kTestLauncherOutput)) { 181 return; 182 } 183 184 FilePath output_path(CommandLine::ForCurrentProcess()->GetSwitchValuePath( 185 switches::kTestLauncherOutput)); 186 187 // Do not add the result printer if output path already exists. It's an 188 // indicator there is a process printing to that file, and we're likely 189 // its child. Do not clobber the results in that case. 190 if (PathExists(output_path)) { 191 LOG(WARNING) << "Test launcher output path " << output_path.AsUTF8Unsafe() 192 << " exists. Not adding test launcher result printer."; 193 return; 194 } 195 196 XmlUnitTestResultPrinter* printer = new XmlUnitTestResultPrinter; 197 CHECK(printer->Initialize(output_path)); 198 testing::TestEventListeners& listeners = 199 testing::UnitTest::GetInstance()->listeners(); 200 listeners.Append(printer); 201 } 202 #endif // !defined(OS_IOS) 203 204 // Don't add additional code to this method. Instead add it to 205 // Initialize(). See bug 6436. 206 int TestSuite::Run() { 207 #if defined(OS_IOS) 208 RunTestsFromIOSApp(); 209 #endif 210 211 #if defined(OS_MACOSX) 212 base::mac::ScopedNSAutoreleasePool scoped_pool; 213 #endif 214 215 Initialize(); 216 std::string client_func = 217 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 218 switches::kTestChildProcess); 219 220 // Check to see if we are being run as a client process. 221 if (!client_func.empty()) 222 return multi_process_function_list::InvokeChildProcessTest(client_func); 223 #if defined(OS_IOS) 224 base::test_listener_ios::RegisterTestEndListener(); 225 #endif 226 int result = RUN_ALL_TESTS(); 227 228 #if defined(OS_MACOSX) 229 // This MUST happen before Shutdown() since Shutdown() tears down 230 // objects (such as NotificationService::current()) that Cocoa 231 // objects use to remove themselves as observers. 232 scoped_pool.Recycle(); 233 #endif 234 235 Shutdown(); 236 237 return result; 238 } 239 240 // static 241 void TestSuite::UnitTestAssertHandler(const std::string& str) { 242 #if defined(OS_ANDROID) 243 // Correlating test stdio with logcat can be difficult, so we emit this 244 // helpful little hint about what was running. Only do this for Android 245 // because other platforms don't separate out the relevant logs in the same 246 // way. 247 const ::testing::TestInfo* const test_info = 248 ::testing::UnitTest::GetInstance()->current_test_info(); 249 if (test_info) { 250 LOG(ERROR) << "Currently running: " << test_info->test_case_name() << "." 251 << test_info->name(); 252 fflush(stderr); 253 } 254 #endif // defined(OS_ANDROID) 255 256 // The logging system actually prints the message before calling the assert 257 // handler. Just exit now to avoid printing too many stack traces. 258 _exit(1); 259 } 260 261 void TestSuite::SuppressErrorDialogs() { 262 #if defined(OS_WIN) 263 UINT new_flags = SEM_FAILCRITICALERRORS | 264 SEM_NOGPFAULTERRORBOX | 265 SEM_NOOPENFILEERRORBOX; 266 267 // Preserve existing error mode, as discussed at 268 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx 269 UINT existing_flags = SetErrorMode(new_flags); 270 SetErrorMode(existing_flags | new_flags); 271 272 #if defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1) 273 // Suppress the "Debug Assertion Failed" dialog. 274 // TODO(hbono): remove this code when gtest has it. 275 // http://groups.google.com/d/topic/googletestframework/OjuwNlXy5ac/discussion 276 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 277 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); 278 #endif // defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1) 279 #endif // defined(OS_WIN) 280 } 281 282 void TestSuite::Initialize() { 283 #if !defined(OS_IOS) 284 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 285 switches::kWaitForDebugger)) { 286 base::debug::WaitForDebugger(60, true); 287 } 288 #endif 289 290 #if defined(OS_MACOSX) && !defined(OS_IOS) 291 // Some of the app unit tests spin runloops. 292 mock_cr_app::RegisterMockCrApp(); 293 #endif 294 295 #if defined(OS_IOS) 296 InitIOSTestMessageLoop(); 297 #endif // OS_IOS 298 299 #if defined(OS_ANDROID) 300 InitAndroidTest(); 301 #else 302 // Initialize logging. 303 base::FilePath exe; 304 PathService::Get(base::FILE_EXE, &exe); 305 base::FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); 306 logging::LoggingSettings settings; 307 settings.logging_dest = logging::LOG_TO_ALL; 308 settings.log_file = log_filename.value().c_str(); 309 settings.delete_old = logging::DELETE_OLD_LOG_FILE; 310 logging::InitLogging(settings); 311 // We want process and thread IDs because we may have multiple processes. 312 // Note: temporarily enabled timestamps in an effort to catch bug 6361. 313 logging::SetLogItems(true, true, true, true); 314 #endif // else defined(OS_ANDROID) 315 316 CHECK(base::debug::EnableInProcessStackDumping()); 317 #if defined(OS_WIN) 318 // Make sure we run with high resolution timer to minimize differences 319 // between production code and test code. 320 base::Time::EnableHighResolutionTimer(true); 321 #endif // defined(OS_WIN) 322 323 // In some cases, we do not want to see standard error dialogs. 324 if (!base::debug::BeingDebugged() && 325 !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { 326 SuppressErrorDialogs(); 327 base::debug::SetSuppressDebugUI(true); 328 logging::SetLogAssertHandler(UnitTestAssertHandler); 329 } 330 331 base::i18n::InitializeICU(); 332 333 CatchMaybeTests(); 334 ResetCommandLine(); 335 #if !defined(OS_IOS) 336 AddTestLauncherResultPrinter(); 337 #endif // !defined(OS_IOS) 338 339 TestTimeouts::Initialize(); 340 341 trace_to_file_.BeginTracingFromCommandLineOptions(); 342 } 343 344 void TestSuite::Shutdown() { 345 } 346