summaryrefslogtreecommitdiffstats
path: root/base/test/test_suite.h
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-09 18:20:30 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-09 18:20:30 +0000
commitfb895c694e2117c29b6afb699095f6e187a44da7 (patch)
tree04a0d1434a470f55f0e639a3e6f15c18416d80e2 /base/test/test_suite.h
parent8ecb6aa0a92d5426c2c98c23e0e3f3c4f06972c5 (diff)
downloadchromium_src-fb895c694e2117c29b6afb699095f6e187a44da7.zip
chromium_src-fb895c694e2117c29b6afb699095f6e187a44da7.tar.gz
chromium_src-fb895c694e2117c29b6afb699095f6e187a44da7.tar.bz2
Move more ICU-dependent stuff from base into base/i18n. Some test stuff also
depended on this, so to make the DEPS work out, I made a new base/test directory where I moved the testing-related files into a new directory base/test. TEST=none BUG=none Review URL: http://codereview.chromium.org/266038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28569 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/test/test_suite.h')
-rw-r--r--base/test/test_suite.h237
1 files changed, 237 insertions, 0 deletions
diff --git a/base/test/test_suite.h b/base/test/test_suite.h
new file mode 100644
index 0000000..1203904
--- /dev/null
+++ b/base/test/test_suite.h
@@ -0,0 +1,237 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_TEST_SUITE_H_
+#define BASE_TEST_SUITE_H_
+
+// Defines a basic test suite framework for running gtest based tests. You can
+// instantiate this class in your main function and call its Run method to run
+// any gtest based tests that are linked into your executable.
+
+#include "base/at_exit.h"
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/debug_on_start.h"
+#include "base/debug_util.h"
+#include "base/file_path.h"
+#include "base/i18n/icu_util.h"
+#include "base/logging.h"
+#include "base/multiprocess_test.h"
+#include "base/scoped_nsautorelease_pool.h"
+#include "base/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#if defined(OS_POSIX)
+#include <signal.h>
+#endif
+
+#if defined(OS_LINUX)
+#include <gtk/gtk.h>
+#endif
+
+#if defined(OS_POSIX)
+static void TestSuiteCrashHandler(int signal) {
+ StackTrace().PrintBacktrace();
+ _exit(1);
+}
+#endif // OS_POSIX
+
+#if defined(OS_WIN)
+// Previous unhandled filter. Will be called if not NULL when we intercept an
+// exception.
+__declspec(selectany) LPTOP_LEVEL_EXCEPTION_FILTER g_previous_filter = NULL;
+
+// Prints the exception call stack.
+// This is the unit tests exception filter.
+inline long WINAPI UnitTestExceptionFilter(EXCEPTION_POINTERS* info) {
+ StackTrace(info).PrintBacktrace();
+ if (g_previous_filter)
+ return g_previous_filter(info);
+ return EXCEPTION_EXECUTE_HANDLER;
+}
+#endif // OS_WIN
+
+// Match function used by the GetTestCount method.
+typedef bool (*TestMatch)(const testing::TestInfo&);
+
+class TestSuite {
+ public:
+ TestSuite(int argc, char** argv) {
+ base::EnableTerminationOnHeapCorruption();
+ CommandLine::Init(argc, argv);
+ testing::InitGoogleTest(&argc, argv);
+#if defined(OS_LINUX)
+ g_thread_init(NULL);
+ gtk_init_check(&argc, &argv);
+#endif
+ // Don't add additional code to this constructor. Instead add it to
+ // Initialize(). See bug 6436.
+ }
+
+ virtual ~TestSuite() {
+ CommandLine::Terminate();
+ }
+
+ // Returns true if a string starts with FLAKY_.
+ static bool IsFlaky(const char* name) {
+ return strncmp(name, "FLAKY_", 6) == 0;
+ }
+
+ // Returns true if the test is marked as flaky.
+ static bool FlakyTest(const testing::TestInfo& test) {
+ return IsFlaky(test.name()) || IsFlaky(test.test_case_name());
+ }
+
+ // Returns true if the test failed and is not marked as flaky.
+ static bool NonFlakyFailures(const testing::TestInfo& test) {
+ return test.should_run() && test.result()->Failed() && !FlakyTest(test);
+ }
+
+ // Returns the number of tests where the match function returns true.
+ int GetTestCount(TestMatch test_match) {
+ testing::UnitTest* instance = testing::UnitTest::GetInstance();
+ int count = 0;
+
+ for (int i = 0; i < instance->total_test_case_count(); ++i) {
+ const testing::TestCase& test_case = *instance->GetTestCase(i);
+ for (int j = 0; j < test_case.total_test_count(); ++j) {
+ if (test_match(*test_case.GetTestInfo(j))) {
+ count++;
+ }
+ }
+ }
+
+ return count;
+ }
+
+ // Don't add additional code to this method. Instead add it to
+ // Initialize(). See bug 6436.
+ int Run() {
+ base::ScopedNSAutoreleasePool scoped_pool;
+
+ Initialize();
+ std::wstring client_func =
+ CommandLine::ForCurrentProcess()->GetSwitchValue(kRunClientProcess);
+ // Check to see if we are being run as a client process.
+ if (!client_func.empty()) {
+ // Convert our function name to a usable string for GetProcAddress.
+ std::string func_name(client_func.begin(), client_func.end());
+
+ return multi_process_function_list::InvokeChildProcessTest(func_name);
+ }
+ int result = RUN_ALL_TESTS();
+
+ // Reset the result code if only flaky test failed.
+ if (result != 0 && GetTestCount(&TestSuite::NonFlakyFailures) == 0) {
+ result = 0;
+ }
+
+ // Display the number of flaky tests.
+ int flaky_count = GetTestCount(&TestSuite::FlakyTest);
+ if (flaky_count) {
+ printf(" YOU HAVE %d FLAKY %s\n\n", flaky_count,
+ flaky_count == 1 ? "TEST" : "TESTS");
+ }
+
+ // This MUST happen before Shutdown() since Shutdown() tears down
+ // objects (such as NotificationService::current()) that Cocoa
+ // objects use to remove themselves as observers.
+ scoped_pool.Recycle();
+
+ Shutdown();
+
+ return result;
+ }
+
+ protected:
+ // All fatal log messages (e.g. DCHECK failures) imply unit test failures.
+ static void UnitTestAssertHandler(const std::string& str) {
+ FAIL() << str;
+ }
+
+#if defined(OS_WIN)
+ // Disable crash dialogs so that it doesn't gum up the buildbot
+ virtual void SuppressErrorDialogs() {
+ UINT new_flags = SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX;
+
+ // Preserve existing error mode, as discussed at
+ // http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx
+ UINT existing_flags = SetErrorMode(new_flags);
+ SetErrorMode(existing_flags | new_flags);
+ }
+#endif
+
+ // Override these for custom initialization and shutdown handling. Use these
+ // instead of putting complex code in your constructor/destructor.
+
+ virtual void Initialize() {
+ // Initialize logging.
+ FilePath exe;
+ PathService::Get(base::FILE_EXE, &exe);
+ FilePath log_filename = exe.ReplaceExtension(FILE_PATH_LITERAL("log"));
+ logging::InitLogging(log_filename.value().c_str(),
+ logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG,
+ logging::LOCK_LOG_FILE,
+ logging::DELETE_OLD_LOG_FILE);
+ // We want process and thread IDs because we may have multiple processes.
+ // Note: temporarily enabled timestamps in an effort to catch bug 6361.
+ logging::SetLogItems(true, true, true, true);
+
+#if defined(OS_POSIX)
+ // When running in an application, our code typically expects SIGPIPE
+ // to be ignored. Therefore, when testing that same code, it should run
+ // with SIGPIPE ignored as well.
+ struct sigaction action;
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ CHECK(sigaction(SIGPIPE, &action, NULL) == 0);
+
+ // TODO(phajdan.jr): Catch other crashy signals, like SIGABRT.
+ CHECK(signal(SIGSEGV, &TestSuiteCrashHandler) != SIG_ERR);
+ CHECK(signal(SIGILL, &TestSuiteCrashHandler) != SIG_ERR);
+ CHECK(signal(SIGBUS, &TestSuiteCrashHandler) != SIG_ERR);
+ CHECK(signal(SIGFPE, &TestSuiteCrashHandler) != SIG_ERR);
+#endif // OS_POSIX
+
+#if defined(OS_WIN)
+ // For unit tests we turn on the high resolution timer and disable
+ // base::Time's use of SystemMonitor. Tests create and destroy the message
+ // loop, which causes a crash with SystemMonitor (http://crbug.com/12187).
+ base::Time::EnableHiResClockForTests();
+
+ // In some cases, we do not want to see standard error dialogs.
+ if (!IsDebuggerPresent() &&
+ !CommandLine::ForCurrentProcess()->HasSwitch(L"show-error-dialogs")) {
+ SuppressErrorDialogs();
+#if !defined(PURIFY)
+ // When the code in this file moved around, bug 6436 resurfaced.
+ // As a hack workaround, just #ifdef out this code for Purify builds.
+ logging::SetLogAssertHandler(UnitTestAssertHandler);
+#endif // !defined(PURIFY)
+ // Add stack dumping support on exception on windows. Similar to OS_POSIX
+ // signal() handling above.
+ g_previous_filter = SetUnhandledExceptionFilter(&UnitTestExceptionFilter);
+ }
+#endif // defined(OS_WIN)
+
+ icu_util::Initialize();
+ }
+
+ virtual void Shutdown() {
+ }
+
+ // Make sure that we setup an AtExitManager so Singleton objects will be
+ // destroyed.
+ base::AtExitManager at_exit_manager_;
+};
+
+#endif // BASE_TEST_SUITE_H_