summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-09-04 18:30:25 +0000
committerzhanyong.wan <zhanyong.wan@861a406c-534a-0410-8894-cb66d6ee9925>2009-09-04 18:30:25 +0000
commitf39160b423e8f90902066cf6774e4180667dcbee (patch)
treef990763455e874fb887364bbd9c712386824d20d
parent89be5763249cbab785abfa310fb1cd6b5e9c4adf (diff)
downloadgoogletest-f39160b423e8f90902066cf6774e4180667dcbee.tar.gz
More implementation of the event listener interface (by Vlad Losev); Reduces the stack space usage of assertions by moving AssertHelper's fields to the heap (by Jorg Brown); Makes String faster, smaller, and simpler (by Zhanyong Wan); Fixes a bug in String::Format() (by Chandler); Adds the /MD version of VC projects to the distribution (by Vlad Losev).
git-svn-id: http://googletest.googlecode.com/svn/trunk@301 861a406c-534a-0410-8894-cb66d6ee9925
-rw-r--r--CHANGES19
-rw-r--r--Makefile.am17
-rw-r--r--README21
-rw-r--r--include/gtest/gtest-test-part.h3
-rw-r--r--include/gtest/gtest.h215
-rw-r--r--include/gtest/internal/gtest-internal.h1
-rw-r--r--include/gtest/internal/gtest-string.h54
-rw-r--r--scons/SConscript3
-rw-r--r--src/gtest-death-test.cc6
-rw-r--r--src/gtest-internal-inl.h43
-rw-r--r--src/gtest.cc451
-rw-r--r--test/gtest-listener_test.cc230
-rwxr-xr-xtest/gtest_env_var_test.py2
-rw-r--r--test/gtest_unittest.cc339
-rwxr-xr-xtest/gtest_xml_output_unittest.py33
-rw-r--r--test/gtest_xml_output_unittest_.cc28
16 files changed, 1173 insertions, 292 deletions
diff --git a/CHANGES b/CHANGES
index 3565588..bad7c3c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,20 @@
+Changes for 1.4.0 (up to r300):
+
+ * New feature: the XML report format is closer to junitreport and can
+ be parsed by Hudson now.
+ * New feature: when a test runs under Visual Studio, its failures are
+ integrated in the IDE.
+ * New feature: /MD(d) versions of VC++ projects.
+ * New feature: elapsed time for the tests is printed by default.
+ * New feature: comes with a TR1 tuple implementation such that Boost
+ is no longer needed for Combine().
+ * New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
+ * New feature: the Xcode project can now produce static gtest
+ libraries in addition to a framework.
+ * Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
+ Symbian, gcc, and C++Builder.
+ * Bug fixes and implementation clean-ups.
+
Changes for 1.3.0:
* New feature: death tests on Windows, Cygwin, and Mac.
@@ -11,7 +28,7 @@ Changes for 1.3.0:
.cc file for easy deployment.
* New feature: support for distributing test functions to multiple
machines (requires support from the test runner).
- * Bug fixes and implementation clean-up.
+ * Bug fixes and implementation clean-ups.
Changes for 1.2.1:
diff --git a/Makefile.am b/Makefile.am
index 2f7e911..19d64ea 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,8 @@ EXTRA_DIST = \
include/gtest/internal/gtest-param-util-generated.h.pump \
make/Makefile \
scons/SConscript \
+ scons/SConstruct \
+ scons/SConstruct.common \
scripts/fuse_gtest_files.py \
scripts/gen_gtest_pred_impl.py \
scripts/test/Makefile \
@@ -24,10 +26,15 @@ EXTRA_DIST += \
msvc/gtest_color_test_.vcproj \
msvc/gtest_env_var_test_.vcproj \
msvc/gtest_environment_test.vcproj \
+ msvc/gtest_main-md.vcproj \
msvc/gtest_main.vcproj \
+ msvc/gtest-md.sln \
+ msvc/gtest-md.vcproj \
msvc/gtest_output_test_.vcproj \
+ msvc/gtest_prod_test-md.vcproj \
msvc/gtest_prod_test.vcproj \
msvc/gtest_uninitialized_test_.vcproj \
+ msvc/gtest_unittest-md.vcproj \
msvc/gtest_unittest.vcproj
# xcode project files
@@ -36,9 +43,8 @@ EXTRA_DIST += \
xcode/Config/FrameworkTarget.xcconfig \
xcode/Config/General.xcconfig \
xcode/Config/ReleaseProject.xcconfig \
+ xcode/Config/StaticLibraryTarget.xcconfig \
xcode/Config/TestTarget.xcconfig \
- xcode/Config/InternalTestTarget.xcconfig \
- xcode/Config/InternalPythonTestTarget.xcconfig \
xcode/Resources/Info.plist \
xcode/Scripts/versiongenerate.py \
xcode/Scripts/runtests.sh \
@@ -299,6 +305,11 @@ check_PROGRAMS += test/gtest-unittest-api_test
test_gtest_unittest_api_test_SOURCES = test/gtest-unittest-api_test.cc
test_gtest_unittest_api_test_LDADD = lib/libgtest_main.la
+TESTS += test/gtest-listener_test
+check_PROGRAMS += test/gtest-listener_test
+test_gtest_listener_test_SOURCES = test/gtest-listener_test.cc
+test_gtest_listener_test_LDADD = lib/libgtest_main.la
+
# Verifies that Google Test works when RTTI is disabled.
TESTS += test/gtest_no_rtti_test
check_PROGRAMS += test/gtest_no_rtti_test
@@ -407,7 +418,7 @@ TESTS += test/gtest_xml_outfiles_test.py
check_PROGRAMS += test/gtest_xml_output_unittest_
test_gtest_xml_output_unittest__SOURCES = test/gtest_xml_output_unittest_.cc
-test_gtest_xml_output_unittest__LDADD = lib/libgtest_main.la
+test_gtest_xml_output_unittest__LDADD = lib/libgtest.la
check_SCRIPTS += test/gtest_xml_output_unittest.py
TESTS += test/gtest_xml_output_unittest.py
diff --git a/README b/README
index d746401..a9172c5 100644
--- a/README
+++ b/README
@@ -190,9 +190,16 @@ see 'gtest-config --help' for more detailed information.
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
### Windows ###
-Open the gtest.sln file in the msvc/ folder using Visual Studio, and
-you are ready to build Google Test the same way you build any Visual
-Studio project.
+The msvc\ folder contains two solutions with Visual C++ projects. Open the
+gtest.sln or gtest-md.sln file using Visual Studio, and you are ready to
+build Google Test the same way you build any Visual Studio project. Files
+that have names ending with -md use DLL versions of Microsoft runtime
+libraries (the /MD or the /MDd compiler option). Files without that suffix
+use static versions of the runtime libraries (the /MT or the /MTd option).
+Please note that one must use the same option to compile both gtest and his
+test code. If you use Visual Studio 2005 or above, we recommend the -md
+version as /MD is the default for new projects in these versions of Visual
+Studio.
### Mac OS X (universal-binary framework) ###
Open the gtest.xcodeproj in the xcode/ folder using Xcode. Build the "gtest"
@@ -201,7 +208,7 @@ directory (selected in the Xcode "Preferences..." -> "Building" pane and
defaults to xcode/build). Alternatively, at the command line, enter:
xcodebuild
-
+
This will build the "Release" configuration of gtest.framework in your
default build location. See the "xcodebuild" man page for more information about
building different configurations and building in different locations.
@@ -213,7 +220,7 @@ ones) as errors. However, you should see a "Build succeeded" message at the end
of the build log. To run all of the tests from the command line, enter:
xcodebuild -target Check
-
+
Installation with xcodebuild requires specifying an installation desitination
directory, known as the DSTROOT. Three items will be installed when using
xcodebuild:
@@ -221,12 +228,12 @@ xcodebuild:
$DSTROOT/Library/Frameworks/gtest.framework
$DSTROOT/usr/local/lib/libgtest.a
$DSTROOT/usr/local/lib/libgtest_main.a
-
+
You specify the installation directory on the command line with the other
xcodebuild options. Here's how you would install in a user-visible location:
xcodebuild install DSTROOT=~
-
+
To perform a system-wide inistall, escalate to an administrator and specify
the file system root as the DSTROOT:
diff --git a/include/gtest/gtest-test-part.h b/include/gtest/gtest-test-part.h
index d5b2713..14d8e7b 100644
--- a/include/gtest/gtest-test-part.h
+++ b/include/gtest/gtest-test-part.h
@@ -41,6 +41,9 @@ namespace testing {
// The possible outcomes of a test part (i.e. an assertion or an
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
+// TODO(vladl@google.com): Rename the enum values to kSuccess,
+// kNonFatalFailure, and kFatalFailure before publishing the event listener
+// API (see issue http://code.google.com/p/googletest/issues/detail?id=165).
enum TestPartResultType {
TPRT_SUCCESS, // Succeeded.
TPRT_NONFATAL_FAILURE, // Failed but the test can continue.
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index 90c36a5..0727adb 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -149,17 +149,23 @@ namespace internal {
class AssertHelper;
class DefaultGlobalTestPartResultReporter;
+class EventListenersAccessor;
class ExecDeathTest;
+class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
class TestCase;
class TestInfoImpl;
class TestResultAccessor;
class UnitTestAccessor;
+// TODO(vladl@google.com): Rename to TestEventRepeater.
+class UnitTestEventsRepeater;
class WindowsDeathTest;
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResultType result_type,
const String& message);
+class PrettyUnitTestResultPrinter;
+class XmlUnitTestResultPrinter;
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@@ -766,6 +772,178 @@ class Environment {
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
};
+namespace internal {
+
+// TODO(vladl@google.com): Order the methods the way they are invoked by
+// Google Test.
+// The interface for tracing execution of tests.
+class UnitTestEventListenerInterface {
+ public:
+ virtual ~UnitTestEventListenerInterface() {}
+
+ // TODO(vladl@google.com): Add events for test program start and test program
+ // end: OnTestIterationStart(const UnitTest&); // Start of one iteration.
+ // Add tests, too.
+ // TODO(vladl@google.com): Rename OnUnitTestStart() and OnUnitTestEnd() to
+ // OnTestProgramStart() and OnTestProgramEnd().
+ // Called before any test activity starts.
+ virtual void OnUnitTestStart(const UnitTest& unit_test) = 0;
+
+ // Called after all test activities have ended.
+ virtual void OnUnitTestEnd(const UnitTest& unit_test) = 0;
+
+ // Called before the test case starts.
+ virtual void OnTestCaseStart(const TestCase& test_case) = 0;
+
+ // Called after the test case ends.
+ virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
+
+ // TODO(vladl@google.com): Rename OnGlobalSetUpStart to
+ // OnEnvironmentsSetUpStart. Make similar changes for the rest of
+ // environment-related events.
+ // Called before the global set-up starts.
+ virtual void OnGlobalSetUpStart(const UnitTest& unit_test) = 0;
+
+ // Called after the global set-up ends.
+ virtual void OnGlobalSetUpEnd(const UnitTest& unit_test) = 0;
+
+ // Called before the global tear-down starts.
+ virtual void OnGlobalTearDownStart(const UnitTest& unit_test) = 0;
+
+ // Called after the global tear-down ends.
+ virtual void OnGlobalTearDownEnd(const UnitTest& unit_test) = 0;
+
+ // Called before the test starts.
+ virtual void OnTestStart(const TestInfo& test_info) = 0;
+
+ // Called after the test ends.
+ virtual void OnTestEnd(const TestInfo& test_info) = 0;
+
+ // Called after a failed assertion or a SUCCESS().
+ virtual void OnNewTestPartResult(const TestPartResult& test_part_result) = 0;
+};
+
+// The convenience class for users who need to override just one or two
+// methods and are not concerned that a possible change to a signature of
+// the methods they override will not be caught during the build.
+class EmptyTestEventListener : public UnitTestEventListenerInterface {
+ public:
+ // Called before the unit test starts.
+ virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {}
+
+ // Called after the unit test ends.
+ virtual void OnUnitTestEnd(const UnitTest& /*unit_test*/) {}
+
+ // Called before the test case starts.
+ virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
+
+ // Called after the test case ends.
+ virtual void OnTestCaseEnd(const TestCase& /*test_case&*/) {}
+
+ // Called before the global set-up starts.
+ virtual void OnGlobalSetUpStart(const UnitTest& /*unit_test*/) {}
+
+ // Called after the global set-up ends.
+ virtual void OnGlobalSetUpEnd(const UnitTest& /*unit_test*/) {}
+
+ // Called before the global tear-down starts.
+ virtual void OnGlobalTearDownStart(const UnitTest& /*unit_test*/) {}
+
+ // Called after the global tear-down ends.
+ virtual void OnGlobalTearDownEnd(const UnitTest& /*unit_test*/) {}
+
+ // Called before the test starts.
+ virtual void OnTestStart(const TestInfo& /*test_info*/) {}
+
+ // Called after the test ends.
+ virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
+
+ // Called after a failed assertion or a SUCCESS().
+ virtual void OnNewTestPartResult(const TestPartResult& /*test_part_result*/) {
+ }
+};
+
+// EventListeners lets users add listeners to track events in Google Test.
+class EventListeners {
+ public:
+ EventListeners();
+ ~EventListeners();
+
+ // Appends an event listener to the end of the list. Google Test assumes
+ // the ownership of the listener (i.e. it will delete the listener when
+ // the test program finishes).
+ void Append(UnitTestEventListenerInterface* listener);
+
+ // Removes the given event listener from the list and returns it. It then
+ // becomes the caller's responsibility to delete the listener. Returns
+ // NULL if the listener is not found in the list.
+ UnitTestEventListenerInterface* Release(
+ UnitTestEventListenerInterface* listener);
+
+ // Returns the standard listener responsible for the default console
+ // output. Can be removed from the listeners list to shut down default
+ // console output. Note that removing this object from the listener list
+ // with Release transfers its ownership to the caller and makes this
+ // function return NULL the next time.
+ UnitTestEventListenerInterface* default_result_printer() const {
+ return default_result_printer_;
+ }
+
+ // Returns the standard listener responsible for the default XML output
+ // controlled by the --gtest_output=xml flag. Can be removed from the
+ // listeners list by users who want to shut down the default XML output
+ // controlled by this flag and substitute it with custom one. Note that
+ // removing this object from the listener list with Release transfers its
+ // ownership to the caller and makes this function return NULL the next
+ // time.
+ UnitTestEventListenerInterface* default_xml_generator() const {
+ return default_xml_generator_;
+ }
+
+ private:
+ friend class internal::DefaultGlobalTestPartResultReporter;
+ friend class internal::EventListenersAccessor;
+ friend class internal::NoExecDeathTest;
+ friend class internal::TestCase;
+ friend class internal::TestInfoImpl;
+ friend class internal::UnitTestImpl;
+
+ // Returns repeater that broadcasts the UnitTestEventListenerInterface
+ // events to all subscribers.
+ UnitTestEventListenerInterface* repeater();
+
+ // Sets the default_result_printer attribute to the provided listener.
+ // The listener is also added to the listener list and previous
+ // default_result_printer is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultResultPrinter(UnitTestEventListenerInterface* listener);
+
+ // Sets the default_xml_generator attribute to the provided listener. The
+ // listener is also added to the listener list and previous
+ // default_xml_generator is removed from it and deleted. The listener can
+ // also be NULL in which case it will not be added to the list. Does
+ // nothing if the previous and the current listener objects are the same.
+ void SetDefaultXmlGenerator(UnitTestEventListenerInterface* listener);
+
+ // Controls whether events will be forwarded by the repeater to the
+ // listeners in the list.
+ bool EventForwardingEnabled() const;
+ void SuppressEventForwarding();
+
+ // The actual list of listeners.
+ internal::UnitTestEventsRepeater* repeater_;
+ // Listener responsible for the standard result output.
+ UnitTestEventListenerInterface* default_result_printer_;
+ // Listener responsible for the creation of the XML output file.
+ UnitTestEventListenerInterface* default_xml_generator_;
+
+ // We disallow copying EventListeners.
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(EventListeners);
+};
+
+} // namespace internal
+
// A UnitTest consists of a vector of TestCases.
//
// This is a singleton class. The only instance of UnitTest is
@@ -886,6 +1064,10 @@ class UnitTest {
// total_test_case_count() - 1. If i is not in that range, returns NULL.
const internal::TestCase* GetTestCase(int i) const;
+ // Returns the list of event listeners that can be used to track events
+ // inside Google Test.
+ internal::EventListeners& listeners();
+
// ScopedTrace is a friend as it needs to modify the per-thread
// trace stack, which is a private member of UnitTest.
// TODO(vladl@google.com): Order all declarations according to the style
@@ -899,9 +1081,12 @@ class UnitTest {
TestPartResultType result_type,
const internal::String& message);
// TODO(vladl@google.com): Remove these when publishing the new accessors.
- friend class PrettyUnitTestResultPrinter;
- friend class XmlUnitTestResultPrinter;
+ friend class internal::PrettyUnitTestResultPrinter;
+ friend class internal::TestCase;
+ friend class internal::TestInfoImpl;
friend class internal::UnitTestAccessor;
+ friend class internal::UnitTestImpl;
+ friend class internal::XmlUnitTestResultPrinter;
friend class FinalSuccessChecker;
FRIEND_TEST(ApiTest, UnitTestImmutableAccessorsWork);
FRIEND_TEST(ApiTest, TestCaseImmutableAccessorsWork);
@@ -1299,14 +1484,32 @@ class AssertHelper {
// Constructor.
AssertHelper(TestPartResultType type, const char* file, int line,
const char* message);
+ ~AssertHelper();
+
// Message assignment is a semantic trick to enable assertion
// streaming; see the GTEST_MESSAGE_ macro below.
void operator=(const Message& message) const;
+
private:
- TestPartResultType const type_;
- const char* const file_;
- int const line_;
- String const message_;
+ // We put our data in a struct so that the size of the AssertHelper class can
+ // be as small as possible. This is important because gcc is incapable of
+ // re-using stack space even for temporary variables, so every EXPECT_EQ
+ // reserves stack space for another AssertHelper.
+ struct AssertHelperData {
+ AssertHelperData(TestPartResultType t, const char* srcfile, int line_num,
+ const char* msg)
+ : type(t), file(srcfile), line(line_num), message(msg) { }
+
+ TestPartResultType const type;
+ const char* const file;
+ int const line;
+ String const message;
+
+ private:
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
+ };
+
+ AssertHelperData* const data_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
};
diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h
index be37726..f0a7966 100644
--- a/include/gtest/internal/gtest-internal.h
+++ b/include/gtest/internal/gtest-internal.h
@@ -107,7 +107,6 @@ class Test; // Represents a test.
class TestInfo; // Information about a test.
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
-class UnitTestEventListenerInterface; // Listens to Google Test events.
namespace internal {
diff --git a/include/gtest/internal/gtest-string.h b/include/gtest/internal/gtest-string.h
index d36146a..39982d1 100644
--- a/include/gtest/internal/gtest-string.h
+++ b/include/gtest/internal/gtest-string.h
@@ -51,22 +51,6 @@
namespace testing {
namespace internal {
-// Holds data in a String object. We need this class in order to put
-// String's data members on the heap instead of on the stack.
-// Otherwise tests using many assertions (and thus Strings) in one
-// function may need too much stack frame space to compile.
-class StringData {
- StringData() : c_str_(NULL), length_(0) {}
- ~StringData() { delete[] c_str_; }
-
- private:
- friend class String;
-
- const char* c_str_;
- size_t length_; // Length of the string (excluding the terminating
- // '\0' character).
-};
-
// String - a UTF-8 string class.
//
// We cannot use std::string as Microsoft's STL implementation in
@@ -202,14 +186,14 @@ class String {
// C'tors
- // The default c'tor constructs a NULL string, which is represented
- // by data_ being NULL.
- String() : data_(NULL) {}
+ // The default c'tor constructs a NULL string.
+ String() : c_str_(NULL), length_(0) {}
// Constructs a String by cloning a 0-terminated C string.
String(const char* c_str) { // NOLINT
if (c_str == NULL) {
- data_ = NULL;
+ c_str_ = NULL;
+ length_ = 0;
} else {
ConstructNonNull(c_str, strlen(c_str));
}
@@ -225,13 +209,11 @@ class String {
// The copy c'tor creates a new copy of the string. The two
// String objects do not share content.
- String(const String& str) : data_(NULL) { *this = str; }
+ String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
// D'tor. String is intended to be a final class, so the d'tor
// doesn't need to be virtual.
- ~String() {
- delete data_;
- }
+ ~String() { delete[] c_str_; }
// Allows a String to be implicitly converted to an ::std::string or
// ::string, and vice versa. Converting a String containing a NULL
@@ -285,12 +267,12 @@ class String {
// Returns the length of the encapsulated string, or 0 if the
// string is NULL.
- size_t length() const { return (data_ == NULL) ? 0 : data_->length_; }
+ size_t length() const { return length_; }
// Gets the 0-terminated C string this String object represents.
// The String object still owns the string. Therefore the caller
// should NOT delete the return value.
- const char* c_str() const { return (data_ == NULL) ? NULL : data_->c_str_; }
+ const char* c_str() const { return c_str_; }
// Assigns a C string to this object. Self-assignment works.
const String& operator=(const char* c_str) { return *this = String(c_str); }
@@ -298,10 +280,12 @@ class String {
// Assigns a String object to this object. Self-assignment works.
const String& operator=(const String& rhs) {
if (this != &rhs) {
- delete data_;
- data_ = NULL;
- if (rhs.data_ != NULL) {
- ConstructNonNull(rhs.data_->c_str_, rhs.data_->length_);
+ delete[] c_str_;
+ if (rhs.c_str() == NULL) {
+ c_str_ = NULL;
+ length_ = 0;
+ } else {
+ ConstructNonNull(rhs.c_str(), rhs.length());
}
}
@@ -314,17 +298,15 @@ class String {
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void ConstructNonNull(const char* buffer, size_t length) {
- data_ = new StringData;
char* const str = new char[length + 1];
memcpy(str, buffer, length);
str[length] = '\0';
- data_->c_str_ = str;
- data_->length_ = length;
+ c_str_ = str;
+ length_ = length;
}
- // Points to the representation of the String. A NULL String is
- // represented by data_ == NULL.
- StringData* data_;
+ const char* c_str_;
+ size_t length_;
}; // class String
// Streams a String to an ostream. Each '\0' character in the String
diff --git a/scons/SConscript b/scons/SConscript
index 8fbd5f5..e881828 100644
--- a/scons/SConscript
+++ b/scons/SConscript
@@ -318,8 +318,9 @@ GtestTest(env, 'gtest_list_tests_unittest_', gtest)
GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
GtestTest(env, 'gtest_xml_outfile2_test_', gtest_main)
-GtestTest(env, 'gtest_xml_output_unittest_', gtest_main)
+GtestTest(env, 'gtest_xml_output_unittest_', gtest)
GtestTest(env, 'gtest-unittest-api_test', gtest)
+GtestTest(env, 'gtest-listener_test', gtest)
############################################################
# Tests targets using custom environments.
diff --git a/src/gtest-death-test.cc b/src/gtest-death-test.cc
index 02ce48d..d975af7 100644
--- a/src/gtest-death-test.cc
+++ b/src/gtest-death-test.cc
@@ -469,7 +469,8 @@ bool DeathTestImpl::Passed(bool status_ok) {
break;
case DIED:
if (status_ok) {
- if (RE::PartialMatch(error_message.c_str(), *regex())) {
+ const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
+ if (matched) {
success = true;
} else {
buffer << " Result: died but not with expected error.\n"
@@ -767,6 +768,9 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
// concurrent writes to the log files. We capture stderr in the parent
// process and append the child process' output to a log.
LogToStderr();
+ // Event forwarding to the listeners of event listener API mush be shut
+ // down in death test subprocesses.
+ GetUnitTestImpl()->listeners()->SuppressEventForwarding();
return EXECUTE_TEST;
} else {
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index 8431971..93217f4 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -741,6 +741,9 @@ class UnitTestImpl {
return test_cases_.GetElementOr(i, NULL);
}
+ // Provides access to the event listener list.
+ EventListeners* listeners() { return &listeners_; }
+
// Returns the TestResult for the test that's currently running, or
// the TestResult for the ad hoc test if no test is running.
TestResult* current_test_result();
@@ -748,18 +751,6 @@ class UnitTestImpl {
// Returns the TestResult for the ad hoc test.
const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
- // Sets the unit test result printer.
- //
- // Does nothing if the input and the current printer object are the
- // same; otherwise, deletes the old printer object and makes the
- // input the current printer.
- void set_result_printer(UnitTestEventListenerInterface* result_printer);
-
- // Returns the current unit test result printer if it is not NULL;
- // otherwise, creates an appropriate result printer, makes it the
- // current printer, and returns it.
- UnitTestEventListenerInterface* result_printer();
-
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter
@@ -907,9 +898,13 @@ class UnitTestImpl {
}
#if GTEST_HAS_DEATH_TEST
+ void InitDeathTestSubprocessControlInfo() {
+ internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
+ }
// Returns a pointer to the parsed --gtest_internal_run_death_test
// flag, or NULL if that flag was not specified.
// This information is useful only in a death test child process.
+ // Must not be called before a call to InitGoogleTest.
const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
return internal_run_death_test_flag_.get();
}
@@ -919,9 +914,22 @@ class UnitTestImpl {
return death_test_factory_.get();
}
+ void SuppressTestEventsIfInSubprocess();
+
friend class ReplaceDeathTestFactory;
#endif // GTEST_HAS_DEATH_TEST
+ // Initializes the event listener performing XML output as specified by
+ // UnitTestOptions. Must not be called before InitGoogleTest.
+ void ConfigureXmlOutput();
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests. Since this function can be
+// called more than once, it has to be idempotent.
+ void PostFlagParsingInit();
+
// Gets the random seed used at the start of the current test run.
int random_seed() const { return random_seed_; }
@@ -992,11 +1000,9 @@ class UnitTestImpl {
// test, and records the result in ad_hoc_test_result_.
TestResult ad_hoc_test_result_;
- // The unit test result printer. Will be deleted when the UnitTest
- // object is destructed. By default, a plain text printer is used,
- // but the user can set this field to use a custom printer if that
- // is desired.
- UnitTestEventListenerInterface* result_printer_;
+ // The list of event listeners that can be used to track events inside
+ // Google Test.
+ EventListeners listeners_;
// The OS stack trace getter. Will be deleted when the UnitTest
// object is destructed. By default, an OsStackTraceGetter is used,
@@ -1004,6 +1010,9 @@ class UnitTestImpl {
// desired.
OsStackTraceGetterInterface* os_stack_trace_getter_;
+ // True iff PostFlagParsingInit() has been called.
+ bool post_flag_parse_init_performed_;
+
// The random number seed used at the beginning of the test run.
int random_seed_;
diff --git a/src/gtest.cc b/src/gtest.cc
index 5cfabf8..1b602f5 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -129,9 +129,12 @@
namespace testing {
+using internal::EventListeners;
+using internal::EmptyTestEventListener;
using internal::TestCase;
using internal::TestProperty;
using internal::TestResult;
+using internal::UnitTestEventListenerInterface;
// Constants.
@@ -303,14 +306,18 @@ static bool ShouldRunTestCase(const TestCase* test_case) {
// AssertHelper constructor.
AssertHelper::AssertHelper(TestPartResultType type, const char* file,
int line, const char* message)
- : type_(type), file_(file), line_(line), message_(message) {
+ : data_(new AssertHelperData(type, file, line, message)) {
+}
+
+AssertHelper::~AssertHelper() {
+ delete data_;
}
// Message assignment, for assertion streaming support.
void AssertHelper::operator=(const Message& message) const {
UnitTest::GetInstance()->
- AddTestPartResult(type_, file_, line_,
- AppendUserMessage(message_, message),
+ AddTestPartResult(data_->type, data_->file, data_->line,
+ AppendUserMessage(data_->message, message),
UnitTest::GetInstance()->impl()
->CurrentOsStackTraceExceptTop(1)
// Skips the stack frame for this function itself.
@@ -476,86 +483,6 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
} // namespace internal
-// The interface for printing the result of a UnitTest
-class UnitTestEventListenerInterface {
- public:
- // The d'tor is pure virtual as this is an abstract class.
- virtual ~UnitTestEventListenerInterface() {}
-
- // Called before the unit test starts.
- virtual void OnUnitTestStart(const UnitTest& unit_test) = 0;
-
- // Called after the unit test ends.
- virtual void OnUnitTestEnd(const UnitTest& unit_test) = 0;
-
- // Called before the test case starts.
- virtual void OnTestCaseStart(const TestCase& test_case) = 0;
-
- // Called after the test case ends.
- virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
-
- // Called before the global set-up starts.
- virtual void OnGlobalSetUpStart(const UnitTest& unit_test) = 0;
-
- // Called after the global set-up ends.
- virtual void OnGlobalSetUpEnd(const UnitTest& unit_test) = 0;
-
- // Called before the global tear-down starts.
- virtual void OnGlobalTearDownStart(const UnitTest& unit_test) = 0;
-
- // Called after the global tear-down ends.
- virtual void OnGlobalTearDownEnd(const UnitTest& unit_test) = 0;
-
- // Called before the test starts.
- virtual void OnTestStart(const TestInfo& test_info) = 0;
-
- // Called after the test ends.
- virtual void OnTestEnd(const TestInfo& test_info) = 0;
-
- // Called after an assertion.
- virtual void OnNewTestPartResult(const TestPartResult& test_part_result) = 0;
-};
-
-// The convenience class for users who need to override just one or two
-// methods and are not concerned that a possible change to a signature of
-// the methods they override will not be caught during the build.
-class EmptyTestEventListener : public UnitTestEventListenerInterface {
- public:
- // Called before the unit test starts.
- virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {}
-
- // Called after the unit test ends.
- virtual void OnUnitTestEnd(const UnitTest& /*unit_test*/) {}
-
- // Called before the test case starts.
- virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
-
- // Called after the test case ends.
- virtual void OnTestCaseEnd(const TestCase& /*test_case&*/) {}
-
- // Called before the global set-up starts.
- virtual void OnGlobalSetUpStart(const UnitTest& /*unit_test*/) {}
-
- // Called after the global set-up ends.
- virtual void OnGlobalSetUpEnd(const UnitTest& /*unit_test*/) {}
-
- // Called before the global tear-down starts.
- virtual void OnGlobalTearDownStart(const UnitTest& /*unit_test*/) {}
-
- // Called after the global tear-down ends.
- virtual void OnGlobalTearDownEnd(const UnitTest& /*unit_test*/) {}
-
- // Called before the test starts.
- virtual void OnTestStart(const TestInfo& /*test_info*/) {}
-
- // Called after the test ends.
- virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
-
- // Called after an assertion.
- virtual void OnNewTestPartResult(const TestPartResult& /*test_part_result*/) {
- }
-};
-
// The c'tor sets this object as the test part result reporter used by
// Google Test. The 'result' parameter specifies where to report the
// results. Intercepts only failures from the current thread.
@@ -690,7 +617,7 @@ DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
const TestPartResult& result) {
unit_test_->current_test_result()->AddTestPartResult(result);
- unit_test_->result_printer()->OnNewTestPartResult(result);
+ unit_test_->listeners()->repeater()->OnNewTestPartResult(result);
}
DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
@@ -1738,28 +1665,38 @@ bool String::EndsWithCaseInsensitive(const char* suffix) const {
// available.
//
// The result is limited to 4096 characters (including the tailing 0).
-// If 4096 characters are not enough to format the input,
-// "<buffer exceeded>" is returned.
+// If 4096 characters are not enough to format the input, or if
+// there's an error, "<formatting error or buffer exceeded>" is
+// returned.
String String::Format(const char * format, ...) {
va_list args;
va_start(args, format);
char buffer[4096];
+ const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
+
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4996) // Temporarily disables warning 4996.
- const int size =
- vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
#pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
- const int size =
- vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
+ const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
va_end(args);
- return (size >= 0) ? String(buffer, size) : String("<buffer exceeded>");
+ // vsnprintf()'s behavior is not portable. When the buffer is not
+ // big enough, it returns a negative value in MSVC, and returns the
+ // needed buffer size on Linux. When there is an output error, it
+ // always returns a negative value. For simplicity, we lump the two
+ // error cases together.
+ if (size < 0 || size >= kBufferSize) {
+ return String("<formatting error or buffer exceeded>");
+ } else {
+ return String(buffer, size);
+ }
}
// Converts the buffer in a StrStream to a String, converting NUL
@@ -2297,11 +2234,11 @@ void TestInfoImpl::Run() {
UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_info(parent_);
- // Notifies the unit test event listener that a test is about to
- // start.
- UnitTestEventListenerInterface* const result_printer =
- impl->result_printer();
- result_printer->OnTestStart(*parent_);
+ UnitTestEventListenerInterface* repeater =
+ UnitTest::GetInstance()->listeners().repeater();
+
+ // Notifies the unit test event listeners that a test is about to start.
+ repeater->OnTestStart(*parent_);
const TimeInMillis start = GetTimeInMillis();
@@ -2344,7 +2281,7 @@ void TestInfoImpl::Run() {
result_.set_elapsed_time(GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
- result_printer->OnTestEnd(*parent_);
+ repeater->OnTestEnd(*parent_);
// Tells UnitTest to stop associating assertion results to this
// test.
@@ -2425,10 +2362,10 @@ void TestCase::Run() {
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_case(this);
- UnitTestEventListenerInterface * const result_printer =
- impl->result_printer();
+ UnitTestEventListenerInterface* repeater =
+ UnitTest::GetInstance()->listeners().repeater();
- result_printer->OnTestCaseStart(*this);
+ repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
set_up_tc_();
@@ -2438,7 +2375,7 @@ void TestCase::Run() {
impl->os_stack_trace_getter()->UponLeavingGTest();
tear_down_tc_();
- result_printer->OnTestCaseEnd(*this);
+ repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
@@ -2471,10 +2408,6 @@ bool TestCase::ShouldRunTest(const TestInfo *test_info) {
} // namespace internal
-// A result printer that never prints anything. Used in the child process
-// of an exec-style death test to avoid needless output clutter.
-class NullUnitTestResultPrinter : public EmptyTestEventListener {};
-
// Formats a countable noun. Depending on its quantity, either the
// singular form or the plural form is used. e.g.
//
@@ -2663,14 +2596,6 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_end(args);
}
-} // namespace internal
-
-using internal::ColoredPrintf;
-using internal::COLOR_DEFAULT;
-using internal::COLOR_RED;
-using internal::COLOR_GREEN;
-using internal::COLOR_YELLOW;
-
// This class implements the UnitTestEventListenerInterface interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
@@ -2888,10 +2813,16 @@ void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
// This class forwards events to other event listeners.
class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
public:
- typedef internal::Vector<UnitTestEventListenerInterface *> Listeners;
- UnitTestEventsRepeater() {}
+ UnitTestEventsRepeater() : forwarding_enabled_(true) {}
virtual ~UnitTestEventsRepeater();
- void AddListener(UnitTestEventListenerInterface *listener);
+ void Append(UnitTestEventListenerInterface *listener);
+ UnitTestEventListenerInterface* Release(
+ UnitTestEventListenerInterface* listener);
+
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled() const { return forwarding_enabled_; }
+ void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
virtual void OnUnitTestStart(const UnitTest& unit_test);
virtual void OnUnitTestEnd(const UnitTest& unit_test);
@@ -2906,7 +2837,11 @@ class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
virtual void OnNewTestPartResult(const TestPartResult& result);
private:
- Listeners listeners_;
+ // Controls whether events will be forwarded to listeners_. Set to false
+ // in death test child processes.
+ bool forwarding_enabled_;
+ // The list of listeners that receive events.
+ Vector<UnitTestEventListenerInterface*> listeners_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestEventsRepeater);
};
@@ -2917,17 +2852,31 @@ UnitTestEventsRepeater::~UnitTestEventsRepeater() {
}
}
-void UnitTestEventsRepeater::AddListener(
- UnitTestEventListenerInterface *listener) {
+void UnitTestEventsRepeater::Append(UnitTestEventListenerInterface *listener) {
listeners_.PushBack(listener);
}
+// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
+UnitTestEventListenerInterface* UnitTestEventsRepeater::Release(
+ UnitTestEventListenerInterface *listener) {
+ for (int i = 0; i < listeners_.size(); ++i) {
+ if (listeners_.GetElement(i) == listener) {
+ listeners_.Erase(i);
+ return listener;
+ }
+ }
+
+ return NULL;
+}
+
// Since the methods are identical, use a macro to reduce boilerplate.
// This defines a member that repeats the call to all listeners.
#define GTEST_REPEATER_METHOD_(Name, Type) \
void UnitTestEventsRepeater::Name(const Type& parameter) { \
- for (int i = 0; i < listeners_.size(); i++) { \
- listeners_.GetElement(i)->Name(parameter); \
+ if (forwarding_enabled_) { \
+ for (int i = 0; i < listeners_.size(); i++) { \
+ listeners_.GetElement(i)->Name(parameter); \
+ } \
} \
}
@@ -2945,7 +2894,7 @@ GTEST_REPEATER_METHOD_(OnNewTestPartResult, TestPartResult)
#undef GTEST_REPEATER_METHOD_
-// End PrettyUnitTestResultPrinter
+// End UnitTestEventsRepeater
// This class generates an XML output file.
class XmlUnitTestResultPrinter : public EmptyTestEventListener {
@@ -2970,18 +2919,15 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// with character references.
- static internal::String EscapeXml(const char* str,
- bool is_attribute);
+ static String EscapeXml(const char* str, bool is_attribute);
// Convenience wrapper around EscapeXml when str is an attribute value.
- static internal::String EscapeXmlAttribute(const char* str) {
+ static String EscapeXmlAttribute(const char* str) {
return EscapeXml(str, true);
}
// Convenience wrapper around EscapeXml when str is not an attribute value.
- static internal::String EscapeXmlText(const char* str) {
- return EscapeXml(str, false);
- }
+ static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
// Prints an XML representation of a TestInfo object.
static void PrintXmlTestInfo(FILE* out,
@@ -2998,11 +2944,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// delimited XML attributes based on the property key="value" pairs.
// When the String is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
- static internal::String TestPropertiesAsXmlAttributes(
- const TestResult& result);
+ static String TestPropertiesAsXmlAttributes(const TestResult& result);
// The output file.
- const internal::String output_file_;
+ const String output_file_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
};
@@ -3020,11 +2965,11 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
FILE* xmlout = NULL;
- internal::FilePath output_file(output_file_);
- internal::FilePath output_dir(output_file.RemoveFileName());
+ FilePath output_file(output_file_);
+ FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
- xmlout = internal::posix::FOpen(output_file_.c_str(), "w");
+ xmlout = posix::FOpen(output_file_.c_str(), "w");
}
if (xmlout == NULL) {
// TODO(wan): report the reason of the failure.
@@ -3059,8 +3004,7 @@ void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
// most invalid characters can be retained using character references.
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
-internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
- bool is_attribute) {
+String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
Message m;
if (str != NULL) {
@@ -3090,7 +3034,7 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
default:
if (IsValidXmlCharacter(*src)) {
if (is_attribute && IsNormalizableWhitespace(*src))
- m << internal::String::Format("&#x%02X;", unsigned(*src));
+ m << String::Format("&#x%02X;", unsigned(*src));
else
m << *src;
}
@@ -3102,7 +3046,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
return m.GetString();
}
-
// The following routines generate an XML representation of a UnitTest
// object.
//
@@ -3119,8 +3062,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
// </testsuite>
// </testsuites>
-namespace internal {
-
// Formats the given time in milliseconds as seconds. The returned
// C-string is owned by this function and cannot be released by the
// caller. Calling the function again invalidates the previous
@@ -3131,8 +3072,6 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
return str.c_str();
}
-} // namespace internal
-
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
@@ -3144,7 +3083,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
"classname=\"%s\"%s",
EscapeXmlAttribute(test_info.name()).c_str(),
test_info.should_run() ? "run" : "notrun",
- internal::FormatTimeInMillisAsSeconds(result.elapsed_time()),
+ FormatTimeInMillisAsSeconds(result.elapsed_time()),
EscapeXmlAttribute(test_case_name).c_str(),
TestPropertiesAsXmlAttributes(result).c_str());
@@ -3152,9 +3091,8 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = result.GetTestPartResult(i);
if (part.failed()) {
- const internal::String message =
- internal::String::Format("%s:%d\n%s", part.file_name(),
- part.line_number(), part.message());
+ const String message = String::Format("%s:%d\n%s", part.file_name(),
+ part.line_number(), part.message());
if (++failures == 1)
fprintf(out, ">\n");
fprintf(out,
@@ -3182,7 +3120,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
test_case.disabled_test_count());
fprintf(out,
"errors=\"0\" time=\"%s\">\n",
- internal::FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
+ FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
for (int i = 0; i < test_case.total_test_count(); ++i)
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
fprintf(out, " </testsuite>\n");
@@ -3198,7 +3136,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
unit_test.total_test_count(),
unit_test.failed_test_count(),
unit_test.disabled_test_count(),
- internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
+ FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
if (GTEST_FLAG(shuffle)) {
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
}
@@ -3210,7 +3148,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
-internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
+String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const TestResult& result) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
@@ -3223,8 +3161,6 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
// End XmlUnitTestResultPrinter
-namespace internal {
-
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@@ -3271,6 +3207,84 @@ OsStackTraceGetter::kElidedFramesMarker =
} // namespace internal
+// class EventListeners
+
+EventListeners::EventListeners()
+ : repeater_(new internal::UnitTestEventsRepeater()),
+ default_result_printer_(NULL),
+ default_xml_generator_(NULL) {
+}
+
+EventListeners::~EventListeners() { delete repeater_; }
+
+// Returns the standard listener responsible for the default console
+// output. Can be removed from the listeners list to shut down default
+// console output. Note that removing this object from the listener list
+// with Release transfers its ownership to the user.
+void EventListeners::Append(UnitTestEventListenerInterface* listener) {
+ repeater_->Append(listener);
+}
+
+// Removes the given event listener from the list and returns it. It then
+// becomes the caller's responsibility to delete the listener. Returns
+// NULL if the listener is not found in the list.
+UnitTestEventListenerInterface* EventListeners::Release(
+ UnitTestEventListenerInterface* listener) {
+ if (listener == default_result_printer_)
+ default_result_printer_ = NULL;
+ else if (listener == default_xml_generator_)
+ default_xml_generator_ = NULL;
+ return repeater_->Release(listener);
+}
+
+// Returns repeater that broadcasts the UnitTestEventListenerInterface
+// events to all subscribers.
+UnitTestEventListenerInterface* EventListeners::repeater() { return repeater_; }
+
+// Sets the default_result_printer attribute to the provided listener.
+// The listener is also added to the listener list and previous
+// default_result_printer is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void EventListeners::SetDefaultResultPrinter(
+ UnitTestEventListenerInterface* listener) {
+ if (default_result_printer_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_result_printer_);
+ default_result_printer_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Sets the default_xml_generator attribute to the provided listener. The
+// listener is also added to the listener list and previous
+// default_xml_generator is removed from it and deleted. The listener can
+// also be NULL in which case it will not be added to the list. Does
+// nothing if the previous and the current listener objects are the same.
+void EventListeners::SetDefaultXmlGenerator(
+ UnitTestEventListenerInterface* listener) {
+ if (default_xml_generator_ != listener) {
+ // It is an error to pass this method a listener that is already in the
+ // list.
+ delete Release(default_xml_generator_);
+ default_xml_generator_ = listener;
+ if (listener != NULL)
+ Append(listener);
+ }
+}
+
+// Controls whether events will be forwarded by the repeater to the
+// listeners in the list.
+bool EventListeners::EventForwardingEnabled() const {
+ return repeater_->forwarding_enabled();
+}
+
+void EventListeners::SuppressEventForwarding() {
+ repeater_->set_forwarding_enabled(false);
+}
+
// class UnitTest
// Gets the singleton UnitTest object. The first time this method is
@@ -3359,6 +3373,12 @@ const TestCase* UnitTest::GetTestCase(int i) const {
return impl()->GetTestCase(i);
}
+// Returns the list of event listeners that can be used to track events
+// inside Google Test.
+EventListeners& UnitTest::listeners() {
+ return *impl()->listeners();
+}
+
// Registers and returns a global test environment. When a test
// program is run, all global test environments will be set-up in the
// order they were registered. After all tests in the program have
@@ -3614,8 +3634,8 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
current_test_case_(NULL),
current_test_info_(NULL),
ad_hoc_test_result_(),
- result_printer_(NULL),
os_stack_trace_getter_(NULL),
+ post_flag_parse_init_performed_(false),
random_seed_(0),
#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
@@ -3624,6 +3644,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
#else
elapsed_time_(0) {
#endif // GTEST_HAS_DEATH_TEST
+ listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
UnitTestImpl::~UnitTestImpl() {
@@ -3633,12 +3654,58 @@ UnitTestImpl::~UnitTestImpl() {
// Deletes every Environment.
environments_.ForEach(internal::Delete<Environment>);
- // Deletes the current test result printer.
- delete result_printer_;
-
delete os_stack_trace_getter_;
}
+#if GTEST_HAS_DEATH_TEST
+// Disables event forwarding if the control is currently in a death test
+// subprocess. Must not be called before InitGoogleTest.
+void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
+ if (internal_run_death_test_flag_.get() != NULL)
+ listeners()->SuppressEventForwarding();
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// Initializes event listeners performing XML output as specified by
+// UnitTestOptions. Must not be called before InitGoogleTest.
+void UnitTestImpl::ConfigureXmlOutput() {
+ const String& output_format = UnitTestOptions::GetOutputFormat();
+ if (output_format == "xml") {
+ listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
+ UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
+ } else if (output_format != "") {
+ printf("WARNING: unrecognized output format \"%s\" ignored.\n",
+ output_format.c_str());
+ fflush(stdout);
+ }
+}
+
+// Performs initialization dependent upon flag values obtained in
+// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
+// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
+// this function is also called from RunAllTests. Since this function can be
+// called more than once, it has to be idempotent.
+void UnitTestImpl::PostFlagParsingInit() {
+ // Ensures that this function does not execute more than once.
+ if (!post_flag_parse_init_performed_) {
+ post_flag_parse_init_performed_ = true;
+
+#if GTEST_HAS_DEATH_TEST
+ InitDeathTestSubprocessControlInfo();
+ SuppressTestEventsIfInSubprocess();
+#endif // GTEST_HAS_DEATH_TEST
+
+ // Registers parameterized tests. This makes parameterized tests
+ // available to the UnitTest reflection API without running
+ // RUN_ALL_TESTS.
+ RegisterParameterizedTests();
+
+ // Configures listeners for XML output. This makes it possible for users
+ // to shut down the default XML output before invoking RUN_ALL_TESTS.
+ ConfigureXmlOutput();
+ }
+}
+
// A predicate that checks the name of a TestCase against a known
// value.
//
@@ -3726,7 +3793,8 @@ int UnitTestImpl::RunAllTests() {
if (g_help_flag)
return 0;
- RegisterParameterizedTests();
+ // TODO(vladl@google.com): Add a call to PostFlagParsingInit() here when
+ // merging into the main branch.
// Even if sharding is not on, test runners may want to use the
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
@@ -3738,12 +3806,9 @@ int UnitTestImpl::RunAllTests() {
bool in_subprocess_for_death_test = false;
#if GTEST_HAS_DEATH_TEST
- internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
#endif // GTEST_HAS_DEATH_TEST
- UnitTestEventListenerInterface * const printer = result_printer();
-
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
in_subprocess_for_death_test);
@@ -3766,6 +3831,8 @@ int UnitTestImpl::RunAllTests() {
// True iff at least one test has failed.
bool failed = false;
+ UnitTestEventListenerInterface* repeater = listeners()->repeater();
+
// How many times to repeat the tests? We don't want to repeat them
// when we are inside the subprocess of a death test.
const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
@@ -3773,21 +3840,24 @@ int UnitTestImpl::RunAllTests() {
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
if (repeat != 1) {
+ // TODO(vladl@google.com): Move this output to
+ // PrettyUnitTestResultPrinter. Add the iteration number parameter to
+ // OnUnitTestStart.
printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
}
- // Tells the unit test event listener that the tests are about to
- // start.
- printer->OnUnitTestStart(*parent_);
+ // Tells the unit test event listeners that the tests are about to start.
+ repeater->OnUnitTestStart(*parent_);
+ // TODO(vladl@google.com): Move to before the OnUnitTestStart notification?
const TimeInMillis start = GetTimeInMillis();
// Runs each test case if there is at least one test to run.
if (has_tests_to_run) {
// Sets up all environments beforehand.
- printer->OnGlobalSetUpStart(*parent_);
+ repeater->OnGlobalSetUpStart(*parent_);
environments_.ForEach(SetUpEnvironment);
- printer->OnGlobalSetUpEnd(*parent_);
+ repeater->OnGlobalSetUpEnd(*parent_);
// Runs the tests only if there was no fatal failure during global
// set-up.
@@ -3796,16 +3866,15 @@ int UnitTestImpl::RunAllTests() {
}
// Tears down all environments in reverse order afterwards.
- printer->OnGlobalTearDownStart(*parent_);
+ repeater->OnGlobalTearDownStart(*parent_);
environments_in_reverse_order_.ForEach(TearDownEnvironment);
- printer->OnGlobalTearDownEnd(*parent_);
+ repeater->OnGlobalTearDownEnd(*parent_);
}
elapsed_time_ = GetTimeInMillis() - start;
- // Tells the unit test event listener that the tests have just
- // finished.
- printer->OnUnitTestEnd(*parent_);
+ // Tells the unit test event listener that the tests have just finished.
+ repeater->OnUnitTestEnd(*parent_);
// Gets the result and clears it.
if (!Passed()) {
@@ -3997,49 +4066,6 @@ void UnitTestImpl::ListTestsMatchingFilter() {
fflush(stdout);
}
-// Sets the unit test result printer.
-//
-// Does nothing if the input and the current printer object are the
-// same; otherwise, deletes the old printer object and makes the
-// input the current printer.
-void UnitTestImpl::set_result_printer(
- UnitTestEventListenerInterface* result_printer) {
- if (result_printer_ != result_printer) {
- delete result_printer_;
- result_printer_ = result_printer;
- }
-}
-
-// Returns the current unit test result printer if it is not NULL;
-// otherwise, creates an appropriate result printer, makes it the
-// current printer, and returns it.
-UnitTestEventListenerInterface* UnitTestImpl::result_printer() {
- if (result_printer_ != NULL) {
- return result_printer_;
- }
-
-#if GTEST_HAS_DEATH_TEST
- if (internal_run_death_test_flag_.get() != NULL) {
- result_printer_ = new NullUnitTestResultPrinter;
- return result_printer_;
- }
-#endif // GTEST_HAS_DEATH_TEST
-
- UnitTestEventsRepeater *repeater = new UnitTestEventsRepeater;
- const String& output_format = internal::UnitTestOptions::GetOutputFormat();
- if (output_format == "xml") {
- repeater->AddListener(new XmlUnitTestResultPrinter(
- internal::UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
- } else if (output_format != "") {
- printf("WARNING: unrecognized output format \"%s\" ignored.\n",
- output_format.c_str());
- fflush(stdout);
- }
- repeater->AddListener(new PrettyUnitTestResultPrinter);
- result_printer_ = repeater;
- return result_printer_;
-}
-
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter are
@@ -4420,6 +4446,7 @@ void InitGoogleTestImpl(int* argc, CharType** argv) {
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
+ GetUnitTestImpl()->PostFlagParsingInit();
}
} // namespace internal
diff --git a/test/gtest-listener_test.cc b/test/gtest-listener_test.cc
new file mode 100644
index 0000000..fb6fcf4
--- /dev/null
+++ b/test/gtest-listener_test.cc
@@ -0,0 +1,230 @@
+// Copyright 2009 Google Inc. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: vladl@google.com (Vlad Losev)
+//
+// The Google C++ Testing Framework (Google Test)
+//
+// This file verifies Google Test event listeners receive events at the
+// right times.
+
+#include <gtest/gtest.h>
+
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h" // For Vector.
+#undef GTEST_IMPLEMENTATION_
+
+using ::testing::AddGlobalTestEnvironment;
+using ::testing::Environment;
+using ::testing::InitGoogleTest;
+using ::testing::Test;
+using ::testing::TestInfo;
+using ::testing::TestPartResult;
+using ::testing::UnitTest;
+using ::testing::internal::String;
+using ::testing::internal::TestCase;
+using ::testing::internal::UnitTestEventListenerInterface;
+using ::testing::internal::Vector;
+
+// Used by tests to register their events.
+Vector<String>* g_events = NULL;
+
+namespace testing {
+namespace internal {
+
+// TODO(vladl@google.com): Remove this and use UnitTest::listeners()
+// directly after it is published.
+class UnitTestAccessor {
+ public:
+ static EventListeners& GetEventListeners() {
+ return UnitTest::GetInstance()->listeners();
+ }
+ static bool UnitTestFailed() { return UnitTest::GetInstance()->Failed(); }
+};
+
+class EventRecordingListener : public UnitTestEventListenerInterface {
+ protected:
+ virtual void OnUnitTestStart(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnUnitTestStart"));
+ }
+
+ virtual void OnGlobalSetUpStart(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnGlobalSetUpStart"));
+ }
+
+ virtual void OnGlobalSetUpEnd(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnGlobalSetUpEnd"));
+ }
+
+ virtual void OnTestCaseStart(const TestCase& test_case) {
+ g_events->PushBack(String("TestEventListener::OnTestCaseStart"));
+ }
+
+ virtual void OnTestStart(const TestInfo& test_info) {
+ g_events->PushBack(String("TestEventListener::OnTestStart"));
+ }
+
+ virtual void OnNewTestPartResult(const TestPartResult& test_part_result) {
+ g_events->PushBack(String("TestEventListener::OnNewTestPartResult"));
+ }
+
+ virtual void OnTestEnd(const TestInfo& test_info) {
+ g_events->PushBack(String("TestEventListener::OnTestEnd"));
+ }
+
+ virtual void OnTestCaseEnd(const TestCase& test_case) {
+ g_events->PushBack(String("TestEventListener::OnTestCaseEnd"));
+ }
+
+ virtual void OnGlobalTearDownStart(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnGlobalTearDownStart"));
+ }
+
+ virtual void OnGlobalTearDownEnd(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnGlobalTearDownEnd"));
+ }
+
+ virtual void OnUnitTestEnd(const UnitTest& unit_test) {
+ g_events->PushBack(String("TestEventListener::OnUnitTestEnd"));
+ }
+};
+
+class EnvironmentInvocationCatcher : public Environment {
+ protected:
+ virtual void SetUp() {
+ g_events->PushBack(String("Environment::SetUp"));
+ }
+
+ virtual void TearDown() {
+ g_events->PushBack(String("Environment::TearDown"));
+ }
+};
+
+class ListenerTest : public Test {
+ protected:
+ static void SetUpTestCase() {
+ g_events->PushBack(String("ListenerTest::SetUpTestCase"));
+ }
+
+ static void TearDownTestCase() {
+ g_events->PushBack(String("ListenerTest::TearDownTestCase"));
+ }
+
+ virtual void SetUp() {
+ g_events->PushBack(String("ListenerTest::SetUp"));
+ }
+
+ virtual void TearDown() {
+ g_events->PushBack(String("ListenerTest::TearDown"));
+ }
+};
+
+TEST_F(ListenerTest, DoesFoo) {
+ // Test execution order within a test case is not guaranteed so we are not
+ // recording the test name.
+ g_events->PushBack(String("ListenerTest::* Test Body"));
+ SUCCEED(); // Triggers OnTestPartResult.
+}
+
+TEST_F(ListenerTest, DoesBar) {
+ g_events->PushBack(String("ListenerTest::* Test Body"));
+ SUCCEED(); // Triggers OnTestPartResult.
+}
+
+} // namespace internal
+
+} // namespace testing
+
+using ::testing::internal::EnvironmentInvocationCatcher;
+using ::testing::internal::EventRecordingListener;
+using ::testing::internal::UnitTestAccessor;
+
+int main(int argc, char **argv) {
+ Vector<String> events;
+ g_events = &events;
+ InitGoogleTest(&argc, argv);
+
+ UnitTestEventListenerInterface* listener = new EventRecordingListener;
+ UnitTestAccessor::GetEventListeners().Append(listener);
+
+ AddGlobalTestEnvironment(new EnvironmentInvocationCatcher);
+
+ GTEST_CHECK_(events.size() == 0)
+ << "AddGlobalTestEnvironment should not generate any events itself.";
+
+ int ret_val = RUN_ALL_TESTS();
+
+ const char* const expected_events[] = {
+ "TestEventListener::OnUnitTestStart",
+ "TestEventListener::OnGlobalSetUpStart",
+ "Environment::SetUp",
+ "TestEventListener::OnGlobalSetUpEnd",
+ "TestEventListener::OnTestCaseStart",
+ "ListenerTest::SetUpTestCase",
+ "TestEventListener::OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "TestEventListener::OnNewTestPartResult",
+ "ListenerTest::TearDown",
+ "TestEventListener::OnTestEnd",
+ "TestEventListener::OnTestStart",
+ "ListenerTest::SetUp",
+ "ListenerTest::* Test Body",
+ "TestEventListener::OnNewTestPartResult",
+ "ListenerTest::TearDown",
+ "TestEventListener::OnTestEnd",
+ "ListenerTest::TearDownTestCase",
+ "TestEventListener::OnTestCaseEnd",
+ "TestEventListener::OnGlobalTearDownStart",
+ "Environment::TearDown",
+ "TestEventListener::OnGlobalTearDownEnd",
+ "TestEventListener::OnUnitTestEnd"
+ };
+ const int kExpectedEventsSize =
+ sizeof(expected_events)/sizeof(expected_events[0]);
+
+ // Cannot use ASSERT_EQ() here because it requires the scoping function to
+ // return void.
+ GTEST_CHECK_(events.size() == kExpectedEventsSize);
+
+ for (int i = 0; i < events.size(); ++i)
+ GTEST_CHECK_(String(events.GetElement(i)) == expected_events[i])
+ << "At position " << i;
+
+ // We need to check manually for ad hoc test failures that happen after
+ // RUN_ALL_TESTS finishes.
+ if (UnitTestAccessor::UnitTestFailed())
+ ret_val = 1;
+
+ return ret_val;
+}
diff --git a/test/gtest_env_var_test.py b/test/gtest_env_var_test.py
index 19fd810..f8250d4 100755
--- a/test/gtest_env_var_test.py
+++ b/test/gtest_env_var_test.py
@@ -85,7 +85,7 @@ class GTestEnvVarTest(gtest_test_utils.TestCase):
TestFlag('break_on_failure', '1', '0')
TestFlag('color', 'yes', 'auto')
TestFlag('filter', 'FooTest.Bar', '*')
- TestFlag('output', 'tmp/foo.xml', '')
+ TestFlag('output', 'xml:tmp/foo.xml', '')
TestFlag('print_time', '0', '1')
TestFlag('repeat', '999', '1')
TestFlag('throw_on_failure', '1', '0')
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index 90d29e5..dcec9da 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -84,11 +84,38 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
bool ParseInt32Flag(const char* str, const char* flag, Int32* value);
+// Provides access to otherwise private parts of the EventListeners class
+// that are needed to test it.
+class EventListenersAccessor {
+ public:
+ static UnitTestEventListenerInterface* GetRepeater(
+ EventListeners* listeners) { return listeners->repeater(); }
+
+ static void SetDefaultResultPrinter(
+ EventListeners* listeners,
+ UnitTestEventListenerInterface* listener) {
+ listeners->SetDefaultResultPrinter(listener);
+ }
+ static void SetDefaultXmlGenerator(EventListeners* listeners,
+ UnitTestEventListenerInterface* listener) {
+ listeners->SetDefaultXmlGenerator(listener);
+ }
+
+ static bool EventForwardingEnabled(const EventListeners& listeners) {
+ return listeners.EventForwardingEnabled();
+ }
+
+ static void SuppressEventForwarding(EventListeners* listeners) {
+ listeners->SuppressEventForwarding();
+ }
+};
+
} // namespace internal
} // namespace testing
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::ParseInt32Flag;
+using testing::internal::EventListenersAccessor;
namespace testing {
@@ -136,7 +163,9 @@ using testing::internal::kMaxRandomSeed;
using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::AppendUserMessage;
using testing::internal::CodePointToUtf8;
+using testing::internal::EmptyTestEventListener;
using testing::internal::EqFailure;
+using testing::internal::EventListeners;
using testing::internal::FloatingPoint;
using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop;
@@ -160,6 +189,7 @@ using testing::internal::ThreadLocal;
using testing::internal::Vector;
using testing::internal::WideStringToUtf8;
using testing::internal::kTestTypeIdInGoogleTest;
+using testing::internal::scoped_ptr;
// This line tests that we can define tests in an unnamed namespace.
namespace {
@@ -695,14 +725,16 @@ TEST(ListDeathTest, GetElement) {
"Invalid Vector index -1: must be in range \\[0, 2\\]\\.");
}
-// Tests the String class.
+// Tests the size of the AssertHelper class.
-TEST(StringTest, SizeIsSmall) {
+TEST(AssertHelperTest, AssertHelperIsSmall) {
// To avoid breaking clients that use lots of assertions in one
- // function, we cannot grow the size of String.
- EXPECT_LE(sizeof(String), sizeof(void*));
+ // function, we cannot grow the size of AssertHelper.
+ EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
}
+// Tests the String class.
+
// Tests String's constructors.
TEST(StringTest, Constructors) {
// Default ctor.
@@ -1037,6 +1069,33 @@ TEST(StringTest, Streams) {
EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
}
+// Tests that String::Format() works.
+TEST(StringTest, FormatWorks) {
+ // Normal case: the format spec is valid, the arguments match the
+ // spec, and the result is < 4095 characters.
+ EXPECT_STREQ("Hello, 42", String::Format("%s, %d", "Hello", 42).c_str());
+
+ // Edge case: the result is 4095 characters.
+ char buffer[4096];
+ const size_t kSize = sizeof(buffer);
+ memset(buffer, 'a', kSize - 1);
+ buffer[kSize - 1] = '\0';
+ EXPECT_STREQ(buffer, String::Format("%s", buffer).c_str());
+
+ // The result needs to be 4096 characters, exceeding Format()'s limit.
+ EXPECT_STREQ("<formatting error or buffer exceeded>",
+ String::Format("x%s", buffer).c_str());
+
+#if GTEST_OS_LINUX
+ // On Linux, invalid format spec should lead to an error message.
+ // In other environment (e.g. MSVC on Windows), String::Format() may
+ // simply ignore a bad format spec, so this assertion is run on
+ // Linux only.
+ EXPECT_STREQ("<formatting error or buffer exceeded>",
+ String::Format("%").c_str());
+#endif
+}
+
#if GTEST_OS_WINDOWS
// Tests String::ShowWideCString().
@@ -6142,3 +6201,275 @@ TEST(HasFailureTest, WorksOutsideOfTestBody2) {
ClearCurrentTestPartResults();
EXPECT_TRUE(has_failure);
}
+
+class TestListener : public EmptyTestEventListener {
+ public:
+ TestListener() : on_start_counter_(NULL), is_destroyed_(NULL) {}
+ TestListener(int* on_start_counter, bool* is_destroyed)
+ : on_start_counter_(on_start_counter),
+ is_destroyed_(is_destroyed) {}
+
+ virtual ~TestListener() {
+ if (is_destroyed_)
+ *is_destroyed_ = true;
+ }
+
+ protected:
+ virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {
+ if (on_start_counter_ != NULL)
+ (*on_start_counter_)++;
+ }
+
+ private:
+ int* on_start_counter_;
+ bool* is_destroyed_;
+};
+
+// Tests the constructor.
+TEST(EventListenersTest, ConstructionWorks) {
+ EventListeners listeners;
+
+ EXPECT_TRUE(EventListenersAccessor::GetRepeater(&listeners) != NULL);
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+}
+
+// Tests that the EventListeners destructor deletes all the listeners it
+// owns.
+TEST(EventListenersTest, DestructionWorks) {
+ bool default_result_printer_is_destroyed = false;
+ bool default_xml_printer_is_destroyed = false;
+ bool extra_listener_is_destroyed = false;
+ TestListener* default_result_printer = new TestListener(
+ NULL, &default_result_printer_is_destroyed);
+ TestListener* default_xml_printer = new TestListener(
+ NULL, &default_xml_printer_is_destroyed);
+ TestListener* extra_listener = new TestListener(
+ NULL, &extra_listener_is_destroyed);
+
+ {
+ EventListeners listeners;
+ EventListenersAccessor::SetDefaultResultPrinter(&listeners,
+ default_result_printer);
+ EventListenersAccessor::SetDefaultXmlGenerator(&listeners,
+ default_xml_printer);
+ listeners.Append(extra_listener);
+ }
+ EXPECT_TRUE(default_result_printer_is_destroyed);
+ EXPECT_TRUE(default_xml_printer_is_destroyed);
+ EXPECT_TRUE(extra_listener_is_destroyed);
+}
+
+// Tests that a listener Append'ed to an EventListeners list starts
+// receiving events.
+TEST(EventListenersTest, Append) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ EventListeners listeners;
+ listeners.Append(listener);
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+ }
+ EXPECT_TRUE(is_destroyed);
+}
+
+// Tests that listeners receive requests in the order they were appended to
+// the list.
+class SequenceTestingListener : public EmptyTestEventListener {
+ public:
+ SequenceTestingListener(Vector<const char*>* vector, const char* signature)
+ : vector_(vector), signature_(signature) {}
+
+ protected:
+ virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {
+ if (vector_ != NULL)
+ vector_->PushBack(signature_);
+ }
+
+ private:
+ Vector<const char*>* vector_;
+ const char* const signature_;
+};
+
+TEST(EventListenerTest, AppendKeepsOrder) {
+ Vector<const char*> vec;
+ EventListeners listeners;
+ listeners.Append(new SequenceTestingListener(&vec, "0"));
+ listeners.Append(new SequenceTestingListener(&vec, "1"));
+ listeners.Append(new SequenceTestingListener(&vec, "2"));
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ ASSERT_EQ(3, vec.size());
+ ASSERT_STREQ("0", vec.GetElement(0));
+ ASSERT_STREQ("1", vec.GetElement(1));
+ ASSERT_STREQ("2", vec.GetElement(2));
+}
+
+// Tests that a listener removed from an EventListeners list stops receiving
+// events and is not deleted when the list is destroyed.
+TEST(EventListenersTest, Release) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ EventListeners listeners;
+ listeners.Append(listener);
+ EXPECT_EQ(listener, listeners.Release(listener));
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_TRUE(listeners.Release(listener) == NULL);
+ }
+ EXPECT_EQ(0, on_start_counter);
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}
+
+// Tests that no events are forwarded when event forwarding is disabled.
+TEST(EventListenerTest, SuppressEventForwarding) {
+ int on_start_counter = 0;
+ TestListener* listener = new TestListener(&on_start_counter, NULL);
+
+ EventListeners listeners;
+ listeners.Append(listener);
+ ASSERT_TRUE(EventListenersAccessor::EventForwardingEnabled(listeners));
+ EventListenersAccessor::SuppressEventForwarding(&listeners);
+ ASSERT_FALSE(EventListenersAccessor::EventForwardingEnabled(listeners));
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+}
+
+#if GTEST_HAS_DEATH_TEST
+// Tests that events generated by Google Test are not forwarded in
+// death test subprocesses.
+TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
+ EXPECT_DEATH({ // NOLINT
+ GTEST_CHECK_(EventListenersAccessor::EventForwardingEnabled(
+ *GetUnitTestImpl()->listeners())) << "expected failure";},
+ "expected failure");
+}
+#endif // GTEST_HAS_DEATH_TEST
+
+// Tests that a listener installed via SetDefaultResultPrinter() starts
+// receiving events and is returned via default_result_printer() and that
+// the previous default_result_printer is removed from the list and deleted.
+TEST(EventListenerTest, default_result_printer) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+ EventListeners listeners;
+ EventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.default_result_printer());
+
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+
+ EXPECT_EQ(1, on_start_counter);
+
+ // Replacing default_result_printer with something else should remove it
+ // from the list and destroy it.
+ EventListenersAccessor::SetDefaultResultPrinter(&listeners, NULL);
+
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_TRUE(is_destroyed);
+
+ // After broadcasting an event the counter is still the same, indicating
+ // the listener is not in the list anymore.
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_result_printer listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ EventListeners listeners;
+ EventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.Release(listener));
+ EXPECT_TRUE(listeners.default_result_printer() == NULL);
+ EXPECT_FALSE(is_destroyed);
+
+ // Broadcasting events now should not affect default_result_printer.
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+ }
+ // Destroying the list should not affect the listener now, too.
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}
+
+// Tests that a listener installed via SetDefaultXmlGenerator() starts
+// receiving events and is returned via default_xml_generator() and that
+// the previous default_xml_generator is removed from the list and deleted.
+TEST(EventListenerTest, default_xml_generator) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+
+ EventListeners listeners;
+ EventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.default_xml_generator());
+
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+
+ EXPECT_EQ(1, on_start_counter);
+
+ // Replacing default_xml_generator with something else should remove it
+ // from the list and destroy it.
+ EventListenersAccessor::SetDefaultXmlGenerator(&listeners, NULL);
+
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+ EXPECT_TRUE(is_destroyed);
+
+ // After broadcasting an event the counter is still the same, indicating
+ // the listener is not in the list anymore.
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(1, on_start_counter);
+}
+
+// Tests that the default_xml_generator listener stops receiving events
+// when removed via Release and that is not owned by the list anymore.
+TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
+ int on_start_counter = 0;
+ bool is_destroyed = false;
+ // Although Append passes the ownership of this object to the list,
+ // the following calls release it, and we need to delete it before the
+ // test ends.
+ TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
+ {
+ EventListeners listeners;
+ EventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
+
+ EXPECT_EQ(listener, listeners.Release(listener));
+ EXPECT_TRUE(listeners.default_xml_generator() == NULL);
+ EXPECT_FALSE(is_destroyed);
+
+ // Broadcasting events now should not affect default_xml_generator.
+ EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
+ *UnitTest::GetInstance());
+ EXPECT_EQ(0, on_start_counter);
+ }
+ // Destroying the list should not affect the listener now, too.
+ EXPECT_FALSE(is_destroyed);
+ delete listener;
+}
diff --git a/test/gtest_xml_output_unittest.py b/test/gtest_xml_output_unittest.py
index a0cd4d0..3ee6846 100755
--- a/test/gtest_xml_output_unittest.py
+++ b/test/gtest_xml_output_unittest.py
@@ -44,6 +44,7 @@ import gtest_xml_test_utils
GTEST_OUTPUT_FLAG = "--gtest_output"
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
+GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
SUPPORTS_STACK_TRACES = False
@@ -108,8 +109,7 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
Runs a test program that generates a non-empty XML output, and
tests that the XML output is expected.
"""
- self._TestXmlOutput("gtest_xml_output_unittest_",
- EXPECTED_NON_EMPTY_XML, 1)
+ self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
def testEmptyXmlOutput(self):
"""
@@ -142,6 +142,35 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
self.assertEquals(0, p.exit_code)
self.assert_(os.path.isfile(output_file))
+ def testSuppressedXmlOutput(self):
+ """
+ Tests that no XML file is generated if the default XML listener is
+ shut down before RUN_ALL_TESTS is invoked.
+ """
+
+ xml_path = os.path.join(gtest_test_utils.GetTempDir(),
+ GTEST_PROGRAM_NAME + "out.xml")
+ if os.path.isfile(xml_path):
+ os.remove(xml_path)
+
+ gtest_prog_path = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
+
+ command = [gtest_prog_path,
+ "%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path),
+ "--shut_down_xml"]
+ p = gtest_test_utils.Subprocess(command)
+ if p.terminated_by_signal:
+ self.assert_(False,
+ "%s was killed by signal %d" % (gtest_prog_name, p.signal))
+ else:
+ self.assert_(p.exited)
+ self.assertEquals(1, p.exit_code,
+ "'%s' exited with code %s, which doesn't match "
+ "the expected exit code %s."
+ % (command, p.exit_code, 1))
+
+ self.assert_(not os.path.isfile(xml_path))
+
def _TestXmlOutput(self, gtest_prog_name, expected_xml, expected_exit_code):
"""
diff --git a/test/gtest_xml_output_unittest_.cc b/test/gtest_xml_output_unittest_.cc
index d7ce2c6..bfeda3d 100644
--- a/test/gtest_xml_output_unittest_.cc
+++ b/test/gtest_xml_output_unittest_.cc
@@ -40,6 +40,20 @@
#include <gtest/gtest.h>
+// TODO(vladl@google.com): Remove this include when the event listener API is
+// published and GetUnitTestImpl is no longer needed.
+//
+// Indicates that this translation unit is part of Google Test's
+// implementation. It must come before gtest-internal-inl.h is
+// included, or there will be a compiler error. This trick is to
+// prevent a user from accidentally including gtest-internal-inl.h in
+// his code.
+#define GTEST_IMPLEMENTATION_ 1
+#include "src/gtest-internal-inl.h"
+#undef GTEST_IMPLEMENTATION_
+
+using ::testing::InitGoogleTest;
+
class SuccessfulTest : public testing::Test {
};
@@ -118,3 +132,17 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
}
+
+int main(int argc, char** argv) {
+ InitGoogleTest(&argc, argv);
+
+ if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
+ // TODO(vladl@google.com): Replace GetUnitTestImpl()->listeners() with
+ // UnitTest::GetInstance()->listeners() when the event listener API is
+ // published.
+ ::testing::internal::EventListeners& listeners =
+ *::testing::internal::GetUnitTestImpl()->listeners();
+ delete listeners.Release(listeners.default_xml_generator());
+ }
+ return RUN_ALL_TESTS();
+}