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
aa4cbcdc
Commit
aa4cbcdc
authored
Aug 23, 2020
by
vslashg
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2904 from AmatanHead:throw-matchers
PiperOrigin-RevId: 327294137
parents
fc1e7788
7f1c8bb4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
353 additions
and
0 deletions
+353
-0
gmock-matchers.h
googlemock/include/gmock/gmock-matchers.h
+169
-0
gmock-matchers_test.cc
googlemock/test/gmock-matchers_test.cc
+184
-0
No files found.
googlemock/include/gmock/gmock-matchers.h
View file @
aa4cbcdc
...
@@ -4725,6 +4725,175 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
...
@@ -4725,6 +4725,175 @@ PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith(
internal
::
variant_matcher
::
VariantMatcher
<
T
>
(
matcher
));
internal
::
variant_matcher
::
VariantMatcher
<
T
>
(
matcher
));
}
}
#if GTEST_HAS_EXCEPTIONS
// Anything inside the `internal` namespace is internal to the implementation
// and must not be used in user code!
namespace
internal
{
class
WithWhatMatcherImpl
{
public
:
WithWhatMatcherImpl
(
Matcher
<
std
::
string
>
matcher
)
:
matcher_
(
std
::
move
(
matcher
))
{}
void
DescribeTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"contains .what() that "
;
matcher_
.
DescribeTo
(
os
);
}
void
DescribeNegationTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"contains .what() that does not "
;
matcher_
.
DescribeTo
(
os
);
}
template
<
typename
Err
>
bool
MatchAndExplain
(
const
Err
&
err
,
MatchResultListener
*
listener
)
const
{
*
listener
<<
"which contains .what() that "
;
return
matcher_
.
MatchAndExplain
(
err
.
what
(),
listener
);
}
private
:
const
Matcher
<
std
::
string
>
matcher_
;
};
inline
PolymorphicMatcher
<
WithWhatMatcherImpl
>
WithWhat
(
Matcher
<
std
::
string
>
m
)
{
return
MakePolymorphicMatcher
(
WithWhatMatcherImpl
(
std
::
move
(
m
)));
}
template
<
typename
Err
>
class
ExceptionMatcherImpl
{
class
NeverThrown
{
public
:
const
char
*
what
()
const
noexcept
{
return
"this exception should never be thrown"
;
}
};
// If the matchee raises an exception of a wrong type, we'd like to
// catch it and print its message and type. To do that, we add an additional
// catch clause:
//
// try { ... }
// catch (const Err&) { /* an expected exception */ }
// catch (const std::exception&) { /* exception of a wrong type */ }
//
// However, if the `Err` itself is `std::exception`, we'd end up with two
// identical `catch` clauses:
//
// try { ... }
// catch (const std::exception&) { /* an expected exception */ }
// catch (const std::exception&) { /* exception of a wrong type */ }
//
// This can cause a warning or an error in some compilers. To resolve
// the issue, we use a fake error type whenever `Err` is `std::exception`:
//
// try { ... }
// catch (const std::exception&) { /* an expected exception */ }
// catch (const NeverThrown&) { /* exception of a wrong type */ }
using
DefaultExceptionType
=
typename
std
::
conditional
<
std
::
is_same
<
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
Err
>::
type
>::
type
,
std
::
exception
>::
value
,
const
NeverThrown
&
,
const
std
::
exception
&>::
type
;
public
:
ExceptionMatcherImpl
(
Matcher
<
const
Err
&>
matcher
)
:
matcher_
(
std
::
move
(
matcher
))
{}
void
DescribeTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"throws an exception which is a "
<<
GetTypeName
<
Err
>
();
*
os
<<
" which "
;
matcher_
.
DescribeTo
(
os
);
}
void
DescribeNegationTo
(
std
::
ostream
*
os
)
const
{
*
os
<<
"throws an exception which is not a "
<<
GetTypeName
<
Err
>
();
*
os
<<
" which "
;
matcher_
.
DescribeNegationTo
(
os
);
}
template
<
typename
T
>
bool
MatchAndExplain
(
T
&&
x
,
MatchResultListener
*
listener
)
const
{
try
{
(
void
)(
std
::
forward
<
T
>
(
x
)());
}
catch
(
const
Err
&
err
)
{
*
listener
<<
"throws an exception which is a "
<<
GetTypeName
<
Err
>
();
*
listener
<<
" "
;
return
matcher_
.
MatchAndExplain
(
err
,
listener
);
}
catch
(
DefaultExceptionType
err
)
{
#if GTEST_HAS_RTTI
*
listener
<<
"throws an exception of type "
<<
GetTypeName
(
typeid
(
err
));
*
listener
<<
" "
;
#else
*
listener
<<
"throws an std::exception-derived type "
;
#endif
*
listener
<<
"with description
\"
"
<<
err
.
what
()
<<
"
\"
"
;
return
false
;
}
catch
(...)
{
*
listener
<<
"throws an exception of an unknown type"
;
return
false
;
}
*
listener
<<
"does not throw any exception"
;
return
false
;
}
private
:
const
Matcher
<
const
Err
&>
matcher_
;
};
}
// namespace internal
// Throws()
// Throws(exceptionMatcher)
// ThrowsMessage(messageMatcher)
//
// This matcher accepts a callable and verifies that when invoked, it throws
// an exception with the given type and properties.
//
// Examples:
//
// EXPECT_THAT(
// []() { throw std::runtime_error("message"); },
// Throws<std::runtime_error>());
//
// EXPECT_THAT(
// []() { throw std::runtime_error("message"); },
// ThrowsMessage<std::runtime_error>(HasSubstr("message")));
//
// EXPECT_THAT(
// []() { throw std::runtime_error("message"); },
// Throws<std::runtime_error>(
// Property(&std::runtime_error::what, HasSubstr("message"))));
template
<
typename
Err
>
PolymorphicMatcher
<
internal
::
ExceptionMatcherImpl
<
Err
>>
Throws
()
{
return
MakePolymorphicMatcher
(
internal
::
ExceptionMatcherImpl
<
Err
>
(
A
<
const
Err
&>
()));
}
template
<
typename
Err
,
typename
ExceptionMatcher
>
PolymorphicMatcher
<
internal
::
ExceptionMatcherImpl
<
Err
>>
Throws
(
const
ExceptionMatcher
&
exception_matcher
)
{
// Using matcher cast allows users to pass a matcher of a more broad type.
// For example user may want to pass Matcher<std::exception>
// to Throws<std::runtime_error>, or Matcher<int64> to Throws<int32>.
return
MakePolymorphicMatcher
(
internal
::
ExceptionMatcherImpl
<
Err
>
(
SafeMatcherCast
<
const
Err
&>
(
exception_matcher
)));
}
template
<
typename
Err
,
typename
MessageMatcher
>
PolymorphicMatcher
<
internal
::
ExceptionMatcherImpl
<
Err
>>
ThrowsMessage
(
MessageMatcher
&&
message_matcher
)
{
static_assert
(
std
::
is_base_of
<
std
::
exception
,
Err
>::
value
,
"expected an std::exception-derived type"
);
return
Throws
<
Err
>
(
internal
::
WithWhat
(
MatcherCast
<
std
::
string
>
(
std
::
forward
<
MessageMatcher
>
(
message_matcher
))));
}
#endif // GTEST_HAS_EXCEPTIONS
// These macros allow using matchers to check values in Google Test
// These macros allow using matchers to check values in Google Test
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
// tests. ASSERT_THAT(value, matcher) and EXPECT_THAT(value, matcher)
// succeed if and only if the value matches the matcher. If the assertion
// succeed if and only if the value matches the matcher. If the assertion
...
...
googlemock/test/gmock-matchers_test.cc
View file @
aa4cbcdc
...
@@ -8117,6 +8117,190 @@ TEST(MatcherPMacroTest, WorksOnMoveOnlyType) {
...
@@ -8117,6 +8117,190 @@ TEST(MatcherPMacroTest, WorksOnMoveOnlyType) {
EXPECT_THAT
(
p
,
Not
(
UniquePointee
(
2
)));
EXPECT_THAT
(
p
,
Not
(
UniquePointee
(
2
)));
}
}
#if GTEST_HAS_EXCEPTIONS
// std::function<void()> is used below for compatibility with older copies of
// GCC. Normally, a raw lambda is all that is needed.
// Test that examples from documentation compile
TEST
(
ThrowsTest
,
Examples
)
{
EXPECT_THAT
(
std
::
function
<
void
()
>
([]()
{
throw
std
::
runtime_error
(
"message"
);
}),
Throws
<
std
::
runtime_error
>
());
EXPECT_THAT
(
std
::
function
<
void
()
>
([]()
{
throw
std
::
runtime_error
(
"message"
);
}),
ThrowsMessage
<
std
::
runtime_error
>
(
HasSubstr
(
"message"
)));
}
TEST
(
ThrowsTest
,
DoesNotGenerateDuplicateCatchClauseWarning
)
{
EXPECT_THAT
(
std
::
function
<
void
()
>
([]()
{
throw
std
::
exception
();
}),
Throws
<
std
::
exception
>
());
}
TEST
(
ThrowsTest
,
CallableExecutedExactlyOnce
)
{
size_t
a
=
0
;
EXPECT_THAT
(
std
::
function
<
void
()
>
([
&
a
]()
{
a
++
;
throw
10
;
}),
Throws
<
int
>
());
EXPECT_EQ
(
a
,
1u
);
EXPECT_THAT
(
std
::
function
<
void
()
>
([
&
a
]()
{
a
++
;
throw
std
::
runtime_error
(
"message"
);
}),
Throws
<
std
::
runtime_error
>
());
EXPECT_EQ
(
a
,
2u
);
EXPECT_THAT
(
std
::
function
<
void
()
>
([
&
a
]()
{
a
++
;
throw
std
::
runtime_error
(
"message"
);
}),
ThrowsMessage
<
std
::
runtime_error
>
(
HasSubstr
(
"message"
)));
EXPECT_EQ
(
a
,
3u
);
EXPECT_THAT
(
std
::
function
<
void
()
>
([
&
a
]()
{
a
++
;
throw
std
::
runtime_error
(
"message"
);
}),
Throws
<
std
::
runtime_error
>
(
Property
(
&
std
::
runtime_error
::
what
,
HasSubstr
(
"message"
))));
EXPECT_EQ
(
a
,
4u
);
}
TEST
(
ThrowsTest
,
Describe
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
std
::
runtime_error
>
();
std
::
stringstream
ss
;
matcher
.
DescribeTo
(
&
ss
);
auto
explanation
=
ss
.
str
();
EXPECT_THAT
(
explanation
,
HasSubstr
(
"std::runtime_error"
));
}
TEST
(
ThrowsTest
,
Success
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
std
::
runtime_error
>
();
StringMatchResultListener
listener
;
EXPECT_TRUE
(
matcher
.
MatchAndExplain
(
[]()
{
throw
std
::
runtime_error
(
"error message"
);
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"std::runtime_error"
));
}
TEST
(
ThrowsTest
,
FailWrongType
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
std
::
runtime_error
>
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
(
[]()
{
throw
std
::
logic_error
(
"error message"
);
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"std::logic_error"
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"
\"
error message
\"
"
));
}
TEST
(
ThrowsTest
,
FailWrongTypeNonStd
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
std
::
runtime_error
>
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
([]()
{
throw
10
;
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"throws an exception of an unknown type"
));
}
TEST
(
ThrowsTest
,
FailNoThrow
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
std
::
runtime_error
>
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
([]()
{
(
void
)
0
;
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"does not throw any exception"
));
}
class
ThrowsPredicateTest
:
public
TestWithParam
<
Matcher
<
std
::
function
<
void
()
>>>
{};
TEST_P
(
ThrowsPredicateTest
,
Describe
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
std
::
stringstream
ss
;
matcher
.
DescribeTo
(
&
ss
);
auto
explanation
=
ss
.
str
();
EXPECT_THAT
(
explanation
,
HasSubstr
(
"std::runtime_error"
));
EXPECT_THAT
(
explanation
,
HasSubstr
(
"error message"
));
}
TEST_P
(
ThrowsPredicateTest
,
Success
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
StringMatchResultListener
listener
;
EXPECT_TRUE
(
matcher
.
MatchAndExplain
(
[]()
{
throw
std
::
runtime_error
(
"error message"
);
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"std::runtime_error"
));
}
TEST_P
(
ThrowsPredicateTest
,
FailWrongType
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
(
[]()
{
throw
std
::
logic_error
(
"error message"
);
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"std::logic_error"
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"
\"
error message
\"
"
));
}
TEST_P
(
ThrowsPredicateTest
,
FailWrongTypeNonStd
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
([]()
{
throw
10
;
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"throws an exception of an unknown type"
));
}
TEST_P
(
ThrowsPredicateTest
,
FailWrongMessage
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
(
[]()
{
throw
std
::
runtime_error
(
"wrong message"
);
},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"std::runtime_error"
));
EXPECT_THAT
(
listener
.
str
(),
Not
(
HasSubstr
(
"wrong message"
)));
}
TEST_P
(
ThrowsPredicateTest
,
FailNoThrow
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
GetParam
();
StringMatchResultListener
listener
;
EXPECT_FALSE
(
matcher
.
MatchAndExplain
([]()
{},
&
listener
));
EXPECT_THAT
(
listener
.
str
(),
HasSubstr
(
"does not throw any exception"
));
}
INSTANTIATE_TEST_SUITE_P
(
AllMessagePredicates
,
ThrowsPredicateTest
,
Values
(
Matcher
<
std
::
function
<
void
()
>>
(
ThrowsMessage
<
std
::
runtime_error
>
(
HasSubstr
(
"error message"
)))));
// Tests that Throws<E1>(Matcher<E2>{}) compiles even when E2 != const E1&.
TEST
(
ThrowsPredicateCompilesTest
,
ExceptionMatcherAcceptsBroadType
)
{
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
ThrowsMessage
<
std
::
runtime_error
>
(
HasSubstr
(
"error message"
));
EXPECT_TRUE
(
matcher
.
Matches
([]()
{
throw
std
::
runtime_error
(
"error message"
);
}));
EXPECT_FALSE
(
matcher
.
Matches
([]()
{
throw
std
::
runtime_error
(
"wrong message"
);
}));
}
{
Matcher
<
uint64_t
>
inner
=
Eq
(
10
);
Matcher
<
std
::
function
<
void
()
>>
matcher
=
Throws
<
uint32_t
>
(
inner
);
EXPECT_TRUE
(
matcher
.
Matches
([]()
{
throw
(
uint32_t
)
10
;
}));
EXPECT_FALSE
(
matcher
.
Matches
([]()
{
throw
(
uint32_t
)
11
;
}));
}
}
// Tests that ThrowsMessage("message") is equivalent
// to ThrowsMessage(Eq<std::string>("message")).
TEST
(
ThrowsPredicateCompilesTest
,
MessageMatcherAcceptsNonMatcher
)
{
Matcher
<
std
::
function
<
void
()
>>
matcher
=
ThrowsMessage
<
std
::
runtime_error
>
(
"error message"
);
EXPECT_TRUE
(
matcher
.
Matches
([]()
{
throw
std
::
runtime_error
(
"error message"
);
}));
EXPECT_FALSE
(
matcher
.
Matches
(
[]()
{
throw
std
::
runtime_error
(
"wrong error message"
);
}));
}
#endif // GTEST_HAS_EXCEPTIONS
}
// namespace
}
// namespace
}
// namespace gmock_matchers_test
}
// namespace gmock_matchers_test
}
// namespace testing
}
// namespace testing
...
...
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