Merge pull request #2904 from AmatanHead:throw-matchers
PiperOrigin-RevId: 327294137
diff --git a/README.md b/README.md
index 1727866..e8eefe5 100644
--- a/README.md
+++ b/README.md
@@ -25,9 +25,6 @@
projects. These were so closely related that it makes sense to maintain and
release them together.
-Please subscribe to the mailing list at googletestframework@googlegroups.com for
-questions, discussions, and development.
-
### Getting started:
The information for **Google Test** is available in the
@@ -76,8 +73,6 @@
* [Protocol Buffers](https://github.com/google/protobuf), Google's data
interchange format.
* The [OpenCV](http://opencv.org/) computer vision library.
-* [tiny-dnn](https://github.com/tiny-dnn/tiny-dnn): header only,
- dependency-free deep learning framework in C++11.
## Related Open Source Projects
@@ -113,8 +108,9 @@
Google Test is designed to have fairly minimal requirements to build and use
with your projects, but there are some. If you notice any problems on your
-platform, please notify
-[googletestframework@googlegroups.com](https://groups.google.com/forum/#!forum/googletestframework).
+platform, please file an issue on the
+[GoogleTest GitHub Issue Tracker](https://github.com/google/googletest/issues).
+
Patches for fixing them are welcome!
### Build Requirements
diff --git a/googlemock/docs/cheat_sheet.md b/googlemock/docs/cheat_sheet.md
index 85620f7..cc7e699 100644
--- a/googlemock/docs/cheat_sheet.md
+++ b/googlemock/docs/cheat_sheet.md
@@ -2,6 +2,8 @@
<!-- GOOGLETEST_CM0019 DO NOT DELETE -->
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
<!-- GOOGLETEST_CM0033 DO NOT DELETE -->
## Defining a Mock Class
@@ -616,7 +618,7 @@
<!-- mdformat off(no multiline tables) -->
| | |
| :----------------------------- | :------------------------------------------ |
-| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void. |
+| `DoAll(a1, a2, ..., an)` | Do all actions `a1` to `an` and return the result of `an` in each invocation. The first `n - 1` sub-actions must return void and will receive a readonly view of the arguments. |
| `IgnoreResult(a)` | Perform action `a` and ignore its result. `a` must not return void. |
| `WithArg<N>(a)` | Pass the `N`-th (0-based) argument of the mock function to action `a` and perform it. |
| `WithArgs<N1, N2, ..., Nk>(a)` | Pass the selected (0-based) arguments of the mock function to action `a` and perform it. |
diff --git a/googlemock/docs/cook_book.md b/googlemock/docs/cook_book.md
index 3fc1198..d7cee69 100644
--- a/googlemock/docs/cook_book.md
+++ b/googlemock/docs/cook_book.md
@@ -10,6 +10,8 @@
name `Foo` defined by gMock. We omit such `using` statements in this section for
brevity, but you should do it in your own code.
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
## Creating Mock Classes
Mock classes are defined as normal classes, using the `MOCK_METHOD` macro to
diff --git a/googlemock/docs/for_dummies.md b/googlemock/docs/for_dummies.md
index 4ce7b94..a9c012b 100644
--- a/googlemock/docs/for_dummies.md
+++ b/googlemock/docs/for_dummies.md
@@ -2,6 +2,8 @@
<!-- GOOGLETEST_CM0013 DO NOT DELETE -->
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
## What Is gMock?
When you write a prototype or test, often it's not feasible or wise to rely on
diff --git a/googlemock/docs/gmock_faq.md b/googlemock/docs/gmock_faq.md
index 7f8c647..14acae5 100644
--- a/googlemock/docs/gmock_faq.md
+++ b/googlemock/docs/gmock_faq.md
@@ -2,6 +2,8 @@
<!-- GOOGLETEST_CM0021 DO NOT DELETE -->
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
### When I call a method on my mock object, the method for the real object is invoked instead. What's the problem?
In order for a method to be mocked, it must be *virtual*, unless you use the
diff --git a/googlemock/docs/pump_manual.md b/googlemock/docs/pump_manual.md
index cdf7c57..19f1a48 100644
--- a/googlemock/docs/pump_manual.md
+++ b/googlemock/docs/pump_manual.md
@@ -1,5 +1,7 @@
<b>P</b>ump is <b>U</b>seful for <b>M</b>eta <b>P</b>rogramming.
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
# The Problem
Template and macro libraries often need to define many classes, functions, or
diff --git a/googlemock/include/gmock/gmock-actions.h b/googlemock/include/gmock/gmock-actions.h
index 79054db..3aba9ec 100644
--- a/googlemock/include/gmock/gmock-actions.h
+++ b/googlemock/include/gmock/gmock-actions.h
@@ -1032,9 +1032,13 @@
template <typename... Actions>
struct DoAllAction {
private:
- template <typename... Args, size_t... I>
- std::vector<Action<void(Args...)>> Convert(IndexSequence<I...>) const {
- return {std::get<I>(actions)...};
+ template <typename T>
+ using NonFinalType =
+ typename std::conditional<std::is_scalar<T>::value, T, const T&>::type;
+
+ template <typename ActionT, size_t... I>
+ std::vector<ActionT> Convert(IndexSequence<I...>) const {
+ return {ActionT(std::get<I>(actions))...};
}
public:
@@ -1043,17 +1047,17 @@
template <typename R, typename... Args>
operator Action<R(Args...)>() const { // NOLINT
struct Op {
- std::vector<Action<void(Args...)>> converted;
+ std::vector<Action<void(NonFinalType<Args>...)>> converted;
Action<R(Args...)> last;
R operator()(Args... args) const {
- auto tuple_args = std::forward_as_tuple(std::forward<Args>(args)...);
for (auto& a : converted) {
- a.Perform(tuple_args);
+ a.Perform(std::forward_as_tuple(std::forward<Args>(args)...));
}
- return last.Perform(tuple_args);
+ return last.Perform(std::forward_as_tuple(std::forward<Args>(args)...));
}
};
- return Op{Convert<Args...>(MakeIndexSequence<sizeof...(Actions) - 1>()),
+ return Op{Convert<Action<void(NonFinalType<Args>...)>>(
+ MakeIndexSequence<sizeof...(Actions) - 1>()),
std::get<sizeof...(Actions) - 1>(actions)};
}
};
@@ -1093,7 +1097,8 @@
typedef internal::IgnoredValue Unused;
// Creates an action that does actions a1, a2, ..., sequentially in
-// each invocation.
+// each invocation. All but the last action will have a readonly view of the
+// arguments.
template <typename... Action>
internal::DoAllAction<typename std::decay<Action>::type...> DoAll(
Action&&... action) {
diff --git a/googlemock/include/gmock/gmock-matchers.h b/googlemock/include/gmock/gmock-matchers.h
index 59ef2f3..a897611 100644
--- a/googlemock/include/gmock/gmock-matchers.h
+++ b/googlemock/include/gmock/gmock-matchers.h
@@ -4725,13 +4725,42 @@
internal::variant_matcher::VariantMatcher<T>(matcher));
}
-
#if GTEST_HAS_EXCEPTIONS
-// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION
-// and MUST NOT BE USED IN USER CODE!!!
+// 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 {
@@ -4763,12 +4792,10 @@
// 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;
+ 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)
@@ -4776,16 +4803,14 @@
void DescribeTo(std::ostream* os) const {
*os << "throws an exception which is a " << GetTypeName<Err>();
- if (matcher_.GetDescriber() != nullptr) {
- *os << " which ";
- matcher_.DescribeTo(os);
- }
+ *os << " which ";
+ matcher_.DescribeTo(os);
}
void DescribeNegationTo(std::ostream* os) const {
- *os << "not (";
- DescribeTo(os);
- *os << ")";
+ *os << "throws an exception which is not a " << GetTypeName<Err>();
+ *os << " which ";
+ matcher_.DescribeNegationTo(os);
}
template <typename T>
@@ -4794,18 +4819,14 @@
(void)(std::forward<T>(x)());
} catch (const Err& err) {
*listener << "throws an exception which is a " << GetTypeName<Err>();
- if (matcher_.GetDescriber() != nullptr) {
- *listener << " ";
- return matcher_.MatchAndExplain(err, listener);
- } else {
- return true;
- }
+ *listener << " ";
+ return matcher_.MatchAndExplain(err, listener);
} catch (DefaultExceptionType err) {
#if GTEST_HAS_RTTI
- *listener << "throws an exception of type "
- << GetTypeName(typeid(err)) << " ";
+ *listener << "throws an exception of type " << GetTypeName(typeid(err));
+ *listener << " ";
#else
- *listener << "throws an std::exception-derived error ";
+ *listener << "throws an std::exception-derived type ";
#endif
*listener << "with description \"" << err.what() << "\"";
return false;
@@ -4813,6 +4834,7 @@
*listener << "throws an exception of an unknown type";
return false;
}
+
*listener << "does not throw any exception";
return false;
}
@@ -4846,36 +4868,28 @@
// Property(&std::runtime_error::what, HasSubstr("message"))));
template <typename Err>
-PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>>
-Throws() {
+PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>> Throws() {
return MakePolymorphicMatcher(
- internal::ExceptionMatcherImpl<Err>{
- Matcher<const Err&>{}});
+ internal::ExceptionMatcherImpl<Err>(A<const Err&>()));
}
+
template <typename Err, typename ExceptionMatcher>
-PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>>
-Throws(const ExceptionMatcher& 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&>(exceptionMatcher)});
+ return MakePolymorphicMatcher(internal::ExceptionMatcherImpl<Err>(
+ SafeMatcherCast<const Err&>(exception_matcher)));
}
+
template <typename Err, typename MessageMatcher>
-PolymorphicMatcher<internal::ExceptionMatcherImpl<Err>>
-ThrowsMessage(const MessageMatcher& messageMatcher) {
- static_assert(
- std::is_base_of<std::exception, Err>::value,
- "expected an std::exception-derived class");
- // We cast matcher to std::string so that we have string semantics instead of
- // pointer semantics. With this cast, we can accept matchers that match types
- // that're constructible from strings. Also, we can accept raw string
- // literals, e.g. ThrowsMessage("message").
- return MakePolymorphicMatcher(
- internal::ExceptionMatcherImpl<Err>{
- Property("what", &std::exception::what,
- MatcherCast<std::string>(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
diff --git a/googlemock/src/gmock-spec-builders.cc b/googlemock/src/gmock-spec-builders.cc
index 346e680..05a50f6 100644
--- a/googlemock/src/gmock-spec-builders.cc
+++ b/googlemock/src/gmock-spec-builders.cc
@@ -433,10 +433,10 @@
// The UntypedFindMatchingExpectation() function acquires and
// releases g_gmock_mutex.
+
const ExpectationBase* const untyped_expectation =
- this->UntypedFindMatchingExpectation(
- untyped_args, &untyped_action, &is_excessive,
- &ss, &why);
+ this->UntypedFindMatchingExpectation(untyped_args, &untyped_action,
+ &is_excessive, &ss, &why);
const bool found = untyped_expectation != nullptr;
// True if and only if we need to print the call's arguments
@@ -461,26 +461,42 @@
untyped_expectation->DescribeLocationTo(&loc);
}
- UntypedActionResultHolderBase* const result =
- untyped_action == nullptr
- ? this->UntypedPerformDefaultAction(untyped_args, ss.str())
- : this->UntypedPerformAction(untyped_action, untyped_args);
- if (result != nullptr) result->PrintAsActionResult(&ss);
- ss << "\n" << why.str();
+ UntypedActionResultHolderBase* result = nullptr;
- if (!found) {
- // No expectation matches this call - reports a failure.
- Expect(false, nullptr, -1, ss.str());
- } else if (is_excessive) {
- // We had an upper-bound violation and the failure message is in ss.
- Expect(false, untyped_expectation->file(),
- untyped_expectation->line(), ss.str());
- } else {
- // We had an expected call and the matching expectation is
- // described in ss.
- Log(kInfo, loc.str() + ss.str(), 2);
+ auto perform_action = [&] {
+ return untyped_action == nullptr
+ ? this->UntypedPerformDefaultAction(untyped_args, ss.str())
+ : this->UntypedPerformAction(untyped_action, untyped_args);
+ };
+ auto handle_failures = [&] {
+ ss << "\n" << why.str();
+
+ if (!found) {
+ // No expectation matches this call - reports a failure.
+ Expect(false, nullptr, -1, ss.str());
+ } else if (is_excessive) {
+ // We had an upper-bound violation and the failure message is in ss.
+ Expect(false, untyped_expectation->file(), untyped_expectation->line(),
+ ss.str());
+ } else {
+ // We had an expected call and the matching expectation is
+ // described in ss.
+ Log(kInfo, loc.str() + ss.str(), 2);
+ }
+ };
+#if GTEST_HAS_EXCEPTIONS
+ try {
+ result = perform_action();
+ } catch (...) {
+ handle_failures();
+ throw;
}
+#else
+ result = perform_action();
+#endif
+ if (result != nullptr) result->PrintAsActionResult(&ss);
+ handle_failures();
return result;
}
diff --git a/googlemock/test/gmock-generated-actions_test.cc b/googlemock/test/gmock-generated-actions_test.cc
index ef39dff..6490616 100644
--- a/googlemock/test/gmock-generated-actions_test.cc
+++ b/googlemock/test/gmock-generated-actions_test.cc
@@ -422,6 +422,33 @@
EXPECT_EQ('g', g);
}
+TEST(DoAllTest, NoArgs) {
+ bool ran_first = false;
+ Action<bool()> a =
+ DoAll([&] { ran_first = true; }, [&] { return ran_first; });
+ EXPECT_TRUE(a.Perform({}));
+}
+
+TEST(DoAllTest, MoveOnlyArgs) {
+ bool ran_first = false;
+ Action<int(std::unique_ptr<int>)> a =
+ DoAll(InvokeWithoutArgs([&] { ran_first = true; }),
+ [](std::unique_ptr<int> p) { return *p; });
+ EXPECT_EQ(7, a.Perform(std::make_tuple(std::unique_ptr<int>(new int(7)))));
+ EXPECT_TRUE(ran_first);
+}
+
+TEST(DoAllTest, ImplicitlyConvertsActionArguments) {
+ bool ran_first = false;
+ // Action<void(std::vector<int>)> isn't an
+ // Action<void(const std::vector<int>&) but can be converted.
+ Action<void(std::vector<int>)> first = [&] { ran_first = true; };
+ Action<int(std::vector<int>)> a =
+ DoAll(first, [](std::vector<int> arg) { return arg.front(); });
+ EXPECT_EQ(7, a.Perform(std::make_tuple(std::vector<int>{7})));
+ EXPECT_TRUE(ran_first);
+}
+
// The ACTION*() macros trigger warning C4100 (unreferenced formal
// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in
// the macro definition, as the warnings are generated when the macro
diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc
index af3b02c..1cba156 100644
--- a/googlemock/test/gmock-matchers_test.cc
+++ b/googlemock/test/gmock-matchers_test.cc
@@ -8119,55 +8119,60 @@
#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(
- []() { throw std::runtime_error("message"); },
+ std::function<void()>([]() { throw std::runtime_error("message"); }),
Throws<std::runtime_error>());
EXPECT_THAT(
- []() { throw std::runtime_error("message"); },
+ std::function<void()>([]() { 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"))));
}
TEST(ThrowsTest, DoesNotGenerateDuplicateCatchClauseWarning) {
- EXPECT_THAT(
- []() { throw std::exception(); },
- Throws<std::exception>());
+ EXPECT_THAT(std::function<void()>([]() { throw std::exception(); }),
+ Throws<std::exception>());
}
TEST(ThrowsTest, CallableExecutedExactlyOnce) {
size_t a = 0;
- EXPECT_THAT(
- [&a]() { a++; throw 10; },
- Throws<int>());
+ EXPECT_THAT(std::function<void()>([&a]() {
+ a++;
+ throw 10;
+ }),
+ Throws<int>());
EXPECT_EQ(a, 1u);
- EXPECT_THAT(
- [&a]() { a++; throw std::runtime_error("message"); },
- Throws<std::runtime_error>());
+ EXPECT_THAT(std::function<void()>([&a]() {
+ a++;
+ throw std::runtime_error("message");
+ }),
+ Throws<std::runtime_error>());
EXPECT_EQ(a, 2u);
- EXPECT_THAT(
- [&a]() { a++; throw std::runtime_error("message"); },
- ThrowsMessage<std::runtime_error>(HasSubstr("message")));
+ EXPECT_THAT(std::function<void()>([&a]() {
+ a++;
+ throw std::runtime_error("message");
+ }),
+ ThrowsMessage<std::runtime_error>(HasSubstr("message")));
EXPECT_EQ(a, 3u);
- EXPECT_THAT(
- [&a]() { a++; throw std::runtime_error("message"); },
- Throws<std::runtime_error>(
- Property(&std::runtime_error::what, HasSubstr("message"))));
+ 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<void (*)()> matcher = Throws<std::runtime_error>();
+ Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
std::stringstream ss;
matcher.DescribeTo(&ss);
auto explanation = ss.str();
@@ -8175,50 +8180,42 @@
}
TEST(ThrowsTest, Success) {
- Matcher<void (*)()> matcher = Throws<std::runtime_error>();
+ Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
StringMatchResultListener listener;
- EXPECT_TRUE(
- matcher.MatchAndExplain(
- []() { throw std::runtime_error("error message"); }, &listener));
+ EXPECT_TRUE(matcher.MatchAndExplain(
+ []() { throw std::runtime_error("error message"); }, &listener));
EXPECT_THAT(listener.str(), HasSubstr("std::runtime_error"));
}
TEST(ThrowsTest, FailWrongType) {
- Matcher<void (*)()> matcher = Throws<std::runtime_error>();
+ Matcher<std::function<void()>> matcher = Throws<std::runtime_error>();
StringMatchResultListener listener;
- EXPECT_FALSE(
- matcher.MatchAndExplain(
- []() { throw std::logic_error("error message"); }, &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<void (*)()> matcher = Throws<std::runtime_error>();
+ 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"));
+ EXPECT_FALSE(matcher.MatchAndExplain([]() { throw 10; }, &listener));
+ EXPECT_THAT(listener.str(),
+ HasSubstr("throws an exception of an unknown type"));
}
TEST(ThrowsTest, FailNoThrow) {
- Matcher<void (*)()> matcher = Throws<std::runtime_error>();
+ 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"));
+ EXPECT_FALSE(matcher.MatchAndExplain([]() { (void)0; }, &listener));
+ EXPECT_THAT(listener.str(), HasSubstr("does not throw any exception"));
}
-class ThrowsPredicateTest: public TestWithParam<Matcher<void (*)()>> {};
+class ThrowsPredicateTest
+ : public TestWithParam<Matcher<std::function<void()>>> {};
TEST_P(ThrowsPredicateTest, Describe) {
- Matcher<void (*)()> matcher = GetParam();
+ Matcher<std::function<void()>> matcher = GetParam();
std::stringstream ss;
matcher.DescribeTo(&ss);
auto explanation = ss.str();
@@ -8227,70 +8224,56 @@
}
TEST_P(ThrowsPredicateTest, Success) {
- Matcher<void (*)()> matcher = GetParam();
+ Matcher<std::function<void()>> matcher = GetParam();
StringMatchResultListener listener;
- EXPECT_TRUE(
- matcher.MatchAndExplain(
- []() { throw std::runtime_error("error message"); }, &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<void (*)()> matcher = GetParam();
+ Matcher<std::function<void()>> matcher = GetParam();
StringMatchResultListener listener;
- EXPECT_FALSE(
- matcher.MatchAndExplain(
- []() { throw std::logic_error("error message"); }, &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<void (*)()> matcher = GetParam();
+ 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"));
+ EXPECT_FALSE(matcher.MatchAndExplain([]() { throw 10; }, &listener));
+ EXPECT_THAT(listener.str(),
+ HasSubstr("throws an exception of an unknown type"));
}
TEST_P(ThrowsPredicateTest, FailWrongMessage) {
- Matcher<void (*)()> matcher = GetParam();
+ Matcher<std::function<void()>> matcher = GetParam();
StringMatchResultListener listener;
- EXPECT_FALSE(
- matcher.MatchAndExplain(
- []() { throw std::runtime_error("wrong message"); }, &listener));
+ EXPECT_FALSE(matcher.MatchAndExplain(
+ []() { throw std::runtime_error("wrong message"); }, &listener));
EXPECT_THAT(listener.str(), HasSubstr("std::runtime_error"));
- EXPECT_THAT(listener.str(), HasSubstr("wrong message"));
+ EXPECT_THAT(listener.str(), Not(HasSubstr("wrong message")));
}
TEST_P(ThrowsPredicateTest, FailNoThrow) {
- Matcher<void (*)()> matcher = GetParam();
+ Matcher<std::function<void()>> matcher = GetParam();
StringMatchResultListener listener;
- EXPECT_FALSE(
- matcher.MatchAndExplain(
- []() { (void)0; }, &listener));
- EXPECT_THAT(
- listener.str(),
- HasSubstr("does not throw any exception"));
+ EXPECT_FALSE(matcher.MatchAndExplain([]() {}, &listener));
+ EXPECT_THAT(listener.str(), HasSubstr("does not throw any exception"));
}
-INSTANTIATE_TEST_SUITE_P(AllMessagePredicates, ThrowsPredicateTest,
- Values(
- static_cast<Matcher<void (*)()>>(
- Throws<std::runtime_error>(
- Property(&std::exception::what, HasSubstr("error message")))),
- static_cast<Matcher<void (*)()>>(
- ThrowsMessage<std::runtime_error>(HasSubstr("error message")))));
+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::exception> inner =
- Property(&std::exception::what, HasSubstr("error message"));
- Matcher<void (*)()> matcher = Throws<std::runtime_error>(inner);
+ Matcher<std::function<void()>> matcher =
+ ThrowsMessage<std::runtime_error>(HasSubstr("error message"));
EXPECT_TRUE(
matcher.Matches([]() { throw std::runtime_error("error message"); }));
EXPECT_FALSE(
@@ -8299,25 +8282,21 @@
{
Matcher<uint64_t> inner = Eq(10);
- Matcher<void (*)()> matcher = Throws<uint32_t>(inner);
- EXPECT_TRUE(
- matcher.Matches([]() { throw (uint32_t)10; }));
- EXPECT_FALSE(
- matcher.Matches([]() { throw (uint32_t)11; }));
+ 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<void (*)()> matcher = ThrowsMessage<std::runtime_error>(
- "error message");
+ 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"); }));
+ matcher.Matches([]() { throw std::runtime_error("error message"); }));
+ EXPECT_FALSE(matcher.Matches(
+ []() { throw std::runtime_error("wrong error message"); }));
}
#endif // GTEST_HAS_EXCEPTIONS
diff --git a/googlemock/test/gmock-more-actions_test.cc b/googlemock/test/gmock-more-actions_test.cc
index 97ec5cf..d6a078b 100644
--- a/googlemock/test/gmock-more-actions_test.cc
+++ b/googlemock/test/gmock-more-actions_test.cc
@@ -38,7 +38,9 @@
#include <memory>
#include <sstream>
#include <string>
+
#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
namespace testing {
@@ -604,6 +606,33 @@
EXPECT_THROW(a.Perform(std::make_tuple()), MyException);
}
+class Object {
+ public:
+ virtual ~Object() {}
+ virtual void Func() {}
+};
+
+class MockObject : public Object {
+ public:
+ ~MockObject() override {}
+ MOCK_METHOD(void, Func, (), (override));
+};
+
+TEST(ThrowActionTest, Times0) {
+ EXPECT_NONFATAL_FAILURE(
+ [] {
+ try {
+ MockObject m;
+ ON_CALL(m, Func()).WillByDefault([] { throw "something"; });
+ EXPECT_CALL(m, Func()).Times(0);
+ m.Func();
+ } catch (...) {
+ // Exception is caught but Times(0) still triggers a failure.
+ }
+ }(),
+ "");
+}
+
#endif // GTEST_HAS_EXCEPTIONS
// Tests that SetArrayArgument<N>(first, last) sets the elements of the array
diff --git a/googletest/docs/advanced.md b/googletest/docs/advanced.md
index ade87e2..32819b6 100644
--- a/googletest/docs/advanced.md
+++ b/googletest/docs/advanced.md
@@ -2,6 +2,8 @@
<!-- GOOGLETEST_CM0016 DO NOT DELETE -->
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
## Introduction
Now that you have read the [googletest Primer](primer.md) and learned how to
@@ -909,6 +911,12 @@
## Using Assertions in Sub-routines
+Note: If you want to put a series of test assertions in a subroutine to check
+for a complex condition, consider using
+[a custom GMock matcher](../../googlemock/docs/cook_book.md#NewMatchers)
+instead. This lets you provide a more readable error message in case of failure
+and avoid all of the issues described below.
+
### Adding Traces to Assertions
If a test sub-routine is called from several places, when an assertion inside it
diff --git a/googletest/docs/faq.md b/googletest/docs/faq.md
index ebfecd3..f290f02 100644
--- a/googletest/docs/faq.md
+++ b/googletest/docs/faq.md
@@ -2,6 +2,8 @@
<!-- GOOGLETEST_CM0014 DO NOT DELETE -->
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
## Why should test suite names and test names not contain underscore?
Underscore (`_`) is special, as C++ reserves the following to be used by the
diff --git a/googletest/docs/pkgconfig.md b/googletest/docs/pkgconfig.md
index b9bef3f..aed4ad4 100644
--- a/googletest/docs/pkgconfig.md
+++ b/googletest/docs/pkgconfig.md
@@ -1,5 +1,7 @@
## Using GoogleTest from various build systems
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
GoogleTest comes with pkg-config files that can be used to determine all
necessary flags for compiling and linking to GoogleTest (and GoogleMock).
Pkg-config is a standardised plain-text format containing
diff --git a/googletest/docs/primer.md b/googletest/docs/primer.md
index 2f459fd..ed44369 100644
--- a/googletest/docs/primer.md
+++ b/googletest/docs/primer.md
@@ -1,5 +1,7 @@
# Googletest Primer
+<!-- GOOGLETEST_CM0035 DO NOT DELETE -->
+
## Introduction: Why googletest?
*googletest* helps you write better C++ tests.
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index 288ff93..233724c 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -520,6 +520,7 @@
static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
SetUpTearDownSuiteFuncType test_case_fp =
GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
SetUpTearDownSuiteFuncType test_suite_fp =
@@ -531,10 +532,16 @@
<< filename << ":" << line_num;
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+ (void)(filename);
+ (void)(line_num);
+ return &T::SetUpTestSuite;
+#endif
}
static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
int line_num) {
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
SetUpTearDownSuiteFuncType test_case_fp =
GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
SetUpTearDownSuiteFuncType test_suite_fp =
@@ -546,6 +553,11 @@
<< filename << ":" << line_num;
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
+#else
+ (void)(filename);
+ (void)(line_num);
+ return &T::TearDownTestSuite;
+#endif
}
};
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index 937556b..96150f1 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -3007,9 +3007,9 @@
// Call both legacy and the new API
repeater->OnTestSuiteStart(*this);
// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
repeater->OnTestCaseStart(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->os_stack_trace_getter()->UponLeavingGTest();
internal::HandleExceptionsInMethodIfSupported(
@@ -3034,9 +3034,9 @@
// Call both legacy and the new API
repeater->OnTestSuiteEnd(*this);
// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
repeater->OnTestCaseEnd(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->set_current_test_suite(nullptr);
}
@@ -3053,9 +3053,9 @@
// Call both legacy and the new API
repeater->OnTestSuiteStart(*this);
// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
repeater->OnTestCaseStart(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
for (int i = 0; i < total_test_count(); i++) {
GetMutableTestInfo(i)->Skip();
@@ -3064,9 +3064,9 @@
// Call both legacy and the new API
repeater->OnTestSuiteEnd(*this);
// Legacy API is deprecated but still available
-#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
repeater->OnTestCaseEnd(*this);
-#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI
+#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
impl->set_current_test_suite(nullptr);
}
diff --git a/googletest/test/googletest-shuffle-test_.cc b/googletest/test/googletest-shuffle-test_.cc
index c1fc106..4505663 100644
--- a/googletest/test/googletest-shuffle-test_.cc
+++ b/googletest/test/googletest-shuffle-test_.cc
@@ -82,7 +82,7 @@
}
void OnTestStart(const TestInfo& test_info) override {
- printf("%s.%s\n", test_info.test_case_name(), test_info.name());
+ printf("%s.%s\n", test_info.test_suite_name(), test_info.name());
}
};
diff --git a/googletest/test/gtest-typed-test_test.cc b/googletest/test/gtest-typed-test_test.cc
index 0c1f660..de1db0c 100644
--- a/googletest/test/gtest-typed-test_test.cc
+++ b/googletest/test/gtest-typed-test_test.cc
@@ -193,13 +193,13 @@
if (std::is_same<TypeParam, char>::value) {
EXPECT_STREQ(::testing::UnitTest::GetInstance()
->current_test_info()
- ->test_case_name(),
+ ->test_suite_name(),
"TypedTestWithNames/char0");
}
if (std::is_same<TypeParam, int>::value) {
EXPECT_STREQ(::testing::UnitTest::GetInstance()
->current_test_info()
- ->test_case_name(),
+ ->test_suite_name(),
"TypedTestWithNames/int1");
}
}
@@ -315,13 +315,13 @@
if (std::is_same<TypeParam, char>::value) {
EXPECT_STREQ(::testing::UnitTest::GetInstance()
->current_test_info()
- ->test_case_name(),
+ ->test_suite_name(),
"CustomName/TypeParametrizedTestWithNames/parChar0");
}
if (std::is_same<TypeParam, int>::value) {
EXPECT_STREQ(::testing::UnitTest::GetInstance()
->current_test_info()
- ->test_case_name(),
+ ->test_suite_name(),
"CustomName/TypeParametrizedTestWithNames/parInt1");
}
}
diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc
index c5e2def..d7fb048 100644
--- a/googletest/test/gtest_unittest.cc
+++ b/googletest/test/gtest_unittest.cc
@@ -218,17 +218,18 @@
using testing::GTEST_FLAG(throw_on_failure);
using testing::IsNotSubstring;
using testing::IsSubstring;
+using testing::kMaxStackTraceDepth;
using testing::Message;
using testing::ScopedFakeTestPartResultReporter;
using testing::StaticAssertTypeEq;
using testing::Test;
-using testing::TestCase;
using testing::TestEventListeners;
using testing::TestInfo;
using testing::TestPartResult;
using testing::TestPartResultArray;
using testing::TestProperty;
using testing::TestResult;
+using testing::TestSuite;
using testing::TimeInMillis;
using testing::UnitTest;
using testing::internal::AlwaysFalse;
@@ -244,7 +245,6 @@
using testing::internal::ForEach;
using testing::internal::FormatEpochTimeInMillisAsIso8601;
using testing::internal::FormatTimeInMillisAsSeconds;
-using testing::internal::GTestFlagSaver;
using testing::internal::GetCurrentOsStackTraceExceptTop;
using testing::internal::GetElementOr;
using testing::internal::GetNextRandomSeed;
@@ -253,11 +253,14 @@
using testing::internal::GetTimeInMillis;
using testing::internal::GetTypeId;
using testing::internal::GetUnitTestImpl;
+using testing::internal::GTestFlagSaver;
using testing::internal::Int32FromEnvOrDie;
using testing::internal::IsAProtocolMessage;
using testing::internal::IsContainer;
using testing::internal::IsContainerTest;
using testing::internal::IsNotContainer;
+using testing::internal::kMaxRandomSeed;
+using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::NativeArray;
using testing::internal::OsStackTraceGetter;
using testing::internal::OsStackTraceGetterInterface;
@@ -279,9 +282,6 @@
using testing::internal::edit_distance::CalculateOptimalEdits;
using testing::internal::edit_distance::CreateUnifiedDiff;
using testing::internal::edit_distance::EditType;
-using testing::internal::kMaxRandomSeed;
-using testing::internal::kTestTypeIdInGoogleTest;
-using testing::kMaxStackTraceDepth;
#if GTEST_HAS_STREAM_REDIRECTION
using testing::internal::CaptureStdout;
@@ -5339,7 +5339,7 @@
TEST_F(TestInfoTest, Names) {
const TestInfo* const test_info = GetTestInfo("Names");
- ASSERT_STREQ("TestInfoTest", test_info->test_case_name());
+ ASSERT_STREQ("TestInfoTest", test_info->test_suite_name());
ASSERT_STREQ("Names", test_info->name());
}
@@ -5409,7 +5409,7 @@
// Tests setting up and tearing down a test case.
// Legacy API is deprecated but still available
-#ifndef REMOVE_LEGACY_TEST_CASEAPI
+#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
class SetUpTestCaseTest : public Test {
protected:
// This will be called once before the first test in this test case
@@ -5468,7 +5468,7 @@
TEST_F(SetUpTestCaseTest, Test2) {
EXPECT_STREQ("123", shared_resource_);
}
-#endif // REMOVE_LEGACY_TEST_CASEAPI
+#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
// Tests SetupTestSuite/TearDown TestSuite
class SetUpTestSuiteTest : public Test {
@@ -6374,8 +6374,8 @@
UnitTest::GetInstance()->current_test_info();
ASSERT_TRUE(nullptr != test_info)
<< "There is a test running so we should have a valid TestInfo.";
- EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
- << "Expected the name of the currently running test case.";
+ EXPECT_STREQ("CurrentTestInfoTest", test_info->test_suite_name())
+ << "Expected the name of the currently running test suite.";
EXPECT_STREQ("WorksForFirstTestInATestSuite", test_info->name())
<< "Expected the name of the currently running test.";
}
@@ -6389,8 +6389,8 @@
UnitTest::GetInstance()->current_test_info();
ASSERT_TRUE(nullptr != test_info)
<< "There is a test running so we should have a valid TestInfo.";
- EXPECT_STREQ("CurrentTestInfoTest", test_info->test_case_name())
- << "Expected the name of the currently running test case.";
+ EXPECT_STREQ("CurrentTestInfoTest", test_info->test_suite_name())
+ << "Expected the name of the currently running test suite.";
EXPECT_STREQ("WorksForSecondTestInATestSuite", test_info->name())
<< "Expected the name of the currently running test.";
}