test_suite.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
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/file_util.h" 15#include "base/files/file_path.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 48namespace { 49 50class 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 60class 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 82namespace base { 83 84int 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 92TestSuite::TestSuite(int argc, char** argv) : initialized_command_line_(false) { 93 PreInitialize(argc, argv, true); 94} 95 96TestSuite::TestSuite(int argc, char** argv, bool create_at_exit_manager) 97 : initialized_command_line_(false) { 98 PreInitialize(argc, argv, create_at_exit_manager); 99} 100 101TestSuite::~TestSuite() { 102 if (initialized_command_line_) 103 CommandLine::Reset(); 104} 105 106void TestSuite::PreInitialize(int argc, char** argv, 107 bool create_at_exit_manager) { 108#if defined(OS_WIN) 109 testing::GTEST_FLAG(catch_exceptions) = false; 110 base::TimeTicks::SetNowIsHighResNowIfSupported(); 111#endif 112 base::EnableTerminationOnHeapCorruption(); 113 initialized_command_line_ = CommandLine::Init(argc, argv); 114 testing::InitGoogleTest(&argc, argv); 115 testing::InitGoogleMock(&argc, argv); 116#if defined(OS_LINUX) && defined(USE_AURA) 117 // When calling native char conversion functions (e.g wrctomb) we need to 118 // have the locale set. In the absence of such a call the "C" locale is the 119 // default. In the gtk code (below) gtk_init() implicitly sets a locale. 120 setlocale(LC_ALL, ""); 121#endif // defined(OS_LINUX) && defined(USE_AURA) 122 123 // On Android, AtExitManager is created in 124 // testing/android/native_test_wrapper.cc before main() is called. 125#if !defined(OS_ANDROID) 126 if (create_at_exit_manager) 127 at_exit_manager_.reset(new base::AtExitManager); 128#endif 129 130#if defined(OS_IOS) 131 InitIOSRunHook(this, argc, argv); 132#endif 133 134 // Don't add additional code to this function. Instead add it to 135 // Initialize(). See bug 6436. 136} 137 138 139// static 140bool TestSuite::IsMarkedMaybe(const testing::TestInfo& test) { 141 return strncmp(test.name(), "MAYBE_", 6) == 0; 142} 143 144void TestSuite::CatchMaybeTests() { 145 testing::TestEventListeners& listeners = 146 testing::UnitTest::GetInstance()->listeners(); 147 listeners.Append(new MaybeTestDisabler); 148} 149 150void TestSuite::ResetCommandLine() { 151 testing::TestEventListeners& listeners = 152 testing::UnitTest::GetInstance()->listeners(); 153 listeners.Append(new TestClientInitializer); 154} 155 156#if !defined(OS_IOS) 157void TestSuite::AddTestLauncherResultPrinter() { 158 // Only add the custom printer if requested. 159 if (!CommandLine::ForCurrentProcess()->HasSwitch( 160 switches::kTestLauncherOutput)) { 161 return; 162 } 163 164 FilePath output_path(CommandLine::ForCurrentProcess()->GetSwitchValuePath( 165 switches::kTestLauncherOutput)); 166 167 // Do not add the result printer if output path already exists. It's an 168 // indicator there is a process printing to that file, and we're likely 169 // its child. Do not clobber the results in that case. 170 if (PathExists(output_path)) { 171 LOG(WARNING) << "Test launcher output path " << output_path.AsUTF8Unsafe() 172 << " exists. Not adding test launcher result printer."; 173 return; 174 } 175 176 XmlUnitTestResultPrinter* printer = new XmlUnitTestResultPrinter; 177 CHECK(printer->Initialize(output_path)); 178 testing::TestEventListeners& listeners = 179 testing::UnitTest::GetInstance()->listeners(); 180 listeners.Append(printer); 181} 182#endif // !defined(OS_IOS) 183 184// Don't add additional code to this method. Instead add it to 185// Initialize(). See bug 6436. 186int TestSuite::Run() { 187#if defined(OS_IOS) 188 RunTestsFromIOSApp(); 189#endif 190 191#if defined(OS_MACOSX) 192 base::mac::ScopedNSAutoreleasePool scoped_pool; 193#endif 194 195 Initialize(); 196 std::string client_func = 197 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 198 switches::kTestChildProcess); 199 200 // Check to see if we are being run as a client process. 201 if (!client_func.empty()) 202 return multi_process_function_list::InvokeChildProcessTest(client_func); 203#if defined(OS_IOS) 204 base::test_listener_ios::RegisterTestEndListener(); 205#endif 206 int result = RUN_ALL_TESTS(); 207 208#if defined(OS_MACOSX) 209 // This MUST happen before Shutdown() since Shutdown() tears down 210 // objects (such as NotificationService::current()) that Cocoa 211 // objects use to remove themselves as observers. 212 scoped_pool.Recycle(); 213#endif 214 215 Shutdown(); 216 217 return result; 218} 219 220// static 221void TestSuite::UnitTestAssertHandler(const std::string& str) { 222#if defined(OS_ANDROID) 223 // Correlating test stdio with logcat can be difficult, so we emit this 224 // helpful little hint about what was running. Only do this for Android 225 // because other platforms don't separate out the relevant logs in the same 226 // way. 227 const ::testing::TestInfo* const test_info = 228 ::testing::UnitTest::GetInstance()->current_test_info(); 229 if (test_info) { 230 LOG(ERROR) << "Currently running: " << test_info->test_case_name() << "." 231 << test_info->name(); 232 fflush(stderr); 233 } 234#endif // defined(OS_ANDROID) 235 236 // The logging system actually prints the message before calling the assert 237 // handler. Just exit now to avoid printing too many stack traces. 238 _exit(1); 239} 240 241void TestSuite::SuppressErrorDialogs() { 242#if defined(OS_WIN) 243 UINT new_flags = SEM_FAILCRITICALERRORS | 244 SEM_NOGPFAULTERRORBOX | 245 SEM_NOOPENFILEERRORBOX; 246 247 // Preserve existing error mode, as discussed at 248 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx 249 UINT existing_flags = SetErrorMode(new_flags); 250 SetErrorMode(existing_flags | new_flags); 251 252#if defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1) 253 // Suppress the "Debug Assertion Failed" dialog. 254 // TODO(hbono): remove this code when gtest has it. 255 // http://groups.google.com/d/topic/googletestframework/OjuwNlXy5ac/discussion 256 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 257 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); 258#endif // defined(_DEBUG) && defined(_HAS_EXCEPTIONS) && (_HAS_EXCEPTIONS == 1) 259#endif // defined(OS_WIN) 260} 261 262void TestSuite::Initialize() { 263#if defined(OS_MACOSX) && !defined(OS_IOS) 264 // Some of the app unit tests spin runloops. 265 mock_cr_app::RegisterMockCrApp(); 266#endif 267 268#if defined(OS_IOS) 269 InitIOSTestMessageLoop(); 270#endif // OS_IOS 271 272#if defined(OS_ANDROID) 273 InitAndroidTest(); 274#else 275 // Initialize logging. 276 base::FilePath exe; 277 PathService::Get(base::FILE_EXE, &exe); 278 base::FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); 279 logging::LoggingSettings settings; 280 settings.logging_dest = logging::LOG_TO_ALL; 281 settings.log_file = log_filename.value().c_str(); 282 settings.delete_old = logging::DELETE_OLD_LOG_FILE; 283 logging::InitLogging(settings); 284 // We want process and thread IDs because we may have multiple processes. 285 // Note: temporarily enabled timestamps in an effort to catch bug 6361. 286 logging::SetLogItems(true, true, true, true); 287#endif // else defined(OS_ANDROID) 288 289 CHECK(base::debug::EnableInProcessStackDumping()); 290#if defined(OS_WIN) 291 // Make sure we run with high resolution timer to minimize differences 292 // between production code and test code. 293 base::Time::EnableHighResolutionTimer(true); 294#endif // defined(OS_WIN) 295 296 // In some cases, we do not want to see standard error dialogs. 297 if (!base::debug::BeingDebugged() && 298 !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { 299 SuppressErrorDialogs(); 300 base::debug::SetSuppressDebugUI(true); 301 logging::SetLogAssertHandler(UnitTestAssertHandler); 302 } 303 304 base::i18n::InitializeICU(); 305 306 CatchMaybeTests(); 307 ResetCommandLine(); 308#if !defined(OS_IOS) 309 AddTestLauncherResultPrinter(); 310#endif // !defined(OS_IOS) 311 312 TestTimeouts::Initialize(); 313} 314 315void TestSuite::Shutdown() { 316} 317