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