test_suite.h revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
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#ifndef BASE_TEST_TEST_SUITE_H_ 6#define BASE_TEST_TEST_SUITE_H_ 7 8// Defines a basic test suite framework for running gtest based tests. You can 9// instantiate this class in your main function and call its Run method to run 10// any gtest based tests that are linked into your executable. 11 12#include "base/at_exit.h" 13#include "base/base_paths.h" 14#include "base/debug_on_start.h" 15#include "base/i18n/icu_util.h" 16#include "base/multiprocess_test.h" 17#include "base/nss_util.h" 18#include "base/path_service.h" 19#include "base/process_util.h" 20#include "base/scoped_nsautorelease_pool.h" 21#include "base/scoped_ptr.h" 22#include "base/time.h" 23#include "testing/gtest/include/gtest/gtest.h" 24#include "testing/multiprocess_func_list.h" 25 26#if defined(OS_POSIX) && !defined(OS_MACOSX) 27#include <gtk/gtk.h> 28#endif 29 30// Match function used by the GetTestCount method. 31typedef bool (*TestMatch)(const testing::TestInfo&); 32 33// By setting up a shadow AtExitManager, this test event listener ensures that 34// no state is carried between tests (like singletons, lazy instances, etc). 35// Of course it won't help if the code under test corrupts memory. 36class TestIsolationEnforcer : public testing::EmptyTestEventListener { 37 public: 38 virtual void OnTestStart(const testing::TestInfo& test_info) { 39 ASSERT_FALSE(exit_manager_.get()); 40 exit_manager_.reset(new base::ShadowingAtExitManager()); 41 } 42 43 virtual void OnTestEnd(const testing::TestInfo& test_info) { 44 ASSERT_TRUE(exit_manager_.get()); 45 exit_manager_.reset(); 46 } 47 48 private: 49 scoped_ptr<base::ShadowingAtExitManager> exit_manager_; 50}; 51 52class TestSuite { 53 public: 54 TestSuite(int argc, char** argv) { 55 base::EnableTerminationOnHeapCorruption(); 56 CommandLine::Init(argc, argv); 57 testing::InitGoogleTest(&argc, argv); 58#if defined(OS_POSIX) && !defined(OS_MACOSX) 59 g_thread_init(NULL); 60 gtk_init_check(&argc, &argv); 61#endif // defined(OS_LINUX) 62 // Don't add additional code to this constructor. Instead add it to 63 // Initialize(). See bug 6436. 64 } 65 66 virtual ~TestSuite() { 67 CommandLine::Reset(); 68 } 69 70 // Returns true if a string starts with FLAKY_. 71 static bool IsFlaky(const char* name) { 72 return strncmp(name, "FLAKY_", 6) == 0; 73 } 74 75 // Returns true if the test is marked as flaky. 76 static bool FlakyTest(const testing::TestInfo& test) { 77 return IsFlaky(test.name()) || IsFlaky(test.test_case_name()); 78 } 79 80 // Returns true if the test failed and is not marked as flaky. 81 static bool NonFlakyFailures(const testing::TestInfo& test) { 82 return test.should_run() && test.result()->Failed() && !FlakyTest(test); 83 } 84 85 // Returns the number of tests where the match function returns true. 86 int GetTestCount(TestMatch test_match) { 87 testing::UnitTest* instance = testing::UnitTest::GetInstance(); 88 int count = 0; 89 90 for (int i = 0; i < instance->total_test_case_count(); ++i) { 91 const testing::TestCase& test_case = *instance->GetTestCase(i); 92 for (int j = 0; j < test_case.total_test_count(); ++j) { 93 if (test_match(*test_case.GetTestInfo(j))) { 94 count++; 95 } 96 } 97 } 98 99 return count; 100 } 101 102 // TODO(phajdan.jr): Enforce isolation for all tests once it's stable. 103 void EnforceTestIsolation() { 104 testing::TestEventListeners& listeners = 105 testing::UnitTest::GetInstance()->listeners(); 106 listeners.Append(new TestIsolationEnforcer); 107 } 108 109 // Don't add additional code to this method. Instead add it to 110 // Initialize(). See bug 6436. 111 int Run() { 112 base::ScopedNSAutoreleasePool scoped_pool; 113 114 Initialize(); 115 std::wstring client_func = 116 CommandLine::ForCurrentProcess()->GetSwitchValue(kRunClientProcess); 117 // Check to see if we are being run as a client process. 118 if (!client_func.empty()) { 119 // Convert our function name to a usable string for GetProcAddress. 120 std::string func_name(client_func.begin(), client_func.end()); 121 122 return multi_process_function_list::InvokeChildProcessTest(func_name); 123 } 124 int result = RUN_ALL_TESTS(); 125 126 // Reset the result code if only flaky test failed. 127 if (result != 0 && GetTestCount(&TestSuite::NonFlakyFailures) == 0) { 128 result = 0; 129 } 130 131 // Display the number of flaky tests. 132 int flaky_count = GetTestCount(&TestSuite::FlakyTest); 133 if (flaky_count) { 134 printf(" YOU HAVE %d FLAKY %s\n\n", flaky_count, 135 flaky_count == 1 ? "TEST" : "TESTS"); 136 } 137 138 // This MUST happen before Shutdown() since Shutdown() tears down 139 // objects (such as NotificationService::current()) that Cocoa 140 // objects use to remove themselves as observers. 141 scoped_pool.Recycle(); 142 143 Shutdown(); 144 145 return result; 146 } 147 148 protected: 149#if defined(OS_WIN) 150 // TODO(phajdan.jr): Clean up the windows-specific hacks. 151 // See http://crbug.com/29997 152 153 // By default, base::LogMessage::~LogMessage calls DebugUtil::BreakDebugger() 154 // when severity is LOG_FATAL. On Windows, this results in error dialogs 155 // which are not friendly to buildbots. 156 // To avoid these problems, we override the LogMessage behaviour by 157 // replacing the assert handler with UnitTestAssertHandler. 158 static void UnitTestAssertHandler(const std::string& str) { 159 // FAIL is a googletest macro, it marks the current test as failed. 160 // If throw_on_failure is set to true, it also ends the process. 161 ::testing::FLAGS_gtest_throw_on_failure = true; 162 FAIL() << str; 163 } 164 165 // Disable crash dialogs so that it doesn't gum up the buildbot 166 virtual void SuppressErrorDialogs() { 167 UINT new_flags = SEM_FAILCRITICALERRORS | 168 SEM_NOGPFAULTERRORBOX | 169 SEM_NOOPENFILEERRORBOX; 170 171 // Preserve existing error mode, as discussed at 172 // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx 173 UINT existing_flags = SetErrorMode(new_flags); 174 SetErrorMode(existing_flags | new_flags); 175 } 176#endif // defined(OS_WIN) 177 178 // Override these for custom initialization and shutdown handling. Use these 179 // instead of putting complex code in your constructor/destructor. 180 181 virtual void Initialize() { 182 // Initialize logging. 183 FilePath exe; 184 PathService::Get(base::FILE_EXE, &exe); 185 FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log")); 186 logging::InitLogging(log_filename.value().c_str(), 187 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, 188 logging::LOCK_LOG_FILE, 189 logging::DELETE_OLD_LOG_FILE); 190 // We want process and thread IDs because we may have multiple processes. 191 // Note: temporarily enabled timestamps in an effort to catch bug 6361. 192 logging::SetLogItems(true, true, true, true); 193 194 CHECK(base::EnableInProcessStackDumping()); 195#if defined(OS_WIN) 196 // Make sure we run with high resolution timer to minimize differences 197 // between production code and test code. 198 bool result = base::Time::UseHighResolutionTimer(true); 199 CHECK(result); 200 201 // In some cases, we do not want to see standard error dialogs. 202 if (!IsDebuggerPresent() && 203 !CommandLine::ForCurrentProcess()->HasSwitch("show-error-dialogs")) { 204 SuppressErrorDialogs(); 205#if !defined(PURIFY) 206 // When the code in this file moved around, bug 6436 resurfaced. 207 // As a hack workaround, just #ifdef out this code for Purify builds. 208 logging::SetLogAssertHandler(UnitTestAssertHandler); 209#endif // !defined(PURIFY) 210 } 211#endif // defined(OS_WIN) 212 213 icu_util::Initialize(); 214 215#if defined(USE_NSS) 216 // Trying to repeatedly initialize and cleanup NSS and NSPR may result in 217 // a deadlock. Such repeated initialization will happen when using test 218 // isolation. Prevent problems by initializing NSS here, so that the cleanup 219 // will be done only on process exit. 220 base::EnsureNSSInit(); 221#endif // defined(USE_NSS) 222 } 223 224 virtual void Shutdown() { 225 } 226 227 // Make sure that we setup an AtExitManager so Singleton objects will be 228 // destroyed. 229 base::AtExitManager at_exit_manager_; 230}; 231 232#endif // BASE_TEST_TEST_SUITE_H_ 233