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