Googletest export

Accept gmock matchers in EXPECT_EXIT and friends to allow matches other than simple regex matches on death output.

PiperOrigin-RevId: 223035409
This commit is contained in:
durandal 2018-11-27 15:17:28 -05:00 committed by Gennadiy Civil
parent 191f9336bc
commit b22d23667b
5 changed files with 335 additions and 249 deletions

View File

@ -97,77 +97,6 @@ class StringMatchResultListener : public MatchResultListener {
GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener);
};
// The PolymorphicMatcher class template makes it easy to implement a
// polymorphic matcher (i.e. a matcher that can match values of more
// than one type, e.g. Eq(n) and NotNull()).
//
// To define a polymorphic matcher, a user should provide an Impl
// class that has a DescribeTo() method and a DescribeNegationTo()
// method, and define a member function (or member function template)
//
// bool MatchAndExplain(const Value& value,
// MatchResultListener* listener) const;
//
// See the definition of NotNull() for a complete example.
template <class Impl>
class PolymorphicMatcher {
public:
explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
// Returns a mutable reference to the underlying matcher
// implementation object.
Impl& mutable_impl() { return impl_; }
// Returns an immutable reference to the underlying matcher
// implementation object.
const Impl& impl() const { return impl_; }
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new MonomorphicImpl<GTEST_REFERENCE_TO_CONST_(T)>(impl_));
}
private:
template <typename T>
class MonomorphicImpl : public MatcherInterface<T> {
public:
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
virtual void DescribeTo(::std::ostream* os) const {
impl_.DescribeTo(os);
}
virtual void DescribeNegationTo(::std::ostream* os) const {
impl_.DescribeNegationTo(os);
}
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
return impl_.MatchAndExplain(x, listener);
}
private:
const Impl impl_;
GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
};
Impl impl_;
GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher);
};
// Creates a polymorphic matcher from its implementation. This is
// easier to use than the PolymorphicMatcher<Impl> constructor as it
// doesn't require you to explicitly write the template argument, e.g.
//
// MakePolymorphicMatcher(foo);
// vs
// PolymorphicMatcher<TypeOfFoo>(foo);
template <class Impl>
inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
return PolymorphicMatcher<Impl>(impl);
}
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
// and MUST NOT BE USED IN USER CODE!!!
namespace internal {
@ -976,62 +905,6 @@ class EndsWithMatcher {
GTEST_DISALLOW_ASSIGN_(EndsWithMatcher);
};
// Implements polymorphic matchers MatchesRegex(regex) and
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
// T can be converted to a string.
class MatchesRegexMatcher {
public:
MatchesRegexMatcher(const RE* regex, bool full_match)
: regex_(regex), full_match_(full_match) {}
#if GTEST_HAS_ABSL
bool MatchAndExplain(const absl::string_view& s,
MatchResultListener* listener) const {
return MatchAndExplain(string(s), listener);
}
#endif // GTEST_HAS_ABSL
// Accepts pointer types, particularly:
// const char*
// char*
// const wchar_t*
// wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != nullptr && MatchAndExplain(std::string(s), listener);
}
// Matches anything that can convert to std::string.
//
// This is a template, not just a plain function with const std::string&,
// because absl::string_view has some interfering non-explicit constructors.
template <class MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const {
const std::string& s2(s);
return full_match_ ? RE::FullMatch(s2, *regex_) :
RE::PartialMatch(s2, *regex_);
}
void DescribeTo(::std::ostream* os) const {
*os << (full_match_ ? "matches" : "contains")
<< " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't " << (full_match_ ? "match" : "contain")
<< " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
private:
const std::shared_ptr<const RE> regex_;
const bool full_match_;
GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher);
};
// Implements a matcher that compares the two fields of a 2-tuple
// using one of the ==, <=, <, etc, operators. The two fields being
// compared don't have to have the same type.
@ -3935,28 +3808,6 @@ inline PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith(
return MakePolymorphicMatcher(internal::EndsWithMatcher<std::string>(suffix));
}
// Matches a string that fully matches regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const std::string& regex) {
return MatchesRegex(new internal::RE(regex));
}
// Matches a string that contains regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const std::string& regex) {
return ContainsRegex(new internal::RE(regex));
}
#if GTEST_HAS_GLOBAL_WSTRING || GTEST_HAS_STD_WSTRING
// Wide string matchers.

View File

@ -43,9 +43,9 @@
#include <ostream>
#include <string>
#include "gtest/gtest-printers.h"
#include "gtest/internal/gtest-internal.h"
#include "gtest/internal/gtest-port.h"
#include "gtest/gtest-printers.h"
GTEST_DISABLE_MSC_WARNINGS_PUSH_(
4251 5046 /* class A needs to have dll-interface to be used by clients of
@ -508,6 +508,63 @@ std::ostream& operator<<(std::ostream& os, const Matcher<T>& matcher) {
return os;
}
// The PolymorphicMatcher class template makes it easy to implement a
// polymorphic matcher (i.e. a matcher that can match values of more
// than one type, e.g. Eq(n) and NotNull()).
//
// To define a polymorphic matcher, a user should provide an Impl
// class that has a DescribeTo() method and a DescribeNegationTo()
// method, and define a member function (or member function template)
//
// bool MatchAndExplain(const Value& value,
// MatchResultListener* listener) const;
//
// See the definition of NotNull() for a complete example.
template <class Impl>
class PolymorphicMatcher {
public:
explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {}
// Returns a mutable reference to the underlying matcher
// implementation object.
Impl& mutable_impl() { return impl_; }
// Returns an immutable reference to the underlying matcher
// implementation object.
const Impl& impl() const { return impl_; }
template <typename T>
operator Matcher<T>() const {
return Matcher<T>(new MonomorphicImpl<GTEST_REFERENCE_TO_CONST_(T)>(impl_));
}
private:
template <typename T>
class MonomorphicImpl : public MatcherInterface<T> {
public:
explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {}
virtual void DescribeTo(::std::ostream* os) const { impl_.DescribeTo(os); }
virtual void DescribeNegationTo(::std::ostream* os) const {
impl_.DescribeNegationTo(os);
}
virtual bool MatchAndExplain(T x, MatchResultListener* listener) const {
return impl_.MatchAndExplain(x, listener);
}
private:
const Impl impl_;
GTEST_DISALLOW_ASSIGN_(MonomorphicImpl);
};
Impl impl_;
GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher);
};
// Creates a matcher from its implementation. This is easier to use
// than the Matcher<T> constructor as it doesn't require you to
// explicitly write the template argument, e.g.
@ -520,6 +577,18 @@ inline Matcher<T> MakeMatcher(const MatcherInterface<T>* impl) {
return Matcher<T>(impl);
}
// Creates a polymorphic matcher from its implementation. This is
// easier to use than the PolymorphicMatcher<Impl> constructor as it
// doesn't require you to explicitly write the template argument, e.g.
//
// MakePolymorphicMatcher(foo);
// vs
// PolymorphicMatcher<TypeOfFoo>(foo);
template <class Impl>
inline PolymorphicMatcher<Impl> MakePolymorphicMatcher(const Impl& impl) {
return PolymorphicMatcher<Impl>(impl);
}
namespace internal {
// Implements a matcher that compares a given value with a
// pre-supplied value using one of the ==, <=, <, etc, operators. The
@ -613,8 +682,85 @@ class GeMatcher : public ComparisonBase<GeMatcher<Rhs>, Rhs, AnyGe> {
static const char* Desc() { return "is >="; }
static const char* NegatedDesc() { return "isn't >="; }
};
// Implements polymorphic matchers MatchesRegex(regex) and
// ContainsRegex(regex), which can be used as a Matcher<T> as long as
// T can be converted to a string.
class MatchesRegexMatcher {
public:
MatchesRegexMatcher(const RE* regex, bool full_match)
: regex_(regex), full_match_(full_match) {}
#if GTEST_HAS_ABSL
bool MatchAndExplain(const absl::string_view& s,
MatchResultListener* listener) const {
return MatchAndExplain(string(s), listener);
}
#endif // GTEST_HAS_ABSL
// Accepts pointer types, particularly:
// const char*
// char*
// const wchar_t*
// wchar_t*
template <typename CharType>
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const {
return s != nullptr && MatchAndExplain(std::string(s), listener);
}
// Matches anything that can convert to std::string.
//
// This is a template, not just a plain function with const std::string&,
// because absl::string_view has some interfering non-explicit constructors.
template <class MatcheeStringType>
bool MatchAndExplain(const MatcheeStringType& s,
MatchResultListener* /* listener */) const {
const std::string& s2(s);
return full_match_ ? RE::FullMatch(s2, *regex_)
: RE::PartialMatch(s2, *regex_);
}
void DescribeTo(::std::ostream* os) const {
*os << (full_match_ ? "matches" : "contains") << " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
void DescribeNegationTo(::std::ostream* os) const {
*os << "doesn't " << (full_match_ ? "match" : "contain")
<< " regular expression ";
UniversalPrinter<std::string>::Print(regex_->pattern(), os);
}
private:
const std::shared_ptr<const RE> regex_;
const bool full_match_;
GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher);
};
} // namespace internal
// Matches a string that fully matches regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, true));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> MatchesRegex(
const std::string& regex) {
return MatchesRegex(new internal::RE(regex));
}
// Matches a string that contains regular expression 'regex'.
// The matcher takes ownership of 'regex'.
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const internal::RE* regex) {
return MakePolymorphicMatcher(internal::MatchesRegexMatcher(regex, false));
}
inline PolymorphicMatcher<internal::MatchesRegexMatcher> ContainsRegex(
const std::string& regex) {
return ContainsRegex(new internal::RE(regex));
}
// Creates a polymorphic matcher that matches anything equal to x.
// Note: if the parameter of Eq() were declared as const T&, Eq("foo")
// wouldn't compile.

View File

@ -36,6 +36,7 @@
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_DEATH_TEST_INTERNAL_H_
#include "gtest/gtest-matchers.h"
#include "gtest/internal/gtest-internal.h"
#include <stdio.h>
@ -79,7 +80,7 @@ class GTEST_API_ DeathTest {
// argument is set. If the death test should be skipped, the pointer
// is set to NULL; otherwise, it is set to the address of a new concrete
// DeathTest object that controls the execution of the current test.
static bool Create(const char* statement, const RE* regex,
static bool Create(const char* statement, Matcher<const std::string&> matcher,
const char* file, int line, DeathTest** test);
DeathTest();
virtual ~DeathTest() { }
@ -145,21 +146,51 @@ GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
class DeathTestFactory {
public:
virtual ~DeathTestFactory() { }
virtual bool Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test) = 0;
virtual bool Create(const char* statement,
Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test) = 0;
};
// A concrete DeathTestFactory implementation for normal use.
class DefaultDeathTestFactory : public DeathTestFactory {
public:
virtual bool Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test);
virtual bool Create(const char* statement,
Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test);
};
// Returns true if exit_status describes a process that was terminated
// by a signal, or exited normally with a nonzero exit code.
GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// A string passed to EXPECT_DEATH (etc.) is caught by one of these overloads
// and interpreted as a regex (rather than an Eq matcher) for legacy
// compatibility.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
::testing::internal::RE regex) {
return ContainsRegex(regex.pattern());
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(const char* regex) {
return ContainsRegex(regex);
}
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
const ::std::string& regex) {
return ContainsRegex(regex);
}
#if GTEST_HAS_GLOBAL_STRING
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
const ::string& regex) {
return ContainsRegex(regex);
}
#endif
// If a Matcher<const ::std::string&> is passed to EXPECT_DEATH (etc.), it's
// used directly.
inline Matcher<const ::std::string&> MakeDeathTestMatcher(
Matcher<const ::std::string&> matcher) {
return matcher;
}
// Traps C++ exceptions escaping statement and reports them as test
// failures. Note that trapping SEH exceptions is not implemented here.
# if GTEST_HAS_EXCEPTIONS
@ -187,37 +218,37 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// This macro is for implementing ASSERT_DEATH*, EXPECT_DEATH*,
// ASSERT_EXIT*, and EXPECT_EXIT*.
#define GTEST_DEATH_TEST_(statement, predicate, regex, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
::testing::internal::DeathTest* gtest_dt; \
if (!::testing::internal::DeathTest::Create( \
#statement, &gtest_regex, __FILE__, __LINE__, &gtest_dt)) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
if (gtest_dt != nullptr) { \
std::unique_ptr< ::testing::internal::DeathTest> \
gtest_dt_ptr(gtest_dt); \
switch (gtest_dt->AssumeRole()) { \
case ::testing::internal::DeathTest::OVERSEE_TEST: \
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
break; \
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
gtest_dt); \
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
default: \
break; \
} \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
#define GTEST_DEATH_TEST_(statement, predicate, regex_or_matcher, fail) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
::testing::internal::DeathTest* gtest_dt; \
if (!::testing::internal::DeathTest::Create( \
#statement, \
::testing::internal::MakeDeathTestMatcher(regex_or_matcher), \
__FILE__, __LINE__, &gtest_dt)) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
if (gtest_dt != nullptr) { \
std::unique_ptr< ::testing::internal::DeathTest> gtest_dt_ptr(gtest_dt); \
switch (gtest_dt->AssumeRole()) { \
case ::testing::internal::DeathTest::OVERSEE_TEST: \
if (!gtest_dt->Passed(predicate(gtest_dt->Wait()))) { \
goto GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__); \
} \
break; \
case ::testing::internal::DeathTest::EXECUTE_TEST: { \
::testing::internal::DeathTest::ReturnSentinel gtest_sentinel( \
gtest_dt); \
GTEST_EXECUTE_DEATH_TEST_STATEMENT_(statement, gtest_dt); \
gtest_dt->Abort(::testing::internal::DeathTest::TEST_DID_NOT_DIE); \
break; \
} \
default: \
break; \
} \
} \
} else \
GTEST_CONCAT_TOKEN_(gtest_label_, __LINE__) \
: fail(::testing::internal::DeathTest::LastMessage())
// The symbol "fail" here expands to something into which a message
// can be streamed.
@ -227,14 +258,13 @@ GTEST_API_ bool ExitedUnsuccessfully(int exit_status);
// must accept a streamed message even though the message is never printed.
// The regex object is not evaluated, but it is used to prevent "unused"
// warnings and to avoid an expression that doesn't compile in debug mode.
#define GTEST_EXECUTE_STATEMENT_(statement, regex) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} else if (!::testing::internal::AlwaysTrue()) { \
const ::testing::internal::RE& gtest_regex = (regex); \
static_cast<void>(gtest_regex); \
} else \
#define GTEST_EXECUTE_STATEMENT_(statement, regex_or_matcher) \
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
if (::testing::internal::AlwaysTrue()) { \
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \
} else if (!::testing::internal::AlwaysTrue()) { \
::testing::internal::MakeDeathTestMatcher(regex_or_matcher); \
} else \
::testing::Message()
// A class representing the parsed contents of the

View File

@ -31,6 +31,9 @@
// This file implements death tests.
#include "gtest/gtest-death-test.h"
#include <utility>
#include "gtest/internal/gtest-port.h"
#include "gtest/internal/custom/gtest.h"
@ -374,10 +377,11 @@ DeathTest::DeathTest() {
// Creates and returns a death test by dispatching to the current
// death test factory.
bool DeathTest::Create(const char* statement, const RE* regex,
const char* file, int line, DeathTest** test) {
bool DeathTest::Create(const char* statement,
Matcher<const std::string&> matcher, const char* file,
int line, DeathTest** test) {
return GetUnitTestImpl()->death_test_factory()->Create(
statement, regex, file, line, test);
statement, std::move(matcher), file, line, test);
}
const char* DeathTest::LastMessage() {
@ -393,9 +397,9 @@ std::string DeathTest::last_death_test_message_;
// Provides cross platform implementation for some death functionality.
class DeathTestImpl : public DeathTest {
protected:
DeathTestImpl(const char* a_statement, const RE* a_regex)
DeathTestImpl(const char* a_statement, Matcher<const std::string&> matcher)
: statement_(a_statement),
regex_(a_regex),
matcher_(std::move(matcher)),
spawned_(false),
status_(-1),
outcome_(IN_PROGRESS),
@ -409,7 +413,6 @@ class DeathTestImpl : public DeathTest {
virtual bool Passed(bool status_ok);
const char* statement() const { return statement_; }
const RE* regex() const { return regex_; }
bool spawned() const { return spawned_; }
void set_spawned(bool is_spawned) { spawned_ = is_spawned; }
int status() const { return status_; }
@ -434,9 +437,8 @@ class DeathTestImpl : public DeathTest {
// The textual content of the code this object is testing. This class
// doesn't own this string and should not attempt to delete it.
const char* const statement_;
// The regular expression which test output must match. DeathTestImpl
// doesn't own this object and should not attempt to delete it.
const RE* const regex_;
// A matcher that's expected to match the stderr output by the child process.
Matcher<const std::string&> matcher_;
// True if the death test child process has been successfully spawned.
bool spawned_;
// The exit status of the child process.
@ -555,9 +557,8 @@ static ::std::string FormatDeathTestOutput(const ::std::string& output) {
// in the format specified by wait(2). On Windows, this is the
// value supplied to the ExitProcess() API or a numeric code
// of the exception that terminated the program.
// regex: A regular expression object to be applied to
// the test's captured standard error output; the death test
// fails if it does not match.
// matcher_: A matcher that's expected to match the stderr output by the child
// process.
//
// Argument:
// status_ok: true if exit_status is acceptable in the context of
@ -591,18 +592,15 @@ bool DeathTestImpl::Passed(bool status_ok) {
break;
case DIED:
if (status_ok) {
# if GTEST_USES_PCRE
// PCRE regexes support embedded NULs.
const bool matched = RE::PartialMatch(error_message, *regex());
# else
const bool matched = RE::PartialMatch(error_message.c_str(), *regex());
# endif // GTEST_USES_PCRE
if (matched) {
if (matcher_.Matches(error_message)) {
success = true;
} else {
std::ostringstream stream;
matcher_.DescribeTo(&stream);
buffer << " Result: died but not with expected error.\n"
<< " Expected: " << regex()->pattern() << "\n"
<< "Actual msg:\n" << FormatDeathTestOutput(error_message);
<< " Expected: " << stream.str() << "\n"
<< "Actual msg:\n"
<< FormatDeathTestOutput(error_message);
}
} else {
buffer << " Result: died but not with expected exit code:\n"
@ -651,11 +649,11 @@ bool DeathTestImpl::Passed(bool status_ok) {
//
class WindowsDeathTest : public DeathTestImpl {
public:
WindowsDeathTest(const char* a_statement,
const RE* a_regex,
const char* file,
int line)
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
WindowsDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line)
: DeathTestImpl(a_statement, std::move(matcher)),
file_(file),
line_(line) {}
// All of these virtual functions are inherited from DeathTest.
virtual int Wait();
@ -815,11 +813,11 @@ DeathTest::TestRole WindowsDeathTest::AssumeRole() {
class FuchsiaDeathTest : public DeathTestImpl {
public:
FuchsiaDeathTest(const char* a_statement,
const RE* a_regex,
const char* file,
int line)
: DeathTestImpl(a_statement, a_regex), file_(file), line_(line) {}
FuchsiaDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line)
: DeathTestImpl(a_statement, std::move(matcher)),
file_(file),
line_(line) {}
// All of these virtual functions are inherited from DeathTest.
int Wait() override;
@ -1064,7 +1062,7 @@ std::string FuchsiaDeathTest::GetErrorLogs() {
// left undefined.
class ForkingDeathTest : public DeathTestImpl {
public:
ForkingDeathTest(const char* statement, const RE* regex);
ForkingDeathTest(const char* statement, Matcher<const std::string&> matcher);
// All of these virtual functions are inherited from DeathTest.
virtual int Wait();
@ -1078,9 +1076,9 @@ class ForkingDeathTest : public DeathTestImpl {
};
// Constructs a ForkingDeathTest.
ForkingDeathTest::ForkingDeathTest(const char* a_statement, const RE* a_regex)
: DeathTestImpl(a_statement, a_regex),
child_pid_(-1) {}
ForkingDeathTest::ForkingDeathTest(const char* a_statement,
Matcher<const std::string&> matcher)
: DeathTestImpl(a_statement, std::move(matcher)), child_pid_(-1) {}
// Waits for the child in a death test to exit, returning its exit
// status, or 0 if no child process exists. As a side effect, sets the
@ -1101,8 +1099,8 @@ int ForkingDeathTest::Wait() {
// in the child process.
class NoExecDeathTest : public ForkingDeathTest {
public:
NoExecDeathTest(const char* a_statement, const RE* a_regex) :
ForkingDeathTest(a_statement, a_regex) { }
NoExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher)
: ForkingDeathTest(a_statement, std::move(matcher)) {}
virtual TestRole AssumeRole();
};
@ -1156,9 +1154,11 @@ DeathTest::TestRole NoExecDeathTest::AssumeRole() {
// only this specific death test to be run.
class ExecDeathTest : public ForkingDeathTest {
public:
ExecDeathTest(const char* a_statement, const RE* a_regex,
const char* file, int line) :
ForkingDeathTest(a_statement, a_regex), file_(file), line_(line) { }
ExecDeathTest(const char* a_statement, Matcher<const std::string&> matcher,
const char* file, int line)
: ForkingDeathTest(a_statement, std::move(matcher)),
file_(file),
line_(line) {}
virtual TestRole AssumeRole();
private:
static ::std::vector<std::string> GetArgvsForDeathTestChildProcess() {
@ -1447,7 +1447,8 @@ DeathTest::TestRole ExecDeathTest::AssumeRole() {
// by the "test" argument to its address. If the test should be
// skipped, sets that pointer to NULL. Returns true, unless the
// flag is set to an invalid value.
bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
bool DefaultDeathTestFactory::Create(const char* statement,
Matcher<const std::string&> matcher,
const char* file, int line,
DeathTest** test) {
UnitTestImpl* const impl = GetUnitTestImpl();
@ -1476,22 +1477,22 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new WindowsDeathTest(statement, regex, file, line);
*test = new WindowsDeathTest(statement, std::move(matcher), file, line);
}
# elif GTEST_OS_FUCHSIA
if (GTEST_FLAG(death_test_style) == "threadsafe" ||
GTEST_FLAG(death_test_style) == "fast") {
*test = new FuchsiaDeathTest(statement, regex, file, line);
*test = new FuchsiaDeathTest(statement, std::move(matcher), file, line);
}
# else
if (GTEST_FLAG(death_test_style) == "threadsafe") {
*test = new ExecDeathTest(statement, regex, file, line);
*test = new ExecDeathTest(statement, std::move(matcher), file, line);
} else if (GTEST_FLAG(death_test_style) == "fast") {
*test = new NoExecDeathTest(statement, regex);
*test = new NoExecDeathTest(statement, std::move(matcher));
}
# endif // GTEST_OS_WINDOWS

View File

@ -31,6 +31,8 @@
// Tests for death tests.
#include "gtest/gtest-death-test.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "gtest/internal/gtest-filepath.h"
@ -59,6 +61,8 @@ using testing::internal::AlwaysTrue;
namespace posix = ::testing::internal::posix;
using testing::HasSubstr;
using testing::Matcher;
using testing::Message;
using testing::internal::DeathTest;
using testing::internal::DeathTestFactory;
@ -97,6 +101,8 @@ class ReplaceDeathTestFactory {
} // namespace internal
} // namespace testing
namespace {
void DieWithMessage(const ::std::string& message) {
fprintf(stderr, "%s", message.c_str());
fflush(stderr); // Make sure the text is printed before the process exits.
@ -452,16 +458,12 @@ TEST_F(TestForDeathTest, MixedStyles) {
# if GTEST_HAS_CLONE && GTEST_HAS_PTHREAD
namespace {
bool pthread_flag;
void SetPthreadFlag() {
pthread_flag = true;
}
} // namespace
TEST_F(TestForDeathTest, DoesNotExecuteAtforkHooks) {
if (!testing::GTEST_FLAG(death_test_use_fork)) {
testing::GTEST_FLAG(death_test_style) = "threadsafe";
@ -885,7 +887,7 @@ class MockDeathTestFactory : public DeathTestFactory {
public:
MockDeathTestFactory();
virtual bool Create(const char* statement,
const ::testing::internal::RE* regex,
testing::Matcher<const std::string&> matcher,
const char* file, int line, DeathTest** test);
// Sets the parameters for subsequent calls to Create.
@ -1000,11 +1002,9 @@ void MockDeathTestFactory::SetParameters(bool create,
// Sets test to NULL (if create_ is false) or to the address of a new
// MockDeathTest object with parameters taken from the last call
// to SetParameters (if create_ is true). Always returns true.
bool MockDeathTestFactory::Create(const char* /*statement*/,
const ::testing::internal::RE* /*regex*/,
const char* /*file*/,
int /*line*/,
DeathTest** test) {
bool MockDeathTestFactory::Create(
const char* /*statement*/, testing::Matcher<const std::string&> /*matcher*/,
const char* /*file*/, int /*line*/, DeathTest** test) {
test_deleted_ = false;
if (create_) {
*test = new MockDeathTest(this, role_, status_, passed_);
@ -1326,8 +1326,60 @@ TEST(InDeathTestChildDeathTest, ReportsDeathTestCorrectlyInThreadSafeStyle) {
}, "Inside");
}
void DieWithMessage(const char* message) {
fputs(message, stderr);
fflush(stderr); // Make sure the text is printed before the process exits.
_exit(1);
}
TEST(MatcherDeathTest, DoesNotBreakBareRegexMatching) {
// googletest tests this, of course; here we ensure that including googlemock
// has not broken it.
EXPECT_DEATH(DieWithMessage("O, I die, Horatio."), "I d[aeiou]e");
}
TEST(MatcherDeathTest, MonomorphicMatcherMatches) {
EXPECT_DEATH(DieWithMessage("Behind O, I am slain!"),
Matcher<const std::string&>(HasSubstr("I am slain")));
}
TEST(MatcherDeathTest, MonomorphicMatcherDoesNotMatch) {
EXPECT_NONFATAL_FAILURE(
EXPECT_DEATH(DieWithMessage("Behind O, I am slain!"),
Matcher<const std::string&>(HasSubstr("Ow, I am slain"))),
"Expected: has substring \"Ow, I am slain\"");
}
TEST(MatcherDeathTest, PolymorphicMatcherMatches) {
EXPECT_DEATH(DieWithMessage("The rest is silence."),
HasSubstr("rest is silence"));
}
TEST(MatcherDeathTest, PolymorphicMatcherDoesNotMatch) {
EXPECT_NONFATAL_FAILURE(EXPECT_DEATH(DieWithMessage("The rest is silence."),
HasSubstr("rest is science")),
"Expected: has substring \"rest is science\"");
}
TEST(MatcherDeathTest, CompositeMatcherMatches) {
EXPECT_DEATH(DieWithMessage("Et tu, Brute! Then fall, Caesar."),
AllOf(HasSubstr("Et tu"), HasSubstr("fall, Caesar")));
}
TEST(MatcherDeathTest, CompositeMatcherDoesNotMatch) {
EXPECT_NONFATAL_FAILURE(
EXPECT_DEATH(DieWithMessage("The rest is silence."),
AnyOf(HasSubstr("Eat two"), HasSubstr("lol Caesar"))),
"Expected: (has substring \"Eat two\") or "
"(has substring \"lol Caesar\")");
}
} // namespace
#else // !GTEST_HAS_DEATH_TEST follows
namespace {
using testing::internal::CaptureStderr;
using testing::internal::GetCapturedStderr;
@ -1376,8 +1428,12 @@ TEST(ConditionalDeathMacrosTest, AssertDeatDoesNotReturnhIfUnsupported) {
EXPECT_EQ(1, n);
}
} // namespace
#endif // !GTEST_HAS_DEATH_TEST
namespace {
// Tests that the death test macros expand to code which may or may not
// be followed by operator<<, and that in either case the complete text
// comprises only a single C++ statement.
@ -1428,3 +1484,5 @@ TEST(ConditionalDeathMacrosSyntaxDeathTest, SwitchStatement) {
TEST(NotADeathTest, Test) {
SUCCEED();
}
} // namespace