test_suite.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2009 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_on_start.h" 12#include "base/debug_util.h" 13#include "base/debug/debugger.h" 14#include "base/debug/debugger.h" 15#include "base/file_path.h" 16#include "base/i18n/icu_util.h" 17#include "base/logging.h" 18#include "base/mac/scoped_nsautorelease_pool.h" 19#include "base/nss_util.h" 20#include "base/path_service.h" 21#include "base/process_util.h" 22#include "base/scoped_ptr.h" 23#include "base/test/multiprocess_test.h" 24#include "base/test/test_timeouts.h" 25#include "base/time.h" 26#include "testing/gtest/include/gtest/gtest.h" 27#include "testing/multiprocess_func_list.h" 28 29#if defined(TOOLKIT_USES_GTK) 30#include <gtk/gtk.h> 31#endif 32 33namespace { 34 35class MaybeTestDisabler : public testing::EmptyTestEventListener { 36 public: 37 virtual void OnTestStart(const testing::TestInfo& test_info) { 38 ASSERT_FALSE(TestSuite::IsMarkedMaybe(test_info)) 39 << "Probably the OS #ifdefs don't include all of the necessary " 40 "platforms.\nPlease ensure that no tests have the MAYBE_ prefix " 41 "after the code is preprocessed."; 42 } 43}; 44 45} // namespace 46 47const char TestSuite::kStrictFailureHandling[] = "strict_failure_handling"; 48 49TestSuite::TestSuite(int argc, char** argv) { 50 base::EnableTerminationOnHeapCorruption(); 51 CommandLine::Init(argc, argv); 52 testing::InitGoogleTest(&argc, argv); 53#if defined(TOOLKIT_USES_GTK) 54 g_thread_init(NULL); 55 gtk_init_check(&argc, &argv); 56#endif // defined(TOOLKIT_USES_GTK) 57 // Don't add additional code to this constructor. Instead add it to 58 // Initialize(). See bug 6436. 59} 60 61TestSuite::~TestSuite() { 62 CommandLine::Reset(); 63} 64 65// static 66bool TestSuite::IsMarkedFlaky(const testing::TestInfo& test) { 67 return strncmp(test.name(), "FLAKY_", 6) == 0; 68} 69 70// static 71bool TestSuite::IsMarkedFailing(const testing::TestInfo& test) { 72 return strncmp(test.name(), "FAILS_", 6) == 0; 73} 74 75// static 76bool TestSuite::IsMarkedMaybe(const testing::TestInfo& test) { 77 return strncmp(test.name(), "MAYBE_", 6) == 0; 78} 79 80// static 81bool TestSuite::ShouldIgnoreFailure(const testing::TestInfo& test) { 82 if (CommandLine::ForCurrentProcess()->HasSwitch(kStrictFailureHandling)) 83 return false; 84 return IsMarkedFlaky(test) || IsMarkedFailing(test); 85} 86 87// static 88bool TestSuite::NonIgnoredFailures(const testing::TestInfo& test) { 89 return test.should_run() && test.result()->Failed() && 90 !ShouldIgnoreFailure(test); 91} 92 93int TestSuite::GetTestCount(TestMatch test_match) { 94 testing::UnitTest* instance = testing::UnitTest::GetInstance(); 95 int count = 0; 96 97 for (int i = 0; i < instance->total_test_case_count(); ++i) { 98 const testing::TestCase& test_case = *instance->GetTestCase(i); 99 for (int j = 0; j < test_case.total_test_count(); ++j) { 100 if (test_match(*test_case.GetTestInfo(j))) { 101 count++; 102 } 103 } 104 } 105 106 return count; 107} 108 109void TestSuite::CatchMaybeTests() { 110 testing::TestEventListeners& listeners = 111 testing::UnitTest::GetInstance()->listeners(); 112 listeners.Append(new MaybeTestDisabler); 113} 114 115// Don't add additional code to this method. Instead add it to 116// Initialize(). See bug 6436. 117int TestSuite::Run() { 118 base::mac::ScopedNSAutoreleasePool scoped_pool; 119 120 Initialize(); 121 std::string client_func = 122 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 123 switches::kTestChildProcess); 124 // Check to see if we are being run as a client process. 125 if (!client_func.empty()) 126 return multi_process_function_list::InvokeChildProcessTest(client_func); 127 int result = RUN_ALL_TESTS(); 128 129 // If there are failed tests, see if we should ignore the failures. 130 if (result != 0 && GetTestCount(&TestSuite::NonIgnoredFailures) == 0) 131 result = 0; 132 133 // Display the number of flaky tests. 134 int flaky_count = GetTestCount(&TestSuite::IsMarkedFlaky); 135 if (flaky_count) { 136 printf(" YOU HAVE %d FLAKY %s\n\n", flaky_count, 137 flaky_count == 1 ? "TEST" : "TESTS"); 138 } 139 140 // Display the number of tests with ignored failures (FAILS). 141 int failing_count = GetTestCount(&TestSuite::IsMarkedFailing); 142 if (failing_count) { 143 printf(" YOU HAVE %d %s with ignored failures (FAILS prefix)\n\n", 144 failing_count, failing_count == 1 ? "test" : "tests"); 145 } 146 147 // This MUST happen before Shutdown() since Shutdown() tears down 148 // objects (such as NotificationService::current()) that Cocoa 149 // objects use to remove themselves as observers. 150 scoped_pool.Recycle(); 151 152 Shutdown(); 153 154 return result; 155} 156 157// static 158void TestSuite::UnitTestAssertHandler(const std::string& str) { 159 RAW_LOG(FATAL, str.c_str()); 160} 161 162void TestSuite::SuppressErrorDialogs() { 163#if defined(OS_WIN) 164 UINT new_flags = SEM_FAILCRITICALERRORS | 165 SEM_NOGPFAULTERRORBOX | 166 SEM_NOOPENFILEERRORBOX; 167 168 // Preserve existing error mode, as discussed at 169 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx 170 UINT existing_flags = SetErrorMode(new_flags); 171 SetErrorMode(existing_flags | new_flags); 172#endif // defined(OS_WIN) 173} 174 175void TestSuite::Initialize() { 176 // Initialize logging. 177 FilePath exe; 178 PathService::Get(base::FILE_EXE, &exe); 179 FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); 180 logging::InitLogging(log_filename.value().c_str(), 181 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, 182 logging::LOCK_LOG_FILE, 183 logging::DELETE_OLD_LOG_FILE); 184 // We want process and thread IDs because we may have multiple processes. 185 // Note: temporarily enabled timestamps in an effort to catch bug 6361. 186 logging::SetLogItems(true, true, true, true); 187 188 CHECK(base::EnableInProcessStackDumping()); 189#if defined(OS_WIN) 190 // Make sure we run with high resolution timer to minimize differences 191 // between production code and test code. 192 base::Time::EnableHighResolutionTimer(true); 193#endif // defined(OS_WIN) 194 195 // In some cases, we do not want to see standard error dialogs. 196 if (!base::debug::BeingDebugged() && 197 !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { 198 SuppressErrorDialogs(); 199 DebugUtil::SuppressDialogs(); 200 logging::SetLogAssertHandler(UnitTestAssertHandler); 201 } 202 203 icu_util::Initialize(); 204 205#if defined(USE_NSS) 206 // Trying to repeatedly initialize and cleanup NSS and NSPR may result in 207 // a deadlock. Such repeated initialization will happen when using test 208 // isolation. Prevent problems by initializing NSS here, so that the cleanup 209 // will be done only on process exit. 210 base::EnsureNSSInit(); 211#endif // defined(USE_NSS) 212 213 CatchMaybeTests(); 214 215 TestTimeouts::Initialize(); 216} 217 218void TestSuite::Shutdown() { 219} 220