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