Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
googletest
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
googletest
Commits
b22d2366
Commit
b22d2366
authored
Nov 27, 2018
by
durandal
Committed by
Gennadiy Civil
Nov 28, 2018
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Googletest export
Accept gmock matchers in EXPECT_EXIT and friends to allow matches other than simple regex matches on death output. PiperOrigin-RevId: 223035409
parent
191f9336
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
335 additions
and
249 deletions
+335
-249
gmock-matchers.h
googlemock/include/gmock/gmock-matchers.h
+0
-149
gtest-matchers.h
googletest/include/gtest/gtest-matchers.h
+147
-1
gtest-death-test-internal.h
...letest/include/gtest/internal/gtest-death-test-internal.h
+74
-44
gtest-death-test.cc
googletest/src/gtest-death-test.cc
+46
-45
googletest-death-test-test.cc
googletest/test/googletest-death-test-test.cc
+68
-10
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
b22d2366
...
...
@@ -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.
...
...
googletest/include/gtest/gtest-matchers.h
View file @
b22d2366
...
...
@@ -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.
...
...
googletest/include/gtest/internal/gtest-death-test-internal.h
View file @
b22d2366
...
...
@@ -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, >est_regex, __FILE__, __LINE__, >est_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__, >est_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
...
...
googletest/src/gtest-death-test.cc
View file @
b22d2366
...
...
@@ -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
...
...
googletest/test/googletest-death-test-test.cc
View file @
b22d2366
...
...
@@ -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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment