summaryrefslogtreecommitdiffstats
path: root/googletest
diff options
context:
space:
mode:
Diffstat (limited to 'googletest')
-rw-r--r--googletest/include/gtest/gtest-matchers.h148
-rw-r--r--googletest/include/gtest/internal/gtest-death-test-internal.h118
-rw-r--r--googletest/src/gtest-death-test.cc91
-rw-r--r--googletest/test/googletest-death-test-test.cc78
4 files changed, 335 insertions, 100 deletions
diff --git a/googletest/include/gtest/gtest-matchers.h b/googletest/include/gtest/gtest-matchers.h
index 3827d7c..4601fbe 100644
--- a/googletest/include/gtest/gtest-matchers.h
+++ b/googletest/include/gtest/gtest-matchers.h
@@ -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.
diff --git a/googletest/include/gtest/internal/gtest-death-test-internal.h b/googletest/include/gtest/internal/gtest-death-test-internal.h
index c9d5908..c3d287f 100644
--- a/googletest/include/gtest/internal/gtest-death-test-internal.h
+++ b/googletest/include/gtest/internal/gtest-death-test-internal.h
@@ -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
diff --git a/googletest/src/gtest-death-test.cc b/googletest/src/gtest-death-test.cc
index fc58ea3..ff04e54 100644
--- a/googletest/src/gtest-death-test.cc
+++ b/googletest/src/gtest-death-test.cc
@@ -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
diff --git a/googletest/test/googletest-death-test-test.cc b/googletest/test/googletest-death-test-test.cc
index f92bb1a..59581d6 100644
--- a/googletest/test/googletest-death-test-test.cc
+++ b/googletest/test/googletest-death-test-test.cc
@@ -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