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).
This commit is contained in:
parent
56a2e686e9
commit
16e9dd6e28
19
CHANGES
19
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:
|
Changes for 1.3.0:
|
||||||
|
|
||||||
* New feature: death tests on Windows, Cygwin, and Mac.
|
* New feature: death tests on Windows, Cygwin, and Mac.
|
||||||
|
@ -11,7 +28,7 @@ Changes for 1.3.0:
|
||||||
.cc file for easy deployment.
|
.cc file for easy deployment.
|
||||||
* New feature: support for distributing test functions to multiple
|
* New feature: support for distributing test functions to multiple
|
||||||
machines (requires support from the test runner).
|
machines (requires support from the test runner).
|
||||||
* Bug fixes and implementation clean-up.
|
* Bug fixes and implementation clean-ups.
|
||||||
|
|
||||||
Changes for 1.2.1:
|
Changes for 1.2.1:
|
||||||
|
|
||||||
|
|
17
Makefile.am
17
Makefile.am
|
@ -12,6 +12,8 @@ EXTRA_DIST = \
|
||||||
include/gtest/internal/gtest-param-util-generated.h.pump \
|
include/gtest/internal/gtest-param-util-generated.h.pump \
|
||||||
make/Makefile \
|
make/Makefile \
|
||||||
scons/SConscript \
|
scons/SConscript \
|
||||||
|
scons/SConstruct \
|
||||||
|
scons/SConstruct.common \
|
||||||
scripts/fuse_gtest_files.py \
|
scripts/fuse_gtest_files.py \
|
||||||
scripts/gen_gtest_pred_impl.py \
|
scripts/gen_gtest_pred_impl.py \
|
||||||
scripts/test/Makefile \
|
scripts/test/Makefile \
|
||||||
|
@ -24,10 +26,15 @@ EXTRA_DIST += \
|
||||||
msvc/gtest_color_test_.vcproj \
|
msvc/gtest_color_test_.vcproj \
|
||||||
msvc/gtest_env_var_test_.vcproj \
|
msvc/gtest_env_var_test_.vcproj \
|
||||||
msvc/gtest_environment_test.vcproj \
|
msvc/gtest_environment_test.vcproj \
|
||||||
|
msvc/gtest_main-md.vcproj \
|
||||||
msvc/gtest_main.vcproj \
|
msvc/gtest_main.vcproj \
|
||||||
|
msvc/gtest-md.sln \
|
||||||
|
msvc/gtest-md.vcproj \
|
||||||
msvc/gtest_output_test_.vcproj \
|
msvc/gtest_output_test_.vcproj \
|
||||||
|
msvc/gtest_prod_test-md.vcproj \
|
||||||
msvc/gtest_prod_test.vcproj \
|
msvc/gtest_prod_test.vcproj \
|
||||||
msvc/gtest_uninitialized_test_.vcproj \
|
msvc/gtest_uninitialized_test_.vcproj \
|
||||||
|
msvc/gtest_unittest-md.vcproj \
|
||||||
msvc/gtest_unittest.vcproj
|
msvc/gtest_unittest.vcproj
|
||||||
|
|
||||||
# xcode project files
|
# xcode project files
|
||||||
|
@ -36,9 +43,8 @@ EXTRA_DIST += \
|
||||||
xcode/Config/FrameworkTarget.xcconfig \
|
xcode/Config/FrameworkTarget.xcconfig \
|
||||||
xcode/Config/General.xcconfig \
|
xcode/Config/General.xcconfig \
|
||||||
xcode/Config/ReleaseProject.xcconfig \
|
xcode/Config/ReleaseProject.xcconfig \
|
||||||
|
xcode/Config/StaticLibraryTarget.xcconfig \
|
||||||
xcode/Config/TestTarget.xcconfig \
|
xcode/Config/TestTarget.xcconfig \
|
||||||
xcode/Config/InternalTestTarget.xcconfig \
|
|
||||||
xcode/Config/InternalPythonTestTarget.xcconfig \
|
|
||||||
xcode/Resources/Info.plist \
|
xcode/Resources/Info.plist \
|
||||||
xcode/Scripts/versiongenerate.py \
|
xcode/Scripts/versiongenerate.py \
|
||||||
xcode/Scripts/runtests.sh \
|
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_SOURCES = test/gtest-unittest-api_test.cc
|
||||||
test_gtest_unittest_api_test_LDADD = lib/libgtest_main.la
|
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.
|
# Verifies that Google Test works when RTTI is disabled.
|
||||||
TESTS += test/gtest_no_rtti_test
|
TESTS += test/gtest_no_rtti_test
|
||||||
check_PROGRAMS += 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_
|
check_PROGRAMS += test/gtest_xml_output_unittest_
|
||||||
test_gtest_xml_output_unittest__SOURCES = test/gtest_xml_output_unittest_.cc
|
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
|
check_SCRIPTS += test/gtest_xml_output_unittest.py
|
||||||
TESTS += test/gtest_xml_output_unittest.py
|
TESTS += test/gtest_xml_output_unittest.py
|
||||||
|
|
||||||
|
|
13
README
13
README
|
@ -190,9 +190,16 @@ see 'gtest-config --help' for more detailed information.
|
||||||
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
|
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
|
||||||
|
|
||||||
### Windows ###
|
### Windows ###
|
||||||
Open the gtest.sln file in the msvc/ folder using Visual Studio, and
|
The msvc\ folder contains two solutions with Visual C++ projects. Open the
|
||||||
you are ready to build Google Test the same way you build any Visual
|
gtest.sln or gtest-md.sln file using Visual Studio, and you are ready to
|
||||||
Studio project.
|
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) ###
|
### Mac OS X (universal-binary framework) ###
|
||||||
Open the gtest.xcodeproj in the xcode/ folder using Xcode. Build the "gtest"
|
Open the gtest.xcodeproj in the xcode/ folder using Xcode. Build the "gtest"
|
||||||
|
|
|
@ -41,6 +41,9 @@ namespace testing {
|
||||||
|
|
||||||
// The possible outcomes of a test part (i.e. an assertion or an
|
// The possible outcomes of a test part (i.e. an assertion or an
|
||||||
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
|
// 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 {
|
enum TestPartResultType {
|
||||||
TPRT_SUCCESS, // Succeeded.
|
TPRT_SUCCESS, // Succeeded.
|
||||||
TPRT_NONFATAL_FAILURE, // Failed but the test can continue.
|
TPRT_NONFATAL_FAILURE, // Failed but the test can continue.
|
||||||
|
|
|
@ -149,17 +149,23 @@ namespace internal {
|
||||||
|
|
||||||
class AssertHelper;
|
class AssertHelper;
|
||||||
class DefaultGlobalTestPartResultReporter;
|
class DefaultGlobalTestPartResultReporter;
|
||||||
|
class EventListenersAccessor;
|
||||||
class ExecDeathTest;
|
class ExecDeathTest;
|
||||||
|
class NoExecDeathTest;
|
||||||
class FinalSuccessChecker;
|
class FinalSuccessChecker;
|
||||||
class GTestFlagSaver;
|
class GTestFlagSaver;
|
||||||
class TestCase;
|
class TestCase;
|
||||||
class TestInfoImpl;
|
class TestInfoImpl;
|
||||||
class TestResultAccessor;
|
class TestResultAccessor;
|
||||||
class UnitTestAccessor;
|
class UnitTestAccessor;
|
||||||
|
// TODO(vladl@google.com): Rename to TestEventRepeater.
|
||||||
|
class UnitTestEventsRepeater;
|
||||||
class WindowsDeathTest;
|
class WindowsDeathTest;
|
||||||
class UnitTestImpl* GetUnitTestImpl();
|
class UnitTestImpl* GetUnitTestImpl();
|
||||||
void ReportFailureInUnknownLocation(TestPartResultType result_type,
|
void ReportFailureInUnknownLocation(TestPartResultType result_type,
|
||||||
const String& message);
|
const String& message);
|
||||||
|
class PrettyUnitTestResultPrinter;
|
||||||
|
class XmlUnitTestResultPrinter;
|
||||||
|
|
||||||
// Converts a streamable value to a String. A NULL pointer is
|
// Converts a streamable value to a String. A NULL pointer is
|
||||||
// converted to "(null)". When the input value is a ::string,
|
// 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; }
|
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.
|
// A UnitTest consists of a vector of TestCases.
|
||||||
//
|
//
|
||||||
// This is a singleton class. The only instance of UnitTest is
|
// 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.
|
// total_test_case_count() - 1. If i is not in that range, returns NULL.
|
||||||
const internal::TestCase* GetTestCase(int i) const;
|
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
|
// ScopedTrace is a friend as it needs to modify the per-thread
|
||||||
// trace stack, which is a private member of UnitTest.
|
// trace stack, which is a private member of UnitTest.
|
||||||
// TODO(vladl@google.com): Order all declarations according to the style
|
// TODO(vladl@google.com): Order all declarations according to the style
|
||||||
|
@ -899,9 +1081,12 @@ class UnitTest {
|
||||||
TestPartResultType result_type,
|
TestPartResultType result_type,
|
||||||
const internal::String& message);
|
const internal::String& message);
|
||||||
// TODO(vladl@google.com): Remove these when publishing the new accessors.
|
// TODO(vladl@google.com): Remove these when publishing the new accessors.
|
||||||
friend class PrettyUnitTestResultPrinter;
|
friend class internal::PrettyUnitTestResultPrinter;
|
||||||
friend class XmlUnitTestResultPrinter;
|
friend class internal::TestCase;
|
||||||
|
friend class internal::TestInfoImpl;
|
||||||
friend class internal::UnitTestAccessor;
|
friend class internal::UnitTestAccessor;
|
||||||
|
friend class internal::UnitTestImpl;
|
||||||
|
friend class internal::XmlUnitTestResultPrinter;
|
||||||
friend class FinalSuccessChecker;
|
friend class FinalSuccessChecker;
|
||||||
FRIEND_TEST(ApiTest, UnitTestImmutableAccessorsWork);
|
FRIEND_TEST(ApiTest, UnitTestImmutableAccessorsWork);
|
||||||
FRIEND_TEST(ApiTest, TestCaseImmutableAccessorsWork);
|
FRIEND_TEST(ApiTest, TestCaseImmutableAccessorsWork);
|
||||||
|
@ -1299,14 +1484,32 @@ class AssertHelper {
|
||||||
// Constructor.
|
// Constructor.
|
||||||
AssertHelper(TestPartResultType type, const char* file, int line,
|
AssertHelper(TestPartResultType type, const char* file, int line,
|
||||||
const char* message);
|
const char* message);
|
||||||
|
~AssertHelper();
|
||||||
|
|
||||||
// Message assignment is a semantic trick to enable assertion
|
// Message assignment is a semantic trick to enable assertion
|
||||||
// streaming; see the GTEST_MESSAGE_ macro below.
|
// streaming; see the GTEST_MESSAGE_ macro below.
|
||||||
void operator=(const Message& message) const;
|
void operator=(const Message& message) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TestPartResultType const type_;
|
// We put our data in a struct so that the size of the AssertHelper class can
|
||||||
const char* const file_;
|
// be as small as possible. This is important because gcc is incapable of
|
||||||
int const line_;
|
// re-using stack space even for temporary variables, so every EXPECT_EQ
|
||||||
String const message_;
|
// 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);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
|
||||||
};
|
};
|
||||||
|
|
|
@ -107,7 +107,6 @@ class Test; // Represents a test.
|
||||||
class TestInfo; // Information about a test.
|
class TestInfo; // Information about a test.
|
||||||
class TestPartResult; // Result of a test part.
|
class TestPartResult; // Result of a test part.
|
||||||
class UnitTest; // A collection of test cases.
|
class UnitTest; // A collection of test cases.
|
||||||
class UnitTestEventListenerInterface; // Listens to Google Test events.
|
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
|
@ -51,22 +51,6 @@
|
||||||
namespace testing {
|
namespace testing {
|
||||||
namespace internal {
|
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.
|
// String - a UTF-8 string class.
|
||||||
//
|
//
|
||||||
// We cannot use std::string as Microsoft's STL implementation in
|
// We cannot use std::string as Microsoft's STL implementation in
|
||||||
|
@ -202,14 +186,14 @@ class String {
|
||||||
|
|
||||||
// C'tors
|
// C'tors
|
||||||
|
|
||||||
// The default c'tor constructs a NULL string, which is represented
|
// The default c'tor constructs a NULL string.
|
||||||
// by data_ being NULL.
|
String() : c_str_(NULL), length_(0) {}
|
||||||
String() : data_(NULL) {}
|
|
||||||
|
|
||||||
// Constructs a String by cloning a 0-terminated C string.
|
// Constructs a String by cloning a 0-terminated C string.
|
||||||
String(const char* c_str) { // NOLINT
|
String(const char* c_str) { // NOLINT
|
||||||
if (c_str == NULL) {
|
if (c_str == NULL) {
|
||||||
data_ = NULL;
|
c_str_ = NULL;
|
||||||
|
length_ = 0;
|
||||||
} else {
|
} else {
|
||||||
ConstructNonNull(c_str, strlen(c_str));
|
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
|
// The copy c'tor creates a new copy of the string. The two
|
||||||
// String objects do not share content.
|
// 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
|
// D'tor. String is intended to be a final class, so the d'tor
|
||||||
// doesn't need to be virtual.
|
// doesn't need to be virtual.
|
||||||
~String() {
|
~String() { delete[] c_str_; }
|
||||||
delete data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allows a String to be implicitly converted to an ::std::string or
|
// Allows a String to be implicitly converted to an ::std::string or
|
||||||
// ::string, and vice versa. Converting a String containing a NULL
|
// ::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
|
// Returns the length of the encapsulated string, or 0 if the
|
||||||
// string is NULL.
|
// 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.
|
// Gets the 0-terminated C string this String object represents.
|
||||||
// The String object still owns the string. Therefore the caller
|
// The String object still owns the string. Therefore the caller
|
||||||
// should NOT delete the return value.
|
// 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.
|
// Assigns a C string to this object. Self-assignment works.
|
||||||
const String& operator=(const char* c_str) { return *this = String(c_str); }
|
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.
|
// Assigns a String object to this object. Self-assignment works.
|
||||||
const String& operator=(const String& rhs) {
|
const String& operator=(const String& rhs) {
|
||||||
if (this != &rhs) {
|
if (this != &rhs) {
|
||||||
delete data_;
|
delete[] c_str_;
|
||||||
data_ = NULL;
|
if (rhs.c_str() == NULL) {
|
||||||
if (rhs.data_ != NULL) {
|
c_str_ = NULL;
|
||||||
ConstructNonNull(rhs.data_->c_str_, rhs.data_->length_);
|
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, 0) results in an empty string ("").
|
||||||
// ConstructNonNull(NULL, non_zero) is undefined behavior.
|
// ConstructNonNull(NULL, non_zero) is undefined behavior.
|
||||||
void ConstructNonNull(const char* buffer, size_t length) {
|
void ConstructNonNull(const char* buffer, size_t length) {
|
||||||
data_ = new StringData;
|
|
||||||
char* const str = new char[length + 1];
|
char* const str = new char[length + 1];
|
||||||
memcpy(str, buffer, length);
|
memcpy(str, buffer, length);
|
||||||
str[length] = '\0';
|
str[length] = '\0';
|
||||||
data_->c_str_ = str;
|
c_str_ = str;
|
||||||
data_->length_ = length;
|
length_ = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Points to the representation of the String. A NULL String is
|
const char* c_str_;
|
||||||
// represented by data_ == NULL.
|
size_t length_;
|
||||||
StringData* data_;
|
|
||||||
}; // class String
|
}; // class String
|
||||||
|
|
||||||
// Streams a String to an ostream. Each '\0' character in the String
|
// Streams a String to an ostream. Each '\0' character in the String
|
||||||
|
|
|
@ -318,8 +318,9 @@ GtestTest(env, 'gtest_list_tests_unittest_', gtest)
|
||||||
GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
|
GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
|
||||||
GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
|
GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
|
||||||
GtestTest(env, 'gtest_xml_outfile2_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-unittest-api_test', gtest)
|
||||||
|
GtestTest(env, 'gtest-listener_test', gtest)
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Tests targets using custom environments.
|
# Tests targets using custom environments.
|
||||||
|
|
|
@ -469,7 +469,8 @@ bool DeathTestImpl::Passed(bool status_ok) {
|
||||||
break;
|
break;
|
||||||
case DIED:
|
case DIED:
|
||||||
if (status_ok) {
|
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;
|
success = true;
|
||||||
} else {
|
} else {
|
||||||
buffer << " Result: died but not with expected error.\n"
|
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
|
// concurrent writes to the log files. We capture stderr in the parent
|
||||||
// process and append the child process' output to a log.
|
// process and append the child process' output to a log.
|
||||||
LogToStderr();
|
LogToStderr();
|
||||||
|
// Event forwarding to the listeners of event listener API mush be shut
|
||||||
|
// down in death test subprocesses.
|
||||||
|
GetUnitTestImpl()->listeners()->SuppressEventForwarding();
|
||||||
return EXECUTE_TEST;
|
return EXECUTE_TEST;
|
||||||
} else {
|
} else {
|
||||||
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));
|
||||||
|
|
|
@ -741,6 +741,9 @@ class UnitTestImpl {
|
||||||
return test_cases_.GetElementOr(i, NULL);
|
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
|
// Returns the TestResult for the test that's currently running, or
|
||||||
// the TestResult for the ad hoc test if no test is running.
|
// the TestResult for the ad hoc test if no test is running.
|
||||||
TestResult* current_test_result();
|
TestResult* current_test_result();
|
||||||
|
@ -748,18 +751,6 @@ class UnitTestImpl {
|
||||||
// Returns the TestResult for the ad hoc test.
|
// Returns the TestResult for the ad hoc test.
|
||||||
const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
|
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.
|
// Sets the OS stack trace getter.
|
||||||
//
|
//
|
||||||
// Does nothing if the input and the current 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
|
#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
|
// Returns a pointer to the parsed --gtest_internal_run_death_test
|
||||||
// flag, or NULL if that flag was not specified.
|
// flag, or NULL if that flag was not specified.
|
||||||
// This information is useful only in a death test child process.
|
// 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 {
|
const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
|
||||||
return internal_run_death_test_flag_.get();
|
return internal_run_death_test_flag_.get();
|
||||||
}
|
}
|
||||||
|
@ -919,9 +914,22 @@ class UnitTestImpl {
|
||||||
return death_test_factory_.get();
|
return death_test_factory_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SuppressTestEventsIfInSubprocess();
|
||||||
|
|
||||||
friend class ReplaceDeathTestFactory;
|
friend class ReplaceDeathTestFactory;
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#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.
|
// Gets the random seed used at the start of the current test run.
|
||||||
int random_seed() const { return random_seed_; }
|
int random_seed() const { return random_seed_; }
|
||||||
|
|
||||||
|
@ -992,11 +1000,9 @@ class UnitTestImpl {
|
||||||
// test, and records the result in ad_hoc_test_result_.
|
// test, and records the result in ad_hoc_test_result_.
|
||||||
TestResult ad_hoc_test_result_;
|
TestResult ad_hoc_test_result_;
|
||||||
|
|
||||||
// The unit test result printer. Will be deleted when the UnitTest
|
// The list of event listeners that can be used to track events inside
|
||||||
// object is destructed. By default, a plain text printer is used,
|
// Google Test.
|
||||||
// but the user can set this field to use a custom printer if that
|
EventListeners listeners_;
|
||||||
// is desired.
|
|
||||||
UnitTestEventListenerInterface* result_printer_;
|
|
||||||
|
|
||||||
// The OS stack trace getter. Will be deleted when the UnitTest
|
// The OS stack trace getter. Will be deleted when the UnitTest
|
||||||
// object is destructed. By default, an OsStackTraceGetter is used,
|
// object is destructed. By default, an OsStackTraceGetter is used,
|
||||||
|
@ -1004,6 +1010,9 @@ class UnitTestImpl {
|
||||||
// desired.
|
// desired.
|
||||||
OsStackTraceGetterInterface* os_stack_trace_getter_;
|
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.
|
// The random number seed used at the beginning of the test run.
|
||||||
int random_seed_;
|
int random_seed_;
|
||||||
|
|
||||||
|
|
445
src/gtest.cc
445
src/gtest.cc
|
@ -129,9 +129,12 @@
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
using internal::EventListeners;
|
||||||
|
using internal::EmptyTestEventListener;
|
||||||
using internal::TestCase;
|
using internal::TestCase;
|
||||||
using internal::TestProperty;
|
using internal::TestProperty;
|
||||||
using internal::TestResult;
|
using internal::TestResult;
|
||||||
|
using internal::UnitTestEventListenerInterface;
|
||||||
|
|
||||||
// Constants.
|
// Constants.
|
||||||
|
|
||||||
|
@ -303,14 +306,18 @@ static bool ShouldRunTestCase(const TestCase* test_case) {
|
||||||
// AssertHelper constructor.
|
// AssertHelper constructor.
|
||||||
AssertHelper::AssertHelper(TestPartResultType type, const char* file,
|
AssertHelper::AssertHelper(TestPartResultType type, const char* file,
|
||||||
int line, const char* message)
|
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.
|
// Message assignment, for assertion streaming support.
|
||||||
void AssertHelper::operator=(const Message& message) const {
|
void AssertHelper::operator=(const Message& message) const {
|
||||||
UnitTest::GetInstance()->
|
UnitTest::GetInstance()->
|
||||||
AddTestPartResult(type_, file_, line_,
|
AddTestPartResult(data_->type, data_->file, data_->line,
|
||||||
AppendUserMessage(message_, message),
|
AppendUserMessage(data_->message, message),
|
||||||
UnitTest::GetInstance()->impl()
|
UnitTest::GetInstance()->impl()
|
||||||
->CurrentOsStackTraceExceptTop(1)
|
->CurrentOsStackTraceExceptTop(1)
|
||||||
// Skips the stack frame for this function itself.
|
// Skips the stack frame for this function itself.
|
||||||
|
@ -476,86 +483,6 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
|
||||||
|
|
||||||
} // namespace internal
|
} // 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
|
// The c'tor sets this object as the test part result reporter used by
|
||||||
// Google Test. The 'result' parameter specifies where to report the
|
// Google Test. The 'result' parameter specifies where to report the
|
||||||
// results. Intercepts only failures from the current thread.
|
// results. Intercepts only failures from the current thread.
|
||||||
|
@ -690,7 +617,7 @@ DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
|
||||||
void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
|
void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
|
||||||
const TestPartResult& result) {
|
const TestPartResult& result) {
|
||||||
unit_test_->current_test_result()->AddTestPartResult(result);
|
unit_test_->current_test_result()->AddTestPartResult(result);
|
||||||
unit_test_->result_printer()->OnNewTestPartResult(result);
|
unit_test_->listeners()->repeater()->OnNewTestPartResult(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
|
DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
|
||||||
|
@ -1738,28 +1665,38 @@ bool String::EndsWithCaseInsensitive(const char* suffix) const {
|
||||||
// available.
|
// available.
|
||||||
//
|
//
|
||||||
// The result is limited to 4096 characters (including the tailing 0).
|
// The result is limited to 4096 characters (including the tailing 0).
|
||||||
// If 4096 characters are not enough to format the input,
|
// If 4096 characters are not enough to format the input, or if
|
||||||
// "<buffer exceeded>" is returned.
|
// there's an error, "<formatting error or buffer exceeded>" is
|
||||||
|
// returned.
|
||||||
String String::Format(const char * format, ...) {
|
String String::Format(const char * format, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
|
||||||
|
|
||||||
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
|
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
|
||||||
// 4996 (deprecated function) there.
|
// 4996 (deprecated function) there.
|
||||||
#ifdef _MSC_VER // We are using MSVC.
|
#ifdef _MSC_VER // We are using MSVC.
|
||||||
#pragma warning(push) // Saves the current warning state.
|
#pragma warning(push) // Saves the current warning state.
|
||||||
#pragma warning(disable:4996) // Temporarily disables warning 4996.
|
#pragma warning(disable:4996) // Temporarily disables warning 4996.
|
||||||
const int size =
|
const int size = vsnprintf(buffer, kBufferSize, format, args);
|
||||||
vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
|
|
||||||
#pragma warning(pop) // Restores the warning state.
|
#pragma warning(pop) // Restores the warning state.
|
||||||
#else // We are not using MSVC.
|
#else // We are not using MSVC.
|
||||||
const int size =
|
const int size = vsnprintf(buffer, kBufferSize, format, args);
|
||||||
vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
|
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
va_end(args);
|
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
|
// Converts the buffer in a StrStream to a String, converting NUL
|
||||||
|
@ -2297,11 +2234,11 @@ void TestInfoImpl::Run() {
|
||||||
UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
||||||
impl->set_current_test_info(parent_);
|
impl->set_current_test_info(parent_);
|
||||||
|
|
||||||
// Notifies the unit test event listener that a test is about to
|
UnitTestEventListenerInterface* repeater =
|
||||||
// start.
|
UnitTest::GetInstance()->listeners().repeater();
|
||||||
UnitTestEventListenerInterface* const result_printer =
|
|
||||||
impl->result_printer();
|
// Notifies the unit test event listeners that a test is about to start.
|
||||||
result_printer->OnTestStart(*parent_);
|
repeater->OnTestStart(*parent_);
|
||||||
|
|
||||||
const TimeInMillis start = GetTimeInMillis();
|
const TimeInMillis start = GetTimeInMillis();
|
||||||
|
|
||||||
|
@ -2344,7 +2281,7 @@ void TestInfoImpl::Run() {
|
||||||
result_.set_elapsed_time(GetTimeInMillis() - start);
|
result_.set_elapsed_time(GetTimeInMillis() - start);
|
||||||
|
|
||||||
// Notifies the unit test event listener that a test has just finished.
|
// 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
|
// Tells UnitTest to stop associating assertion results to this
|
||||||
// test.
|
// test.
|
||||||
|
@ -2425,10 +2362,10 @@ void TestCase::Run() {
|
||||||
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
|
||||||
impl->set_current_test_case(this);
|
impl->set_current_test_case(this);
|
||||||
|
|
||||||
UnitTestEventListenerInterface * const result_printer =
|
UnitTestEventListenerInterface* repeater =
|
||||||
impl->result_printer();
|
UnitTest::GetInstance()->listeners().repeater();
|
||||||
|
|
||||||
result_printer->OnTestCaseStart(*this);
|
repeater->OnTestCaseStart(*this);
|
||||||
impl->os_stack_trace_getter()->UponLeavingGTest();
|
impl->os_stack_trace_getter()->UponLeavingGTest();
|
||||||
set_up_tc_();
|
set_up_tc_();
|
||||||
|
|
||||||
|
@ -2438,7 +2375,7 @@ void TestCase::Run() {
|
||||||
|
|
||||||
impl->os_stack_trace_getter()->UponLeavingGTest();
|
impl->os_stack_trace_getter()->UponLeavingGTest();
|
||||||
tear_down_tc_();
|
tear_down_tc_();
|
||||||
result_printer->OnTestCaseEnd(*this);
|
repeater->OnTestCaseEnd(*this);
|
||||||
impl->set_current_test_case(NULL);
|
impl->set_current_test_case(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2471,10 +2408,6 @@ bool TestCase::ShouldRunTest(const TestInfo *test_info) {
|
||||||
|
|
||||||
} // namespace internal
|
} // 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
|
// Formats a countable noun. Depending on its quantity, either the
|
||||||
// singular form or the plural form is used. e.g.
|
// singular form or the plural form is used. e.g.
|
||||||
//
|
//
|
||||||
|
@ -2663,14 +2596,6 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
|
||||||
va_end(args);
|
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.
|
// This class implements the UnitTestEventListenerInterface interface.
|
||||||
//
|
//
|
||||||
// Class PrettyUnitTestResultPrinter is copyable.
|
// Class PrettyUnitTestResultPrinter is copyable.
|
||||||
|
@ -2888,10 +2813,16 @@ void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
|
||||||
// This class forwards events to other event listeners.
|
// This class forwards events to other event listeners.
|
||||||
class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
|
class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
|
||||||
public:
|
public:
|
||||||
typedef internal::Vector<UnitTestEventListenerInterface *> Listeners;
|
UnitTestEventsRepeater() : forwarding_enabled_(true) {}
|
||||||
UnitTestEventsRepeater() {}
|
|
||||||
virtual ~UnitTestEventsRepeater();
|
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 OnUnitTestStart(const UnitTest& unit_test);
|
||||||
virtual void OnUnitTestEnd(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);
|
virtual void OnNewTestPartResult(const TestPartResult& result);
|
||||||
|
|
||||||
private:
|
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);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestEventsRepeater);
|
||||||
};
|
};
|
||||||
|
@ -2917,18 +2852,32 @@ UnitTestEventsRepeater::~UnitTestEventsRepeater() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitTestEventsRepeater::AddListener(
|
void UnitTestEventsRepeater::Append(UnitTestEventListenerInterface *listener) {
|
||||||
UnitTestEventListenerInterface *listener) {
|
|
||||||
listeners_.PushBack(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.
|
// Since the methods are identical, use a macro to reduce boilerplate.
|
||||||
// This defines a member that repeats the call to all listeners.
|
// This defines a member that repeats the call to all listeners.
|
||||||
#define GTEST_REPEATER_METHOD_(Name, Type) \
|
#define GTEST_REPEATER_METHOD_(Name, Type) \
|
||||||
void UnitTestEventsRepeater::Name(const Type& parameter) { \
|
void UnitTestEventsRepeater::Name(const Type& parameter) { \
|
||||||
|
if (forwarding_enabled_) { \
|
||||||
for (int i = 0; i < listeners_.size(); i++) { \
|
for (int i = 0; i < listeners_.size(); i++) { \
|
||||||
listeners_.GetElement(i)->Name(parameter); \
|
listeners_.GetElement(i)->Name(parameter); \
|
||||||
} \
|
} \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
GTEST_REPEATER_METHOD_(OnUnitTestStart, UnitTest)
|
GTEST_REPEATER_METHOD_(OnUnitTestStart, UnitTest)
|
||||||
|
@ -2945,7 +2894,7 @@ GTEST_REPEATER_METHOD_(OnNewTestPartResult, TestPartResult)
|
||||||
|
|
||||||
#undef GTEST_REPEATER_METHOD_
|
#undef GTEST_REPEATER_METHOD_
|
||||||
|
|
||||||
// End PrettyUnitTestResultPrinter
|
// End UnitTestEventsRepeater
|
||||||
|
|
||||||
// This class generates an XML output file.
|
// This class generates an XML output file.
|
||||||
class XmlUnitTestResultPrinter : public EmptyTestEventListener {
|
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
|
// is_attribute is true, the text is meant to appear as an attribute
|
||||||
// value, and normalizable whitespace is preserved by replacing it
|
// value, and normalizable whitespace is preserved by replacing it
|
||||||
// with character references.
|
// with character references.
|
||||||
static internal::String EscapeXml(const char* str,
|
static String EscapeXml(const char* str, bool is_attribute);
|
||||||
bool is_attribute);
|
|
||||||
|
|
||||||
// Convenience wrapper around EscapeXml when str is an attribute value.
|
// 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);
|
return EscapeXml(str, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convenience wrapper around EscapeXml when str is not an attribute value.
|
// Convenience wrapper around EscapeXml when str is not an attribute value.
|
||||||
static internal::String EscapeXmlText(const char* str) {
|
static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
|
||||||
return EscapeXml(str, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints an XML representation of a TestInfo object.
|
// Prints an XML representation of a TestInfo object.
|
||||||
static void PrintXmlTestInfo(FILE* out,
|
static void PrintXmlTestInfo(FILE* out,
|
||||||
|
@ -2998,11 +2944,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
|
||||||
// delimited XML attributes based on the property key="value" pairs.
|
// delimited XML attributes based on the property key="value" pairs.
|
||||||
// When the String is not empty, it includes a space at the beginning,
|
// When the String is not empty, it includes a space at the beginning,
|
||||||
// to delimit this attribute from prior attributes.
|
// to delimit this attribute from prior attributes.
|
||||||
static internal::String TestPropertiesAsXmlAttributes(
|
static String TestPropertiesAsXmlAttributes(const TestResult& result);
|
||||||
const TestResult& result);
|
|
||||||
|
|
||||||
// The output file.
|
// The output file.
|
||||||
const internal::String output_file_;
|
const String output_file_;
|
||||||
|
|
||||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
|
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
|
||||||
};
|
};
|
||||||
|
@ -3020,11 +2965,11 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
|
||||||
// Called after the unit test ends.
|
// Called after the unit test ends.
|
||||||
void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
|
void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
|
||||||
FILE* xmlout = NULL;
|
FILE* xmlout = NULL;
|
||||||
internal::FilePath output_file(output_file_);
|
FilePath output_file(output_file_);
|
||||||
internal::FilePath output_dir(output_file.RemoveFileName());
|
FilePath output_dir(output_file.RemoveFileName());
|
||||||
|
|
||||||
if (output_dir.CreateDirectoriesRecursively()) {
|
if (output_dir.CreateDirectoriesRecursively()) {
|
||||||
xmlout = internal::posix::FOpen(output_file_.c_str(), "w");
|
xmlout = posix::FOpen(output_file_.c_str(), "w");
|
||||||
}
|
}
|
||||||
if (xmlout == NULL) {
|
if (xmlout == NULL) {
|
||||||
// TODO(wan): report the reason of the failure.
|
// 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.
|
// most invalid characters can be retained using character references.
|
||||||
// TODO(wan): It might be nice to have a minimally invasive, human-readable
|
// TODO(wan): It might be nice to have a minimally invasive, human-readable
|
||||||
// escaping scheme for invalid characters, rather than dropping them.
|
// escaping scheme for invalid characters, rather than dropping them.
|
||||||
internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
|
String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
|
||||||
bool is_attribute) {
|
|
||||||
Message m;
|
Message m;
|
||||||
|
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
|
@ -3090,7 +3034,7 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
|
||||||
default:
|
default:
|
||||||
if (IsValidXmlCharacter(*src)) {
|
if (IsValidXmlCharacter(*src)) {
|
||||||
if (is_attribute && IsNormalizableWhitespace(*src))
|
if (is_attribute && IsNormalizableWhitespace(*src))
|
||||||
m << internal::String::Format("&#x%02X;", unsigned(*src));
|
m << String::Format("&#x%02X;", unsigned(*src));
|
||||||
else
|
else
|
||||||
m << *src;
|
m << *src;
|
||||||
}
|
}
|
||||||
|
@ -3102,7 +3046,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
|
||||||
return m.GetString();
|
return m.GetString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The following routines generate an XML representation of a UnitTest
|
// The following routines generate an XML representation of a UnitTest
|
||||||
// object.
|
// object.
|
||||||
//
|
//
|
||||||
|
@ -3119,8 +3062,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
|
||||||
// </testsuite>
|
// </testsuite>
|
||||||
// </testsuites>
|
// </testsuites>
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Formats the given time in milliseconds as seconds. The returned
|
// Formats the given time in milliseconds as seconds. The returned
|
||||||
// C-string is owned by this function and cannot be released by the
|
// C-string is owned by this function and cannot be released by the
|
||||||
// caller. Calling the function again invalidates the previous
|
// caller. Calling the function again invalidates the previous
|
||||||
|
@ -3131,8 +3072,6 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
|
||||||
return str.c_str();
|
return str.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
// Prints an XML representation of a TestInfo object.
|
// Prints an XML representation of a TestInfo object.
|
||||||
// TODO(wan): There is also value in printing properties with the plain printer.
|
// TODO(wan): There is also value in printing properties with the plain printer.
|
||||||
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
|
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
|
||||||
|
@ -3144,7 +3083,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
|
||||||
"classname=\"%s\"%s",
|
"classname=\"%s\"%s",
|
||||||
EscapeXmlAttribute(test_info.name()).c_str(),
|
EscapeXmlAttribute(test_info.name()).c_str(),
|
||||||
test_info.should_run() ? "run" : "notrun",
|
test_info.should_run() ? "run" : "notrun",
|
||||||
internal::FormatTimeInMillisAsSeconds(result.elapsed_time()),
|
FormatTimeInMillisAsSeconds(result.elapsed_time()),
|
||||||
EscapeXmlAttribute(test_case_name).c_str(),
|
EscapeXmlAttribute(test_case_name).c_str(),
|
||||||
TestPropertiesAsXmlAttributes(result).c_str());
|
TestPropertiesAsXmlAttributes(result).c_str());
|
||||||
|
|
||||||
|
@ -3152,8 +3091,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
|
||||||
for (int i = 0; i < result.total_part_count(); ++i) {
|
for (int i = 0; i < result.total_part_count(); ++i) {
|
||||||
const TestPartResult& part = result.GetTestPartResult(i);
|
const TestPartResult& part = result.GetTestPartResult(i);
|
||||||
if (part.failed()) {
|
if (part.failed()) {
|
||||||
const internal::String message =
|
const String message = String::Format("%s:%d\n%s", part.file_name(),
|
||||||
internal::String::Format("%s:%d\n%s", part.file_name(),
|
|
||||||
part.line_number(), part.message());
|
part.line_number(), part.message());
|
||||||
if (++failures == 1)
|
if (++failures == 1)
|
||||||
fprintf(out, ">\n");
|
fprintf(out, ">\n");
|
||||||
|
@ -3182,7 +3120,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
|
||||||
test_case.disabled_test_count());
|
test_case.disabled_test_count());
|
||||||
fprintf(out,
|
fprintf(out,
|
||||||
"errors=\"0\" time=\"%s\">\n",
|
"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)
|
for (int i = 0; i < test_case.total_test_count(); ++i)
|
||||||
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
|
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
|
||||||
fprintf(out, " </testsuite>\n");
|
fprintf(out, " </testsuite>\n");
|
||||||
|
@ -3198,7 +3136,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
|
||||||
unit_test.total_test_count(),
|
unit_test.total_test_count(),
|
||||||
unit_test.failed_test_count(),
|
unit_test.failed_test_count(),
|
||||||
unit_test.disabled_test_count(),
|
unit_test.disabled_test_count(),
|
||||||
internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
|
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
|
||||||
if (GTEST_FLAG(shuffle)) {
|
if (GTEST_FLAG(shuffle)) {
|
||||||
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
|
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
|
// Produces a string representing the test properties in a result as space
|
||||||
// delimited XML attributes based on the property key="value" pairs.
|
// delimited XML attributes based on the property key="value" pairs.
|
||||||
internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
|
String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
|
||||||
const TestResult& result) {
|
const TestResult& result) {
|
||||||
Message attributes;
|
Message attributes;
|
||||||
for (int i = 0; i < result.test_property_count(); ++i) {
|
for (int i = 0; i < result.test_property_count(); ++i) {
|
||||||
|
@ -3223,8 +3161,6 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
|
||||||
|
|
||||||
// End XmlUnitTestResultPrinter
|
// End XmlUnitTestResultPrinter
|
||||||
|
|
||||||
namespace internal {
|
|
||||||
|
|
||||||
// Class ScopedTrace
|
// Class ScopedTrace
|
||||||
|
|
||||||
// Pushes the given source file location and message onto a per-thread
|
// Pushes the given source file location and message onto a per-thread
|
||||||
|
@ -3271,6 +3207,84 @@ OsStackTraceGetter::kElidedFramesMarker =
|
||||||
|
|
||||||
} // namespace internal
|
} // 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
|
// class UnitTest
|
||||||
|
|
||||||
// Gets the singleton UnitTest object. The first time this method is
|
// 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);
|
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
|
// Registers and returns a global test environment. When a test
|
||||||
// program is run, all global test environments will be set-up in the
|
// program is run, all global test environments will be set-up in the
|
||||||
// order they were registered. After all tests in the program have
|
// 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_case_(NULL),
|
||||||
current_test_info_(NULL),
|
current_test_info_(NULL),
|
||||||
ad_hoc_test_result_(),
|
ad_hoc_test_result_(),
|
||||||
result_printer_(NULL),
|
|
||||||
os_stack_trace_getter_(NULL),
|
os_stack_trace_getter_(NULL),
|
||||||
|
post_flag_parse_init_performed_(false),
|
||||||
random_seed_(0),
|
random_seed_(0),
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
elapsed_time_(0),
|
elapsed_time_(0),
|
||||||
|
@ -3624,6 +3644,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
|
||||||
#else
|
#else
|
||||||
elapsed_time_(0) {
|
elapsed_time_(0) {
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
|
||||||
}
|
}
|
||||||
|
|
||||||
UnitTestImpl::~UnitTestImpl() {
|
UnitTestImpl::~UnitTestImpl() {
|
||||||
|
@ -3633,12 +3654,58 @@ UnitTestImpl::~UnitTestImpl() {
|
||||||
// Deletes every Environment.
|
// Deletes every Environment.
|
||||||
environments_.ForEach(internal::Delete<Environment>);
|
environments_.ForEach(internal::Delete<Environment>);
|
||||||
|
|
||||||
// Deletes the current test result printer.
|
|
||||||
delete result_printer_;
|
|
||||||
|
|
||||||
delete os_stack_trace_getter_;
|
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
|
// A predicate that checks the name of a TestCase against a known
|
||||||
// value.
|
// value.
|
||||||
//
|
//
|
||||||
|
@ -3726,7 +3793,8 @@ int UnitTestImpl::RunAllTests() {
|
||||||
if (g_help_flag)
|
if (g_help_flag)
|
||||||
return 0;
|
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
|
// 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
|
// 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;
|
bool in_subprocess_for_death_test = false;
|
||||||
|
|
||||||
#if GTEST_HAS_DEATH_TEST
|
#if GTEST_HAS_DEATH_TEST
|
||||||
internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
|
|
||||||
in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
|
in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
|
||||||
#endif // GTEST_HAS_DEATH_TEST
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
UnitTestEventListenerInterface * const printer = result_printer();
|
|
||||||
|
|
||||||
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
|
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
|
||||||
in_subprocess_for_death_test);
|
in_subprocess_for_death_test);
|
||||||
|
|
||||||
|
@ -3766,6 +3831,8 @@ int UnitTestImpl::RunAllTests() {
|
||||||
// True iff at least one test has failed.
|
// True iff at least one test has failed.
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
|
UnitTestEventListenerInterface* repeater = listeners()->repeater();
|
||||||
|
|
||||||
// How many times to repeat the tests? We don't want to repeat them
|
// How many times to repeat the tests? We don't want to repeat them
|
||||||
// when we are inside the subprocess of a death test.
|
// when we are inside the subprocess of a death test.
|
||||||
const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
|
const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
|
||||||
|
@ -3773,21 +3840,24 @@ int UnitTestImpl::RunAllTests() {
|
||||||
const bool forever = repeat < 0;
|
const bool forever = repeat < 0;
|
||||||
for (int i = 0; forever || i != repeat; i++) {
|
for (int i = 0; forever || i != repeat; i++) {
|
||||||
if (repeat != 1) {
|
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);
|
printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tells the unit test event listener that the tests are about to
|
// Tells the unit test event listeners that the tests are about to start.
|
||||||
// start.
|
repeater->OnUnitTestStart(*parent_);
|
||||||
printer->OnUnitTestStart(*parent_);
|
|
||||||
|
|
||||||
|
// TODO(vladl@google.com): Move to before the OnUnitTestStart notification?
|
||||||
const TimeInMillis start = GetTimeInMillis();
|
const TimeInMillis start = GetTimeInMillis();
|
||||||
|
|
||||||
// Runs each test case if there is at least one test to run.
|
// Runs each test case if there is at least one test to run.
|
||||||
if (has_tests_to_run) {
|
if (has_tests_to_run) {
|
||||||
// Sets up all environments beforehand.
|
// Sets up all environments beforehand.
|
||||||
printer->OnGlobalSetUpStart(*parent_);
|
repeater->OnGlobalSetUpStart(*parent_);
|
||||||
environments_.ForEach(SetUpEnvironment);
|
environments_.ForEach(SetUpEnvironment);
|
||||||
printer->OnGlobalSetUpEnd(*parent_);
|
repeater->OnGlobalSetUpEnd(*parent_);
|
||||||
|
|
||||||
// Runs the tests only if there was no fatal failure during global
|
// Runs the tests only if there was no fatal failure during global
|
||||||
// set-up.
|
// set-up.
|
||||||
|
@ -3796,16 +3866,15 @@ int UnitTestImpl::RunAllTests() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tears down all environments in reverse order afterwards.
|
// Tears down all environments in reverse order afterwards.
|
||||||
printer->OnGlobalTearDownStart(*parent_);
|
repeater->OnGlobalTearDownStart(*parent_);
|
||||||
environments_in_reverse_order_.ForEach(TearDownEnvironment);
|
environments_in_reverse_order_.ForEach(TearDownEnvironment);
|
||||||
printer->OnGlobalTearDownEnd(*parent_);
|
repeater->OnGlobalTearDownEnd(*parent_);
|
||||||
}
|
}
|
||||||
|
|
||||||
elapsed_time_ = GetTimeInMillis() - start;
|
elapsed_time_ = GetTimeInMillis() - start;
|
||||||
|
|
||||||
// Tells the unit test event listener that the tests have just
|
// Tells the unit test event listener that the tests have just finished.
|
||||||
// finished.
|
repeater->OnUnitTestEnd(*parent_);
|
||||||
printer->OnUnitTestEnd(*parent_);
|
|
||||||
|
|
||||||
// Gets the result and clears it.
|
// Gets the result and clears it.
|
||||||
if (!Passed()) {
|
if (!Passed()) {
|
||||||
|
@ -3997,49 +4066,6 @@ void UnitTestImpl::ListTestsMatchingFilter() {
|
||||||
fflush(stdout);
|
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.
|
// Sets the OS stack trace getter.
|
||||||
//
|
//
|
||||||
// Does nothing if the input and the current OS stack trace getter are
|
// 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
|
#endif // GTEST_HAS_DEATH_TEST
|
||||||
|
|
||||||
ParseGoogleTestFlagsOnly(argc, argv);
|
ParseGoogleTestFlagsOnly(argc, argv);
|
||||||
|
GetUnitTestImpl()->PostFlagParsingInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
230
test/gtest-listener_test.cc
Normal file
230
test/gtest-listener_test.cc
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -85,7 +85,7 @@ class GTestEnvVarTest(gtest_test_utils.TestCase):
|
||||||
TestFlag('break_on_failure', '1', '0')
|
TestFlag('break_on_failure', '1', '0')
|
||||||
TestFlag('color', 'yes', 'auto')
|
TestFlag('color', 'yes', 'auto')
|
||||||
TestFlag('filter', 'FooTest.Bar', '*')
|
TestFlag('filter', 'FooTest.Bar', '*')
|
||||||
TestFlag('output', 'tmp/foo.xml', '')
|
TestFlag('output', 'xml:tmp/foo.xml', '')
|
||||||
TestFlag('print_time', '0', '1')
|
TestFlag('print_time', '0', '1')
|
||||||
TestFlag('repeat', '999', '1')
|
TestFlag('repeat', '999', '1')
|
||||||
TestFlag('throw_on_failure', '1', '0')
|
TestFlag('throw_on_failure', '1', '0')
|
||||||
|
|
|
@ -84,11 +84,38 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
|
||||||
|
|
||||||
bool ParseInt32Flag(const char* str, const char* flag, Int32* value);
|
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 internal
|
||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
using testing::internal::FormatTimeInMillisAsSeconds;
|
using testing::internal::FormatTimeInMillisAsSeconds;
|
||||||
using testing::internal::ParseInt32Flag;
|
using testing::internal::ParseInt32Flag;
|
||||||
|
using testing::internal::EventListenersAccessor;
|
||||||
|
|
||||||
namespace testing {
|
namespace testing {
|
||||||
|
|
||||||
|
@ -136,7 +163,9 @@ using testing::internal::kMaxRandomSeed;
|
||||||
using testing::internal::kTestTypeIdInGoogleTest;
|
using testing::internal::kTestTypeIdInGoogleTest;
|
||||||
using testing::internal::AppendUserMessage;
|
using testing::internal::AppendUserMessage;
|
||||||
using testing::internal::CodePointToUtf8;
|
using testing::internal::CodePointToUtf8;
|
||||||
|
using testing::internal::EmptyTestEventListener;
|
||||||
using testing::internal::EqFailure;
|
using testing::internal::EqFailure;
|
||||||
|
using testing::internal::EventListeners;
|
||||||
using testing::internal::FloatingPoint;
|
using testing::internal::FloatingPoint;
|
||||||
using testing::internal::GTestFlagSaver;
|
using testing::internal::GTestFlagSaver;
|
||||||
using testing::internal::GetCurrentOsStackTraceExceptTop;
|
using testing::internal::GetCurrentOsStackTraceExceptTop;
|
||||||
|
@ -160,6 +189,7 @@ using testing::internal::ThreadLocal;
|
||||||
using testing::internal::Vector;
|
using testing::internal::Vector;
|
||||||
using testing::internal::WideStringToUtf8;
|
using testing::internal::WideStringToUtf8;
|
||||||
using testing::internal::kTestTypeIdInGoogleTest;
|
using testing::internal::kTestTypeIdInGoogleTest;
|
||||||
|
using testing::internal::scoped_ptr;
|
||||||
|
|
||||||
// This line tests that we can define tests in an unnamed namespace.
|
// This line tests that we can define tests in an unnamed namespace.
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -695,14 +725,16 @@ TEST(ListDeathTest, GetElement) {
|
||||||
"Invalid Vector index -1: must be in range \\[0, 2\\]\\.");
|
"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
|
// To avoid breaking clients that use lots of assertions in one
|
||||||
// function, we cannot grow the size of String.
|
// function, we cannot grow the size of AssertHelper.
|
||||||
EXPECT_LE(sizeof(String), sizeof(void*));
|
EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests the String class.
|
||||||
|
|
||||||
// Tests String's constructors.
|
// Tests String's constructors.
|
||||||
TEST(StringTest, Constructors) {
|
TEST(StringTest, Constructors) {
|
||||||
// Default ctor.
|
// Default ctor.
|
||||||
|
@ -1037,6 +1069,33 @@ TEST(StringTest, Streams) {
|
||||||
EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
|
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
|
#if GTEST_OS_WINDOWS
|
||||||
|
|
||||||
// Tests String::ShowWideCString().
|
// Tests String::ShowWideCString().
|
||||||
|
@ -6142,3 +6201,275 @@ TEST(HasFailureTest, WorksOutsideOfTestBody2) {
|
||||||
ClearCurrentTestPartResults();
|
ClearCurrentTestPartResults();
|
||||||
EXPECT_TRUE(has_failure);
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import gtest_xml_test_utils
|
||||||
|
|
||||||
GTEST_OUTPUT_FLAG = "--gtest_output"
|
GTEST_OUTPUT_FLAG = "--gtest_output"
|
||||||
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
|
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
|
||||||
|
GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
|
||||||
|
|
||||||
SUPPORTS_STACK_TRACES = False
|
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
|
Runs a test program that generates a non-empty XML output, and
|
||||||
tests that the XML output is expected.
|
tests that the XML output is expected.
|
||||||
"""
|
"""
|
||||||
self._TestXmlOutput("gtest_xml_output_unittest_",
|
self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
|
||||||
EXPECTED_NON_EMPTY_XML, 1)
|
|
||||||
|
|
||||||
def testEmptyXmlOutput(self):
|
def testEmptyXmlOutput(self):
|
||||||
"""
|
"""
|
||||||
|
@ -142,6 +142,35 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
|
||||||
self.assertEquals(0, p.exit_code)
|
self.assertEquals(0, p.exit_code)
|
||||||
self.assert_(os.path.isfile(output_file))
|
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):
|
def _TestXmlOutput(self, gtest_prog_name, expected_xml, expected_exit_code):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -40,6 +40,20 @@
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#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 {
|
class SuccessfulTest : public testing::Test {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,3 +132,17 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
|
||||||
TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
|
TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
|
||||||
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
|
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();
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user