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:
zhanyong.wan 2009-09-04 18:30:25 +00:00
parent 56a2e686e9
commit 16e9dd6e28
16 changed files with 1173 additions and 292 deletions

19
CHANGES
View File

@ -1,3 +1,20 @@
Changes for 1.4.0 (up to r300):
* New feature: the XML report format is closer to junitreport and can
be parsed by Hudson now.
* New feature: when a test runs under Visual Studio, its failures are
integrated in the IDE.
* New feature: /MD(d) versions of VC++ projects.
* New feature: elapsed time for the tests is printed by default.
* New feature: comes with a TR1 tuple implementation such that Boost
is no longer needed for Combine().
* New feature: EXPECT_DEATH_IF_SUPPORTED macro and friends.
* New feature: the Xcode project can now produce static gtest
libraries in addition to a framework.
* Compatibility fixes for Solaris, Cygwin, minGW, Windows Mobile,
Symbian, gcc, and C++Builder.
* Bug fixes and implementation clean-ups.
Changes for 1.3.0:
* New feature: death tests on Windows, Cygwin, and Mac.
@ -11,7 +28,7 @@ Changes for 1.3.0:
.cc file for easy deployment.
* New feature: support for distributing test functions to multiple
machines (requires support from the test runner).
* Bug fixes and implementation clean-up.
* Bug fixes and implementation clean-ups.
Changes for 1.2.1:

View File

@ -12,6 +12,8 @@ EXTRA_DIST = \
include/gtest/internal/gtest-param-util-generated.h.pump \
make/Makefile \
scons/SConscript \
scons/SConstruct \
scons/SConstruct.common \
scripts/fuse_gtest_files.py \
scripts/gen_gtest_pred_impl.py \
scripts/test/Makefile \
@ -24,10 +26,15 @@ EXTRA_DIST += \
msvc/gtest_color_test_.vcproj \
msvc/gtest_env_var_test_.vcproj \
msvc/gtest_environment_test.vcproj \
msvc/gtest_main-md.vcproj \
msvc/gtest_main.vcproj \
msvc/gtest-md.sln \
msvc/gtest-md.vcproj \
msvc/gtest_output_test_.vcproj \
msvc/gtest_prod_test-md.vcproj \
msvc/gtest_prod_test.vcproj \
msvc/gtest_uninitialized_test_.vcproj \
msvc/gtest_unittest-md.vcproj \
msvc/gtest_unittest.vcproj
# xcode project files
@ -36,9 +43,8 @@ EXTRA_DIST += \
xcode/Config/FrameworkTarget.xcconfig \
xcode/Config/General.xcconfig \
xcode/Config/ReleaseProject.xcconfig \
xcode/Config/StaticLibraryTarget.xcconfig \
xcode/Config/TestTarget.xcconfig \
xcode/Config/InternalTestTarget.xcconfig \
xcode/Config/InternalPythonTestTarget.xcconfig \
xcode/Resources/Info.plist \
xcode/Scripts/versiongenerate.py \
xcode/Scripts/runtests.sh \
@ -299,6 +305,11 @@ check_PROGRAMS += test/gtest-unittest-api_test
test_gtest_unittest_api_test_SOURCES = test/gtest-unittest-api_test.cc
test_gtest_unittest_api_test_LDADD = lib/libgtest_main.la
TESTS += test/gtest-listener_test
check_PROGRAMS += test/gtest-listener_test
test_gtest_listener_test_SOURCES = test/gtest-listener_test.cc
test_gtest_listener_test_LDADD = lib/libgtest_main.la
# Verifies that Google Test works when RTTI is disabled.
TESTS += test/gtest_no_rtti_test
check_PROGRAMS += test/gtest_no_rtti_test
@ -407,7 +418,7 @@ TESTS += test/gtest_xml_outfiles_test.py
check_PROGRAMS += test/gtest_xml_output_unittest_
test_gtest_xml_output_unittest__SOURCES = test/gtest_xml_output_unittest_.cc
test_gtest_xml_output_unittest__LDADD = lib/libgtest_main.la
test_gtest_xml_output_unittest__LDADD = lib/libgtest.la
check_SCRIPTS += test/gtest_xml_output_unittest.py
TESTS += test/gtest_xml_output_unittest.py

13
README
View File

@ -190,9 +190,16 @@ see 'gtest-config --help' for more detailed information.
g++ $(../../my_gtest_build/scripts/gtest-config ...) ...
### Windows ###
Open the gtest.sln file in the msvc/ folder using Visual Studio, and
you are ready to build Google Test the same way you build any Visual
Studio project.
The msvc\ folder contains two solutions with Visual C++ projects. Open the
gtest.sln or gtest-md.sln file using Visual Studio, and you are ready to
build Google Test the same way you build any Visual Studio project. Files
that have names ending with -md use DLL versions of Microsoft runtime
libraries (the /MD or the /MDd compiler option). Files without that suffix
use static versions of the runtime libraries (the /MT or the /MTd option).
Please note that one must use the same option to compile both gtest and his
test code. If you use Visual Studio 2005 or above, we recommend the -md
version as /MD is the default for new projects in these versions of Visual
Studio.
### Mac OS X (universal-binary framework) ###
Open the gtest.xcodeproj in the xcode/ folder using Xcode. Build the "gtest"

View File

@ -41,6 +41,9 @@ namespace testing {
// The possible outcomes of a test part (i.e. an assertion or an
// explicit SUCCEED(), FAIL(), or ADD_FAILURE()).
// TODO(vladl@google.com): Rename the enum values to kSuccess,
// kNonFatalFailure, and kFatalFailure before publishing the event listener
// API (see issue http://code.google.com/p/googletest/issues/detail?id=165).
enum TestPartResultType {
TPRT_SUCCESS, // Succeeded.
TPRT_NONFATAL_FAILURE, // Failed but the test can continue.

View File

@ -149,17 +149,23 @@ namespace internal {
class AssertHelper;
class DefaultGlobalTestPartResultReporter;
class EventListenersAccessor;
class ExecDeathTest;
class NoExecDeathTest;
class FinalSuccessChecker;
class GTestFlagSaver;
class TestCase;
class TestInfoImpl;
class TestResultAccessor;
class UnitTestAccessor;
// TODO(vladl@google.com): Rename to TestEventRepeater.
class UnitTestEventsRepeater;
class WindowsDeathTest;
class UnitTestImpl* GetUnitTestImpl();
void ReportFailureInUnknownLocation(TestPartResultType result_type,
const String& message);
class PrettyUnitTestResultPrinter;
class XmlUnitTestResultPrinter;
// Converts a streamable value to a String. A NULL pointer is
// converted to "(null)". When the input value is a ::string,
@ -766,6 +772,178 @@ class Environment {
virtual Setup_should_be_spelled_SetUp* Setup() { return NULL; }
};
namespace internal {
// TODO(vladl@google.com): Order the methods the way they are invoked by
// Google Test.
// The interface for tracing execution of tests.
class UnitTestEventListenerInterface {
public:
virtual ~UnitTestEventListenerInterface() {}
// TODO(vladl@google.com): Add events for test program start and test program
// end: OnTestIterationStart(const UnitTest&); // Start of one iteration.
// Add tests, too.
// TODO(vladl@google.com): Rename OnUnitTestStart() and OnUnitTestEnd() to
// OnTestProgramStart() and OnTestProgramEnd().
// Called before any test activity starts.
virtual void OnUnitTestStart(const UnitTest& unit_test) = 0;
// Called after all test activities have ended.
virtual void OnUnitTestEnd(const UnitTest& unit_test) = 0;
// Called before the test case starts.
virtual void OnTestCaseStart(const TestCase& test_case) = 0;
// Called after the test case ends.
virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
// TODO(vladl@google.com): Rename OnGlobalSetUpStart to
// OnEnvironmentsSetUpStart. Make similar changes for the rest of
// environment-related events.
// Called before the global set-up starts.
virtual void OnGlobalSetUpStart(const UnitTest& unit_test) = 0;
// Called after the global set-up ends.
virtual void OnGlobalSetUpEnd(const UnitTest& unit_test) = 0;
// Called before the global tear-down starts.
virtual void OnGlobalTearDownStart(const UnitTest& unit_test) = 0;
// Called after the global tear-down ends.
virtual void OnGlobalTearDownEnd(const UnitTest& unit_test) = 0;
// Called before the test starts.
virtual void OnTestStart(const TestInfo& test_info) = 0;
// Called after the test ends.
virtual void OnTestEnd(const TestInfo& test_info) = 0;
// Called after a failed assertion or a SUCCESS().
virtual void OnNewTestPartResult(const TestPartResult& test_part_result) = 0;
};
// The convenience class for users who need to override just one or two
// methods and are not concerned that a possible change to a signature of
// the methods they override will not be caught during the build.
class EmptyTestEventListener : public UnitTestEventListenerInterface {
public:
// Called before the unit test starts.
virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {}
// Called after the unit test ends.
virtual void OnUnitTestEnd(const UnitTest& /*unit_test*/) {}
// Called before the test case starts.
virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
// Called after the test case ends.
virtual void OnTestCaseEnd(const TestCase& /*test_case&*/) {}
// Called before the global set-up starts.
virtual void OnGlobalSetUpStart(const UnitTest& /*unit_test*/) {}
// Called after the global set-up ends.
virtual void OnGlobalSetUpEnd(const UnitTest& /*unit_test*/) {}
// Called before the global tear-down starts.
virtual void OnGlobalTearDownStart(const UnitTest& /*unit_test*/) {}
// Called after the global tear-down ends.
virtual void OnGlobalTearDownEnd(const UnitTest& /*unit_test*/) {}
// Called before the test starts.
virtual void OnTestStart(const TestInfo& /*test_info*/) {}
// Called after the test ends.
virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
// Called after a failed assertion or a SUCCESS().
virtual void OnNewTestPartResult(const TestPartResult& /*test_part_result*/) {
}
};
// EventListeners lets users add listeners to track events in Google Test.
class EventListeners {
public:
EventListeners();
~EventListeners();
// Appends an event listener to the end of the list. Google Test assumes
// the ownership of the listener (i.e. it will delete the listener when
// the test program finishes).
void Append(UnitTestEventListenerInterface* listener);
// Removes the given event listener from the list and returns it. It then
// becomes the caller's responsibility to delete the listener. Returns
// NULL if the listener is not found in the list.
UnitTestEventListenerInterface* Release(
UnitTestEventListenerInterface* listener);
// Returns the standard listener responsible for the default console
// output. Can be removed from the listeners list to shut down default
// console output. Note that removing this object from the listener list
// with Release transfers its ownership to the caller and makes this
// function return NULL the next time.
UnitTestEventListenerInterface* default_result_printer() const {
return default_result_printer_;
}
// Returns the standard listener responsible for the default XML output
// controlled by the --gtest_output=xml flag. Can be removed from the
// listeners list by users who want to shut down the default XML output
// controlled by this flag and substitute it with custom one. Note that
// removing this object from the listener list with Release transfers its
// ownership to the caller and makes this function return NULL the next
// time.
UnitTestEventListenerInterface* default_xml_generator() const {
return default_xml_generator_;
}
private:
friend class internal::DefaultGlobalTestPartResultReporter;
friend class internal::EventListenersAccessor;
friend class internal::NoExecDeathTest;
friend class internal::TestCase;
friend class internal::TestInfoImpl;
friend class internal::UnitTestImpl;
// Returns repeater that broadcasts the UnitTestEventListenerInterface
// events to all subscribers.
UnitTestEventListenerInterface* repeater();
// Sets the default_result_printer attribute to the provided listener.
// The listener is also added to the listener list and previous
// default_result_printer is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void SetDefaultResultPrinter(UnitTestEventListenerInterface* listener);
// Sets the default_xml_generator attribute to the provided listener. The
// listener is also added to the listener list and previous
// default_xml_generator is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void SetDefaultXmlGenerator(UnitTestEventListenerInterface* listener);
// Controls whether events will be forwarded by the repeater to the
// listeners in the list.
bool EventForwardingEnabled() const;
void SuppressEventForwarding();
// The actual list of listeners.
internal::UnitTestEventsRepeater* repeater_;
// Listener responsible for the standard result output.
UnitTestEventListenerInterface* default_result_printer_;
// Listener responsible for the creation of the XML output file.
UnitTestEventListenerInterface* default_xml_generator_;
// We disallow copying EventListeners.
GTEST_DISALLOW_COPY_AND_ASSIGN_(EventListeners);
};
} // namespace internal
// A UnitTest consists of a vector of TestCases.
//
// This is a singleton class. The only instance of UnitTest is
@ -886,6 +1064,10 @@ class UnitTest {
// total_test_case_count() - 1. If i is not in that range, returns NULL.
const internal::TestCase* GetTestCase(int i) const;
// Returns the list of event listeners that can be used to track events
// inside Google Test.
internal::EventListeners& listeners();
// ScopedTrace is a friend as it needs to modify the per-thread
// trace stack, which is a private member of UnitTest.
// TODO(vladl@google.com): Order all declarations according to the style
@ -899,9 +1081,12 @@ class UnitTest {
TestPartResultType result_type,
const internal::String& message);
// TODO(vladl@google.com): Remove these when publishing the new accessors.
friend class PrettyUnitTestResultPrinter;
friend class XmlUnitTestResultPrinter;
friend class internal::PrettyUnitTestResultPrinter;
friend class internal::TestCase;
friend class internal::TestInfoImpl;
friend class internal::UnitTestAccessor;
friend class internal::UnitTestImpl;
friend class internal::XmlUnitTestResultPrinter;
friend class FinalSuccessChecker;
FRIEND_TEST(ApiTest, UnitTestImmutableAccessorsWork);
FRIEND_TEST(ApiTest, TestCaseImmutableAccessorsWork);
@ -1299,14 +1484,32 @@ class AssertHelper {
// Constructor.
AssertHelper(TestPartResultType type, const char* file, int line,
const char* message);
~AssertHelper();
// Message assignment is a semantic trick to enable assertion
// streaming; see the GTEST_MESSAGE_ macro below.
void operator=(const Message& message) const;
private:
TestPartResultType const type_;
const char* const file_;
int const line_;
String const message_;
// We put our data in a struct so that the size of the AssertHelper class can
// be as small as possible. This is important because gcc is incapable of
// re-using stack space even for temporary variables, so every EXPECT_EQ
// reserves stack space for another AssertHelper.
struct AssertHelperData {
AssertHelperData(TestPartResultType t, const char* srcfile, int line_num,
const char* msg)
: type(t), file(srcfile), line(line_num), message(msg) { }
TestPartResultType const type;
const char* const file;
int const line;
String const message;
private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelperData);
};
AssertHelperData* const data_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(AssertHelper);
};

View File

@ -107,7 +107,6 @@ class Test; // Represents a test.
class TestInfo; // Information about a test.
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
class UnitTestEventListenerInterface; // Listens to Google Test events.
namespace internal {

View File

@ -51,22 +51,6 @@
namespace testing {
namespace internal {
// Holds data in a String object. We need this class in order to put
// String's data members on the heap instead of on the stack.
// Otherwise tests using many assertions (and thus Strings) in one
// function may need too much stack frame space to compile.
class StringData {
StringData() : c_str_(NULL), length_(0) {}
~StringData() { delete[] c_str_; }
private:
friend class String;
const char* c_str_;
size_t length_; // Length of the string (excluding the terminating
// '\0' character).
};
// String - a UTF-8 string class.
//
// We cannot use std::string as Microsoft's STL implementation in
@ -202,14 +186,14 @@ class String {
// C'tors
// The default c'tor constructs a NULL string, which is represented
// by data_ being NULL.
String() : data_(NULL) {}
// The default c'tor constructs a NULL string.
String() : c_str_(NULL), length_(0) {}
// Constructs a String by cloning a 0-terminated C string.
String(const char* c_str) { // NOLINT
if (c_str == NULL) {
data_ = NULL;
c_str_ = NULL;
length_ = 0;
} else {
ConstructNonNull(c_str, strlen(c_str));
}
@ -225,13 +209,11 @@ class String {
// The copy c'tor creates a new copy of the string. The two
// String objects do not share content.
String(const String& str) : data_(NULL) { *this = str; }
String(const String& str) : c_str_(NULL), length_(0) { *this = str; }
// D'tor. String is intended to be a final class, so the d'tor
// doesn't need to be virtual.
~String() {
delete data_;
}
~String() { delete[] c_str_; }
// Allows a String to be implicitly converted to an ::std::string or
// ::string, and vice versa. Converting a String containing a NULL
@ -285,12 +267,12 @@ class String {
// Returns the length of the encapsulated string, or 0 if the
// string is NULL.
size_t length() const { return (data_ == NULL) ? 0 : data_->length_; }
size_t length() const { return length_; }
// Gets the 0-terminated C string this String object represents.
// The String object still owns the string. Therefore the caller
// should NOT delete the return value.
const char* c_str() const { return (data_ == NULL) ? NULL : data_->c_str_; }
const char* c_str() const { return c_str_; }
// Assigns a C string to this object. Self-assignment works.
const String& operator=(const char* c_str) { return *this = String(c_str); }
@ -298,10 +280,12 @@ class String {
// Assigns a String object to this object. Self-assignment works.
const String& operator=(const String& rhs) {
if (this != &rhs) {
delete data_;
data_ = NULL;
if (rhs.data_ != NULL) {
ConstructNonNull(rhs.data_->c_str_, rhs.data_->length_);
delete[] c_str_;
if (rhs.c_str() == NULL) {
c_str_ = NULL;
length_ = 0;
} else {
ConstructNonNull(rhs.c_str(), rhs.length());
}
}
@ -314,17 +298,15 @@ class String {
// ConstructNonNull(NULL, 0) results in an empty string ("").
// ConstructNonNull(NULL, non_zero) is undefined behavior.
void ConstructNonNull(const char* buffer, size_t length) {
data_ = new StringData;
char* const str = new char[length + 1];
memcpy(str, buffer, length);
str[length] = '\0';
data_->c_str_ = str;
data_->length_ = length;
c_str_ = str;
length_ = length;
}
// Points to the representation of the String. A NULL String is
// represented by data_ == NULL.
StringData* data_;
const char* c_str_;
size_t length_;
}; // class String
// Streams a String to an ostream. Each '\0' character in the String

View File

@ -318,8 +318,9 @@ GtestTest(env, 'gtest_list_tests_unittest_', gtest)
GtestTest(env, 'gtest_throw_on_failure_test_', gtest)
GtestTest(env, 'gtest_xml_outfile1_test_', gtest_main)
GtestTest(env, 'gtest_xml_outfile2_test_', gtest_main)
GtestTest(env, 'gtest_xml_output_unittest_', gtest_main)
GtestTest(env, 'gtest_xml_output_unittest_', gtest)
GtestTest(env, 'gtest-unittest-api_test', gtest)
GtestTest(env, 'gtest-listener_test', gtest)
############################################################
# Tests targets using custom environments.

View File

@ -469,7 +469,8 @@ bool DeathTestImpl::Passed(bool status_ok) {
break;
case DIED:
if (status_ok) {
if (RE::PartialMatch(error_message.c_str(), *regex())) {
const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
if (matched) {
success = true;
} else {
buffer << " Result: died but not with expected error.\n"
@ -767,6 +768,9 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
// concurrent writes to the log files. We capture stderr in the parent
// process and append the child process' output to a log.
LogToStderr();
// Event forwarding to the listeners of event listener API mush be shut
// down in death test subprocesses.
GetUnitTestImpl()->listeners()->SuppressEventForwarding();
return EXECUTE_TEST;
} else {
GTEST_DEATH_TEST_CHECK_SYSCALL_(close(pipe_fd[1]));

View File

@ -741,6 +741,9 @@ class UnitTestImpl {
return test_cases_.GetElementOr(i, NULL);
}
// Provides access to the event listener list.
EventListeners* listeners() { return &listeners_; }
// Returns the TestResult for the test that's currently running, or
// the TestResult for the ad hoc test if no test is running.
TestResult* current_test_result();
@ -748,18 +751,6 @@ class UnitTestImpl {
// Returns the TestResult for the ad hoc test.
const TestResult* ad_hoc_test_result() const { return &ad_hoc_test_result_; }
// Sets the unit test result printer.
//
// Does nothing if the input and the current printer object are the
// same; otherwise, deletes the old printer object and makes the
// input the current printer.
void set_result_printer(UnitTestEventListenerInterface* result_printer);
// Returns the current unit test result printer if it is not NULL;
// otherwise, creates an appropriate result printer, makes it the
// current printer, and returns it.
UnitTestEventListenerInterface* result_printer();
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter
@ -907,9 +898,13 @@ class UnitTestImpl {
}
#if GTEST_HAS_DEATH_TEST
void InitDeathTestSubprocessControlInfo() {
internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
}
// Returns a pointer to the parsed --gtest_internal_run_death_test
// flag, or NULL if that flag was not specified.
// This information is useful only in a death test child process.
// Must not be called before a call to InitGoogleTest.
const InternalRunDeathTestFlag* internal_run_death_test_flag() const {
return internal_run_death_test_flag_.get();
}
@ -919,9 +914,22 @@ class UnitTestImpl {
return death_test_factory_.get();
}
void SuppressTestEventsIfInSubprocess();
friend class ReplaceDeathTestFactory;
#endif // GTEST_HAS_DEATH_TEST
// Initializes the event listener performing XML output as specified by
// UnitTestOptions. Must not be called before InitGoogleTest.
void ConfigureXmlOutput();
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
// this function is also called from RunAllTests. Since this function can be
// called more than once, it has to be idempotent.
void PostFlagParsingInit();
// Gets the random seed used at the start of the current test run.
int random_seed() const { return random_seed_; }
@ -992,11 +1000,9 @@ class UnitTestImpl {
// test, and records the result in ad_hoc_test_result_.
TestResult ad_hoc_test_result_;
// The unit test result printer. Will be deleted when the UnitTest
// object is destructed. By default, a plain text printer is used,
// but the user can set this field to use a custom printer if that
// is desired.
UnitTestEventListenerInterface* result_printer_;
// The list of event listeners that can be used to track events inside
// Google Test.
EventListeners listeners_;
// The OS stack trace getter. Will be deleted when the UnitTest
// object is destructed. By default, an OsStackTraceGetter is used,
@ -1004,6 +1010,9 @@ class UnitTestImpl {
// desired.
OsStackTraceGetterInterface* os_stack_trace_getter_;
// True iff PostFlagParsingInit() has been called.
bool post_flag_parse_init_performed_;
// The random number seed used at the beginning of the test run.
int random_seed_;

View File

@ -129,9 +129,12 @@
namespace testing {
using internal::EventListeners;
using internal::EmptyTestEventListener;
using internal::TestCase;
using internal::TestProperty;
using internal::TestResult;
using internal::UnitTestEventListenerInterface;
// Constants.
@ -303,14 +306,18 @@ static bool ShouldRunTestCase(const TestCase* test_case) {
// AssertHelper constructor.
AssertHelper::AssertHelper(TestPartResultType type, const char* file,
int line, const char* message)
: type_(type), file_(file), line_(line), message_(message) {
: data_(new AssertHelperData(type, file, line, message)) {
}
AssertHelper::~AssertHelper() {
delete data_;
}
// Message assignment, for assertion streaming support.
void AssertHelper::operator=(const Message& message) const {
UnitTest::GetInstance()->
AddTestPartResult(type_, file_, line_,
AppendUserMessage(message_, message),
AddTestPartResult(data_->type, data_->file, data_->line,
AppendUserMessage(data_->message, message),
UnitTest::GetInstance()->impl()
->CurrentOsStackTraceExceptTop(1)
// Skips the stack frame for this function itself.
@ -476,86 +483,6 @@ int UnitTestOptions::GTestShouldProcessSEH(DWORD exception_code) {
} // namespace internal
// The interface for printing the result of a UnitTest
class UnitTestEventListenerInterface {
public:
// The d'tor is pure virtual as this is an abstract class.
virtual ~UnitTestEventListenerInterface() {}
// Called before the unit test starts.
virtual void OnUnitTestStart(const UnitTest& unit_test) = 0;
// Called after the unit test ends.
virtual void OnUnitTestEnd(const UnitTest& unit_test) = 0;
// Called before the test case starts.
virtual void OnTestCaseStart(const TestCase& test_case) = 0;
// Called after the test case ends.
virtual void OnTestCaseEnd(const TestCase& test_case) = 0;
// Called before the global set-up starts.
virtual void OnGlobalSetUpStart(const UnitTest& unit_test) = 0;
// Called after the global set-up ends.
virtual void OnGlobalSetUpEnd(const UnitTest& unit_test) = 0;
// Called before the global tear-down starts.
virtual void OnGlobalTearDownStart(const UnitTest& unit_test) = 0;
// Called after the global tear-down ends.
virtual void OnGlobalTearDownEnd(const UnitTest& unit_test) = 0;
// Called before the test starts.
virtual void OnTestStart(const TestInfo& test_info) = 0;
// Called after the test ends.
virtual void OnTestEnd(const TestInfo& test_info) = 0;
// Called after an assertion.
virtual void OnNewTestPartResult(const TestPartResult& test_part_result) = 0;
};
// The convenience class for users who need to override just one or two
// methods and are not concerned that a possible change to a signature of
// the methods they override will not be caught during the build.
class EmptyTestEventListener : public UnitTestEventListenerInterface {
public:
// Called before the unit test starts.
virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {}
// Called after the unit test ends.
virtual void OnUnitTestEnd(const UnitTest& /*unit_test*/) {}
// Called before the test case starts.
virtual void OnTestCaseStart(const TestCase& /*test_case*/) {}
// Called after the test case ends.
virtual void OnTestCaseEnd(const TestCase& /*test_case&*/) {}
// Called before the global set-up starts.
virtual void OnGlobalSetUpStart(const UnitTest& /*unit_test*/) {}
// Called after the global set-up ends.
virtual void OnGlobalSetUpEnd(const UnitTest& /*unit_test*/) {}
// Called before the global tear-down starts.
virtual void OnGlobalTearDownStart(const UnitTest& /*unit_test*/) {}
// Called after the global tear-down ends.
virtual void OnGlobalTearDownEnd(const UnitTest& /*unit_test*/) {}
// Called before the test starts.
virtual void OnTestStart(const TestInfo& /*test_info*/) {}
// Called after the test ends.
virtual void OnTestEnd(const TestInfo& /*test_info*/) {}
// Called after an assertion.
virtual void OnNewTestPartResult(const TestPartResult& /*test_part_result*/) {
}
};
// The c'tor sets this object as the test part result reporter used by
// Google Test. The 'result' parameter specifies where to report the
// results. Intercepts only failures from the current thread.
@ -690,7 +617,7 @@ DefaultGlobalTestPartResultReporter::DefaultGlobalTestPartResultReporter(
void DefaultGlobalTestPartResultReporter::ReportTestPartResult(
const TestPartResult& result) {
unit_test_->current_test_result()->AddTestPartResult(result);
unit_test_->result_printer()->OnNewTestPartResult(result);
unit_test_->listeners()->repeater()->OnNewTestPartResult(result);
}
DefaultPerThreadTestPartResultReporter::DefaultPerThreadTestPartResultReporter(
@ -1738,28 +1665,38 @@ bool String::EndsWithCaseInsensitive(const char* suffix) const {
// available.
//
// The result is limited to 4096 characters (including the tailing 0).
// If 4096 characters are not enough to format the input,
// "<buffer exceeded>" is returned.
// If 4096 characters are not enough to format the input, or if
// there's an error, "<formatting error or buffer exceeded>" is
// returned.
String String::Format(const char * format, ...) {
va_list args;
va_start(args, format);
char buffer[4096];
const int kBufferSize = sizeof(buffer)/sizeof(buffer[0]);
// MSVC 8 deprecates vsnprintf(), so we want to suppress warning
// 4996 (deprecated function) there.
#ifdef _MSC_VER // We are using MSVC.
#pragma warning(push) // Saves the current warning state.
#pragma warning(disable:4996) // Temporarily disables warning 4996.
const int size =
vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
const int size = vsnprintf(buffer, kBufferSize, format, args);
#pragma warning(pop) // Restores the warning state.
#else // We are not using MSVC.
const int size =
vsnprintf(buffer, sizeof(buffer)/sizeof(buffer[0]) - 1, format, args);
const int size = vsnprintf(buffer, kBufferSize, format, args);
#endif // _MSC_VER
va_end(args);
return (size >= 0) ? String(buffer, size) : String("<buffer exceeded>");
// vsnprintf()'s behavior is not portable. When the buffer is not
// big enough, it returns a negative value in MSVC, and returns the
// needed buffer size on Linux. When there is an output error, it
// always returns a negative value. For simplicity, we lump the two
// error cases together.
if (size < 0 || size >= kBufferSize) {
return String("<formatting error or buffer exceeded>");
} else {
return String(buffer, size);
}
}
// Converts the buffer in a StrStream to a String, converting NUL
@ -2297,11 +2234,11 @@ void TestInfoImpl::Run() {
UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_info(parent_);
// Notifies the unit test event listener that a test is about to
// start.
UnitTestEventListenerInterface* const result_printer =
impl->result_printer();
result_printer->OnTestStart(*parent_);
UnitTestEventListenerInterface* repeater =
UnitTest::GetInstance()->listeners().repeater();
// Notifies the unit test event listeners that a test is about to start.
repeater->OnTestStart(*parent_);
const TimeInMillis start = GetTimeInMillis();
@ -2344,7 +2281,7 @@ void TestInfoImpl::Run() {
result_.set_elapsed_time(GetTimeInMillis() - start);
// Notifies the unit test event listener that a test has just finished.
result_printer->OnTestEnd(*parent_);
repeater->OnTestEnd(*parent_);
// Tells UnitTest to stop associating assertion results to this
// test.
@ -2425,10 +2362,10 @@ void TestCase::Run() {
internal::UnitTestImpl* const impl = internal::GetUnitTestImpl();
impl->set_current_test_case(this);
UnitTestEventListenerInterface * const result_printer =
impl->result_printer();
UnitTestEventListenerInterface* repeater =
UnitTest::GetInstance()->listeners().repeater();
result_printer->OnTestCaseStart(*this);
repeater->OnTestCaseStart(*this);
impl->os_stack_trace_getter()->UponLeavingGTest();
set_up_tc_();
@ -2438,7 +2375,7 @@ void TestCase::Run() {
impl->os_stack_trace_getter()->UponLeavingGTest();
tear_down_tc_();
result_printer->OnTestCaseEnd(*this);
repeater->OnTestCaseEnd(*this);
impl->set_current_test_case(NULL);
}
@ -2471,10 +2408,6 @@ bool TestCase::ShouldRunTest(const TestInfo *test_info) {
} // namespace internal
// A result printer that never prints anything. Used in the child process
// of an exec-style death test to avoid needless output clutter.
class NullUnitTestResultPrinter : public EmptyTestEventListener {};
// Formats a countable noun. Depending on its quantity, either the
// singular form or the plural form is used. e.g.
//
@ -2663,14 +2596,6 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_end(args);
}
} // namespace internal
using internal::ColoredPrintf;
using internal::COLOR_DEFAULT;
using internal::COLOR_RED;
using internal::COLOR_GREEN;
using internal::COLOR_YELLOW;
// This class implements the UnitTestEventListenerInterface interface.
//
// Class PrettyUnitTestResultPrinter is copyable.
@ -2888,10 +2813,16 @@ void PrettyUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
// This class forwards events to other event listeners.
class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
public:
typedef internal::Vector<UnitTestEventListenerInterface *> Listeners;
UnitTestEventsRepeater() {}
UnitTestEventsRepeater() : forwarding_enabled_(true) {}
virtual ~UnitTestEventsRepeater();
void AddListener(UnitTestEventListenerInterface *listener);
void Append(UnitTestEventListenerInterface *listener);
UnitTestEventListenerInterface* Release(
UnitTestEventListenerInterface* listener);
// Controls whether events will be forwarded to listeners_. Set to false
// in death test child processes.
bool forwarding_enabled() const { return forwarding_enabled_; }
void set_forwarding_enabled(bool enable) { forwarding_enabled_ = enable; }
virtual void OnUnitTestStart(const UnitTest& unit_test);
virtual void OnUnitTestEnd(const UnitTest& unit_test);
@ -2906,7 +2837,11 @@ class UnitTestEventsRepeater : public UnitTestEventListenerInterface {
virtual void OnNewTestPartResult(const TestPartResult& result);
private:
Listeners listeners_;
// Controls whether events will be forwarded to listeners_. Set to false
// in death test child processes.
bool forwarding_enabled_;
// The list of listeners that receive events.
Vector<UnitTestEventListenerInterface*> listeners_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(UnitTestEventsRepeater);
};
@ -2917,18 +2852,32 @@ UnitTestEventsRepeater::~UnitTestEventsRepeater() {
}
}
void UnitTestEventsRepeater::AddListener(
UnitTestEventListenerInterface *listener) {
void UnitTestEventsRepeater::Append(UnitTestEventListenerInterface *listener) {
listeners_.PushBack(listener);
}
// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
UnitTestEventListenerInterface* UnitTestEventsRepeater::Release(
UnitTestEventListenerInterface *listener) {
for (int i = 0; i < listeners_.size(); ++i) {
if (listeners_.GetElement(i) == listener) {
listeners_.Erase(i);
return listener;
}
}
return NULL;
}
// Since the methods are identical, use a macro to reduce boilerplate.
// This defines a member that repeats the call to all listeners.
#define GTEST_REPEATER_METHOD_(Name, Type) \
void UnitTestEventsRepeater::Name(const Type& parameter) { \
if (forwarding_enabled_) { \
for (int i = 0; i < listeners_.size(); i++) { \
listeners_.GetElement(i)->Name(parameter); \
} \
} \
}
GTEST_REPEATER_METHOD_(OnUnitTestStart, UnitTest)
@ -2945,7 +2894,7 @@ GTEST_REPEATER_METHOD_(OnNewTestPartResult, TestPartResult)
#undef GTEST_REPEATER_METHOD_
// End PrettyUnitTestResultPrinter
// End UnitTestEventsRepeater
// This class generates an XML output file.
class XmlUnitTestResultPrinter : public EmptyTestEventListener {
@ -2970,18 +2919,15 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// with character references.
static internal::String EscapeXml(const char* str,
bool is_attribute);
static String EscapeXml(const char* str, bool is_attribute);
// Convenience wrapper around EscapeXml when str is an attribute value.
static internal::String EscapeXmlAttribute(const char* str) {
static String EscapeXmlAttribute(const char* str) {
return EscapeXml(str, true);
}
// Convenience wrapper around EscapeXml when str is not an attribute value.
static internal::String EscapeXmlText(const char* str) {
return EscapeXml(str, false);
}
static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
// Prints an XML representation of a TestInfo object.
static void PrintXmlTestInfo(FILE* out,
@ -2998,11 +2944,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// delimited XML attributes based on the property key="value" pairs.
// When the String is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static internal::String TestPropertiesAsXmlAttributes(
const TestResult& result);
static String TestPropertiesAsXmlAttributes(const TestResult& result);
// The output file.
const internal::String output_file_;
const String output_file_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
};
@ -3020,11 +2965,11 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
FILE* xmlout = NULL;
internal::FilePath output_file(output_file_);
internal::FilePath output_dir(output_file.RemoveFileName());
FilePath output_file(output_file_);
FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
xmlout = internal::posix::FOpen(output_file_.c_str(), "w");
xmlout = posix::FOpen(output_file_.c_str(), "w");
}
if (xmlout == NULL) {
// TODO(wan): report the reason of the failure.
@ -3059,8 +3004,7 @@ void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
// most invalid characters can be retained using character references.
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
bool is_attribute) {
String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
Message m;
if (str != NULL) {
@ -3090,7 +3034,7 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
default:
if (IsValidXmlCharacter(*src)) {
if (is_attribute && IsNormalizableWhitespace(*src))
m << internal::String::Format("&#x%02X;", unsigned(*src));
m << String::Format("&#x%02X;", unsigned(*src));
else
m << *src;
}
@ -3102,7 +3046,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
return m.GetString();
}
// The following routines generate an XML representation of a UnitTest
// object.
//
@ -3119,8 +3062,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
// </testsuite>
// </testsuites>
namespace internal {
// Formats the given time in milliseconds as seconds. The returned
// C-string is owned by this function and cannot be released by the
// caller. Calling the function again invalidates the previous
@ -3131,8 +3072,6 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
return str.c_str();
}
} // namespace internal
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
@ -3144,7 +3083,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
"classname=\"%s\"%s",
EscapeXmlAttribute(test_info.name()).c_str(),
test_info.should_run() ? "run" : "notrun",
internal::FormatTimeInMillisAsSeconds(result.elapsed_time()),
FormatTimeInMillisAsSeconds(result.elapsed_time()),
EscapeXmlAttribute(test_case_name).c_str(),
TestPropertiesAsXmlAttributes(result).c_str());
@ -3152,8 +3091,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = result.GetTestPartResult(i);
if (part.failed()) {
const internal::String message =
internal::String::Format("%s:%d\n%s", part.file_name(),
const String message = String::Format("%s:%d\n%s", part.file_name(),
part.line_number(), part.message());
if (++failures == 1)
fprintf(out, ">\n");
@ -3182,7 +3120,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
test_case.disabled_test_count());
fprintf(out,
"errors=\"0\" time=\"%s\">\n",
internal::FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
for (int i = 0; i < test_case.total_test_count(); ++i)
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
fprintf(out, " </testsuite>\n");
@ -3198,7 +3136,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
unit_test.total_test_count(),
unit_test.failed_test_count(),
unit_test.disabled_test_count(),
internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
if (GTEST_FLAG(shuffle)) {
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
}
@ -3210,7 +3148,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const TestResult& result) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
@ -3223,8 +3161,6 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
// End XmlUnitTestResultPrinter
namespace internal {
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@ -3271,6 +3207,84 @@ OsStackTraceGetter::kElidedFramesMarker =
} // namespace internal
// class EventListeners
EventListeners::EventListeners()
: repeater_(new internal::UnitTestEventsRepeater()),
default_result_printer_(NULL),
default_xml_generator_(NULL) {
}
EventListeners::~EventListeners() { delete repeater_; }
// Returns the standard listener responsible for the default console
// output. Can be removed from the listeners list to shut down default
// console output. Note that removing this object from the listener list
// with Release transfers its ownership to the user.
void EventListeners::Append(UnitTestEventListenerInterface* listener) {
repeater_->Append(listener);
}
// Removes the given event listener from the list and returns it. It then
// becomes the caller's responsibility to delete the listener. Returns
// NULL if the listener is not found in the list.
UnitTestEventListenerInterface* EventListeners::Release(
UnitTestEventListenerInterface* listener) {
if (listener == default_result_printer_)
default_result_printer_ = NULL;
else if (listener == default_xml_generator_)
default_xml_generator_ = NULL;
return repeater_->Release(listener);
}
// Returns repeater that broadcasts the UnitTestEventListenerInterface
// events to all subscribers.
UnitTestEventListenerInterface* EventListeners::repeater() { return repeater_; }
// Sets the default_result_printer attribute to the provided listener.
// The listener is also added to the listener list and previous
// default_result_printer is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void EventListeners::SetDefaultResultPrinter(
UnitTestEventListenerInterface* listener) {
if (default_result_printer_ != listener) {
// It is an error to pass this method a listener that is already in the
// list.
delete Release(default_result_printer_);
default_result_printer_ = listener;
if (listener != NULL)
Append(listener);
}
}
// Sets the default_xml_generator attribute to the provided listener. The
// listener is also added to the listener list and previous
// default_xml_generator is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void EventListeners::SetDefaultXmlGenerator(
UnitTestEventListenerInterface* listener) {
if (default_xml_generator_ != listener) {
// It is an error to pass this method a listener that is already in the
// list.
delete Release(default_xml_generator_);
default_xml_generator_ = listener;
if (listener != NULL)
Append(listener);
}
}
// Controls whether events will be forwarded by the repeater to the
// listeners in the list.
bool EventListeners::EventForwardingEnabled() const {
return repeater_->forwarding_enabled();
}
void EventListeners::SuppressEventForwarding() {
repeater_->set_forwarding_enabled(false);
}
// class UnitTest
// Gets the singleton UnitTest object. The first time this method is
@ -3359,6 +3373,12 @@ const TestCase* UnitTest::GetTestCase(int i) const {
return impl()->GetTestCase(i);
}
// Returns the list of event listeners that can be used to track events
// inside Google Test.
EventListeners& UnitTest::listeners() {
return *impl()->listeners();
}
// Registers and returns a global test environment. When a test
// program is run, all global test environments will be set-up in the
// order they were registered. After all tests in the program have
@ -3614,8 +3634,8 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
current_test_case_(NULL),
current_test_info_(NULL),
ad_hoc_test_result_(),
result_printer_(NULL),
os_stack_trace_getter_(NULL),
post_flag_parse_init_performed_(false),
random_seed_(0),
#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
@ -3624,6 +3644,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
#else
elapsed_time_(0) {
#endif // GTEST_HAS_DEATH_TEST
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
UnitTestImpl::~UnitTestImpl() {
@ -3633,12 +3654,58 @@ UnitTestImpl::~UnitTestImpl() {
// Deletes every Environment.
environments_.ForEach(internal::Delete<Environment>);
// Deletes the current test result printer.
delete result_printer_;
delete os_stack_trace_getter_;
}
#if GTEST_HAS_DEATH_TEST
// Disables event forwarding if the control is currently in a death test
// subprocess. Must not be called before InitGoogleTest.
void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
if (internal_run_death_test_flag_.get() != NULL)
listeners()->SuppressEventForwarding();
}
#endif // GTEST_HAS_DEATH_TEST
// Initializes event listeners performing XML output as specified by
// UnitTestOptions. Must not be called before InitGoogleTest.
void UnitTestImpl::ConfigureXmlOutput() {
const String& output_format = UnitTestOptions::GetOutputFormat();
if (output_format == "xml") {
listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") {
printf("WARNING: unrecognized output format \"%s\" ignored.\n",
output_format.c_str());
fflush(stdout);
}
}
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
// this function is also called from RunAllTests. Since this function can be
// called more than once, it has to be idempotent.
void UnitTestImpl::PostFlagParsingInit() {
// Ensures that this function does not execute more than once.
if (!post_flag_parse_init_performed_) {
post_flag_parse_init_performed_ = true;
#if GTEST_HAS_DEATH_TEST
InitDeathTestSubprocessControlInfo();
SuppressTestEventsIfInSubprocess();
#endif // GTEST_HAS_DEATH_TEST
// Registers parameterized tests. This makes parameterized tests
// available to the UnitTest reflection API without running
// RUN_ALL_TESTS.
RegisterParameterizedTests();
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
}
}
// A predicate that checks the name of a TestCase against a known
// value.
//
@ -3726,7 +3793,8 @@ int UnitTestImpl::RunAllTests() {
if (g_help_flag)
return 0;
RegisterParameterizedTests();
// TODO(vladl@google.com): Add a call to PostFlagParsingInit() here when
// merging into the main branch.
// Even if sharding is not on, test runners may want to use the
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
@ -3738,12 +3806,9 @@ int UnitTestImpl::RunAllTests() {
bool in_subprocess_for_death_test = false;
#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
#endif // GTEST_HAS_DEATH_TEST
UnitTestEventListenerInterface * const printer = result_printer();
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
in_subprocess_for_death_test);
@ -3766,6 +3831,8 @@ int UnitTestImpl::RunAllTests() {
// True iff at least one test has failed.
bool failed = false;
UnitTestEventListenerInterface* repeater = listeners()->repeater();
// How many times to repeat the tests? We don't want to repeat them
// when we are inside the subprocess of a death test.
const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
@ -3773,21 +3840,24 @@ int UnitTestImpl::RunAllTests() {
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
if (repeat != 1) {
// TODO(vladl@google.com): Move this output to
// PrettyUnitTestResultPrinter. Add the iteration number parameter to
// OnUnitTestStart.
printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
}
// Tells the unit test event listener that the tests are about to
// start.
printer->OnUnitTestStart(*parent_);
// Tells the unit test event listeners that the tests are about to start.
repeater->OnUnitTestStart(*parent_);
// TODO(vladl@google.com): Move to before the OnUnitTestStart notification?
const TimeInMillis start = GetTimeInMillis();
// Runs each test case if there is at least one test to run.
if (has_tests_to_run) {
// Sets up all environments beforehand.
printer->OnGlobalSetUpStart(*parent_);
repeater->OnGlobalSetUpStart(*parent_);
environments_.ForEach(SetUpEnvironment);
printer->OnGlobalSetUpEnd(*parent_);
repeater->OnGlobalSetUpEnd(*parent_);
// Runs the tests only if there was no fatal failure during global
// set-up.
@ -3796,16 +3866,15 @@ int UnitTestImpl::RunAllTests() {
}
// Tears down all environments in reverse order afterwards.
printer->OnGlobalTearDownStart(*parent_);
repeater->OnGlobalTearDownStart(*parent_);
environments_in_reverse_order_.ForEach(TearDownEnvironment);
printer->OnGlobalTearDownEnd(*parent_);
repeater->OnGlobalTearDownEnd(*parent_);
}
elapsed_time_ = GetTimeInMillis() - start;
// Tells the unit test event listener that the tests have just
// finished.
printer->OnUnitTestEnd(*parent_);
// Tells the unit test event listener that the tests have just finished.
repeater->OnUnitTestEnd(*parent_);
// Gets the result and clears it.
if (!Passed()) {
@ -3997,49 +4066,6 @@ void UnitTestImpl::ListTestsMatchingFilter() {
fflush(stdout);
}
// Sets the unit test result printer.
//
// Does nothing if the input and the current printer object are the
// same; otherwise, deletes the old printer object and makes the
// input the current printer.
void UnitTestImpl::set_result_printer(
UnitTestEventListenerInterface* result_printer) {
if (result_printer_ != result_printer) {
delete result_printer_;
result_printer_ = result_printer;
}
}
// Returns the current unit test result printer if it is not NULL;
// otherwise, creates an appropriate result printer, makes it the
// current printer, and returns it.
UnitTestEventListenerInterface* UnitTestImpl::result_printer() {
if (result_printer_ != NULL) {
return result_printer_;
}
#if GTEST_HAS_DEATH_TEST
if (internal_run_death_test_flag_.get() != NULL) {
result_printer_ = new NullUnitTestResultPrinter;
return result_printer_;
}
#endif // GTEST_HAS_DEATH_TEST
UnitTestEventsRepeater *repeater = new UnitTestEventsRepeater;
const String& output_format = internal::UnitTestOptions::GetOutputFormat();
if (output_format == "xml") {
repeater->AddListener(new XmlUnitTestResultPrinter(
internal::UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") {
printf("WARNING: unrecognized output format \"%s\" ignored.\n",
output_format.c_str());
fflush(stdout);
}
repeater->AddListener(new PrettyUnitTestResultPrinter);
result_printer_ = repeater;
return result_printer_;
}
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter are
@ -4420,6 +4446,7 @@ void InitGoogleTestImpl(int* argc, CharType** argv) {
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
GetUnitTestImpl()->PostFlagParsingInit();
}
} // namespace internal

230
test/gtest-listener_test.cc Normal file
View 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;
}

View File

@ -85,7 +85,7 @@ class GTestEnvVarTest(gtest_test_utils.TestCase):
TestFlag('break_on_failure', '1', '0')
TestFlag('color', 'yes', 'auto')
TestFlag('filter', 'FooTest.Bar', '*')
TestFlag('output', 'tmp/foo.xml', '')
TestFlag('output', 'xml:tmp/foo.xml', '')
TestFlag('print_time', '0', '1')
TestFlag('repeat', '999', '1')
TestFlag('throw_on_failure', '1', '0')

View File

@ -84,11 +84,38 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms);
bool ParseInt32Flag(const char* str, const char* flag, Int32* value);
// Provides access to otherwise private parts of the EventListeners class
// that are needed to test it.
class EventListenersAccessor {
public:
static UnitTestEventListenerInterface* GetRepeater(
EventListeners* listeners) { return listeners->repeater(); }
static void SetDefaultResultPrinter(
EventListeners* listeners,
UnitTestEventListenerInterface* listener) {
listeners->SetDefaultResultPrinter(listener);
}
static void SetDefaultXmlGenerator(EventListeners* listeners,
UnitTestEventListenerInterface* listener) {
listeners->SetDefaultXmlGenerator(listener);
}
static bool EventForwardingEnabled(const EventListeners& listeners) {
return listeners.EventForwardingEnabled();
}
static void SuppressEventForwarding(EventListeners* listeners) {
listeners->SuppressEventForwarding();
}
};
} // namespace internal
} // namespace testing
using testing::internal::FormatTimeInMillisAsSeconds;
using testing::internal::ParseInt32Flag;
using testing::internal::EventListenersAccessor;
namespace testing {
@ -136,7 +163,9 @@ using testing::internal::kMaxRandomSeed;
using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::AppendUserMessage;
using testing::internal::CodePointToUtf8;
using testing::internal::EmptyTestEventListener;
using testing::internal::EqFailure;
using testing::internal::EventListeners;
using testing::internal::FloatingPoint;
using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop;
@ -160,6 +189,7 @@ using testing::internal::ThreadLocal;
using testing::internal::Vector;
using testing::internal::WideStringToUtf8;
using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::scoped_ptr;
// This line tests that we can define tests in an unnamed namespace.
namespace {
@ -695,14 +725,16 @@ TEST(ListDeathTest, GetElement) {
"Invalid Vector index -1: must be in range \\[0, 2\\]\\.");
}
// Tests the String class.
// Tests the size of the AssertHelper class.
TEST(StringTest, SizeIsSmall) {
TEST(AssertHelperTest, AssertHelperIsSmall) {
// To avoid breaking clients that use lots of assertions in one
// function, we cannot grow the size of String.
EXPECT_LE(sizeof(String), sizeof(void*));
// function, we cannot grow the size of AssertHelper.
EXPECT_LE(sizeof(testing::internal::AssertHelper), sizeof(void*));
}
// Tests the String class.
// Tests String's constructors.
TEST(StringTest, Constructors) {
// Default ctor.
@ -1037,6 +1069,33 @@ TEST(StringTest, Streams) {
EXPECT_EQ(StreamableToString(String("a\0b", 3)), "a\\0b");
}
// Tests that String::Format() works.
TEST(StringTest, FormatWorks) {
// Normal case: the format spec is valid, the arguments match the
// spec, and the result is < 4095 characters.
EXPECT_STREQ("Hello, 42", String::Format("%s, %d", "Hello", 42).c_str());
// Edge case: the result is 4095 characters.
char buffer[4096];
const size_t kSize = sizeof(buffer);
memset(buffer, 'a', kSize - 1);
buffer[kSize - 1] = '\0';
EXPECT_STREQ(buffer, String::Format("%s", buffer).c_str());
// The result needs to be 4096 characters, exceeding Format()'s limit.
EXPECT_STREQ("<formatting error or buffer exceeded>",
String::Format("x%s", buffer).c_str());
#if GTEST_OS_LINUX
// On Linux, invalid format spec should lead to an error message.
// In other environment (e.g. MSVC on Windows), String::Format() may
// simply ignore a bad format spec, so this assertion is run on
// Linux only.
EXPECT_STREQ("<formatting error or buffer exceeded>",
String::Format("%").c_str());
#endif
}
#if GTEST_OS_WINDOWS
// Tests String::ShowWideCString().
@ -6142,3 +6201,275 @@ TEST(HasFailureTest, WorksOutsideOfTestBody2) {
ClearCurrentTestPartResults();
EXPECT_TRUE(has_failure);
}
class TestListener : public EmptyTestEventListener {
public:
TestListener() : on_start_counter_(NULL), is_destroyed_(NULL) {}
TestListener(int* on_start_counter, bool* is_destroyed)
: on_start_counter_(on_start_counter),
is_destroyed_(is_destroyed) {}
virtual ~TestListener() {
if (is_destroyed_)
*is_destroyed_ = true;
}
protected:
virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {
if (on_start_counter_ != NULL)
(*on_start_counter_)++;
}
private:
int* on_start_counter_;
bool* is_destroyed_;
};
// Tests the constructor.
TEST(EventListenersTest, ConstructionWorks) {
EventListeners listeners;
EXPECT_TRUE(EventListenersAccessor::GetRepeater(&listeners) != NULL);
EXPECT_TRUE(listeners.default_result_printer() == NULL);
EXPECT_TRUE(listeners.default_xml_generator() == NULL);
}
// Tests that the EventListeners destructor deletes all the listeners it
// owns.
TEST(EventListenersTest, DestructionWorks) {
bool default_result_printer_is_destroyed = false;
bool default_xml_printer_is_destroyed = false;
bool extra_listener_is_destroyed = false;
TestListener* default_result_printer = new TestListener(
NULL, &default_result_printer_is_destroyed);
TestListener* default_xml_printer = new TestListener(
NULL, &default_xml_printer_is_destroyed);
TestListener* extra_listener = new TestListener(
NULL, &extra_listener_is_destroyed);
{
EventListeners listeners;
EventListenersAccessor::SetDefaultResultPrinter(&listeners,
default_result_printer);
EventListenersAccessor::SetDefaultXmlGenerator(&listeners,
default_xml_printer);
listeners.Append(extra_listener);
}
EXPECT_TRUE(default_result_printer_is_destroyed);
EXPECT_TRUE(default_xml_printer_is_destroyed);
EXPECT_TRUE(extra_listener_is_destroyed);
}
// Tests that a listener Append'ed to an EventListeners list starts
// receiving events.
TEST(EventListenersTest, Append) {
int on_start_counter = 0;
bool is_destroyed = false;
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
{
EventListeners listeners;
listeners.Append(listener);
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(1, on_start_counter);
}
EXPECT_TRUE(is_destroyed);
}
// Tests that listeners receive requests in the order they were appended to
// the list.
class SequenceTestingListener : public EmptyTestEventListener {
public:
SequenceTestingListener(Vector<const char*>* vector, const char* signature)
: vector_(vector), signature_(signature) {}
protected:
virtual void OnUnitTestStart(const UnitTest& /*unit_test*/) {
if (vector_ != NULL)
vector_->PushBack(signature_);
}
private:
Vector<const char*>* vector_;
const char* const signature_;
};
TEST(EventListenerTest, AppendKeepsOrder) {
Vector<const char*> vec;
EventListeners listeners;
listeners.Append(new SequenceTestingListener(&vec, "0"));
listeners.Append(new SequenceTestingListener(&vec, "1"));
listeners.Append(new SequenceTestingListener(&vec, "2"));
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
ASSERT_EQ(3, vec.size());
ASSERT_STREQ("0", vec.GetElement(0));
ASSERT_STREQ("1", vec.GetElement(1));
ASSERT_STREQ("2", vec.GetElement(2));
}
// Tests that a listener removed from an EventListeners list stops receiving
// events and is not deleted when the list is destroyed.
TEST(EventListenersTest, Release) {
int on_start_counter = 0;
bool is_destroyed = false;
// Although Append passes the ownership of this object to the list,
// the following calls release it, and we need to delete it before the
// test ends.
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
{
EventListeners listeners;
listeners.Append(listener);
EXPECT_EQ(listener, listeners.Release(listener));
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_TRUE(listeners.Release(listener) == NULL);
}
EXPECT_EQ(0, on_start_counter);
EXPECT_FALSE(is_destroyed);
delete listener;
}
// Tests that no events are forwarded when event forwarding is disabled.
TEST(EventListenerTest, SuppressEventForwarding) {
int on_start_counter = 0;
TestListener* listener = new TestListener(&on_start_counter, NULL);
EventListeners listeners;
listeners.Append(listener);
ASSERT_TRUE(EventListenersAccessor::EventForwardingEnabled(listeners));
EventListenersAccessor::SuppressEventForwarding(&listeners);
ASSERT_FALSE(EventListenersAccessor::EventForwardingEnabled(listeners));
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(0, on_start_counter);
}
#if GTEST_HAS_DEATH_TEST
// Tests that events generated by Google Test are not forwarded in
// death test subprocesses.
TEST(EventListenerDeathTest, EventsNotForwardedInDeathTestSubprecesses) {
EXPECT_DEATH({ // NOLINT
GTEST_CHECK_(EventListenersAccessor::EventForwardingEnabled(
*GetUnitTestImpl()->listeners())) << "expected failure";},
"expected failure");
}
#endif // GTEST_HAS_DEATH_TEST
// Tests that a listener installed via SetDefaultResultPrinter() starts
// receiving events and is returned via default_result_printer() and that
// the previous default_result_printer is removed from the list and deleted.
TEST(EventListenerTest, default_result_printer) {
int on_start_counter = 0;
bool is_destroyed = false;
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
EventListeners listeners;
EventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
EXPECT_EQ(listener, listeners.default_result_printer());
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(1, on_start_counter);
// Replacing default_result_printer with something else should remove it
// from the list and destroy it.
EventListenersAccessor::SetDefaultResultPrinter(&listeners, NULL);
EXPECT_TRUE(listeners.default_result_printer() == NULL);
EXPECT_TRUE(is_destroyed);
// After broadcasting an event the counter is still the same, indicating
// the listener is not in the list anymore.
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(1, on_start_counter);
}
// Tests that the default_result_printer listener stops receiving events
// when removed via Release and that is not owned by the list anymore.
TEST(EventListenerTest, RemovingDefaultResultPrinterWorks) {
int on_start_counter = 0;
bool is_destroyed = false;
// Although Append passes the ownership of this object to the list,
// the following calls release it, and we need to delete it before the
// test ends.
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
{
EventListeners listeners;
EventListenersAccessor::SetDefaultResultPrinter(&listeners, listener);
EXPECT_EQ(listener, listeners.Release(listener));
EXPECT_TRUE(listeners.default_result_printer() == NULL);
EXPECT_FALSE(is_destroyed);
// Broadcasting events now should not affect default_result_printer.
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(0, on_start_counter);
}
// Destroying the list should not affect the listener now, too.
EXPECT_FALSE(is_destroyed);
delete listener;
}
// Tests that a listener installed via SetDefaultXmlGenerator() starts
// receiving events and is returned via default_xml_generator() and that
// the previous default_xml_generator is removed from the list and deleted.
TEST(EventListenerTest, default_xml_generator) {
int on_start_counter = 0;
bool is_destroyed = false;
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
EventListeners listeners;
EventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
EXPECT_EQ(listener, listeners.default_xml_generator());
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(1, on_start_counter);
// Replacing default_xml_generator with something else should remove it
// from the list and destroy it.
EventListenersAccessor::SetDefaultXmlGenerator(&listeners, NULL);
EXPECT_TRUE(listeners.default_xml_generator() == NULL);
EXPECT_TRUE(is_destroyed);
// After broadcasting an event the counter is still the same, indicating
// the listener is not in the list anymore.
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(1, on_start_counter);
}
// Tests that the default_xml_generator listener stops receiving events
// when removed via Release and that is not owned by the list anymore.
TEST(EventListenerTest, RemovingDefaultXmlGeneratorWorks) {
int on_start_counter = 0;
bool is_destroyed = false;
// Although Append passes the ownership of this object to the list,
// the following calls release it, and we need to delete it before the
// test ends.
TestListener* listener = new TestListener(&on_start_counter, &is_destroyed);
{
EventListeners listeners;
EventListenersAccessor::SetDefaultXmlGenerator(&listeners, listener);
EXPECT_EQ(listener, listeners.Release(listener));
EXPECT_TRUE(listeners.default_xml_generator() == NULL);
EXPECT_FALSE(is_destroyed);
// Broadcasting events now should not affect default_xml_generator.
EventListenersAccessor::GetRepeater(&listeners)->OnUnitTestStart(
*UnitTest::GetInstance());
EXPECT_EQ(0, on_start_counter);
}
// Destroying the list should not affect the listener now, too.
EXPECT_FALSE(is_destroyed);
delete listener;
}

View File

@ -44,6 +44,7 @@ import gtest_xml_test_utils
GTEST_OUTPUT_FLAG = "--gtest_output"
GTEST_DEFAULT_OUTPUT_FILE = "test_detail.xml"
GTEST_PROGRAM_NAME = "gtest_xml_output_unittest_"
SUPPORTS_STACK_TRACES = False
@ -108,8 +109,7 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
Runs a test program that generates a non-empty XML output, and
tests that the XML output is expected.
"""
self._TestXmlOutput("gtest_xml_output_unittest_",
EXPECTED_NON_EMPTY_XML, 1)
self._TestXmlOutput(GTEST_PROGRAM_NAME, EXPECTED_NON_EMPTY_XML, 1)
def testEmptyXmlOutput(self):
"""
@ -142,6 +142,35 @@ class GTestXMLOutputUnitTest(gtest_xml_test_utils.GTestXMLTestCase):
self.assertEquals(0, p.exit_code)
self.assert_(os.path.isfile(output_file))
def testSuppressedXmlOutput(self):
"""
Tests that no XML file is generated if the default XML listener is
shut down before RUN_ALL_TESTS is invoked.
"""
xml_path = os.path.join(gtest_test_utils.GetTempDir(),
GTEST_PROGRAM_NAME + "out.xml")
if os.path.isfile(xml_path):
os.remove(xml_path)
gtest_prog_path = gtest_test_utils.GetTestExecutablePath(GTEST_PROGRAM_NAME)
command = [gtest_prog_path,
"%s=xml:%s" % (GTEST_OUTPUT_FLAG, xml_path),
"--shut_down_xml"]
p = gtest_test_utils.Subprocess(command)
if p.terminated_by_signal:
self.assert_(False,
"%s was killed by signal %d" % (gtest_prog_name, p.signal))
else:
self.assert_(p.exited)
self.assertEquals(1, p.exit_code,
"'%s' exited with code %s, which doesn't match "
"the expected exit code %s."
% (command, p.exit_code, 1))
self.assert_(not os.path.isfile(xml_path))
def _TestXmlOutput(self, gtest_prog_name, expected_xml, expected_exit_code):
"""

View File

@ -40,6 +40,20 @@
#include <gtest/gtest.h>
// TODO(vladl@google.com): Remove this include when the event listener API is
// published and GetUnitTestImpl is no longer needed.
//
// Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to
// prevent a user from accidentally including gtest-internal-inl.h in
// his code.
#define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_
using ::testing::InitGoogleTest;
class SuccessfulTest : public testing::Test {
};
@ -118,3 +132,17 @@ TEST(NoFixtureTest, ExternalUtilityThatCallsRecordIntValuedProperty) {
TEST(NoFixtureTest, ExternalUtilityThatCallsRecordStringValuedProperty) {
ExternalUtilityThatCallsRecordProperty("key_for_utility_string", "1");
}
int main(int argc, char** argv) {
InitGoogleTest(&argc, argv);
if (argc > 1 && strcmp(argv[1], "--shut_down_xml") == 0) {
// TODO(vladl@google.com): Replace GetUnitTestImpl()->listeners() with
// UnitTest::GetInstance()->listeners() when the event listener API is
// published.
::testing::internal::EventListeners& listeners =
*::testing::internal::GetUnitTestImpl()->listeners();
delete listeners.Release(listeners.default_xml_generator());
}
return RUN_ALL_TESTS();
}