• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
31 typedef 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.
36 class TestIsolationEnforcer : public testing::EmptyTestEventListener {
37  public:
OnTestStart(const testing::TestInfo & test_info)38   virtual void OnTestStart(const testing::TestInfo& test_info) {
39     ASSERT_FALSE(exit_manager_.get());
40     exit_manager_.reset(new base::ShadowingAtExitManager());
41   }
42 
OnTestEnd(const testing::TestInfo & test_info)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 
52 class TestSuite {
53  public:
TestSuite(int argc,char ** argv)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 
~TestSuite()66   virtual ~TestSuite() {
67     CommandLine::Reset();
68   }
69 
70   // Returns true if a string starts with FLAKY_.
IsFlaky(const char * name)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.
FlakyTest(const testing::TestInfo & test)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.
NonFlakyFailures(const testing::TestInfo & test)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.
GetTestCount(TestMatch test_match)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.
EnforceTestIsolation()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.
Run()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.
UnitTestAssertHandler(const std::string & str)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
SuppressErrorDialogs()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 
Initialize()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 
Shutdown()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