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