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

21
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"
@ -201,7 +208,7 @@ directory (selected in the Xcode "Preferences..." -> "Building" pane and
defaults to xcode/build). Alternatively, at the command line, enter:
xcodebuild
This will build the "Release" configuration of gtest.framework in your
default build location. See the "xcodebuild" man page for more information about
building different configurations and building in different locations.
@ -213,7 +220,7 @@ ones) as errors. However, you should see a "Build succeeded" message at the end
of the build log. To run all of the tests from the command line, enter:
xcodebuild -target Check
Installation with xcodebuild requires specifying an installation desitination
directory, known as the DSTROOT. Three items will be installed when using
xcodebuild:
@ -221,12 +228,12 @@ xcodebuild:
$DSTROOT/Library/Frameworks/gtest.framework
$DSTROOT/usr/local/lib/libgtest.a
$DSTROOT/usr/local/lib/libgtest_main.a
You specify the installation directory on the command line with the other
xcodebuild options. Here's how you would install in a user-visible location:
xcodebuild install DSTROOT=~
To perform a system-wide inistall, escalate to an administrator and specify
the file system root as the DSTROOT:

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,17 +2852,31 @@ UnitTestEventsRepeater::~UnitTestEventsRepeater() {
}
}
void UnitTestEventsRepeater::AddListener(
UnitTestEventListenerInterface *listener) {
void UnitTestEventsRepeater::Append(UnitTestEventListenerInterface *listener) {
listeners_.PushBack(listener);
}
// TODO(vladl@google.com): Factor the search functionality into Vector::Find.
UnitTestEventListenerInterface* UnitTestEventsRepeater::Release(
UnitTestEventListenerInterface *listener) {
for (int i = 0; i < listeners_.size(); ++i) {
if (listeners_.GetElement(i) == listener) {
listeners_.Erase(i);
return listener;
}
}
return NULL;
}
// Since the methods are identical, use a macro to reduce boilerplate.
// This defines a member that repeats the call to all listeners.
#define GTEST_REPEATER_METHOD_(Name, Type) \
void UnitTestEventsRepeater::Name(const Type& parameter) { \
for (int i = 0; i < listeners_.size(); i++) { \
listeners_.GetElement(i)->Name(parameter); \
if (forwarding_enabled_) { \
for (int i = 0; i < listeners_.size(); i++) { \
listeners_.GetElement(i)->Name(parameter); \
} \
} \
}
@ -2945,7 +2894,7 @@ GTEST_REPEATER_METHOD_(OnNewTestPartResult, TestPartResult)
#undef GTEST_REPEATER_METHOD_
// End PrettyUnitTestResultPrinter
// End UnitTestEventsRepeater
// This class generates an XML output file.
class XmlUnitTestResultPrinter : public EmptyTestEventListener {
@ -2970,18 +2919,15 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// is_attribute is true, the text is meant to appear as an attribute
// value, and normalizable whitespace is preserved by replacing it
// with character references.
static internal::String EscapeXml(const char* str,
bool is_attribute);
static String EscapeXml(const char* str, bool is_attribute);
// Convenience wrapper around EscapeXml when str is an attribute value.
static internal::String EscapeXmlAttribute(const char* str) {
static String EscapeXmlAttribute(const char* str) {
return EscapeXml(str, true);
}
// Convenience wrapper around EscapeXml when str is not an attribute value.
static internal::String EscapeXmlText(const char* str) {
return EscapeXml(str, false);
}
static String EscapeXmlText(const char* str) { return EscapeXml(str, false); }
// Prints an XML representation of a TestInfo object.
static void PrintXmlTestInfo(FILE* out,
@ -2998,11 +2944,10 @@ class XmlUnitTestResultPrinter : public EmptyTestEventListener {
// delimited XML attributes based on the property key="value" pairs.
// When the String is not empty, it includes a space at the beginning,
// to delimit this attribute from prior attributes.
static internal::String TestPropertiesAsXmlAttributes(
const TestResult& result);
static String TestPropertiesAsXmlAttributes(const TestResult& result);
// The output file.
const internal::String output_file_;
const String output_file_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(XmlUnitTestResultPrinter);
};
@ -3020,11 +2965,11 @@ XmlUnitTestResultPrinter::XmlUnitTestResultPrinter(const char* output_file)
// Called after the unit test ends.
void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
FILE* xmlout = NULL;
internal::FilePath output_file(output_file_);
internal::FilePath output_dir(output_file.RemoveFileName());
FilePath output_file(output_file_);
FilePath output_dir(output_file.RemoveFileName());
if (output_dir.CreateDirectoriesRecursively()) {
xmlout = internal::posix::FOpen(output_file_.c_str(), "w");
xmlout = posix::FOpen(output_file_.c_str(), "w");
}
if (xmlout == NULL) {
// TODO(wan): report the reason of the failure.
@ -3059,8 +3004,7 @@ void XmlUnitTestResultPrinter::OnUnitTestEnd(const UnitTest& unit_test) {
// most invalid characters can be retained using character references.
// TODO(wan): It might be nice to have a minimally invasive, human-readable
// escaping scheme for invalid characters, rather than dropping them.
internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
bool is_attribute) {
String XmlUnitTestResultPrinter::EscapeXml(const char* str, bool is_attribute) {
Message m;
if (str != NULL) {
@ -3090,7 +3034,7 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
default:
if (IsValidXmlCharacter(*src)) {
if (is_attribute && IsNormalizableWhitespace(*src))
m << internal::String::Format("&#x%02X;", unsigned(*src));
m << String::Format("&#x%02X;", unsigned(*src));
else
m << *src;
}
@ -3102,7 +3046,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
return m.GetString();
}
// The following routines generate an XML representation of a UnitTest
// object.
//
@ -3119,8 +3062,6 @@ internal::String XmlUnitTestResultPrinter::EscapeXml(const char* str,
// </testsuite>
// </testsuites>
namespace internal {
// Formats the given time in milliseconds as seconds. The returned
// C-string is owned by this function and cannot be released by the
// caller. Calling the function again invalidates the previous
@ -3131,8 +3072,6 @@ const char* FormatTimeInMillisAsSeconds(TimeInMillis ms) {
return str.c_str();
}
} // namespace internal
// Prints an XML representation of a TestInfo object.
// TODO(wan): There is also value in printing properties with the plain printer.
void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
@ -3144,7 +3083,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
"classname=\"%s\"%s",
EscapeXmlAttribute(test_info.name()).c_str(),
test_info.should_run() ? "run" : "notrun",
internal::FormatTimeInMillisAsSeconds(result.elapsed_time()),
FormatTimeInMillisAsSeconds(result.elapsed_time()),
EscapeXmlAttribute(test_case_name).c_str(),
TestPropertiesAsXmlAttributes(result).c_str());
@ -3152,9 +3091,8 @@ void XmlUnitTestResultPrinter::PrintXmlTestInfo(FILE* out,
for (int i = 0; i < result.total_part_count(); ++i) {
const TestPartResult& part = result.GetTestPartResult(i);
if (part.failed()) {
const internal::String message =
internal::String::Format("%s:%d\n%s", part.file_name(),
part.line_number(), part.message());
const String message = String::Format("%s:%d\n%s", part.file_name(),
part.line_number(), part.message());
if (++failures == 1)
fprintf(out, ">\n");
fprintf(out,
@ -3182,7 +3120,7 @@ void XmlUnitTestResultPrinter::PrintXmlTestCase(FILE* out,
test_case.disabled_test_count());
fprintf(out,
"errors=\"0\" time=\"%s\">\n",
internal::FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
FormatTimeInMillisAsSeconds(test_case.elapsed_time()));
for (int i = 0; i < test_case.total_test_count(); ++i)
PrintXmlTestInfo(out, test_case.name(), *test_case.GetTestInfo(i));
fprintf(out, " </testsuite>\n");
@ -3198,7 +3136,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
unit_test.total_test_count(),
unit_test.failed_test_count(),
unit_test.disabled_test_count(),
internal::FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
FormatTimeInMillisAsSeconds(unit_test.elapsed_time()));
if (GTEST_FLAG(shuffle)) {
fprintf(out, "random_seed=\"%d\" ", unit_test.random_seed());
}
@ -3210,7 +3148,7 @@ void XmlUnitTestResultPrinter::PrintXmlUnitTest(FILE* out,
// Produces a string representing the test properties in a result as space
// delimited XML attributes based on the property key="value" pairs.
internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
const TestResult& result) {
Message attributes;
for (int i = 0; i < result.test_property_count(); ++i) {
@ -3223,8 +3161,6 @@ internal::String XmlUnitTestResultPrinter::TestPropertiesAsXmlAttributes(
// End XmlUnitTestResultPrinter
namespace internal {
// Class ScopedTrace
// Pushes the given source file location and message onto a per-thread
@ -3271,6 +3207,84 @@ OsStackTraceGetter::kElidedFramesMarker =
} // namespace internal
// class EventListeners
EventListeners::EventListeners()
: repeater_(new internal::UnitTestEventsRepeater()),
default_result_printer_(NULL),
default_xml_generator_(NULL) {
}
EventListeners::~EventListeners() { delete repeater_; }
// Returns the standard listener responsible for the default console
// output. Can be removed from the listeners list to shut down default
// console output. Note that removing this object from the listener list
// with Release transfers its ownership to the user.
void EventListeners::Append(UnitTestEventListenerInterface* listener) {
repeater_->Append(listener);
}
// Removes the given event listener from the list and returns it. It then
// becomes the caller's responsibility to delete the listener. Returns
// NULL if the listener is not found in the list.
UnitTestEventListenerInterface* EventListeners::Release(
UnitTestEventListenerInterface* listener) {
if (listener == default_result_printer_)
default_result_printer_ = NULL;
else if (listener == default_xml_generator_)
default_xml_generator_ = NULL;
return repeater_->Release(listener);
}
// Returns repeater that broadcasts the UnitTestEventListenerInterface
// events to all subscribers.
UnitTestEventListenerInterface* EventListeners::repeater() { return repeater_; }
// Sets the default_result_printer attribute to the provided listener.
// The listener is also added to the listener list and previous
// default_result_printer is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void EventListeners::SetDefaultResultPrinter(
UnitTestEventListenerInterface* listener) {
if (default_result_printer_ != listener) {
// It is an error to pass this method a listener that is already in the
// list.
delete Release(default_result_printer_);
default_result_printer_ = listener;
if (listener != NULL)
Append(listener);
}
}
// Sets the default_xml_generator attribute to the provided listener. The
// listener is also added to the listener list and previous
// default_xml_generator is removed from it and deleted. The listener can
// also be NULL in which case it will not be added to the list. Does
// nothing if the previous and the current listener objects are the same.
void EventListeners::SetDefaultXmlGenerator(
UnitTestEventListenerInterface* listener) {
if (default_xml_generator_ != listener) {
// It is an error to pass this method a listener that is already in the
// list.
delete Release(default_xml_generator_);
default_xml_generator_ = listener;
if (listener != NULL)
Append(listener);
}
}
// Controls whether events will be forwarded by the repeater to the
// listeners in the list.
bool EventListeners::EventForwardingEnabled() const {
return repeater_->forwarding_enabled();
}
void EventListeners::SuppressEventForwarding() {
repeater_->set_forwarding_enabled(false);
}
// class UnitTest
// Gets the singleton UnitTest object. The first time this method is
@ -3359,6 +3373,12 @@ const TestCase* UnitTest::GetTestCase(int i) const {
return impl()->GetTestCase(i);
}
// Returns the list of event listeners that can be used to track events
// inside Google Test.
EventListeners& UnitTest::listeners() {
return *impl()->listeners();
}
// Registers and returns a global test environment. When a test
// program is run, all global test environments will be set-up in the
// order they were registered. After all tests in the program have
@ -3614,8 +3634,8 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
current_test_case_(NULL),
current_test_info_(NULL),
ad_hoc_test_result_(),
result_printer_(NULL),
os_stack_trace_getter_(NULL),
post_flag_parse_init_performed_(false),
random_seed_(0),
#if GTEST_HAS_DEATH_TEST
elapsed_time_(0),
@ -3624,6 +3644,7 @@ UnitTestImpl::UnitTestImpl(UnitTest* parent)
#else
elapsed_time_(0) {
#endif // GTEST_HAS_DEATH_TEST
listeners()->SetDefaultResultPrinter(new PrettyUnitTestResultPrinter);
}
UnitTestImpl::~UnitTestImpl() {
@ -3633,12 +3654,58 @@ UnitTestImpl::~UnitTestImpl() {
// Deletes every Environment.
environments_.ForEach(internal::Delete<Environment>);
// Deletes the current test result printer.
delete result_printer_;
delete os_stack_trace_getter_;
}
#if GTEST_HAS_DEATH_TEST
// Disables event forwarding if the control is currently in a death test
// subprocess. Must not be called before InitGoogleTest.
void UnitTestImpl::SuppressTestEventsIfInSubprocess() {
if (internal_run_death_test_flag_.get() != NULL)
listeners()->SuppressEventForwarding();
}
#endif // GTEST_HAS_DEATH_TEST
// Initializes event listeners performing XML output as specified by
// UnitTestOptions. Must not be called before InitGoogleTest.
void UnitTestImpl::ConfigureXmlOutput() {
const String& output_format = UnitTestOptions::GetOutputFormat();
if (output_format == "xml") {
listeners()->SetDefaultXmlGenerator(new XmlUnitTestResultPrinter(
UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") {
printf("WARNING: unrecognized output format \"%s\" ignored.\n",
output_format.c_str());
fflush(stdout);
}
}
// Performs initialization dependent upon flag values obtained in
// ParseGoogleTestFlagsOnly. Is called from InitGoogleTest after the call to
// ParseGoogleTestFlagsOnly. In case a user neglects to call InitGoogleTest
// this function is also called from RunAllTests. Since this function can be
// called more than once, it has to be idempotent.
void UnitTestImpl::PostFlagParsingInit() {
// Ensures that this function does not execute more than once.
if (!post_flag_parse_init_performed_) {
post_flag_parse_init_performed_ = true;
#if GTEST_HAS_DEATH_TEST
InitDeathTestSubprocessControlInfo();
SuppressTestEventsIfInSubprocess();
#endif // GTEST_HAS_DEATH_TEST
// Registers parameterized tests. This makes parameterized tests
// available to the UnitTest reflection API without running
// RUN_ALL_TESTS.
RegisterParameterizedTests();
// Configures listeners for XML output. This makes it possible for users
// to shut down the default XML output before invoking RUN_ALL_TESTS.
ConfigureXmlOutput();
}
}
// A predicate that checks the name of a TestCase against a known
// value.
//
@ -3726,7 +3793,8 @@ int UnitTestImpl::RunAllTests() {
if (g_help_flag)
return 0;
RegisterParameterizedTests();
// TODO(vladl@google.com): Add a call to PostFlagParsingInit() here when
// merging into the main branch.
// Even if sharding is not on, test runners may want to use the
// GTEST_SHARD_STATUS_FILE to query whether the test supports the sharding
@ -3738,12 +3806,9 @@ int UnitTestImpl::RunAllTests() {
bool in_subprocess_for_death_test = false;
#if GTEST_HAS_DEATH_TEST
internal_run_death_test_flag_.reset(ParseInternalRunDeathTestFlag());
in_subprocess_for_death_test = (internal_run_death_test_flag_.get() != NULL);
#endif // GTEST_HAS_DEATH_TEST
UnitTestEventListenerInterface * const printer = result_printer();
const bool should_shard = ShouldShard(kTestTotalShards, kTestShardIndex,
in_subprocess_for_death_test);
@ -3766,6 +3831,8 @@ int UnitTestImpl::RunAllTests() {
// True iff at least one test has failed.
bool failed = false;
UnitTestEventListenerInterface* repeater = listeners()->repeater();
// How many times to repeat the tests? We don't want to repeat them
// when we are inside the subprocess of a death test.
const int repeat = in_subprocess_for_death_test ? 1 : GTEST_FLAG(repeat);
@ -3773,21 +3840,24 @@ int UnitTestImpl::RunAllTests() {
const bool forever = repeat < 0;
for (int i = 0; forever || i != repeat; i++) {
if (repeat != 1) {
// TODO(vladl@google.com): Move this output to
// PrettyUnitTestResultPrinter. Add the iteration number parameter to
// OnUnitTestStart.
printf("\nRepeating all tests (iteration %d) . . .\n\n", i + 1);
}
// Tells the unit test event listener that the tests are about to
// start.
printer->OnUnitTestStart(*parent_);
// Tells the unit test event listeners that the tests are about to start.
repeater->OnUnitTestStart(*parent_);
// TODO(vladl@google.com): Move to before the OnUnitTestStart notification?
const TimeInMillis start = GetTimeInMillis();
// Runs each test case if there is at least one test to run.
if (has_tests_to_run) {
// Sets up all environments beforehand.
printer->OnGlobalSetUpStart(*parent_);
repeater->OnGlobalSetUpStart(*parent_);
environments_.ForEach(SetUpEnvironment);
printer->OnGlobalSetUpEnd(*parent_);
repeater->OnGlobalSetUpEnd(*parent_);
// Runs the tests only if there was no fatal failure during global
// set-up.
@ -3796,16 +3866,15 @@ int UnitTestImpl::RunAllTests() {
}
// Tears down all environments in reverse order afterwards.
printer->OnGlobalTearDownStart(*parent_);
repeater->OnGlobalTearDownStart(*parent_);
environments_in_reverse_order_.ForEach(TearDownEnvironment);
printer->OnGlobalTearDownEnd(*parent_);
repeater->OnGlobalTearDownEnd(*parent_);
}
elapsed_time_ = GetTimeInMillis() - start;
// Tells the unit test event listener that the tests have just
// finished.
printer->OnUnitTestEnd(*parent_);
// Tells the unit test event listener that the tests have just finished.
repeater->OnUnitTestEnd(*parent_);
// Gets the result and clears it.
if (!Passed()) {
@ -3997,49 +4066,6 @@ void UnitTestImpl::ListTestsMatchingFilter() {
fflush(stdout);
}
// Sets the unit test result printer.
//
// Does nothing if the input and the current printer object are the
// same; otherwise, deletes the old printer object and makes the
// input the current printer.
void UnitTestImpl::set_result_printer(
UnitTestEventListenerInterface* result_printer) {
if (result_printer_ != result_printer) {
delete result_printer_;
result_printer_ = result_printer;
}
}
// Returns the current unit test result printer if it is not NULL;
// otherwise, creates an appropriate result printer, makes it the
// current printer, and returns it.
UnitTestEventListenerInterface* UnitTestImpl::result_printer() {
if (result_printer_ != NULL) {
return result_printer_;
}
#if GTEST_HAS_DEATH_TEST
if (internal_run_death_test_flag_.get() != NULL) {
result_printer_ = new NullUnitTestResultPrinter;
return result_printer_;
}
#endif // GTEST_HAS_DEATH_TEST
UnitTestEventsRepeater *repeater = new UnitTestEventsRepeater;
const String& output_format = internal::UnitTestOptions::GetOutputFormat();
if (output_format == "xml") {
repeater->AddListener(new XmlUnitTestResultPrinter(
internal::UnitTestOptions::GetAbsolutePathToOutputFile().c_str()));
} else if (output_format != "") {
printf("WARNING: unrecognized output format \"%s\" ignored.\n",
output_format.c_str());
fflush(stdout);
}
repeater->AddListener(new PrettyUnitTestResultPrinter);
result_printer_ = repeater;
return result_printer_;
}
// Sets the OS stack trace getter.
//
// Does nothing if the input and the current OS stack trace getter are
@ -4420,6 +4446,7 @@ void InitGoogleTestImpl(int* argc, CharType** argv) {
#endif // GTEST_HAS_DEATH_TEST
ParseGoogleTestFlagsOnly(argc, argv);
GetUnitTestImpl()->PostFlagParsingInit();
}
} // namespace internal

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();
}