gmock-matchers.h (googletest-release-1.10.0) | : | gmock-matchers.h (googletest-release-1.11.0) | ||
---|---|---|---|---|
skipping to change at line 32 | skipping to change at line 32 | |||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
// Google Mock - a framework for writing C++ mock classes. | // Google Mock - a framework for writing C++ mock classes. | |||
// | // | |||
// This file implements some commonly used argument matchers. More | // The MATCHER* family of macros can be used in a namespace scope to | |||
// define custom matchers easily. | ||||
// | ||||
// Basic Usage | ||||
// =========== | ||||
// | ||||
// The syntax | ||||
// | ||||
// MATCHER(name, description_string) { statements; } | ||||
// | ||||
// defines a matcher with the given name that executes the statements, | ||||
// which must return a bool to indicate if the match succeeds. Inside | ||||
// the statements, you can refer to the value being matched by 'arg', | ||||
// and refer to its type by 'arg_type'. | ||||
// | ||||
// The description string documents what the matcher does, and is used | ||||
// to generate the failure message when the match fails. Since a | ||||
// MATCHER() is usually defined in a header file shared by multiple | ||||
// C++ source files, we require the description to be a C-string | ||||
// literal to avoid possible side effects. It can be empty, in which | ||||
// case we'll use the sequence of words in the matcher name as the | ||||
// description. | ||||
// | ||||
// For example: | ||||
// | ||||
// MATCHER(IsEven, "") { return (arg % 2) == 0; } | ||||
// | ||||
// allows you to write | ||||
// | ||||
// // Expects mock_foo.Bar(n) to be called where n is even. | ||||
// EXPECT_CALL(mock_foo, Bar(IsEven())); | ||||
// | ||||
// or, | ||||
// | ||||
// // Verifies that the value of some_expression is even. | ||||
// EXPECT_THAT(some_expression, IsEven()); | ||||
// | ||||
// If the above assertion fails, it will print something like: | ||||
// | ||||
// Value of: some_expression | ||||
// Expected: is even | ||||
// Actual: 7 | ||||
// | ||||
// where the description "is even" is automatically calculated from the | ||||
// matcher name IsEven. | ||||
// | ||||
// Argument Type | ||||
// ============= | ||||
// | ||||
// Note that the type of the value being matched (arg_type) is | ||||
// determined by the context in which you use the matcher and is | ||||
// supplied to you by the compiler, so you don't need to worry about | ||||
// declaring it (nor can you). This allows the matcher to be | ||||
// polymorphic. For example, IsEven() can be used to match any type | ||||
// where the value of "(arg % 2) == 0" can be implicitly converted to | ||||
// a bool. In the "Bar(IsEven())" example above, if method Bar() | ||||
// takes an int, 'arg_type' will be int; if it takes an unsigned long, | ||||
// 'arg_type' will be unsigned long; and so on. | ||||
// | ||||
// Parameterizing Matchers | ||||
// ======================= | ||||
// | ||||
// Sometimes you'll want to parameterize the matcher. For that you | ||||
// can use another macro: | ||||
// | ||||
// MATCHER_P(name, param_name, description_string) { statements; } | ||||
// | ||||
// For example: | ||||
// | ||||
// MATCHER_P(HasAbsoluteValue, value, "") { return abs(arg) == value; } | ||||
// | ||||
// will allow you to write: | ||||
// | ||||
// EXPECT_THAT(Blah("a"), HasAbsoluteValue(n)); | ||||
// | ||||
// which may lead to this message (assuming n is 10): | ||||
// | ||||
// Value of: Blah("a") | ||||
// Expected: has absolute value 10 | ||||
// Actual: -9 | ||||
// | ||||
// Note that both the matcher description and its parameter are | ||||
// printed, making the message human-friendly. | ||||
// | ||||
// In the matcher definition body, you can write 'foo_type' to | ||||
// reference the type of a parameter named 'foo'. For example, in the | ||||
// body of MATCHER_P(HasAbsoluteValue, value) above, you can write | ||||
// 'value_type' to refer to the type of 'value'. | ||||
// | ||||
// We also provide MATCHER_P2, MATCHER_P3, ..., up to MATCHER_P$n to | ||||
// support multi-parameter matchers. | ||||
// | ||||
// Describing Parameterized Matchers | ||||
// ================================= | ||||
// | ||||
// The last argument to MATCHER*() is a string-typed expression. The | ||||
// expression can reference all of the matcher's parameters and a | ||||
// special bool-typed variable named 'negation'. When 'negation' is | ||||
// false, the expression should evaluate to the matcher's description; | ||||
// otherwise it should evaluate to the description of the negation of | ||||
// the matcher. For example, | ||||
// | ||||
// using testing::PrintToString; | ||||
// | ||||
// MATCHER_P2(InClosedRange, low, hi, | ||||
// std::string(negation ? "is not" : "is") + " in range [" + | ||||
// PrintToString(low) + ", " + PrintToString(hi) + "]") { | ||||
// return low <= arg && arg <= hi; | ||||
// } | ||||
// ... | ||||
// EXPECT_THAT(3, InClosedRange(4, 6)); | ||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4))); | ||||
// | ||||
// would generate two failures that contain the text: | ||||
// | ||||
// Expected: is in range [4, 6] | ||||
// ... | ||||
// Expected: is not in range [2, 4] | ||||
// | ||||
// If you specify "" as the description, the failure message will | ||||
// contain the sequence of words in the matcher name followed by the | ||||
// parameter values printed as a tuple. For example, | ||||
// | ||||
// MATCHER_P2(InClosedRange, low, hi, "") { ... } | ||||
// ... | ||||
// EXPECT_THAT(3, InClosedRange(4, 6)); | ||||
// EXPECT_THAT(3, Not(InClosedRange(2, 4))); | ||||
// | ||||
// would generate two failures that contain the text: | ||||
// | ||||
// Expected: in closed range (4, 6) | ||||
// ... | ||||
// Expected: not (in closed range (2, 4)) | ||||
// | ||||
// Types of Matcher Parameters | ||||
// =========================== | ||||
// | ||||
// For the purpose of typing, you can view | ||||
// | ||||
// MATCHER_Pk(Foo, p1, ..., pk, description_string) { ... } | ||||
// | ||||
// as shorthand for | ||||
// | ||||
// template <typename p1_type, ..., typename pk_type> | ||||
// FooMatcherPk<p1_type, ..., pk_type> | ||||
// Foo(p1_type p1, ..., pk_type pk) { ... } | ||||
// | ||||
// When you write Foo(v1, ..., vk), the compiler infers the types of | ||||
// the parameters v1, ..., and vk for you. If you are not happy with | ||||
// the result of the type inference, you can specify the types by | ||||
// explicitly instantiating the template, as in Foo<long, bool>(5, | ||||
// false). As said earlier, you don't get to (or need to) specify | ||||
// 'arg_type' as that's determined by the context in which the matcher | ||||
// is used. You can assign the result of expression Foo(p1, ..., pk) | ||||
// to a variable of type FooMatcherPk<p1_type, ..., pk_type>. This | ||||
// can be useful when composing matchers. | ||||
// | ||||
// While you can instantiate a matcher template with reference types, | ||||
// passing the parameters by pointer usually makes your code more | ||||
// readable. If, however, you still want to pass a parameter by | ||||
// reference, be aware that in the failure message generated by the | ||||
// matcher you will see the value of the referenced object but not its | ||||
// address. | ||||
// | ||||
// Explaining Match Results | ||||
// ======================== | ||||
// | ||||
// Sometimes the matcher description alone isn't enough to explain why | ||||
// the match has failed or succeeded. For example, when expecting a | ||||
// long string, it can be very helpful to also print the diff between | ||||
// the expected string and the actual one. To achieve that, you can | ||||
// optionally stream additional information to a special variable | ||||
// named result_listener, whose type is a pointer to class | ||||
// MatchResultListener: | ||||
// | ||||
// MATCHER_P(EqualsLongString, str, "") { | ||||
// if (arg == str) return true; | ||||
// | ||||
// *result_listener << "the difference: " | ||||
/// << DiffStrings(str, arg); | ||||
// return false; | ||||
// } | ||||
// | ||||
// Overloading Matchers | ||||
// ==================== | ||||
// | ||||
// You can overload matchers with different numbers of parameters: | ||||
// | ||||
// MATCHER_P(Blah, a, description_string1) { ... } | ||||
// MATCHER_P2(Blah, a, b, description_string2) { ... } | ||||
// | ||||
// Caveats | ||||
// ======= | ||||
// | ||||
// When defining a new matcher, you should also consider implementing | ||||
// MatcherInterface or using MakePolymorphicMatcher(). These | ||||
// approaches require more work than the MATCHER* macros, but also | ||||
// give you more control on the types of the value being matched and | ||||
// the matcher parameters, which may leads to better compiler error | ||||
// messages when the matcher is used wrong. They also allow | ||||
// overloading matchers based on parameter types (as opposed to just | ||||
// based on the number of parameters). | ||||
// | ||||
// MATCHER*() can only be used in a namespace scope as templates cannot be | ||||
// declared inside of a local class. | ||||
// | ||||
// More Information | ||||
// ================ | ||||
// | ||||
// To learn more about using these macros, please search for 'MATCHER' | ||||
// on | ||||
// https://github.com/google/googletest/blob/master/docs/gmock_cook_book.md | ||||
// | ||||
// This file also implements some commonly used argument matchers. More | ||||
// matchers can be defined by the user implementing the | // matchers can be defined by the user implementing the | |||
// MatcherInterface<T> interface if necessary. | // MatcherInterface<T> interface if necessary. | |||
// | // | |||
// See googletest/include/gtest/gtest-matchers.h for the definition of class | // See googletest/include/gtest/gtest-matchers.h for the definition of class | |||
// Matcher, class MatcherInterface, and others. | // Matcher, class MatcherInterface, and others. | |||
// GOOGLETEST_CM0002 DO NOT DELETE | // GOOGLETEST_CM0002 DO NOT DELETE | |||
#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | #ifndef GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | |||
#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | #define GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | |||
#include <math.h> | ||||
#include <algorithm> | #include <algorithm> | |||
#include <cmath> | ||||
#include <initializer_list> | #include <initializer_list> | |||
#include <iterator> | #include <iterator> | |||
#include <limits> | #include <limits> | |||
#include <memory> | #include <memory> | |||
#include <ostream> // NOLINT | #include <ostream> // NOLINT | |||
#include <sstream> | #include <sstream> | |||
#include <string> | #include <string> | |||
#include <type_traits> | #include <type_traits> | |||
#include <utility> | #include <utility> | |||
#include <vector> | #include <vector> | |||
#include "gmock/internal/gmock-internal-utils.h" | #include "gmock/internal/gmock-internal-utils.h" | |||
#include "gmock/internal/gmock-port.h" | #include "gmock/internal/gmock-port.h" | |||
#include "gmock/internal/gmock-pp.h" | ||||
#include "gtest/gtest.h" | #include "gtest/gtest.h" | |||
// MSVC warning C5046 is new as of VS2017 version 15.8. | // MSVC warning C5046 is new as of VS2017 version 15.8. | |||
#if defined(_MSC_VER) && _MSC_VER >= 1915 | #if defined(_MSC_VER) && _MSC_VER >= 1915 | |||
#define GMOCK_MAYBE_5046_ 5046 | #define GMOCK_MAYBE_5046_ 5046 | |||
#else | #else | |||
#define GMOCK_MAYBE_5046_ | #define GMOCK_MAYBE_5046_ | |||
#endif | #endif | |||
GTEST_DISABLE_MSC_WARNINGS_PUSH_( | GTEST_DISABLE_MSC_WARNINGS_PUSH_( | |||
skipping to change at line 130 | skipping to change at line 345 | |||
static Matcher<T> Cast(const M& polymorphic_matcher_or_value) { | static Matcher<T> Cast(const M& polymorphic_matcher_or_value) { | |||
// M can be a polymorphic matcher, in which case we want to use | // M can be a polymorphic matcher, in which case we want to use | |||
// its conversion operator to create Matcher<T>. Or it can be a value | // its conversion operator to create Matcher<T>. Or it can be a value | |||
// that should be passed to the Matcher<T>'s constructor. | // that should be passed to the Matcher<T>'s constructor. | |||
// | // | |||
// We can't call Matcher<T>(polymorphic_matcher_or_value) when M is a | // We can't call Matcher<T>(polymorphic_matcher_or_value) when M is a | |||
// polymorphic matcher because it'll be ambiguous if T has an implicit | // polymorphic matcher because it'll be ambiguous if T has an implicit | |||
// constructor from M (this usually happens when T has an implicit | // constructor from M (this usually happens when T has an implicit | |||
// constructor from any type). | // constructor from any type). | |||
// | // | |||
// It won't work to unconditionally implict_cast | // It won't work to unconditionally implicit_cast | |||
// polymorphic_matcher_or_value to Matcher<T> because it won't trigger | // polymorphic_matcher_or_value to Matcher<T> because it won't trigger | |||
// a user-defined conversion from M to T if one exists (assuming M is | // a user-defined conversion from M to T if one exists (assuming M is | |||
// a value). | // a value). | |||
return CastImpl(polymorphic_matcher_or_value, | return CastImpl(polymorphic_matcher_or_value, | |||
std::is_convertible<M, Matcher<T>>{}, | std::is_convertible<M, Matcher<T>>{}, | |||
std::is_convertible<M, T>{}); | std::is_convertible<M, T>{}); | |||
} | } | |||
private: | private: | |||
template <bool Ignore> | template <bool Ignore> | |||
static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value, | static Matcher<T> CastImpl(const M& polymorphic_matcher_or_value, | |||
std::true_type /* convertible_to_matcher */, | std::true_type /* convertible_to_matcher */, | |||
bool_constant<Ignore>) { | std::integral_constant<bool, Ignore>) { | |||
// M is implicitly convertible to Matcher<T>, which means that either | // M is implicitly convertible to Matcher<T>, which means that either | |||
// M is a polymorphic matcher or Matcher<T> has an implicit constructor | // M is a polymorphic matcher or Matcher<T> has an implicit constructor | |||
// from M. In both cases using the implicit conversion will produce a | // from M. In both cases using the implicit conversion will produce a | |||
// matcher. | // matcher. | |||
// | // | |||
// Even if T has an implicit constructor from M, it won't be called because | // Even if T has an implicit constructor from M, it won't be called because | |||
// creating Matcher<T> would require a chain of two user-defined conversions | // creating Matcher<T> would require a chain of two user-defined conversions | |||
// (first to create T from M and then to create Matcher<T> from T). | // (first to create T from M and then to create Matcher<T> from T). | |||
return polymorphic_matcher_or_value; | return polymorphic_matcher_or_value; | |||
} | } | |||
skipping to change at line 211 | skipping to change at line 426 | |||
// Do not allow implicitly converting base*/& to derived*/&. | // Do not allow implicitly converting base*/& to derived*/&. | |||
static_assert( | static_assert( | |||
// Do not trigger if only one of them is a pointer. That implies a | // Do not trigger if only one of them is a pointer. That implies a | |||
// regular conversion and not a down_cast. | // regular conversion and not a down_cast. | |||
(std::is_pointer<typename std::remove_reference<T>::type>::value != | (std::is_pointer<typename std::remove_reference<T>::type>::value != | |||
std::is_pointer<typename std::remove_reference<U>::type>::value) || | std::is_pointer<typename std::remove_reference<U>::type>::value) || | |||
std::is_same<FromType, ToType>::value || | std::is_same<FromType, ToType>::value || | |||
!std::is_base_of<FromType, ToType>::value, | !std::is_base_of<FromType, ToType>::value, | |||
"Can't implicitly convert from <base> to <derived>"); | "Can't implicitly convert from <base> to <derived>"); | |||
return source_matcher_.MatchAndExplain(static_cast<U>(x), listener); | // Do the cast to `U` explicitly if necessary. | |||
// Otherwise, let implicit conversions do the trick. | ||||
using CastType = | ||||
typename std::conditional<std::is_convertible<T&, const U&>::value, | ||||
T&, U>::type; | ||||
return source_matcher_.MatchAndExplain(static_cast<CastType>(x), | ||||
listener); | ||||
} | } | |||
void DescribeTo(::std::ostream* os) const override { | void DescribeTo(::std::ostream* os) const override { | |||
source_matcher_.DescribeTo(os); | source_matcher_.DescribeTo(os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
source_matcher_.DescribeNegationTo(os); | source_matcher_.DescribeNegationTo(os); | |||
} | } | |||
private: | private: | |||
const Matcher<U> source_matcher_; | const Matcher<U> source_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
}; | }; | |||
// This even more specialized version is used for efficiently casting | // This even more specialized version is used for efficiently casting | |||
// a matcher to its own type. | // a matcher to its own type. | |||
template <typename T> | template <typename T> | |||
class MatcherCastImpl<T, Matcher<T> > { | class MatcherCastImpl<T, Matcher<T> > { | |||
public: | public: | |||
static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; } | static Matcher<T> Cast(const Matcher<T>& matcher) { return matcher; } | |||
}; | }; | |||
// Template specialization for parameterless Matcher. | ||||
template <typename Derived> | ||||
class MatcherBaseImpl { | ||||
public: | ||||
MatcherBaseImpl() = default; | ||||
template <typename T> | ||||
operator ::testing::Matcher<T>() const { // NOLINT(runtime/explicit) | ||||
return ::testing::Matcher<T>(new | ||||
typename Derived::template gmock_Impl<T>()); | ||||
} | ||||
}; | ||||
// Template specialization for Matcher with parameters. | ||||
template <template <typename...> class Derived, typename... Ts> | ||||
class MatcherBaseImpl<Derived<Ts...>> { | ||||
public: | ||||
// Mark the constructor explicit for single argument T to avoid implicit | ||||
// conversions. | ||||
template <typename E = std::enable_if<sizeof...(Ts) == 1>, | ||||
typename E::type* = nullptr> | ||||
explicit MatcherBaseImpl(Ts... params) | ||||
: params_(std::forward<Ts>(params)...) {} | ||||
template <typename E = std::enable_if<sizeof...(Ts) != 1>, | ||||
typename = typename E::type> | ||||
MatcherBaseImpl(Ts... params) // NOLINT | ||||
: params_(std::forward<Ts>(params)...) {} | ||||
template <typename F> | ||||
operator ::testing::Matcher<F>() const { // NOLINT(runtime/explicit) | ||||
return Apply<F>(MakeIndexSequence<sizeof...(Ts)>{}); | ||||
} | ||||
private: | ||||
template <typename F, std::size_t... tuple_ids> | ||||
::testing::Matcher<F> Apply(IndexSequence<tuple_ids...>) const { | ||||
return ::testing::Matcher<F>( | ||||
new typename Derived<Ts...>::template gmock_Impl<F>( | ||||
std::get<tuple_ids>(params_)...)); | ||||
} | ||||
const std::tuple<Ts...> params_; | ||||
}; | ||||
} // namespace internal | } // namespace internal | |||
// In order to be safe and clear, casting between different matcher | // In order to be safe and clear, casting between different matcher | |||
// types is done explicitly via MatcherCast<T>(m), which takes a | // types is done explicitly via MatcherCast<T>(m), which takes a | |||
// matcher m and returns a Matcher<T>. It compiles only when T can be | // matcher m and returns a Matcher<T>. It compiles only when T can be | |||
// statically converted to the argument type of m. | // statically converted to the argument type of m. | |||
template <typename T, typename M> | template <typename T, typename M> | |||
inline Matcher<T> MatcherCast(const M& matcher) { | inline Matcher<T> MatcherCast(const M& matcher) { | |||
return internal::MatcherCastImpl<T, M>::Cast(matcher); | return internal::MatcherCastImpl<T, M>::Cast(matcher); | |||
} | } | |||
// Implements SafeMatcherCast(). | // This overload handles polymorphic matchers and values only since | |||
// | // monomorphic matchers are handled by the next one. | |||
// FIXME: The intermediate SafeMatcherCastImpl class was introduced as a | ||||
// workaround for a compiler bug, and can now be removed. | ||||
template <typename T> | ||||
class SafeMatcherCastImpl { | ||||
public: | ||||
// This overload handles polymorphic matchers and values only since | ||||
// monomorphic matchers are handled by the next one. | ||||
template <typename M> | ||||
static inline Matcher<T> Cast(const M& polymorphic_matcher_or_value) { | ||||
return internal::MatcherCastImpl<T, M>::Cast(polymorphic_matcher_or_value); | ||||
} | ||||
// This overload handles monomorphic matchers. | ||||
// | ||||
// In general, if type T can be implicitly converted to type U, we can | ||||
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is | ||||
// contravariant): just keep a copy of the original Matcher<U>, convert the | ||||
// argument from type T to U, and then pass it to the underlying Matcher<U>. | ||||
// The only exception is when U is a reference and T is not, as the | ||||
// underlying Matcher<U> may be interested in the argument's address, which | ||||
// is not preserved in the conversion from T to U. | ||||
template <typename U> | ||||
static inline Matcher<T> Cast(const Matcher<U>& matcher) { | ||||
// Enforce that T can be implicitly converted to U. | ||||
GTEST_COMPILE_ASSERT_((std::is_convertible<T, U>::value), | ||||
"T must be implicitly convertible to U"); | ||||
// Enforce that we are not converting a non-reference type T to a reference | ||||
// type U. | ||||
GTEST_COMPILE_ASSERT_( | ||||
std::is_reference<T>::value || !std::is_reference<U>::value, | ||||
cannot_convert_non_reference_arg_to_reference); | ||||
// In case both T and U are arithmetic types, enforce that the | ||||
// conversion is not lossy. | ||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; | ||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; | ||||
const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; | ||||
const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; | ||||
GTEST_COMPILE_ASSERT_( | ||||
kTIsOther || kUIsOther || | ||||
(internal::LosslessArithmeticConvertible<RawT, RawU>::value), | ||||
conversion_of_arithmetic_types_must_be_lossless); | ||||
return MatcherCast<T>(matcher); | ||||
} | ||||
}; | ||||
template <typename T, typename M> | template <typename T, typename M> | |||
inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher) { | inline Matcher<T> SafeMatcherCast(const M& polymorphic_matcher_or_value) { | |||
return SafeMatcherCastImpl<T>::Cast(polymorphic_matcher); | return MatcherCast<T>(polymorphic_matcher_or_value); | |||
} | ||||
// This overload handles monomorphic matchers. | ||||
// | ||||
// In general, if type T can be implicitly converted to type U, we can | ||||
// safely convert a Matcher<U> to a Matcher<T> (i.e. Matcher is | ||||
// contravariant): just keep a copy of the original Matcher<U>, convert the | ||||
// argument from type T to U, and then pass it to the underlying Matcher<U>. | ||||
// The only exception is when U is a reference and T is not, as the | ||||
// underlying Matcher<U> may be interested in the argument's address, which | ||||
// is not preserved in the conversion from T to U. | ||||
template <typename T, typename U> | ||||
inline Matcher<T> SafeMatcherCast(const Matcher<U>& matcher) { | ||||
// Enforce that T can be implicitly converted to U. | ||||
static_assert(std::is_convertible<const T&, const U&>::value, | ||||
"T must be implicitly convertible to U"); | ||||
// Enforce that we are not converting a non-reference type T to a reference | ||||
// type U. | ||||
GTEST_COMPILE_ASSERT_( | ||||
std::is_reference<T>::value || !std::is_reference<U>::value, | ||||
cannot_convert_non_reference_arg_to_reference); | ||||
// In case both T and U are arithmetic types, enforce that the | ||||
// conversion is not lossy. | ||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; | ||||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; | ||||
constexpr bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; | ||||
constexpr bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; | ||||
GTEST_COMPILE_ASSERT_( | ||||
kTIsOther || kUIsOther || | ||||
(internal::LosslessArithmeticConvertible<RawT, RawU>::value), | ||||
conversion_of_arithmetic_types_must_be_lossless); | ||||
return MatcherCast<T>(matcher); | ||||
} | } | |||
// A<T>() returns a matcher that matches any value of type T. | // A<T>() returns a matcher that matches any value of type T. | |||
template <typename T> | template <typename T> | |||
Matcher<T> A(); | Matcher<T> A(); | |||
// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION | // Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION | |||
// and MUST NOT BE USED IN USER CODE!!! | // and MUST NOT BE USED IN USER CODE!!! | |||
namespace internal { | namespace internal { | |||
skipping to change at line 486 | skipping to change at line 737 | |||
}; | }; | |||
// Successively invokes 'f(element)' on each element of the tuple 't', | // Successively invokes 'f(element)' on each element of the tuple 't', | |||
// appending each result to the 'out' iterator. Returns the final value | // appending each result to the 'out' iterator. Returns the final value | |||
// of 'out'. | // of 'out'. | |||
template <typename Tuple, typename Func, typename OutIter> | template <typename Tuple, typename Func, typename OutIter> | |||
OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { | OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { | |||
return TransformTupleValuesHelper<Tuple, Func, OutIter>::Run(f, t, out); | return TransformTupleValuesHelper<Tuple, Func, OutIter>::Run(f, t, out); | |||
} | } | |||
// Implements A<T>(). | ||||
template <typename T> | ||||
class AnyMatcherImpl : public MatcherInterface<const T&> { | ||||
public: | ||||
bool MatchAndExplain(const T& /* x */, | ||||
MatchResultListener* /* listener */) const override { | ||||
return true; | ||||
} | ||||
void DescribeTo(::std::ostream* os) const override { *os << "is anything"; } | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
// This is mostly for completeness' safe, as it's not very useful | ||||
// to write Not(A<bool>()). However we cannot completely rule out | ||||
// such a possibility, and it doesn't hurt to be prepared. | ||||
*os << "never matches"; | ||||
} | ||||
}; | ||||
// Implements _, a matcher that matches any value of any | // Implements _, a matcher that matches any value of any | |||
// type. This is a polymorphic matcher, so we need a template type | // type. This is a polymorphic matcher, so we need a template type | |||
// conversion operator to make it appearing as a Matcher<T> for any | // conversion operator to make it appearing as a Matcher<T> for any | |||
// type T. | // type T. | |||
class AnythingMatcher { | class AnythingMatcher { | |||
public: | public: | |||
using is_gtest_matcher = void; | ||||
template <typename T> | template <typename T> | |||
operator Matcher<T>() const { return A<T>(); } | bool MatchAndExplain(const T& /* x */, std::ostream* /* listener */) const { | |||
return true; | ||||
} | ||||
void DescribeTo(std::ostream* os) const { *os << "is anything"; } | ||||
void DescribeNegationTo(::std::ostream* os) const { | ||||
// This is mostly for completeness' sake, as it's not very useful | ||||
// to write Not(A<bool>()). However we cannot completely rule out | ||||
// such a possibility, and it doesn't hurt to be prepared. | ||||
*os << "never matches"; | ||||
} | ||||
}; | }; | |||
// Implements the polymorphic IsNull() matcher, which matches any raw or smart | // Implements the polymorphic IsNull() matcher, which matches any raw or smart | |||
// pointer that is NULL. | // pointer that is NULL. | |||
class IsNullMatcher { | class IsNullMatcher { | |||
public: | public: | |||
template <typename Pointer> | template <typename Pointer> | |||
bool MatchAndExplain(const Pointer& p, | bool MatchAndExplain(const Pointer& p, | |||
MatchResultListener* /* listener */) const { | MatchResultListener* /* listener */) const { | |||
return p == nullptr; | return p == nullptr; | |||
skipping to change at line 610 | skipping to change at line 855 | |||
UniversalPrinter<Super&>::Print(object_, os); | UniversalPrinter<Super&>::Print(object_, os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
*os << "does not reference the variable "; | *os << "does not reference the variable "; | |||
UniversalPrinter<Super&>::Print(object_, os); | UniversalPrinter<Super&>::Print(object_, os); | |||
} | } | |||
private: | private: | |||
const Super& object_; | const Super& object_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
T& object_; | T& object_; | |||
GTEST_DISALLOW_ASSIGN_(RefMatcher); | ||||
}; | }; | |||
// Polymorphic helper functions for narrow and wide string matchers. | // Polymorphic helper functions for narrow and wide string matchers. | |||
inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) { | inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) { | |||
return String::CaseInsensitiveCStringEquals(lhs, rhs); | return String::CaseInsensitiveCStringEquals(lhs, rhs); | |||
} | } | |||
inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, | inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, | |||
const wchar_t* rhs) { | const wchar_t* rhs) { | |||
return String::CaseInsensitiveWideCStringEquals(lhs, rhs); | return String::CaseInsensitiveWideCStringEquals(lhs, rhs); | |||
skipping to change at line 658 | skipping to change at line 899 | |||
// Are the tails equal? | // Are the tails equal? | |||
return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1)); | return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1)); | |||
} | } | |||
// String matchers. | // String matchers. | |||
// Implements equality-based string matchers like StrEq, StrCaseNe, and etc. | // Implements equality-based string matchers like StrEq, StrCaseNe, and etc. | |||
template <typename StringType> | template <typename StringType> | |||
class StrEqualityMatcher { | class StrEqualityMatcher { | |||
public: | public: | |||
StrEqualityMatcher(const StringType& str, bool expect_eq, | StrEqualityMatcher(StringType str, bool expect_eq, bool case_sensitive) | |||
bool case_sensitive) | : string_(std::move(str)), | |||
: string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} | expect_eq_(expect_eq), | |||
case_sensitive_(case_sensitive) {} | ||||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
bool MatchAndExplain(const absl::string_view& s, | bool MatchAndExplain(const internal::StringView& s, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
// This should fail to compile if absl::string_view is used with wide | // This should fail to compile if StringView is used with wide | |||
// strings. | // strings. | |||
const StringType& str = std::string(s); | const StringType& str = std::string(s); | |||
return MatchAndExplain(str, listener); | return MatchAndExplain(str, listener); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Accepts pointer types, particularly: | // Accepts pointer types, particularly: | |||
// const char* | // const char* | |||
// char* | // char* | |||
// const wchar_t* | // const wchar_t* | |||
// wchar_t* | // wchar_t* | |||
template <typename CharType> | template <typename CharType> | |||
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | |||
if (s == nullptr) { | if (s == nullptr) { | |||
return !expect_eq_; | return !expect_eq_; | |||
} | } | |||
return MatchAndExplain(StringType(s), listener); | return MatchAndExplain(StringType(s), listener); | |||
} | } | |||
// Matches anything that can convert to StringType. | // Matches anything that can convert to StringType. | |||
// | // | |||
// This is a template, not just a plain function with const StringType&, | // This is a template, not just a plain function with const StringType&, | |||
// because absl::string_view has some interfering non-explicit constructors. | // because StringView has some interfering non-explicit constructors. | |||
template <typename MatcheeStringType> | template <typename MatcheeStringType> | |||
bool MatchAndExplain(const MatcheeStringType& s, | bool MatchAndExplain(const MatcheeStringType& s, | |||
MatchResultListener* /* listener */) const { | MatchResultListener* /* listener */) const { | |||
const StringType& s2(s); | const StringType s2(s); | |||
const bool eq = case_sensitive_ ? s2 == string_ : | const bool eq = case_sensitive_ ? s2 == string_ : | |||
CaseInsensitiveStringEquals(s2, string_); | CaseInsensitiveStringEquals(s2, string_); | |||
return expect_eq_ == eq; | return expect_eq_ == eq; | |||
} | } | |||
void DescribeTo(::std::ostream* os) const { | void DescribeTo(::std::ostream* os) const { | |||
DescribeToHelper(expect_eq_, os); | DescribeToHelper(expect_eq_, os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const { | |||
skipping to change at line 719 | skipping to change at line 961 | |||
*os << "equal to "; | *os << "equal to "; | |||
if (!case_sensitive_) { | if (!case_sensitive_) { | |||
*os << "(ignoring case) "; | *os << "(ignoring case) "; | |||
} | } | |||
UniversalPrint(string_, os); | UniversalPrint(string_, os); | |||
} | } | |||
const StringType string_; | const StringType string_; | |||
const bool expect_eq_; | const bool expect_eq_; | |||
const bool case_sensitive_; | const bool case_sensitive_; | |||
GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher); | ||||
}; | }; | |||
// Implements the polymorphic HasSubstr(substring) matcher, which | // Implements the polymorphic HasSubstr(substring) matcher, which | |||
// can be used as a Matcher<T> as long as T can be converted to a | // can be used as a Matcher<T> as long as T can be converted to a | |||
// string. | // string. | |||
template <typename StringType> | template <typename StringType> | |||
class HasSubstrMatcher { | class HasSubstrMatcher { | |||
public: | public: | |||
explicit HasSubstrMatcher(const StringType& substring) | explicit HasSubstrMatcher(const StringType& substring) | |||
: substring_(substring) {} | : substring_(substring) {} | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
bool MatchAndExplain(const absl::string_view& s, | bool MatchAndExplain(const internal::StringView& s, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
// This should fail to compile if absl::string_view is used with wide | // This should fail to compile if StringView is used with wide | |||
// strings. | // strings. | |||
const StringType& str = std::string(s); | const StringType& str = std::string(s); | |||
return MatchAndExplain(str, listener); | return MatchAndExplain(str, listener); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Accepts pointer types, particularly: | // Accepts pointer types, particularly: | |||
// const char* | // const char* | |||
// char* | // char* | |||
// const wchar_t* | // const wchar_t* | |||
// wchar_t* | // wchar_t* | |||
template <typename CharType> | template <typename CharType> | |||
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | |||
return s != nullptr && MatchAndExplain(StringType(s), listener); | return s != nullptr && MatchAndExplain(StringType(s), listener); | |||
} | } | |||
// Matches anything that can convert to StringType. | // Matches anything that can convert to StringType. | |||
// | // | |||
// This is a template, not just a plain function with const StringType&, | // This is a template, not just a plain function with const StringType&, | |||
// because absl::string_view has some interfering non-explicit constructors. | // because StringView has some interfering non-explicit constructors. | |||
template <typename MatcheeStringType> | template <typename MatcheeStringType> | |||
bool MatchAndExplain(const MatcheeStringType& s, | bool MatchAndExplain(const MatcheeStringType& s, | |||
MatchResultListener* /* listener */) const { | MatchResultListener* /* listener */) const { | |||
const StringType& s2(s); | return StringType(s).find(substring_) != StringType::npos; | |||
return s2.find(substring_) != StringType::npos; | ||||
} | } | |||
// Describes what this matcher matches. | // Describes what this matcher matches. | |||
void DescribeTo(::std::ostream* os) const { | void DescribeTo(::std::ostream* os) const { | |||
*os << "has substring "; | *os << "has substring "; | |||
UniversalPrint(substring_, os); | UniversalPrint(substring_, os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const { | |||
*os << "has no substring "; | *os << "has no substring "; | |||
UniversalPrint(substring_, os); | UniversalPrint(substring_, os); | |||
} | } | |||
private: | private: | |||
const StringType substring_; | const StringType substring_; | |||
GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher); | ||||
}; | }; | |||
// Implements the polymorphic StartsWith(substring) matcher, which | // Implements the polymorphic StartsWith(substring) matcher, which | |||
// can be used as a Matcher<T> as long as T can be converted to a | // can be used as a Matcher<T> as long as T can be converted to a | |||
// string. | // string. | |||
template <typename StringType> | template <typename StringType> | |||
class StartsWithMatcher { | class StartsWithMatcher { | |||
public: | public: | |||
explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { | explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { | |||
} | } | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
bool MatchAndExplain(const absl::string_view& s, | bool MatchAndExplain(const internal::StringView& s, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
// This should fail to compile if absl::string_view is used with wide | // This should fail to compile if StringView is used with wide | |||
// strings. | // strings. | |||
const StringType& str = std::string(s); | const StringType& str = std::string(s); | |||
return MatchAndExplain(str, listener); | return MatchAndExplain(str, listener); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Accepts pointer types, particularly: | // Accepts pointer types, particularly: | |||
// const char* | // const char* | |||
// char* | // char* | |||
// const wchar_t* | // const wchar_t* | |||
// wchar_t* | // wchar_t* | |||
template <typename CharType> | template <typename CharType> | |||
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | |||
return s != nullptr && MatchAndExplain(StringType(s), listener); | return s != nullptr && MatchAndExplain(StringType(s), listener); | |||
} | } | |||
// Matches anything that can convert to StringType. | // Matches anything that can convert to StringType. | |||
// | // | |||
// This is a template, not just a plain function with const StringType&, | // This is a template, not just a plain function with const StringType&, | |||
// because absl::string_view has some interfering non-explicit constructors. | // because StringView has some interfering non-explicit constructors. | |||
template <typename MatcheeStringType> | template <typename MatcheeStringType> | |||
bool MatchAndExplain(const MatcheeStringType& s, | bool MatchAndExplain(const MatcheeStringType& s, | |||
MatchResultListener* /* listener */) const { | MatchResultListener* /* listener */) const { | |||
const StringType& s2(s); | const StringType& s2(s); | |||
return s2.length() >= prefix_.length() && | return s2.length() >= prefix_.length() && | |||
s2.substr(0, prefix_.length()) == prefix_; | s2.substr(0, prefix_.length()) == prefix_; | |||
} | } | |||
void DescribeTo(::std::ostream* os) const { | void DescribeTo(::std::ostream* os) const { | |||
*os << "starts with "; | *os << "starts with "; | |||
UniversalPrint(prefix_, os); | UniversalPrint(prefix_, os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const { | |||
*os << "doesn't start with "; | *os << "doesn't start with "; | |||
UniversalPrint(prefix_, os); | UniversalPrint(prefix_, os); | |||
} | } | |||
private: | private: | |||
const StringType prefix_; | const StringType prefix_; | |||
GTEST_DISALLOW_ASSIGN_(StartsWithMatcher); | ||||
}; | }; | |||
// Implements the polymorphic EndsWith(substring) matcher, which | // Implements the polymorphic EndsWith(substring) matcher, which | |||
// can be used as a Matcher<T> as long as T can be converted to a | // can be used as a Matcher<T> as long as T can be converted to a | |||
// string. | // string. | |||
template <typename StringType> | template <typename StringType> | |||
class EndsWithMatcher { | class EndsWithMatcher { | |||
public: | public: | |||
explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} | explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} | |||
#if GTEST_HAS_ABSL | #if GTEST_INTERNAL_HAS_STRING_VIEW | |||
bool MatchAndExplain(const absl::string_view& s, | bool MatchAndExplain(const internal::StringView& s, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
// This should fail to compile if absl::string_view is used with wide | // This should fail to compile if StringView is used with wide | |||
// strings. | // strings. | |||
const StringType& str = std::string(s); | const StringType& str = std::string(s); | |||
return MatchAndExplain(str, listener); | return MatchAndExplain(str, listener); | |||
} | } | |||
#endif // GTEST_HAS_ABSL | #endif // GTEST_INTERNAL_HAS_STRING_VIEW | |||
// Accepts pointer types, particularly: | // Accepts pointer types, particularly: | |||
// const char* | // const char* | |||
// char* | // char* | |||
// const wchar_t* | // const wchar_t* | |||
// wchar_t* | // wchar_t* | |||
template <typename CharType> | template <typename CharType> | |||
bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { | |||
return s != nullptr && MatchAndExplain(StringType(s), listener); | return s != nullptr && MatchAndExplain(StringType(s), listener); | |||
} | } | |||
// Matches anything that can convert to StringType. | // Matches anything that can convert to StringType. | |||
// | // | |||
// This is a template, not just a plain function with const StringType&, | // This is a template, not just a plain function with const StringType&, | |||
// because absl::string_view has some interfering non-explicit constructors. | // because StringView has some interfering non-explicit constructors. | |||
template <typename MatcheeStringType> | template <typename MatcheeStringType> | |||
bool MatchAndExplain(const MatcheeStringType& s, | bool MatchAndExplain(const MatcheeStringType& s, | |||
MatchResultListener* /* listener */) const { | MatchResultListener* /* listener */) const { | |||
const StringType& s2(s); | const StringType& s2(s); | |||
return s2.length() >= suffix_.length() && | return s2.length() >= suffix_.length() && | |||
s2.substr(s2.length() - suffix_.length()) == suffix_; | s2.substr(s2.length() - suffix_.length()) == suffix_; | |||
} | } | |||
void DescribeTo(::std::ostream* os) const { | void DescribeTo(::std::ostream* os) const { | |||
*os << "ends with "; | *os << "ends with "; | |||
UniversalPrint(suffix_, os); | UniversalPrint(suffix_, os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const { | |||
*os << "doesn't end with "; | *os << "doesn't end with "; | |||
UniversalPrint(suffix_, os); | UniversalPrint(suffix_, os); | |||
} | } | |||
private: | private: | |||
const StringType suffix_; | const StringType suffix_; | |||
GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); | ||||
}; | }; | |||
// Implements a matcher that compares the two fields of a 2-tuple | // Implements a matcher that compares the two fields of a 2-tuple | |||
// using one of the ==, <=, <, etc, operators. The two fields being | // using one of the ==, <=, <, etc, operators. The two fields being | |||
// compared don't have to have the same type. | // compared don't have to have the same type. | |||
// | // | |||
// The matcher defined here is polymorphic (for example, Eq() can be | // The matcher defined here is polymorphic (for example, Eq() can be | |||
// used to match a std::tuple<int, short>, a std::tuple<const long&, double>, | // used to match a std::tuple<int, short>, a std::tuple<const long&, double>, | |||
// etc). Therefore we use a template type conversion operator in the | // etc). Therefore we use a template type conversion operator in the | |||
// implementation. | // implementation. | |||
skipping to change at line 984 | skipping to change at line 1217 | |||
void DescribeTo(::std::ostream* os) const override { | void DescribeTo(::std::ostream* os) const override { | |||
matcher_.DescribeNegationTo(os); | matcher_.DescribeNegationTo(os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
matcher_.DescribeTo(os); | matcher_.DescribeTo(os); | |||
} | } | |||
private: | private: | |||
const Matcher<T> matcher_; | const Matcher<T> matcher_; | |||
GTEST_DISALLOW_ASSIGN_(NotMatcherImpl); | ||||
}; | }; | |||
// Implements the Not(m) matcher, which matches a value that doesn't | // Implements the Not(m) matcher, which matches a value that doesn't | |||
// match matcher m. | // match matcher m. | |||
template <typename InnerMatcher> | template <typename InnerMatcher> | |||
class NotMatcher { | class NotMatcher { | |||
public: | public: | |||
explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {} | explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {} | |||
// This template type conversion operator allows Not(m) to be used | // This template type conversion operator allows Not(m) to be used | |||
// to match any type m can match. | // to match any type m can match. | |||
template <typename T> | template <typename T> | |||
operator Matcher<T>() const { | operator Matcher<T>() const { | |||
return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_))); | return Matcher<T>(new NotMatcherImpl<T>(SafeMatcherCast<T>(matcher_))); | |||
} | } | |||
private: | private: | |||
InnerMatcher matcher_; | InnerMatcher matcher_; | |||
GTEST_DISALLOW_ASSIGN_(NotMatcher); | ||||
}; | }; | |||
// Implements the AllOf(m1, m2) matcher for a particular argument type | // Implements the AllOf(m1, m2) matcher for a particular argument type | |||
// T. We do not nest it inside the BothOfMatcher class template, as | // T. We do not nest it inside the BothOfMatcher class template, as | |||
// that will prevent different instantiations of BothOfMatcher from | // that will prevent different instantiations of BothOfMatcher from | |||
// sharing the same BothOfMatcherImpl<T> class. | // sharing the same BothOfMatcherImpl<T> class. | |||
template <typename T> | template <typename T> | |||
class AllOfMatcherImpl : public MatcherInterface<const T&> { | class AllOfMatcherImpl : public MatcherInterface<const T&> { | |||
public: | public: | |||
explicit AllOfMatcherImpl(std::vector<Matcher<T> > matchers) | explicit AllOfMatcherImpl(std::vector<Matcher<T> > matchers) | |||
skipping to change at line 1067 | skipping to change at line 1296 | |||
} | } | |||
} | } | |||
// Otherwise we need to explain why *both* of them match. | // Otherwise we need to explain why *both* of them match. | |||
*listener << all_match_result; | *listener << all_match_result; | |||
return true; | return true; | |||
} | } | |||
private: | private: | |||
const std::vector<Matcher<T> > matchers_; | const std::vector<Matcher<T> > matchers_; | |||
GTEST_DISALLOW_ASSIGN_(AllOfMatcherImpl); | ||||
}; | }; | |||
// VariadicMatcher is used for the variadic implementation of | // VariadicMatcher is used for the variadic implementation of | |||
// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). | // AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). | |||
// CombiningMatcher<T> is used to recursively combine the provided matchers | // CombiningMatcher<T> is used to recursively combine the provided matchers | |||
// (of type Args...). | // (of type Args...). | |||
template <template <typename T> class CombiningMatcher, typename... Args> | template <template <typename T> class CombiningMatcher, typename... Args> | |||
class VariadicMatcher { | class VariadicMatcher { | |||
public: | public: | |||
VariadicMatcher(const Args&... matchers) // NOLINT | VariadicMatcher(const Args&... matchers) // NOLINT | |||
: matchers_(matchers...) { | : matchers_(matchers...) { | |||
static_assert(sizeof...(Args) > 0, "Must have at least one matcher."); | static_assert(sizeof...(Args) > 0, "Must have at least one matcher."); | |||
} | } | |||
VariadicMatcher(const VariadicMatcher&) = default; | ||||
VariadicMatcher& operator=(const VariadicMatcher&) = delete; | ||||
// This template type conversion operator allows an | // This template type conversion operator allows an | |||
// VariadicMatcher<Matcher1, Matcher2...> object to match any type that | // VariadicMatcher<Matcher1, Matcher2...> object to match any type that | |||
// all of the provided matchers (Matcher1, Matcher2, ...) can match. | // all of the provided matchers (Matcher1, Matcher2, ...) can match. | |||
template <typename T> | template <typename T> | |||
operator Matcher<T>() const { | operator Matcher<T>() const { | |||
std::vector<Matcher<T> > values; | std::vector<Matcher<T> > values; | |||
CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>()); | CreateVariadicMatcher<T>(&values, std::integral_constant<size_t, 0>()); | |||
return Matcher<T>(new CombiningMatcher<T>(std::move(values))); | return Matcher<T>(new CombiningMatcher<T>(std::move(values))); | |||
} | } | |||
skipping to change at line 1107 | skipping to change at line 1337 | |||
values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_))); | values->push_back(SafeMatcherCast<T>(std::get<I>(matchers_))); | |||
CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>()); | CreateVariadicMatcher<T>(values, std::integral_constant<size_t, I + 1>()); | |||
} | } | |||
template <typename T> | template <typename T> | |||
void CreateVariadicMatcher( | void CreateVariadicMatcher( | |||
std::vector<Matcher<T> >*, | std::vector<Matcher<T> >*, | |||
std::integral_constant<size_t, sizeof...(Args)>) const {} | std::integral_constant<size_t, sizeof...(Args)>) const {} | |||
std::tuple<Args...> matchers_; | std::tuple<Args...> matchers_; | |||
GTEST_DISALLOW_ASSIGN_(VariadicMatcher); | ||||
}; | }; | |||
template <typename... Args> | template <typename... Args> | |||
using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>; | using AllOfMatcher = VariadicMatcher<AllOfMatcherImpl, Args...>; | |||
// Implements the AnyOf(m1, m2) matcher for a particular argument type | // Implements the AnyOf(m1, m2) matcher for a particular argument type | |||
// T. We do not nest it inside the AnyOfMatcher class template, as | // T. We do not nest it inside the AnyOfMatcher class template, as | |||
// that will prevent different instantiations of AnyOfMatcher from | // that will prevent different instantiations of AnyOfMatcher from | |||
// sharing the same EitherOfMatcherImpl<T> class. | // sharing the same EitherOfMatcherImpl<T> class. | |||
template <typename T> | template <typename T> | |||
skipping to change at line 1173 | skipping to change at line 1401 | |||
} | } | |||
} | } | |||
// Otherwise we need to explain why *both* of them fail. | // Otherwise we need to explain why *both* of them fail. | |||
*listener << no_match_result; | *listener << no_match_result; | |||
return false; | return false; | |||
} | } | |||
private: | private: | |||
const std::vector<Matcher<T> > matchers_; | const std::vector<Matcher<T> > matchers_; | |||
GTEST_DISALLOW_ASSIGN_(AnyOfMatcherImpl); | ||||
}; | }; | |||
// AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). | // AnyOfMatcher is used for the variadic implementation of AnyOf(m_1, m_2, ...). | |||
template <typename... Args> | template <typename... Args> | |||
using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; | using AnyOfMatcher = VariadicMatcher<AnyOfMatcherImpl, Args...>; | |||
// Wrapper for implementation of Any/AllOfArray(). | // Wrapper for implementation of Any/AllOfArray(). | |||
template <template <class> class MatcherImpl, typename T> | template <template <class> class MatcherImpl, typename T> | |||
class SomeOfArrayMatcher { | class SomeOfArrayMatcher { | |||
public: | public: | |||
skipping to change at line 1202 | skipping to change at line 1428 | |||
using RawU = typename std::decay<U>::type; | using RawU = typename std::decay<U>::type; | |||
std::vector<Matcher<RawU>> matchers; | std::vector<Matcher<RawU>> matchers; | |||
for (const auto& matcher : matchers_) { | for (const auto& matcher : matchers_) { | |||
matchers.push_back(MatcherCast<RawU>(matcher)); | matchers.push_back(MatcherCast<RawU>(matcher)); | |||
} | } | |||
return Matcher<U>(new MatcherImpl<RawU>(std::move(matchers))); | return Matcher<U>(new MatcherImpl<RawU>(std::move(matchers))); | |||
} | } | |||
private: | private: | |||
const ::std::vector<T> matchers_; | const ::std::vector<T> matchers_; | |||
GTEST_DISALLOW_ASSIGN_(SomeOfArrayMatcher); | ||||
}; | }; | |||
template <typename T> | template <typename T> | |||
using AllOfArrayMatcher = SomeOfArrayMatcher<AllOfMatcherImpl, T>; | using AllOfArrayMatcher = SomeOfArrayMatcher<AllOfMatcherImpl, T>; | |||
template <typename T> | template <typename T> | |||
using AnyOfArrayMatcher = SomeOfArrayMatcher<AnyOfMatcherImpl, T>; | using AnyOfArrayMatcher = SomeOfArrayMatcher<AnyOfMatcherImpl, T>; | |||
// Used for implementing Truly(pred), which turns a predicate into a | // Used for implementing Truly(pred), which turns a predicate into a | |||
// matcher. | // matcher. | |||
skipping to change at line 1225 | skipping to change at line 1449 | |||
class TrulyMatcher { | class TrulyMatcher { | |||
public: | public: | |||
explicit TrulyMatcher(Predicate pred) : predicate_(pred) {} | explicit TrulyMatcher(Predicate pred) : predicate_(pred) {} | |||
// This method template allows Truly(pred) to be used as a matcher | // This method template allows Truly(pred) to be used as a matcher | |||
// for type T where T is the argument type of predicate 'pred'. The | // for type T where T is the argument type of predicate 'pred'. The | |||
// argument is passed by reference as the predicate may be | // argument is passed by reference as the predicate may be | |||
// interested in the address of the argument. | // interested in the address of the argument. | |||
template <typename T> | template <typename T> | |||
bool MatchAndExplain(T& x, // NOLINT | bool MatchAndExplain(T& x, // NOLINT | |||
MatchResultListener* /* listener */) const { | MatchResultListener* listener) const { | |||
// Without the if-statement, MSVC sometimes warns about converting | // Without the if-statement, MSVC sometimes warns about converting | |||
// a value to bool (warning 4800). | // a value to bool (warning 4800). | |||
// | // | |||
// We cannot write 'return !!predicate_(x);' as that doesn't work | // We cannot write 'return !!predicate_(x);' as that doesn't work | |||
// when predicate_(x) returns a class convertible to bool but | // when predicate_(x) returns a class convertible to bool but | |||
// having no operator!(). | // having no operator!(). | |||
if (predicate_(x)) | if (predicate_(x)) | |||
return true; | return true; | |||
*listener << "didn't satisfy the given predicate"; | ||||
return false; | return false; | |||
} | } | |||
void DescribeTo(::std::ostream* os) const { | void DescribeTo(::std::ostream* os) const { | |||
*os << "satisfies the given predicate"; | *os << "satisfies the given predicate"; | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const { | void DescribeNegationTo(::std::ostream* os) const { | |||
*os << "doesn't satisfy the given predicate"; | *os << "doesn't satisfy the given predicate"; | |||
} | } | |||
private: | private: | |||
Predicate predicate_; | Predicate predicate_; | |||
GTEST_DISALLOW_ASSIGN_(TrulyMatcher); | ||||
}; | }; | |||
// Used for implementing Matches(matcher), which turns a matcher into | // Used for implementing Matches(matcher), which turns a matcher into | |||
// a predicate. | // a predicate. | |||
template <typename M> | template <typename M> | |||
class MatcherAsPredicate { | class MatcherAsPredicate { | |||
public: | public: | |||
explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {} | explicit MatcherAsPredicate(M matcher) : matcher_(matcher) {} | |||
// This template operator() allows Matches(m) to be used as a | // This template operator() allows Matches(m) to be used as a | |||
skipping to change at line 1285 | skipping to change at line 1508 | |||
// matcher_.Matches(x), it won't compile when matcher_ is | // matcher_.Matches(x), it won't compile when matcher_ is | |||
// polymorphic, e.g. Eq(5). | // polymorphic, e.g. Eq(5). | |||
// | // | |||
// MatcherCast<const T&>() is necessary for making the code work | // MatcherCast<const T&>() is necessary for making the code work | |||
// in all of the above situations. | // in all of the above situations. | |||
return MatcherCast<const T&>(matcher_).Matches(x); | return MatcherCast<const T&>(matcher_).Matches(x); | |||
} | } | |||
private: | private: | |||
M matcher_; | M matcher_; | |||
GTEST_DISALLOW_ASSIGN_(MatcherAsPredicate); | ||||
}; | }; | |||
// For implementing ASSERT_THAT() and EXPECT_THAT(). The template | // For implementing ASSERT_THAT() and EXPECT_THAT(). The template | |||
// argument M must be a type that can be converted to a matcher. | // argument M must be a type that can be converted to a matcher. | |||
template <typename M> | template <typename M> | |||
class PredicateFormatterFromMatcher { | class PredicateFormatterFromMatcher { | |||
public: | public: | |||
explicit PredicateFormatterFromMatcher(M m) : matcher_(std::move(m)) {} | explicit PredicateFormatterFromMatcher(M m) : matcher_(std::move(m)) {} | |||
// This template () operator allows a PredicateFormatterFromMatcher | // This template () operator allows a PredicateFormatterFromMatcher | |||
skipping to change at line 1325 | skipping to change at line 1546 | |||
// tests pass) so optimize for this case. | // tests pass) so optimize for this case. | |||
if (matcher.Matches(x)) { | if (matcher.Matches(x)) { | |||
return AssertionSuccess(); | return AssertionSuccess(); | |||
} | } | |||
::std::stringstream ss; | ::std::stringstream ss; | |||
ss << "Value of: " << value_text << "\n" | ss << "Value of: " << value_text << "\n" | |||
<< "Expected: "; | << "Expected: "; | |||
matcher.DescribeTo(&ss); | matcher.DescribeTo(&ss); | |||
// Rerun the matcher to "PrintAndExain" the failure. | // Rerun the matcher to "PrintAndExplain" the failure. | |||
StringMatchResultListener listener; | StringMatchResultListener listener; | |||
if (MatchPrintAndExplain(x, matcher, &listener)) { | if (MatchPrintAndExplain(x, matcher, &listener)) { | |||
ss << "\n The matcher failed on the initial attempt; but passed when " | ss << "\n The matcher failed on the initial attempt; but passed when " | |||
"rerun to generate the explanation."; | "rerun to generate the explanation."; | |||
} | } | |||
ss << "\n Actual: " << listener.str(); | ss << "\n Actual: " << listener.str(); | |||
return AssertionFailure() << ss.str(); | return AssertionFailure() << ss.str(); | |||
} | } | |||
private: | private: | |||
const M matcher_; | const M matcher_; | |||
GTEST_DISALLOW_ASSIGN_(PredicateFormatterFromMatcher); | ||||
}; | }; | |||
// A helper function for converting a matcher to a predicate-formatter | // A helper function for converting a matcher to a predicate-formatter | |||
// without the user needing to explicitly write the type. This is | // without the user needing to explicitly write the type. This is | |||
// used for implementing ASSERT_THAT() and EXPECT_THAT(). | // used for implementing ASSERT_THAT() and EXPECT_THAT(). | |||
// Implementation detail: 'matcher' is received by-value to force decaying. | // Implementation detail: 'matcher' is received by-value to force decaying. | |||
template <typename M> | template <typename M> | |||
inline PredicateFormatterFromMatcher<M> | inline PredicateFormatterFromMatcher<M> | |||
MakePredicateFormatterFromMatcher(M matcher) { | MakePredicateFormatterFromMatcher(M matcher) { | |||
return PredicateFormatterFromMatcher<M>(std::move(matcher)); | return PredicateFormatterFromMatcher<M>(std::move(matcher)); | |||
} | } | |||
// Implements the polymorphic IsNan() matcher, which matches any floating type | ||||
// value that is Nan. | ||||
class IsNanMatcher { | ||||
public: | ||||
template <typename FloatType> | ||||
bool MatchAndExplain(const FloatType& f, | ||||
MatchResultListener* /* listener */) const { | ||||
return (::std::isnan)(f); | ||||
} | ||||
void DescribeTo(::std::ostream* os) const { *os << "is NaN"; } | ||||
void DescribeNegationTo(::std::ostream* os) const { | ||||
*os << "isn't NaN"; | ||||
} | ||||
}; | ||||
// Implements the polymorphic floating point equality matcher, which matches | // Implements the polymorphic floating point equality matcher, which matches | |||
// two float values using ULP-based approximation or, optionally, a | // two float values using ULP-based approximation or, optionally, a | |||
// user-specified epsilon. The template is meant to be instantiated with | // user-specified epsilon. The template is meant to be instantiated with | |||
// FloatType being either float or double. | // FloatType being either float or double. | |||
template <typename FloatType> | template <typename FloatType> | |||
class FloatingEqMatcher { | class FloatingEqMatcher { | |||
public: | public: | |||
// Constructor for FloatingEqMatcher. | // Constructor for FloatingEqMatcher. | |||
// The matcher's input will be compared with expected. The matcher treats two | // The matcher's input will be compared with expected. The matcher treats two | |||
// NANs as equal if nan_eq_nan is true. Otherwise, under IEEE standards, | // NANs as equal if nan_eq_nan is true. Otherwise, under IEEE standards, | |||
skipping to change at line 1411 | skipping to change at line 1646 | |||
if (HasMaxAbsError()) { | if (HasMaxAbsError()) { | |||
// We perform an equality check so that inf will match inf, regardless | // We perform an equality check so that inf will match inf, regardless | |||
// of error bounds. If the result of value - expected_ would result in | // of error bounds. If the result of value - expected_ would result in | |||
// overflow or if either value is inf, the default result is infinity, | // overflow or if either value is inf, the default result is infinity, | |||
// which should only match if max_abs_error_ is also infinity. | // which should only match if max_abs_error_ is also infinity. | |||
if (value == expected_) { | if (value == expected_) { | |||
return true; | return true; | |||
} | } | |||
const FloatType diff = value - expected_; | const FloatType diff = value - expected_; | |||
if (fabs(diff) <= max_abs_error_) { | if (::std::fabs(diff) <= max_abs_error_) { | |||
return true; | return true; | |||
} | } | |||
if (listener->IsInterested()) { | if (listener->IsInterested()) { | |||
*listener << "which is " << diff << " from " << expected_; | *listener << "which is " << diff << " from " << expected_; | |||
} | } | |||
return false; | return false; | |||
} else { | } else { | |||
return actual.AlmostEquals(expected); | return actual.AlmostEquals(expected); | |||
} | } | |||
skipping to change at line 1474 | skipping to change at line 1709 | |||
private: | private: | |||
bool HasMaxAbsError() const { | bool HasMaxAbsError() const { | |||
return max_abs_error_ >= 0; | return max_abs_error_ >= 0; | |||
} | } | |||
const FloatType expected_; | const FloatType expected_; | |||
const bool nan_eq_nan_; | const bool nan_eq_nan_; | |||
// max_abs_error will be used for value comparison when >= 0. | // max_abs_error will be used for value comparison when >= 0. | |||
const FloatType max_abs_error_; | const FloatType max_abs_error_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
// The following 3 type conversion operators allow FloatEq(expected) and | // The following 3 type conversion operators allow FloatEq(expected) and | |||
// NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a | // NanSensitiveFloatEq(expected) to be used as a Matcher<float>, a | |||
// Matcher<const float&>, or a Matcher<float&>, but nothing else. | // Matcher<const float&>, or a Matcher<float&>, but nothing else. | |||
// (While Google's C++ coding style doesn't allow arguments passed | ||||
// by non-const reference, we may see them in code not conforming to | ||||
// the style. Therefore Google Mock needs to support them.) | ||||
operator Matcher<FloatType>() const { | operator Matcher<FloatType>() const { | |||
return MakeMatcher( | return MakeMatcher( | |||
new Impl<FloatType>(expected_, nan_eq_nan_, max_abs_error_)); | new Impl<FloatType>(expected_, nan_eq_nan_, max_abs_error_)); | |||
} | } | |||
operator Matcher<const FloatType&>() const { | operator Matcher<const FloatType&>() const { | |||
return MakeMatcher( | return MakeMatcher( | |||
new Impl<const FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); | new Impl<const FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); | |||
} | } | |||
operator Matcher<FloatType&>() const { | operator Matcher<FloatType&>() const { | |||
return MakeMatcher( | return MakeMatcher( | |||
new Impl<FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); | new Impl<FloatType&>(expected_, nan_eq_nan_, max_abs_error_)); | |||
} | } | |||
private: | private: | |||
const FloatType expected_; | const FloatType expected_; | |||
const bool nan_eq_nan_; | const bool nan_eq_nan_; | |||
// max_abs_error will be used for value comparison when >= 0. | // max_abs_error will be used for value comparison when >= 0. | |||
const FloatType max_abs_error_; | const FloatType max_abs_error_; | |||
GTEST_DISALLOW_ASSIGN_(FloatingEqMatcher); | ||||
}; | }; | |||
// A 2-tuple ("binary") wrapper around FloatingEqMatcher: | // A 2-tuple ("binary") wrapper around FloatingEqMatcher: | |||
// FloatingEq2Matcher() matches (x, y) by matching FloatingEqMatcher(x, false) | // FloatingEq2Matcher() matches (x, y) by matching FloatingEqMatcher(x, false) | |||
// against y, and FloatingEq2Matcher(e) matches FloatingEqMatcher(x, false, e) | // against y, and FloatingEq2Matcher(e) matches FloatingEqMatcher(x, false, e) | |||
// against y. The former implements "Eq", the latter "Near". At present, there | // against y. The former implements "Eq", the latter "Near". At present, there | |||
// is no version that compares NaNs as equal. | // is no version that compares NaNs as equal. | |||
template <typename FloatType> | template <typename FloatType> | |||
class FloatingEq2Matcher { | class FloatingEq2Matcher { | |||
public: | public: | |||
skipping to change at line 1609 | skipping to change at line 1837 | |||
template <typename Pointer> | template <typename Pointer> | |||
operator Matcher<Pointer>() const { | operator Matcher<Pointer>() const { | |||
return Matcher<Pointer>(new Impl<const Pointer&>(matcher_)); | return Matcher<Pointer>(new Impl<const Pointer&>(matcher_)); | |||
} | } | |||
private: | private: | |||
// The monomorphic implementation that works for a particular pointer type. | // The monomorphic implementation that works for a particular pointer type. | |||
template <typename Pointer> | template <typename Pointer> | |||
class Impl : public MatcherInterface<Pointer> { | class Impl : public MatcherInterface<Pointer> { | |||
public: | public: | |||
typedef typename PointeeOf<typename std::remove_const< | using Pointee = | |||
typename std::remove_reference<Pointer>::type>::type>::type Pointee; | typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_( | |||
Pointer)>::element_type; | ||||
explicit Impl(const InnerMatcher& matcher) | explicit Impl(const InnerMatcher& matcher) | |||
: matcher_(MatcherCast<const Pointee&>(matcher)) {} | : matcher_(MatcherCast<const Pointee&>(matcher)) {} | |||
void DescribeTo(::std::ostream* os) const override { | void DescribeTo(::std::ostream* os) const override { | |||
*os << "points to a value that "; | *os << "points to a value that "; | |||
matcher_.DescribeTo(os); | matcher_.DescribeTo(os); | |||
} | } | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
skipping to change at line 1635 | skipping to change at line 1864 | |||
bool MatchAndExplain(Pointer pointer, | bool MatchAndExplain(Pointer pointer, | |||
MatchResultListener* listener) const override { | MatchResultListener* listener) const override { | |||
if (GetRawPointer(pointer) == nullptr) return false; | if (GetRawPointer(pointer) == nullptr) return false; | |||
*listener << "which points to "; | *listener << "which points to "; | |||
return MatchPrintAndExplain(*pointer, matcher_, listener); | return MatchPrintAndExplain(*pointer, matcher_, listener); | |||
} | } | |||
private: | private: | |||
const Matcher<const Pointee&> matcher_; | const Matcher<const Pointee&> matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
const InnerMatcher matcher_; | const InnerMatcher matcher_; | |||
}; | ||||
GTEST_DISALLOW_ASSIGN_(PointeeMatcher); | // Implements the Pointer(m) matcher | |||
// Implements the Pointer(m) matcher for matching a pointer that matches matcher | ||||
// m. The pointer can be either raw or smart, and will match `m` against the | ||||
// raw pointer. | ||||
template <typename InnerMatcher> | ||||
class PointerMatcher { | ||||
public: | ||||
explicit PointerMatcher(const InnerMatcher& matcher) : matcher_(matcher) {} | ||||
// This type conversion operator template allows Pointer(m) to be | ||||
// used as a matcher for any pointer type whose pointer type is | ||||
// compatible with the inner matcher, where type PointerType can be | ||||
// either a raw pointer or a smart pointer. | ||||
// | ||||
// The reason we do this instead of relying on | ||||
// MakePolymorphicMatcher() is that the latter is not flexible | ||||
// enough for implementing the DescribeTo() method of Pointer(). | ||||
template <typename PointerType> | ||||
operator Matcher<PointerType>() const { // NOLINT | ||||
return Matcher<PointerType>(new Impl<const PointerType&>(matcher_)); | ||||
} | ||||
private: | ||||
// The monomorphic implementation that works for a particular pointer type. | ||||
template <typename PointerType> | ||||
class Impl : public MatcherInterface<PointerType> { | ||||
public: | ||||
using Pointer = | ||||
const typename std::pointer_traits<GTEST_REMOVE_REFERENCE_AND_CONST_( | ||||
PointerType)>::element_type*; | ||||
explicit Impl(const InnerMatcher& matcher) | ||||
: matcher_(MatcherCast<Pointer>(matcher)) {} | ||||
void DescribeTo(::std::ostream* os) const override { | ||||
*os << "is a pointer that "; | ||||
matcher_.DescribeTo(os); | ||||
} | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
*os << "is not a pointer that "; | ||||
matcher_.DescribeTo(os); | ||||
} | ||||
bool MatchAndExplain(PointerType pointer, | ||||
MatchResultListener* listener) const override { | ||||
*listener << "which is a pointer that "; | ||||
Pointer p = GetRawPointer(pointer); | ||||
return MatchPrintAndExplain(p, matcher_, listener); | ||||
} | ||||
private: | ||||
Matcher<Pointer> matcher_; | ||||
}; | ||||
const InnerMatcher matcher_; | ||||
}; | }; | |||
#if GTEST_HAS_RTTI | #if GTEST_HAS_RTTI | |||
// Implements the WhenDynamicCastTo<T>(m) matcher that matches a pointer or | // Implements the WhenDynamicCastTo<T>(m) matcher that matches a pointer or | |||
// reference that matches inner_matcher when dynamic_cast<T> is applied. | // reference that matches inner_matcher when dynamic_cast<T> is applied. | |||
// The result of dynamic_cast<To> is forwarded to the inner matcher. | // The result of dynamic_cast<To> is forwarded to the inner matcher. | |||
// If To is a pointer and the cast fails, the inner matcher will receive NULL. | // If To is a pointer and the cast fails, the inner matcher will receive NULL. | |||
// If To is a reference and the cast fails, this matcher returns false | // If To is a reference and the cast fails, this matcher returns false | |||
// immediately. | // immediately. | |||
template <typename To> | template <typename To> | |||
skipping to change at line 1678 | skipping to change at line 1961 | |||
const Matcher<To> matcher_; | const Matcher<To> matcher_; | |||
static std::string GetToName() { | static std::string GetToName() { | |||
return GetTypeName<To>(); | return GetTypeName<To>(); | |||
} | } | |||
private: | private: | |||
static void GetCastTypeDescription(::std::ostream* os) { | static void GetCastTypeDescription(::std::ostream* os) { | |||
*os << "when dynamic_cast to " << GetToName() << ", "; | *os << "when dynamic_cast to " << GetToName() << ", "; | |||
} | } | |||
GTEST_DISALLOW_ASSIGN_(WhenDynamicCastToMatcherBase); | ||||
}; | }; | |||
// Primary template. | // Primary template. | |||
// To is a pointer. Cast and forward the result. | // To is a pointer. Cast and forward the result. | |||
template <typename To> | template <typename To> | |||
class WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase<To> { | class WhenDynamicCastToMatcher : public WhenDynamicCastToMatcherBase<To> { | |||
public: | public: | |||
explicit WhenDynamicCastToMatcher(const Matcher<To>& matcher) | explicit WhenDynamicCastToMatcher(const Matcher<To>& matcher) | |||
: WhenDynamicCastToMatcherBase<To>(matcher) {} | : WhenDynamicCastToMatcherBase<To>(matcher) {} | |||
skipping to change at line 1777 | skipping to change at line 2058 | |||
// the first argument. | // the first argument. | |||
return MatchAndExplainImpl(std::false_type(), *p, listener); | return MatchAndExplainImpl(std::false_type(), *p, listener); | |||
} | } | |||
const FieldType Class::*field_; | const FieldType Class::*field_; | |||
const Matcher<const FieldType&> matcher_; | const Matcher<const FieldType&> matcher_; | |||
// Contains either "whose given field " if the name of the field is unknown | // Contains either "whose given field " if the name of the field is unknown | |||
// or "whose field `name_of_field` " if the name is known. | // or "whose field `name_of_field` " if the name is known. | |||
const std::string whose_field_; | const std::string whose_field_; | |||
GTEST_DISALLOW_ASSIGN_(FieldMatcher); | ||||
}; | }; | |||
// Implements the Property() matcher for matching a property | // Implements the Property() matcher for matching a property | |||
// (i.e. return value of a getter method) of an object. | // (i.e. return value of a getter method) of an object. | |||
// | // | |||
// Property is a const-qualified member function of Class returning | // Property is a const-qualified member function of Class returning | |||
// PropertyType. | // PropertyType. | |||
template <typename Class, typename PropertyType, typename Property> | template <typename Class, typename PropertyType, typename Property> | |||
class PropertyMatcher { | class PropertyMatcher { | |||
public: | public: | |||
skipping to change at line 1847 | skipping to change at line 2126 | |||
// false_type() as the first argument. | // false_type() as the first argument. | |||
return MatchAndExplainImpl(std::false_type(), *p, listener); | return MatchAndExplainImpl(std::false_type(), *p, listener); | |||
} | } | |||
Property property_; | Property property_; | |||
const Matcher<RefToConstProperty> matcher_; | const Matcher<RefToConstProperty> matcher_; | |||
// Contains either "whose given property " if the name of the property is | // Contains either "whose given property " if the name of the property is | |||
// unknown or "whose property `name_of_property` " if the name is known. | // unknown or "whose property `name_of_property` " if the name is known. | |||
const std::string whose_property_; | const std::string whose_property_; | |||
GTEST_DISALLOW_ASSIGN_(PropertyMatcher); | ||||
}; | }; | |||
// Type traits specifying various features of different functors for ResultOf. | // Type traits specifying various features of different functors for ResultOf. | |||
// The default template specifies features for functor objects. | // The default template specifies features for functor objects. | |||
template <typename Functor> | template <typename Functor> | |||
struct CallableTraits { | struct CallableTraits { | |||
typedef Functor StorageType; | typedef Functor StorageType; | |||
static void CheckIsValid(Functor /* functor */) {} | static void CheckIsValid(Functor /* functor */) {} | |||
skipping to change at line 1938 | skipping to change at line 2215 | |||
} | } | |||
private: | private: | |||
// Functors often define operator() as non-const method even though | // Functors often define operator() as non-const method even though | |||
// they are actually stateless. But we need to use them even when | // they are actually stateless. But we need to use them even when | |||
// 'this' is a const pointer. It's the user's responsibility not to | // 'this' is a const pointer. It's the user's responsibility not to | |||
// use stateful callables with ResultOf(), which doesn't guarantee | // use stateful callables with ResultOf(), which doesn't guarantee | |||
// how many times the callable will be invoked. | // how many times the callable will be invoked. | |||
mutable CallableStorageType callable_; | mutable CallableStorageType callable_; | |||
const Matcher<ResultType> matcher_; | const Matcher<ResultType> matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; // class Impl | }; // class Impl | |||
const CallableStorageType callable_; | const CallableStorageType callable_; | |||
const InnerMatcher matcher_; | const InnerMatcher matcher_; | |||
GTEST_DISALLOW_ASSIGN_(ResultOfMatcher); | ||||
}; | }; | |||
// Implements a matcher that checks the size of an STL-style container. | // Implements a matcher that checks the size of an STL-style container. | |||
template <typename SizeMatcher> | template <typename SizeMatcher> | |||
class SizeIsMatcher { | class SizeIsMatcher { | |||
public: | public: | |||
explicit SizeIsMatcher(const SizeMatcher& size_matcher) | explicit SizeIsMatcher(const SizeMatcher& size_matcher) | |||
: size_matcher_(size_matcher) { | : size_matcher_(size_matcher) { | |||
} | } | |||
skipping to change at line 1990 | skipping to change at line 2263 | |||
StringMatchResultListener size_listener; | StringMatchResultListener size_listener; | |||
const bool result = size_matcher_.MatchAndExplain(size, &size_listener); | const bool result = size_matcher_.MatchAndExplain(size, &size_listener); | |||
*listener | *listener | |||
<< "whose size " << size << (result ? " matches" : " doesn't match"); | << "whose size " << size << (result ? " matches" : " doesn't match"); | |||
PrintIfNotEmpty(size_listener.str(), listener->stream()); | PrintIfNotEmpty(size_listener.str(), listener->stream()); | |||
return result; | return result; | |||
} | } | |||
private: | private: | |||
const Matcher<SizeType> size_matcher_; | const Matcher<SizeType> size_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
private: | private: | |||
const SizeMatcher size_matcher_; | const SizeMatcher size_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(SizeIsMatcher); | ||||
}; | }; | |||
// Implements a matcher that checks the begin()..end() distance of an STL-style | // Implements a matcher that checks the begin()..end() distance of an STL-style | |||
// container. | // container. | |||
template <typename DistanceMatcher> | template <typename DistanceMatcher> | |||
class BeginEndDistanceIsMatcher { | class BeginEndDistanceIsMatcher { | |||
public: | public: | |||
explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher) | explicit BeginEndDistanceIsMatcher(const DistanceMatcher& distance_matcher) | |||
: distance_matcher_(distance_matcher) {} | : distance_matcher_(distance_matcher) {} | |||
skipping to change at line 2047 | skipping to change at line 2318 | |||
const bool result = | const bool result = | |||
distance_matcher_.MatchAndExplain(distance, &distance_listener); | distance_matcher_.MatchAndExplain(distance, &distance_listener); | |||
*listener << "whose distance between begin() and end() " << distance | *listener << "whose distance between begin() and end() " << distance | |||
<< (result ? " matches" : " doesn't match"); | << (result ? " matches" : " doesn't match"); | |||
PrintIfNotEmpty(distance_listener.str(), listener->stream()); | PrintIfNotEmpty(distance_listener.str(), listener->stream()); | |||
return result; | return result; | |||
} | } | |||
private: | private: | |||
const Matcher<DistanceType> distance_matcher_; | const Matcher<DistanceType> distance_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
private: | private: | |||
const DistanceMatcher distance_matcher_; | const DistanceMatcher distance_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(BeginEndDistanceIsMatcher); | ||||
}; | }; | |||
// Implements an equality matcher for any STL-style container whose elements | // Implements an equality matcher for any STL-style container whose elements | |||
// support ==. This matcher is like Eq(), but its failure explanations provide | // support ==. This matcher is like Eq(), but its failure explanations provide | |||
// more detailed information that is useful when the container is used as a set. | // more detailed information that is useful when the container is used as a set. | |||
// The failure message reports elements that are in one of the operands but not | // The failure message reports elements that are in one of the operands but not | |||
// the other. The failure messages do not report duplicate or out-of-order | // the other. The failure messages do not report duplicate or out-of-order | |||
// elements in the containers (which don't properly matter to sets, but can | // elements in the containers (which don't properly matter to sets, but can | |||
// occur if the containers are vectors or lists, for example). | // occur if the containers are vectors or lists, for example). | |||
// | // | |||
skipping to change at line 2145 | skipping to change at line 2414 | |||
UniversalPrint(*it, os); | UniversalPrint(*it, os); | |||
} | } | |||
} | } | |||
} | } | |||
return false; | return false; | |||
} | } | |||
private: | private: | |||
const StlContainer expected_; | const StlContainer expected_; | |||
GTEST_DISALLOW_ASSIGN_(ContainerEqMatcher); | ||||
}; | }; | |||
// A comparator functor that uses the < operator to compare two values. | // A comparator functor that uses the < operator to compare two values. | |||
struct LessComparator { | struct LessComparator { | |||
template <typename T, typename U> | template <typename T, typename U> | |||
bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; } | bool operator()(const T& lhs, const U& rhs) const { return lhs < rhs; } | |||
}; | }; | |||
// Implements WhenSortedBy(comparator, container_matcher). | // Implements WhenSortedBy(comparator, container_matcher). | |||
template <typename Comparator, typename ContainerMatcher> | template <typename Comparator, typename ContainerMatcher> | |||
skipping to change at line 2228 | skipping to change at line 2495 | |||
private: | private: | |||
const Comparator comparator_; | const Comparator comparator_; | |||
const Matcher<const ::std::vector<LhsValue>&> matcher_; | const Matcher<const ::std::vector<LhsValue>&> matcher_; | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); | GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); | |||
}; | }; | |||
private: | private: | |||
const Comparator comparator_; | const Comparator comparator_; | |||
const ContainerMatcher matcher_; | const ContainerMatcher matcher_; | |||
GTEST_DISALLOW_ASSIGN_(WhenSortedByMatcher); | ||||
}; | }; | |||
// Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher | // Implements Pointwise(tuple_matcher, rhs_container). tuple_matcher | |||
// must be able to be safely cast to Matcher<std::tuple<const T1&, const | // must be able to be safely cast to Matcher<std::tuple<const T1&, const | |||
// T2&> >, where T1 and T2 are the types of elements in the LHS | // T2&> >, where T1 and T2 are the types of elements in the LHS | |||
// container and the RHS container respectively. | // container and the RHS container respectively. | |||
template <typename TupleMatcher, typename RhsContainer> | template <typename TupleMatcher, typename RhsContainer> | |||
class PointwiseMatcher { | class PointwiseMatcher { | |||
GTEST_COMPILE_ASSERT_( | GTEST_COMPILE_ASSERT_( | |||
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value, | !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(RhsContainer)>::value, | |||
skipping to change at line 2345 | skipping to change at line 2610 | |||
return false; | return false; | |||
} | } | |||
} | } | |||
return true; | return true; | |||
} | } | |||
private: | private: | |||
const Matcher<InnerMatcherArg> mono_tuple_matcher_; | const Matcher<InnerMatcherArg> mono_tuple_matcher_; | |||
const RhsStlContainer rhs_; | const RhsStlContainer rhs_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
private: | private: | |||
const TupleMatcher tuple_matcher_; | const TupleMatcher tuple_matcher_; | |||
const RhsStlContainer rhs_; | const RhsStlContainer rhs_; | |||
GTEST_DISALLOW_ASSIGN_(PointwiseMatcher); | ||||
}; | }; | |||
// Holds the logic common to ContainsMatcherImpl and EachMatcherImpl. | // Holds the logic common to ContainsMatcherImpl and EachMatcherImpl. | |||
template <typename Container> | template <typename Container> | |||
class QuantifierMatcherImpl : public MatcherInterface<Container> { | class QuantifierMatcherImpl : public MatcherInterface<Container> { | |||
public: | public: | |||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | |||
typedef StlContainerView<RawContainer> View; | typedef StlContainerView<RawContainer> View; | |||
typedef typename View::type StlContainer; | typedef typename View::type StlContainer; | |||
typedef typename View::const_reference StlContainerReference; | typedef typename View::const_reference StlContainerReference; | |||
skipping to change at line 2396 | skipping to change at line 2657 | |||
<< (matches ? " matches" : " doesn't match"); | << (matches ? " matches" : " doesn't match"); | |||
PrintIfNotEmpty(inner_listener.str(), listener->stream()); | PrintIfNotEmpty(inner_listener.str(), listener->stream()); | |||
return !all_elements_should_match; | return !all_elements_should_match; | |||
} | } | |||
} | } | |||
return all_elements_should_match; | return all_elements_should_match; | |||
} | } | |||
protected: | protected: | |||
const Matcher<const Element&> inner_matcher_; | const Matcher<const Element&> inner_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(QuantifierMatcherImpl); | ||||
}; | }; | |||
// Implements Contains(element_matcher) for the given argument type Container. | // Implements Contains(element_matcher) for the given argument type Container. | |||
// Symmetric to EachMatcherImpl. | // Symmetric to EachMatcherImpl. | |||
template <typename Container> | template <typename Container> | |||
class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> { | class ContainsMatcherImpl : public QuantifierMatcherImpl<Container> { | |||
public: | public: | |||
template <typename InnerMatcher> | template <typename InnerMatcher> | |||
explicit ContainsMatcherImpl(InnerMatcher inner_matcher) | explicit ContainsMatcherImpl(InnerMatcher inner_matcher) | |||
: QuantifierMatcherImpl<Container>(inner_matcher) {} | : QuantifierMatcherImpl<Container>(inner_matcher) {} | |||
skipping to change at line 2424 | skipping to change at line 2683 | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
*os << "doesn't contain any element that "; | *os << "doesn't contain any element that "; | |||
this->inner_matcher_.DescribeTo(os); | this->inner_matcher_.DescribeTo(os); | |||
} | } | |||
bool MatchAndExplain(Container container, | bool MatchAndExplain(Container container, | |||
MatchResultListener* listener) const override { | MatchResultListener* listener) const override { | |||
return this->MatchAndExplainImpl(false, container, listener); | return this->MatchAndExplainImpl(false, container, listener); | |||
} | } | |||
private: | ||||
GTEST_DISALLOW_ASSIGN_(ContainsMatcherImpl); | ||||
}; | }; | |||
// Implements Each(element_matcher) for the given argument type Container. | // Implements Each(element_matcher) for the given argument type Container. | |||
// Symmetric to ContainsMatcherImpl. | // Symmetric to ContainsMatcherImpl. | |||
template <typename Container> | template <typename Container> | |||
class EachMatcherImpl : public QuantifierMatcherImpl<Container> { | class EachMatcherImpl : public QuantifierMatcherImpl<Container> { | |||
public: | public: | |||
template <typename InnerMatcher> | template <typename InnerMatcher> | |||
explicit EachMatcherImpl(InnerMatcher inner_matcher) | explicit EachMatcherImpl(InnerMatcher inner_matcher) | |||
: QuantifierMatcherImpl<Container>(inner_matcher) {} | : QuantifierMatcherImpl<Container>(inner_matcher) {} | |||
skipping to change at line 2453 | skipping to change at line 2709 | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
*os << "contains some element that "; | *os << "contains some element that "; | |||
this->inner_matcher_.DescribeNegationTo(os); | this->inner_matcher_.DescribeNegationTo(os); | |||
} | } | |||
bool MatchAndExplain(Container container, | bool MatchAndExplain(Container container, | |||
MatchResultListener* listener) const override { | MatchResultListener* listener) const override { | |||
return this->MatchAndExplainImpl(true, container, listener); | return this->MatchAndExplainImpl(true, container, listener); | |||
} | } | |||
private: | ||||
GTEST_DISALLOW_ASSIGN_(EachMatcherImpl); | ||||
}; | }; | |||
// Implements polymorphic Contains(element_matcher). | // Implements polymorphic Contains(element_matcher). | |||
template <typename M> | template <typename M> | |||
class ContainsMatcher { | class ContainsMatcher { | |||
public: | public: | |||
explicit ContainsMatcher(M m) : inner_matcher_(m) {} | explicit ContainsMatcher(M m) : inner_matcher_(m) {} | |||
template <typename Container> | template <typename Container> | |||
operator Matcher<Container>() const { | operator Matcher<Container>() const { | |||
return Matcher<Container>( | return Matcher<Container>( | |||
new ContainsMatcherImpl<const Container&>(inner_matcher_)); | new ContainsMatcherImpl<const Container&>(inner_matcher_)); | |||
} | } | |||
private: | private: | |||
const M inner_matcher_; | const M inner_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(ContainsMatcher); | ||||
}; | }; | |||
// Implements polymorphic Each(element_matcher). | // Implements polymorphic Each(element_matcher). | |||
template <typename M> | template <typename M> | |||
class EachMatcher { | class EachMatcher { | |||
public: | public: | |||
explicit EachMatcher(M m) : inner_matcher_(m) {} | explicit EachMatcher(M m) : inner_matcher_(m) {} | |||
template <typename Container> | template <typename Container> | |||
operator Matcher<Container>() const { | operator Matcher<Container>() const { | |||
return Matcher<Container>( | return Matcher<Container>( | |||
new EachMatcherImpl<const Container&>(inner_matcher_)); | new EachMatcherImpl<const Container&>(inner_matcher_)); | |||
} | } | |||
private: | private: | |||
const M inner_matcher_; | const M inner_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(EachMatcher); | ||||
}; | }; | |||
struct Rank1 {}; | struct Rank1 {}; | |||
struct Rank0 : Rank1 {}; | struct Rank0 : Rank1 {}; | |||
namespace pair_getters { | namespace pair_getters { | |||
using std::get; | using std::get; | |||
template <typename T> | template <typename T> | |||
auto First(T& x, Rank1) -> decltype(get<0>(x)) { // NOLINT | auto First(T& x, Rank1) -> decltype(get<0>(x)) { // NOLINT | |||
return get<0>(x); | return get<0>(x); | |||
skipping to change at line 2562 | skipping to change at line 2811 | |||
} | } | |||
// Describes what the negation of this matcher does. | // Describes what the negation of this matcher does. | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
*os << "doesn't have a key that "; | *os << "doesn't have a key that "; | |||
inner_matcher_.DescribeTo(os); | inner_matcher_.DescribeTo(os); | |||
} | } | |||
private: | private: | |||
const Matcher<const KeyType&> inner_matcher_; | const Matcher<const KeyType&> inner_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(KeyMatcherImpl); | ||||
}; | }; | |||
// Implements polymorphic Key(matcher_for_key). | // Implements polymorphic Key(matcher_for_key). | |||
template <typename M> | template <typename M> | |||
class KeyMatcher { | class KeyMatcher { | |||
public: | public: | |||
explicit KeyMatcher(M m) : matcher_for_key_(m) {} | explicit KeyMatcher(M m) : matcher_for_key_(m) {} | |||
template <typename PairType> | template <typename PairType> | |||
operator Matcher<PairType>() const { | operator Matcher<PairType>() const { | |||
return Matcher<PairType>( | return Matcher<PairType>( | |||
new KeyMatcherImpl<const PairType&>(matcher_for_key_)); | new KeyMatcherImpl<const PairType&>(matcher_for_key_)); | |||
} | } | |||
private: | private: | |||
const M matcher_for_key_; | const M matcher_for_key_; | |||
}; | ||||
GTEST_DISALLOW_ASSIGN_(KeyMatcher); | // Implements polymorphic Address(matcher_for_address). | |||
template <typename InnerMatcher> | ||||
class AddressMatcher { | ||||
public: | ||||
explicit AddressMatcher(InnerMatcher m) : matcher_(m) {} | ||||
template <typename Type> | ||||
operator Matcher<Type>() const { // NOLINT | ||||
return Matcher<Type>(new Impl<const Type&>(matcher_)); | ||||
} | ||||
private: | ||||
// The monomorphic implementation that works for a particular object type. | ||||
template <typename Type> | ||||
class Impl : public MatcherInterface<Type> { | ||||
public: | ||||
using Address = const GTEST_REMOVE_REFERENCE_AND_CONST_(Type) *; | ||||
explicit Impl(const InnerMatcher& matcher) | ||||
: matcher_(MatcherCast<Address>(matcher)) {} | ||||
void DescribeTo(::std::ostream* os) const override { | ||||
*os << "has address that "; | ||||
matcher_.DescribeTo(os); | ||||
} | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
*os << "does not have address that "; | ||||
matcher_.DescribeTo(os); | ||||
} | ||||
bool MatchAndExplain(Type object, | ||||
MatchResultListener* listener) const override { | ||||
*listener << "which has address "; | ||||
Address address = std::addressof(object); | ||||
return MatchPrintAndExplain(address, matcher_, listener); | ||||
} | ||||
private: | ||||
const Matcher<Address> matcher_; | ||||
}; | ||||
const InnerMatcher matcher_; | ||||
}; | }; | |||
// Implements Pair(first_matcher, second_matcher) for the given argument pair | // Implements Pair(first_matcher, second_matcher) for the given argument pair | |||
// type with its two matchers. See Pair() function below. | // type with its two matchers. See Pair() function below. | |||
template <typename PairType> | template <typename PairType> | |||
class PairMatcherImpl : public MatcherInterface<PairType> { | class PairMatcherImpl : public MatcherInterface<PairType> { | |||
public: | public: | |||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; | typedef GTEST_REMOVE_REFERENCE_AND_CONST_(PairType) RawPairType; | |||
typedef typename RawPairType::first_type FirstType; | typedef typename RawPairType::first_type FirstType; | |||
typedef typename RawPairType::second_type SecondType; | typedef typename RawPairType::second_type SecondType; | |||
skipping to change at line 2667 | skipping to change at line 2955 | |||
*listener << "and "; | *listener << "and "; | |||
} else { | } else { | |||
*listener << "where "; | *listener << "where "; | |||
} | } | |||
*listener << "the second field is a value " << second_explanation; | *listener << "the second field is a value " << second_explanation; | |||
} | } | |||
} | } | |||
const Matcher<const FirstType&> first_matcher_; | const Matcher<const FirstType&> first_matcher_; | |||
const Matcher<const SecondType&> second_matcher_; | const Matcher<const SecondType&> second_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(PairMatcherImpl); | ||||
}; | }; | |||
// Implements polymorphic Pair(first_matcher, second_matcher). | // Implements polymorphic Pair(first_matcher, second_matcher). | |||
template <typename FirstMatcher, typename SecondMatcher> | template <typename FirstMatcher, typename SecondMatcher> | |||
class PairMatcher { | class PairMatcher { | |||
public: | public: | |||
PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher) | PairMatcher(FirstMatcher first_matcher, SecondMatcher second_matcher) | |||
: first_matcher_(first_matcher), second_matcher_(second_matcher) {} | : first_matcher_(first_matcher), second_matcher_(second_matcher) {} | |||
template <typename PairType> | template <typename PairType> | |||
operator Matcher<PairType> () const { | operator Matcher<PairType> () const { | |||
return Matcher<PairType>( | return Matcher<PairType>( | |||
new PairMatcherImpl<const PairType&>(first_matcher_, second_matcher_)); | new PairMatcherImpl<const PairType&>(first_matcher_, second_matcher_)); | |||
} | } | |||
private: | private: | |||
const FirstMatcher first_matcher_; | const FirstMatcher first_matcher_; | |||
const SecondMatcher second_matcher_; | const SecondMatcher second_matcher_; | |||
}; | ||||
GTEST_DISALLOW_ASSIGN_(PairMatcher); | template <typename T, size_t... I> | |||
auto UnpackStructImpl(const T& t, IndexSequence<I...>, int) | ||||
-> decltype(std::tie(get<I>(t)...)) { | ||||
static_assert(std::tuple_size<T>::value == sizeof...(I), | ||||
"Number of arguments doesn't match the number of fields."); | ||||
return std::tie(get<I>(t)...); | ||||
} | ||||
#if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 201606 | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<1>, char) { | ||||
const auto& [a] = t; | ||||
return std::tie(a); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<2>, char) { | ||||
const auto& [a, b] = t; | ||||
return std::tie(a, b); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<3>, char) { | ||||
const auto& [a, b, c] = t; | ||||
return std::tie(a, b, c); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<4>, char) { | ||||
const auto& [a, b, c, d] = t; | ||||
return std::tie(a, b, c, d); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<5>, char) { | ||||
const auto& [a, b, c, d, e] = t; | ||||
return std::tie(a, b, c, d, e); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<6>, char) { | ||||
const auto& [a, b, c, d, e, f] = t; | ||||
return std::tie(a, b, c, d, e, f); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<7>, char) { | ||||
const auto& [a, b, c, d, e, f, g] = t; | ||||
return std::tie(a, b, c, d, e, f, g); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<8>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<9>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<10>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<11>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<12>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<13>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<14>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<15>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o); | ||||
} | ||||
template <typename T> | ||||
auto UnpackStructImpl(const T& t, MakeIndexSequence<16>, char) { | ||||
const auto& [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p] = t; | ||||
return std::tie(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p); | ||||
} | ||||
#endif // defined(__cpp_structured_bindings) | ||||
template <size_t I, typename T> | ||||
auto UnpackStruct(const T& t) | ||||
-> decltype((UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0)) { | ||||
return (UnpackStructImpl)(t, MakeIndexSequence<I>{}, 0); | ||||
} | ||||
// Helper function to do comma folding in C++11. | ||||
// The array ensures left-to-right order of evaluation. | ||||
// Usage: VariadicExpand({expr...}); | ||||
template <typename T, size_t N> | ||||
void VariadicExpand(const T (&)[N]) {} | ||||
template <typename Struct, typename StructSize> | ||||
class FieldsAreMatcherImpl; | ||||
template <typename Struct, size_t... I> | ||||
class FieldsAreMatcherImpl<Struct, IndexSequence<I...>> | ||||
: public MatcherInterface<Struct> { | ||||
using UnpackedType = | ||||
decltype(UnpackStruct<sizeof...(I)>(std::declval<const Struct&>())); | ||||
using MatchersType = std::tuple< | ||||
Matcher<const typename std::tuple_element<I, UnpackedType>::type&>...>; | ||||
public: | ||||
template <typename Inner> | ||||
explicit FieldsAreMatcherImpl(const Inner& matchers) | ||||
: matchers_(testing::SafeMatcherCast< | ||||
const typename std::tuple_element<I, UnpackedType>::type&>( | ||||
std::get<I>(matchers))...) {} | ||||
void DescribeTo(::std::ostream* os) const override { | ||||
const char* separator = ""; | ||||
VariadicExpand( | ||||
{(*os << separator << "has field #" << I << " that ", | ||||
std::get<I>(matchers_).DescribeTo(os), separator = ", and ")...}); | ||||
} | ||||
void DescribeNegationTo(::std::ostream* os) const override { | ||||
const char* separator = ""; | ||||
VariadicExpand({(*os << separator << "has field #" << I << " that ", | ||||
std::get<I>(matchers_).DescribeNegationTo(os), | ||||
separator = ", or ")...}); | ||||
} | ||||
bool MatchAndExplain(Struct t, MatchResultListener* listener) const override { | ||||
return MatchInternal((UnpackStruct<sizeof...(I)>)(t), listener); | ||||
} | ||||
private: | ||||
bool MatchInternal(UnpackedType tuple, MatchResultListener* listener) const { | ||||
if (!listener->IsInterested()) { | ||||
// If the listener is not interested, we don't need to construct the | ||||
// explanation. | ||||
bool good = true; | ||||
VariadicExpand({good = good && std::get<I>(matchers_).Matches( | ||||
std::get<I>(tuple))...}); | ||||
return good; | ||||
} | ||||
size_t failed_pos = ~size_t{}; | ||||
std::vector<StringMatchResultListener> inner_listener(sizeof...(I)); | ||||
VariadicExpand( | ||||
{failed_pos == ~size_t{} && !std::get<I>(matchers_).MatchAndExplain( | ||||
std::get<I>(tuple), &inner_listener[I]) | ||||
? failed_pos = I | ||||
: 0 ...}); | ||||
if (failed_pos != ~size_t{}) { | ||||
*listener << "whose field #" << failed_pos << " does not match"; | ||||
PrintIfNotEmpty(inner_listener[failed_pos].str(), listener->stream()); | ||||
return false; | ||||
} | ||||
*listener << "whose all elements match"; | ||||
const char* separator = ", where"; | ||||
for (size_t index = 0; index < sizeof...(I); ++index) { | ||||
const std::string str = inner_listener[index].str(); | ||||
if (!str.empty()) { | ||||
*listener << separator << " field #" << index << " is a value " << str; | ||||
separator = ", and"; | ||||
} | ||||
} | ||||
return true; | ||||
} | ||||
MatchersType matchers_; | ||||
}; | ||||
template <typename... Inner> | ||||
class FieldsAreMatcher { | ||||
public: | ||||
explicit FieldsAreMatcher(Inner... inner) : matchers_(std::move(inner)...) {} | ||||
template <typename Struct> | ||||
operator Matcher<Struct>() const { // NOLINT | ||||
return Matcher<Struct>( | ||||
new FieldsAreMatcherImpl<const Struct&, IndexSequenceFor<Inner...>>( | ||||
matchers_)); | ||||
} | ||||
private: | ||||
std::tuple<Inner...> matchers_; | ||||
}; | }; | |||
// Implements ElementsAre() and ElementsAreArray(). | // Implements ElementsAre() and ElementsAreArray(). | |||
template <typename Container> | template <typename Container> | |||
class ElementsAreMatcherImpl : public MatcherInterface<Container> { | class ElementsAreMatcherImpl : public MatcherInterface<Container> { | |||
public: | public: | |||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | |||
typedef internal::StlContainerView<RawContainer> View; | typedef internal::StlContainerView<RawContainer> View; | |||
typedef typename View::type StlContainer; | typedef typename View::type StlContainer; | |||
typedef typename View::const_reference StlContainerReference; | typedef typename View::const_reference StlContainerReference; | |||
skipping to change at line 2834 | skipping to change at line 3315 | |||
} | } | |||
private: | private: | |||
static Message Elements(size_t count) { | static Message Elements(size_t count) { | |||
return Message() << count << (count == 1 ? " element" : " elements"); | return Message() << count << (count == 1 ? " element" : " elements"); | |||
} | } | |||
size_t count() const { return matchers_.size(); } | size_t count() const { return matchers_.size(); } | |||
::std::vector<Matcher<const Element&> > matchers_; | ::std::vector<Matcher<const Element&> > matchers_; | |||
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcherImpl); | ||||
}; | }; | |||
// Connectivity matrix of (elements X matchers), in element-major order. | // Connectivity matrix of (elements X matchers), in element-major order. | |||
// Initially, there are no edges. | // Initially, there are no edges. | |||
// Use NextGraph() to iterate over all possible edge configurations. | // Use NextGraph() to iterate over all possible edge configurations. | |||
// Use Randomize() to generate a random edge configuration. | // Use Randomize() to generate a random edge configuration. | |||
class GTEST_API_ MatchMatrix { | class GTEST_API_ MatchMatrix { | |||
public: | public: | |||
MatchMatrix(size_t num_elements, size_t num_matchers) | MatchMatrix(size_t num_elements, size_t num_matchers) | |||
: num_elements_(num_elements), | : num_elements_(num_elements), | |||
skipping to change at line 2938 | skipping to change at line 3417 | |||
static Message Elements(size_t n) { | static Message Elements(size_t n) { | |||
return Message() << n << " element" << (n == 1 ? "" : "s"); | return Message() << n << " element" << (n == 1 ? "" : "s"); | |||
} | } | |||
UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; } | UnorderedMatcherRequire::Flags match_flags() const { return match_flags_; } | |||
private: | private: | |||
UnorderedMatcherRequire::Flags match_flags_; | UnorderedMatcherRequire::Flags match_flags_; | |||
MatcherDescriberVec matcher_describers_; | MatcherDescriberVec matcher_describers_; | |||
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImplBase); | ||||
}; | }; | |||
// Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and | // Implements UnorderedElementsAre, UnorderedElementsAreArray, IsSubsetOf, and | |||
// IsSupersetOf. | // IsSupersetOf. | |||
template <typename Container> | template <typename Container> | |||
class UnorderedElementsAreMatcherImpl | class UnorderedElementsAreMatcherImpl | |||
: public MatcherInterface<Container>, | : public MatcherInterface<Container>, | |||
public UnorderedElementsAreMatcherImplBase { | public UnorderedElementsAreMatcherImplBase { | |||
public: | public: | |||
typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | typedef GTEST_REMOVE_REFERENCE_AND_CONST_(Container) RawContainer; | |||
skipping to change at line 2962 | skipping to change at line 3439 | |||
typedef typename View::const_reference StlContainerReference; | typedef typename View::const_reference StlContainerReference; | |||
typedef typename StlContainer::const_iterator StlContainerConstIterator; | typedef typename StlContainer::const_iterator StlContainerConstIterator; | |||
typedef typename StlContainer::value_type Element; | typedef typename StlContainer::value_type Element; | |||
template <typename InputIter> | template <typename InputIter> | |||
UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags, | UnorderedElementsAreMatcherImpl(UnorderedMatcherRequire::Flags matcher_flags, | |||
InputIter first, InputIter last) | InputIter first, InputIter last) | |||
: UnorderedElementsAreMatcherImplBase(matcher_flags) { | : UnorderedElementsAreMatcherImplBase(matcher_flags) { | |||
for (; first != last; ++first) { | for (; first != last; ++first) { | |||
matchers_.push_back(MatcherCast<const Element&>(*first)); | matchers_.push_back(MatcherCast<const Element&>(*first)); | |||
matcher_describers().push_back(matchers_.back().GetDescriber()); | } | |||
for (const auto& m : matchers_) { | ||||
matcher_describers().push_back(m.GetDescriber()); | ||||
} | } | |||
} | } | |||
// Describes what this matcher does. | // Describes what this matcher does. | |||
void DescribeTo(::std::ostream* os) const override { | void DescribeTo(::std::ostream* os) const override { | |||
return UnorderedElementsAreMatcherImplBase::DescribeToImpl(os); | return UnorderedElementsAreMatcherImplBase::DescribeToImpl(os); | |||
} | } | |||
// Describes what the negation of this matcher does. | // Describes what the negation of this matcher does. | |||
void DescribeNegationTo(::std::ostream* os) const override { | void DescribeNegationTo(::std::ostream* os) const override { | |||
skipping to change at line 3013 | skipping to change at line 3492 | |||
} | } | |||
private: | private: | |||
template <typename ElementIter> | template <typename ElementIter> | |||
MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last, | MatchMatrix AnalyzeElements(ElementIter elem_first, ElementIter elem_last, | |||
::std::vector<std::string>* element_printouts, | ::std::vector<std::string>* element_printouts, | |||
MatchResultListener* listener) const { | MatchResultListener* listener) const { | |||
element_printouts->clear(); | element_printouts->clear(); | |||
::std::vector<char> did_match; | ::std::vector<char> did_match; | |||
size_t num_elements = 0; | size_t num_elements = 0; | |||
DummyMatchResultListener dummy; | ||||
for (; elem_first != elem_last; ++num_elements, ++elem_first) { | for (; elem_first != elem_last; ++num_elements, ++elem_first) { | |||
if (listener->IsInterested()) { | if (listener->IsInterested()) { | |||
element_printouts->push_back(PrintToString(*elem_first)); | element_printouts->push_back(PrintToString(*elem_first)); | |||
} | } | |||
for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { | for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { | |||
did_match.push_back(Matches(matchers_[irhs])(*elem_first)); | did_match.push_back( | |||
matchers_[irhs].MatchAndExplain(*elem_first, &dummy)); | ||||
} | } | |||
} | } | |||
MatchMatrix matrix(num_elements, matchers_.size()); | MatchMatrix matrix(num_elements, matchers_.size()); | |||
::std::vector<char>::const_iterator did_match_iter = did_match.begin(); | ::std::vector<char>::const_iterator did_match_iter = did_match.begin(); | |||
for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) { | for (size_t ilhs = 0; ilhs != num_elements; ++ilhs) { | |||
for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { | for (size_t irhs = 0; irhs != matchers_.size(); ++irhs) { | |||
matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0); | matrix.SetEdge(ilhs, irhs, *did_match_iter++ != 0); | |||
} | } | |||
} | } | |||
return matrix; | return matrix; | |||
} | } | |||
::std::vector<Matcher<const Element&> > matchers_; | ::std::vector<Matcher<const Element&> > matchers_; | |||
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcherImpl); | ||||
}; | }; | |||
// Functor for use in TransformTuple. | // Functor for use in TransformTuple. | |||
// Performs MatcherCast<Target> on an input argument of any type. | // Performs MatcherCast<Target> on an input argument of any type. | |||
template <typename Target> | template <typename Target> | |||
struct CastAndAppendTransform { | struct CastAndAppendTransform { | |||
template <typename Arg> | template <typename Arg> | |||
Matcher<Target> operator()(const Arg& a) const { | Matcher<Target> operator()(const Arg& a) const { | |||
return MatcherCast<Target>(a); | return MatcherCast<Target>(a); | |||
} | } | |||
skipping to change at line 3072 | skipping to change at line 3551 | |||
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, | TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, | |||
::std::back_inserter(matchers)); | ::std::back_inserter(matchers)); | |||
return Matcher<Container>( | return Matcher<Container>( | |||
new UnorderedElementsAreMatcherImpl<const Container&>( | new UnorderedElementsAreMatcherImpl<const Container&>( | |||
UnorderedMatcherRequire::ExactMatch, matchers.begin(), | UnorderedMatcherRequire::ExactMatch, matchers.begin(), | |||
matchers.end())); | matchers.end())); | |||
} | } | |||
private: | private: | |||
const MatcherTuple matchers_; | const MatcherTuple matchers_; | |||
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreMatcher); | ||||
}; | }; | |||
// Implements ElementsAre. | // Implements ElementsAre. | |||
template <typename MatcherTuple> | template <typename MatcherTuple> | |||
class ElementsAreMatcher { | class ElementsAreMatcher { | |||
public: | public: | |||
explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {} | explicit ElementsAreMatcher(const MatcherTuple& args) : matchers_(args) {} | |||
template <typename Container> | template <typename Container> | |||
operator Matcher<Container>() const { | operator Matcher<Container>() const { | |||
skipping to change at line 3102 | skipping to change at line 3580 | |||
MatcherVec matchers; | MatcherVec matchers; | |||
matchers.reserve(::std::tuple_size<MatcherTuple>::value); | matchers.reserve(::std::tuple_size<MatcherTuple>::value); | |||
TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, | TransformTupleValues(CastAndAppendTransform<const Element&>(), matchers_, | |||
::std::back_inserter(matchers)); | ::std::back_inserter(matchers)); | |||
return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( | return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( | |||
matchers.begin(), matchers.end())); | matchers.begin(), matchers.end())); | |||
} | } | |||
private: | private: | |||
const MatcherTuple matchers_; | const MatcherTuple matchers_; | |||
GTEST_DISALLOW_ASSIGN_(ElementsAreMatcher); | ||||
}; | }; | |||
// Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf(). | // Implements UnorderedElementsAreArray(), IsSubsetOf(), and IsSupersetOf(). | |||
template <typename T> | template <typename T> | |||
class UnorderedElementsAreArrayMatcher { | class UnorderedElementsAreArrayMatcher { | |||
public: | public: | |||
template <typename Iter> | template <typename Iter> | |||
UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags, | UnorderedElementsAreArrayMatcher(UnorderedMatcherRequire::Flags match_flags, | |||
Iter first, Iter last) | Iter first, Iter last) | |||
: match_flags_(match_flags), matchers_(first, last) {} | : match_flags_(match_flags), matchers_(first, last) {} | |||
skipping to change at line 3124 | skipping to change at line 3601 | |||
template <typename Container> | template <typename Container> | |||
operator Matcher<Container>() const { | operator Matcher<Container>() const { | |||
return Matcher<Container>( | return Matcher<Container>( | |||
new UnorderedElementsAreMatcherImpl<const Container&>( | new UnorderedElementsAreMatcherImpl<const Container&>( | |||
match_flags_, matchers_.begin(), matchers_.end())); | match_flags_, matchers_.begin(), matchers_.end())); | |||
} | } | |||
private: | private: | |||
UnorderedMatcherRequire::Flags match_flags_; | UnorderedMatcherRequire::Flags match_flags_; | |||
::std::vector<T> matchers_; | ::std::vector<T> matchers_; | |||
GTEST_DISALLOW_ASSIGN_(UnorderedElementsAreArrayMatcher); | ||||
}; | }; | |||
// Implements ElementsAreArray(). | // Implements ElementsAreArray(). | |||
template <typename T> | template <typename T> | |||
class ElementsAreArrayMatcher { | class ElementsAreArrayMatcher { | |||
public: | public: | |||
template <typename Iter> | template <typename Iter> | |||
ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} | ElementsAreArrayMatcher(Iter first, Iter last) : matchers_(first, last) {} | |||
template <typename Container> | template <typename Container> | |||
skipping to change at line 3147 | skipping to change at line 3622 | |||
GTEST_COMPILE_ASSERT_( | GTEST_COMPILE_ASSERT_( | |||
!IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value, | !IsHashTable<GTEST_REMOVE_REFERENCE_AND_CONST_(Container)>::value, | |||
use_UnorderedElementsAreArray_with_hash_tables); | use_UnorderedElementsAreArray_with_hash_tables); | |||
return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( | return Matcher<Container>(new ElementsAreMatcherImpl<const Container&>( | |||
matchers_.begin(), matchers_.end())); | matchers_.begin(), matchers_.end())); | |||
} | } | |||
private: | private: | |||
const ::std::vector<T> matchers_; | const ::std::vector<T> matchers_; | |||
GTEST_DISALLOW_ASSIGN_(ElementsAreArrayMatcher); | ||||
}; | }; | |||
// Given a 2-tuple matcher tm of type Tuple2Matcher and a value second | // Given a 2-tuple matcher tm of type Tuple2Matcher and a value second | |||
// of type Second, BoundSecondMatcher<Tuple2Matcher, Second>(tm, | // of type Second, BoundSecondMatcher<Tuple2Matcher, Second>(tm, | |||
// second) is a polymorphic matcher that matches a value x if and only if | // second) is a polymorphic matcher that matches a value x if and only if | |||
// tm matches tuple (x, second). Useful for implementing | // tm matches tuple (x, second). Useful for implementing | |||
// UnorderedPointwise() in terms of UnorderedElementsAreArray(). | // UnorderedPointwise() in terms of UnorderedElementsAreArray(). | |||
// | // | |||
// BoundSecondMatcher is copyable and assignable, as we need to put | // BoundSecondMatcher is copyable and assignable, as we need to put | |||
// instances of this class in a vector when implementing | // instances of this class in a vector when implementing | |||
// UnorderedPointwise(). | // UnorderedPointwise(). | |||
template <typename Tuple2Matcher, typename Second> | template <typename Tuple2Matcher, typename Second> | |||
class BoundSecondMatcher { | class BoundSecondMatcher { | |||
public: | public: | |||
BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second) | BoundSecondMatcher(const Tuple2Matcher& tm, const Second& second) | |||
: tuple2_matcher_(tm), second_value_(second) {} | : tuple2_matcher_(tm), second_value_(second) {} | |||
BoundSecondMatcher(const BoundSecondMatcher& other) = default; | ||||
template <typename T> | template <typename T> | |||
operator Matcher<T>() const { | operator Matcher<T>() const { | |||
return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_)); | return MakeMatcher(new Impl<T>(tuple2_matcher_, second_value_)); | |||
} | } | |||
// We have to define this for UnorderedPointwise() to compile in | // We have to define this for UnorderedPointwise() to compile in | |||
// C++98 mode, as it puts BoundSecondMatcher instances in a vector, | // C++98 mode, as it puts BoundSecondMatcher instances in a vector, | |||
// which requires the elements to be assignable in C++98. The | // which requires the elements to be assignable in C++98. The | |||
// compiler cannot generate the operator= for us, as Tuple2Matcher | // compiler cannot generate the operator= for us, as Tuple2Matcher | |||
// and Second may not be assignable. | // and Second may not be assignable. | |||
skipping to change at line 3208 | skipping to change at line 3683 | |||
} | } | |||
bool MatchAndExplain(T x, MatchResultListener* listener) const override { | bool MatchAndExplain(T x, MatchResultListener* listener) const override { | |||
return mono_tuple2_matcher_.MatchAndExplain(ArgTuple(x, second_value_), | return mono_tuple2_matcher_.MatchAndExplain(ArgTuple(x, second_value_), | |||
listener); | listener); | |||
} | } | |||
private: | private: | |||
const Matcher<const ArgTuple&> mono_tuple2_matcher_; | const Matcher<const ArgTuple&> mono_tuple2_matcher_; | |||
const Second second_value_; | const Second second_value_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
const Tuple2Matcher tuple2_matcher_; | const Tuple2Matcher tuple2_matcher_; | |||
const Second second_value_; | const Second second_value_; | |||
}; | }; | |||
// Given a 2-tuple matcher tm and a value second, | // Given a 2-tuple matcher tm and a value second, | |||
// MatcherBindSecond(tm, second) returns a matcher that matches a | // MatcherBindSecond(tm, second) returns a matcher that matches a | |||
// value x if and only if tm matches tuple (x, second). Useful for | // value x if and only if tm matches tuple (x, second). Useful for | |||
// implementing UnorderedPointwise() in terms of UnorderedElementsAreArray(). | // implementing UnorderedPointwise() in terms of UnorderedElementsAreArray(). | |||
skipping to change at line 3282 | skipping to change at line 3755 | |||
StringMatchResultListener value_listener; | StringMatchResultListener value_listener; | |||
const bool match = value_matcher_.MatchAndExplain(value, &value_listener); | const bool match = value_matcher_.MatchAndExplain(value, &value_listener); | |||
*listener << "whose value " << PrintToString(value) | *listener << "whose value " << PrintToString(value) | |||
<< (match ? " matches" : " doesn't match"); | << (match ? " matches" : " doesn't match"); | |||
PrintIfNotEmpty(value_listener.str(), listener->stream()); | PrintIfNotEmpty(value_listener.str(), listener->stream()); | |||
return match; | return match; | |||
} | } | |||
private: | private: | |||
const Matcher<ValueType> value_matcher_; | const Matcher<ValueType> value_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(Impl); | ||||
}; | }; | |||
private: | private: | |||
const ValueMatcher value_matcher_; | const ValueMatcher value_matcher_; | |||
GTEST_DISALLOW_ASSIGN_(OptionalMatcher); | ||||
}; | }; | |||
namespace variant_matcher { | namespace variant_matcher { | |||
// Overloads to allow VariantMatcher to do proper ADL lookup. | // Overloads to allow VariantMatcher to do proper ADL lookup. | |||
template <typename T> | template <typename T> | |||
void holds_alternative() {} | void holds_alternative() {} | |||
template <typename T> | template <typename T> | |||
void get() {} | void get() {} | |||
// Implements a matcher that checks the value of a variant<> type variable. | // Implements a matcher that checks the value of a variant<> type variable. | |||
skipping to change at line 3595 | skipping to change at line 4066 | |||
// | // | |||
// 1. The C++ standard permits using the name _ in a namespace that | // 1. The C++ standard permits using the name _ in a namespace that | |||
// is not the global namespace or ::std. | // is not the global namespace or ::std. | |||
// 2. The AnythingMatcher class has no data member or constructor, | // 2. The AnythingMatcher class has no data member or constructor, | |||
// so it's OK to create global variables of this type. | // so it's OK to create global variables of this type. | |||
// 3. c-style has approved of using _ in this case. | // 3. c-style has approved of using _ in this case. | |||
const internal::AnythingMatcher _ = {}; | const internal::AnythingMatcher _ = {}; | |||
// Creates a matcher that matches any value of the given type T. | // Creates a matcher that matches any value of the given type T. | |||
template <typename T> | template <typename T> | |||
inline Matcher<T> A() { | inline Matcher<T> A() { | |||
return Matcher<T>(new internal::AnyMatcherImpl<T>()); | return _; | |||
} | } | |||
// Creates a matcher that matches any value of the given type T. | // Creates a matcher that matches any value of the given type T. | |||
template <typename T> | template <typename T> | |||
inline Matcher<T> An() { return A<T>(); } | inline Matcher<T> An() { | |||
return _; | ||||
} | ||||
template <typename T, typename M> | template <typename T, typename M> | |||
Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl( | Matcher<T> internal::MatcherCastImpl<T, M>::CastImpl( | |||
const M& value, std::false_type /* convertible_to_matcher */, | const M& value, std::false_type /* convertible_to_matcher */, | |||
std::false_type /* convertible_to_T */) { | std::false_type /* convertible_to_T */) { | |||
return Eq(value); | return Eq(value); | |||
} | } | |||
// Creates a polymorphic matcher that matches any NULL pointer. | // Creates a polymorphic matcher that matches any NULL pointer. | |||
inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() { | inline PolymorphicMatcher<internal::IsNullMatcher > IsNull() { | |||
skipping to change at line 3628 | skipping to change at line 4101 | |||
return MakePolymorphicMatcher(internal::NotNullMatcher()); | return MakePolymorphicMatcher(internal::NotNullMatcher()); | |||
} | } | |||
// Creates a polymorphic matcher that matches any argument that | // Creates a polymorphic matcher that matches any argument that | |||
// references variable x. | // references variable x. | |||
template <typename T> | template <typename T> | |||
inline internal::RefMatcher<T&> Ref(T& x) { // NOLINT | inline internal::RefMatcher<T&> Ref(T& x) { // NOLINT | |||
return internal::RefMatcher<T&>(x); | return internal::RefMatcher<T&>(x); | |||
} | } | |||
// Creates a polymorphic matcher that matches any NaN floating point. | ||||
inline PolymorphicMatcher<internal::IsNanMatcher> IsNan() { | ||||
return MakePolymorphicMatcher(internal::IsNanMatcher()); | ||||
} | ||||
// Creates a matcher that matches any double argument approximately | // Creates a matcher that matches any double argument approximately | |||
// equal to rhs, where two NANs are considered unequal. | // equal to rhs, where two NANs are considered unequal. | |||
inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) { | inline internal::FloatingEqMatcher<double> DoubleEq(double rhs) { | |||
return internal::FloatingEqMatcher<double>(rhs, false); | return internal::FloatingEqMatcher<double>(rhs, false); | |||
} | } | |||
// Creates a matcher that matches any double argument approximately | // Creates a matcher that matches any double argument approximately | |||
// equal to rhs, including NaN values when rhs is NaN. | // equal to rhs, including NaN values when rhs is NaN. | |||
inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) { | inline internal::FloatingEqMatcher<double> NanSensitiveDoubleEq(double rhs) { | |||
return internal::FloatingEqMatcher<double>(rhs, true); | return internal::FloatingEqMatcher<double>(rhs, true); | |||
skipping to change at line 3810 | skipping to change at line 4288 | |||
template <typename Callable, typename InnerMatcher> | template <typename Callable, typename InnerMatcher> | |||
internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( | internal::ResultOfMatcher<Callable, InnerMatcher> ResultOf( | |||
Callable callable, InnerMatcher matcher) { | Callable callable, InnerMatcher matcher) { | |||
return internal::ResultOfMatcher<Callable, InnerMatcher>( | return internal::ResultOfMatcher<Callable, InnerMatcher>( | |||
std::move(callable), std::move(matcher)); | std::move(callable), std::move(matcher)); | |||
} | } | |||
// String matchers. | // String matchers. | |||
// Matches a string equal to str. | // Matches a string equal to str. | |||
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq( | template <typename T = std::string> | |||
const std::string& str) { | PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrEq( | |||
const internal::StringLike<T>& str) { | ||||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::StrEqualityMatcher<std::string>(str, true, true)); | internal::StrEqualityMatcher<std::string>(std::string(str), true, true)); | |||
} | } | |||
// Matches a string not equal to str. | // Matches a string not equal to str. | |||
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe( | template <typename T = std::string> | |||
const std::string& str) { | PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrNe( | |||
const internal::StringLike<T>& str) { | ||||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::StrEqualityMatcher<std::string>(str, false, true)); | internal::StrEqualityMatcher<std::string>(std::string(str), false, true)); | |||
} | } | |||
// Matches a string equal to str, ignoring case. | // Matches a string equal to str, ignoring case. | |||
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq( | template <typename T = std::string> | |||
const std::string& str) { | PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseEq( | |||
const internal::StringLike<T>& str) { | ||||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::StrEqualityMatcher<std::string>(str, true, false)); | internal::StrEqualityMatcher<std::string>(std::string(str), true, false)); | |||
} | } | |||
// Matches a string not equal to str, ignoring case. | // Matches a string not equal to str, ignoring case. | |||
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe( | template <typename T = std::string> | |||
const std::string& str) { | PolymorphicMatcher<internal::StrEqualityMatcher<std::string> > StrCaseNe( | |||
return MakePolymorphicMatcher( | const internal::StringLike<T>& str) { | |||
internal::StrEqualityMatcher<std::string>(str, false, false)); | return MakePolymorphicMatcher(internal::StrEqualityMatcher<std::string>( | |||
std::string(str), false, false)); | ||||
} | } | |||
// Creates a matcher that matches any string, std::string, or C string | // Creates a matcher that matches any string, std::string, or C string | |||
// that contains the given substring. | // that contains the given substring. | |||
inline PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr( | template <typename T = std::string> | |||
const std::string& substring) { | PolymorphicMatcher<internal::HasSubstrMatcher<std::string> > HasSubstr( | |||
const internal::StringLike<T>& substring) { | ||||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::HasSubstrMatcher<std::string>(substring)); | internal::HasSubstrMatcher<std::string>(std::string(substring))); | |||
} | } | |||
// Matches a string that starts with 'prefix' (case-sensitive). | // Matches a string that starts with 'prefix' (case-sensitive). | |||
inline PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith( | template <typename T = std::string> | |||
const std::string& prefix) { | PolymorphicMatcher<internal::StartsWithMatcher<std::string> > StartsWith( | |||
const internal::StringLike<T>& prefix) { | ||||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::StartsWithMatcher<std::string>(prefix)); | internal::StartsWithMatcher<std::string>(std::string(prefix))); | |||
} | } | |||
// Matches a string that ends with 'suffix' (case-sensitive). | // Matches a string that ends with 'suffix' (case-sensitive). | |||
inline PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith( | template <typename T = std::string> | |||
const std::string& suffix) { | PolymorphicMatcher<internal::EndsWithMatcher<std::string> > EndsWith( | |||
return MakePolymorphicMatcher(internal::EndsWithMatcher<std::string>(suffix)); | const internal::StringLike<T>& suffix) { | |||
return MakePolymorphicMatcher( | ||||
internal::EndsWithMatcher<std::string>(std::string(suffix))); | ||||
} | } | |||
#if GTEST_HAS_STD_WSTRING | #if GTEST_HAS_STD_WSTRING | |||
// Wide string matchers. | // Wide string matchers. | |||
// Matches a string equal to str. | // Matches a string equal to str. | |||
inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> > StrEq( | inline PolymorphicMatcher<internal::StrEqualityMatcher<std::wstring> > StrEq( | |||
const std::wstring& str) { | const std::wstring& str) { | |||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
internal::StrEqualityMatcher<std::wstring>(str, true, true)); | internal::StrEqualityMatcher<std::wstring>(str, true, true)); | |||
skipping to change at line 4036 | skipping to change at line 4522 | |||
} | } | |||
// Returns a matcher that matches an equal container. | // Returns a matcher that matches an equal container. | |||
// This matcher behaves like Eq(), but in the event of mismatch lists the | // This matcher behaves like Eq(), but in the event of mismatch lists the | |||
// values that are included in one container but not the other. (Duplicate | // values that are included in one container but not the other. (Duplicate | |||
// values and order differences are not explained.) | // values and order differences are not explained.) | |||
template <typename Container> | template <typename Container> | |||
inline PolymorphicMatcher<internal::ContainerEqMatcher< | inline PolymorphicMatcher<internal::ContainerEqMatcher< | |||
typename std::remove_const<Container>::type>> | typename std::remove_const<Container>::type>> | |||
ContainerEq(const Container& rhs) { | ContainerEq(const Container& rhs) { | |||
// This following line is for working around a bug in MSVC 8.0, | return MakePolymorphicMatcher(internal::ContainerEqMatcher<Container>(rhs)); | |||
// which causes Container to be a const type sometimes. | ||||
typedef typename std::remove_const<Container>::type RawContainer; | ||||
return MakePolymorphicMatcher( | ||||
internal::ContainerEqMatcher<RawContainer>(rhs)); | ||||
} | } | |||
// Returns a matcher that matches a container that, when sorted using | // Returns a matcher that matches a container that, when sorted using | |||
// the given comparator, matches container_matcher. | // the given comparator, matches container_matcher. | |||
template <typename Comparator, typename ContainerMatcher> | template <typename Comparator, typename ContainerMatcher> | |||
inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher> | inline internal::WhenSortedByMatcher<Comparator, ContainerMatcher> | |||
WhenSortedBy(const Comparator& comparator, | WhenSortedBy(const Comparator& comparator, | |||
const ContainerMatcher& container_matcher) { | const ContainerMatcher& container_matcher) { | |||
return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>( | return internal::WhenSortedByMatcher<Comparator, ContainerMatcher>( | |||
comparator, container_matcher); | comparator, container_matcher); | |||
skipping to change at line 4073 | skipping to change at line 4555 | |||
// Matches an STL-style container or a native array that contains the | // Matches an STL-style container or a native array that contains the | |||
// same number of elements as in rhs, where its i-th element and rhs's | // same number of elements as in rhs, where its i-th element and rhs's | |||
// i-th element (as a pair) satisfy the given pair matcher, for all i. | // i-th element (as a pair) satisfy the given pair matcher, for all i. | |||
// TupleMatcher must be able to be safely cast to Matcher<std::tuple<const | // TupleMatcher must be able to be safely cast to Matcher<std::tuple<const | |||
// T1&, const T2&> >, where T1 and T2 are the types of elements in the | // T1&, const T2&> >, where T1 and T2 are the types of elements in the | |||
// LHS container and the RHS container respectively. | // LHS container and the RHS container respectively. | |||
template <typename TupleMatcher, typename Container> | template <typename TupleMatcher, typename Container> | |||
inline internal::PointwiseMatcher<TupleMatcher, | inline internal::PointwiseMatcher<TupleMatcher, | |||
typename std::remove_const<Container>::type> | typename std::remove_const<Container>::type> | |||
Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) { | Pointwise(const TupleMatcher& tuple_matcher, const Container& rhs) { | |||
// This following line is for working around a bug in MSVC 8.0, | return internal::PointwiseMatcher<TupleMatcher, Container>(tuple_matcher, | |||
// which causes Container to be a const type sometimes (e.g. when | rhs); | |||
// rhs is a const int[]).. | ||||
typedef typename std::remove_const<Container>::type RawContainer; | ||||
return internal::PointwiseMatcher<TupleMatcher, RawContainer>( | ||||
tuple_matcher, rhs); | ||||
} | } | |||
// Supports the Pointwise(m, {a, b, c}) syntax. | // Supports the Pointwise(m, {a, b, c}) syntax. | |||
template <typename TupleMatcher, typename T> | template <typename TupleMatcher, typename T> | |||
inline internal::PointwiseMatcher<TupleMatcher, std::vector<T> > Pointwise( | inline internal::PointwiseMatcher<TupleMatcher, std::vector<T> > Pointwise( | |||
const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) { | const TupleMatcher& tuple_matcher, std::initializer_list<T> rhs) { | |||
return Pointwise(tuple_matcher, std::vector<T>(rhs)); | return Pointwise(tuple_matcher, std::vector<T>(rhs)); | |||
} | } | |||
// UnorderedPointwise(pair_matcher, rhs) matches an STL-style | // UnorderedPointwise(pair_matcher, rhs) matches an STL-style | |||
skipping to change at line 4107 | skipping to change at line 4585 | |||
// This is like Pointwise(pair_matcher, rhs), except that the element | // This is like Pointwise(pair_matcher, rhs), except that the element | |||
// order doesn't matter. | // order doesn't matter. | |||
template <typename Tuple2Matcher, typename RhsContainer> | template <typename Tuple2Matcher, typename RhsContainer> | |||
inline internal::UnorderedElementsAreArrayMatcher< | inline internal::UnorderedElementsAreArrayMatcher< | |||
typename internal::BoundSecondMatcher< | typename internal::BoundSecondMatcher< | |||
Tuple2Matcher, | Tuple2Matcher, | |||
typename internal::StlContainerView< | typename internal::StlContainerView< | |||
typename std::remove_const<RhsContainer>::type>::type::value_type>> | typename std::remove_const<RhsContainer>::type>::type::value_type>> | |||
UnorderedPointwise(const Tuple2Matcher& tuple2_matcher, | UnorderedPointwise(const Tuple2Matcher& tuple2_matcher, | |||
const RhsContainer& rhs_container) { | const RhsContainer& rhs_container) { | |||
// This following line is for working around a bug in MSVC 8.0, | ||||
// which causes RhsContainer to be a const type sometimes (e.g. when | ||||
// rhs_container is a const int[]). | ||||
typedef typename std::remove_const<RhsContainer>::type RawRhsContainer; | ||||
// RhsView allows the same code to handle RhsContainer being a | // RhsView allows the same code to handle RhsContainer being a | |||
// STL-style container and it being a native C-style array. | // STL-style container and it being a native C-style array. | |||
typedef typename internal::StlContainerView<RawRhsContainer> RhsView; | typedef typename internal::StlContainerView<RhsContainer> RhsView; | |||
typedef typename RhsView::type RhsStlContainer; | typedef typename RhsView::type RhsStlContainer; | |||
typedef typename RhsStlContainer::value_type Second; | typedef typename RhsStlContainer::value_type Second; | |||
const RhsStlContainer& rhs_stl_container = | const RhsStlContainer& rhs_stl_container = | |||
RhsView::ConstReference(rhs_container); | RhsView::ConstReference(rhs_container); | |||
// Create a matcher for each element in rhs_container. | // Create a matcher for each element in rhs_container. | |||
::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second> > matchers; | ::std::vector<internal::BoundSecondMatcher<Tuple2Matcher, Second> > matchers; | |||
for (typename RhsStlContainer::const_iterator it = rhs_stl_container.begin(); | for (typename RhsStlContainer::const_iterator it = rhs_stl_container.begin(); | |||
it != rhs_stl_container.end(); ++it) { | it != rhs_stl_container.end(); ++it) { | |||
matchers.push_back( | matchers.push_back( | |||
skipping to change at line 4334 | skipping to change at line 4807 | |||
// example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used | // example, EXPECT_THAT(map_type, ElementsAre(Pair(Ge(5), "foo"))) can be used | |||
// to match a std::map<int, string> that contains exactly one element whose key | // to match a std::map<int, string> that contains exactly one element whose key | |||
// is >= 5 and whose value equals "foo". | // is >= 5 and whose value equals "foo". | |||
template <typename FirstMatcher, typename SecondMatcher> | template <typename FirstMatcher, typename SecondMatcher> | |||
inline internal::PairMatcher<FirstMatcher, SecondMatcher> | inline internal::PairMatcher<FirstMatcher, SecondMatcher> | |||
Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) { | Pair(FirstMatcher first_matcher, SecondMatcher second_matcher) { | |||
return internal::PairMatcher<FirstMatcher, SecondMatcher>( | return internal::PairMatcher<FirstMatcher, SecondMatcher>( | |||
first_matcher, second_matcher); | first_matcher, second_matcher); | |||
} | } | |||
namespace no_adl { | ||||
// FieldsAre(matchers...) matches piecewise the fields of compatible structs. | ||||
// These include those that support `get<I>(obj)`, and when structured bindings | ||||
// are enabled any class that supports them. | ||||
// In particular, `std::tuple`, `std::pair`, `std::array` and aggregate types. | ||||
template <typename... M> | ||||
internal::FieldsAreMatcher<typename std::decay<M>::type...> FieldsAre( | ||||
M&&... matchers) { | ||||
return internal::FieldsAreMatcher<typename std::decay<M>::type...>( | ||||
std::forward<M>(matchers)...); | ||||
} | ||||
// Creates a matcher that matches a pointer (raw or smart) that matches | ||||
// inner_matcher. | ||||
template <typename InnerMatcher> | ||||
inline internal::PointerMatcher<InnerMatcher> Pointer( | ||||
const InnerMatcher& inner_matcher) { | ||||
return internal::PointerMatcher<InnerMatcher>(inner_matcher); | ||||
} | ||||
// Creates a matcher that matches an object that has an address that matches | ||||
// inner_matcher. | ||||
template <typename InnerMatcher> | ||||
inline internal::AddressMatcher<InnerMatcher> Address( | ||||
const InnerMatcher& inner_matcher) { | ||||
return internal::AddressMatcher<InnerMatcher>(inner_matcher); | ||||
} | ||||
} // namespace no_adl | ||||
// Returns a predicate that is satisfied by anything that matches the | // Returns a predicate that is satisfied by anything that matches the | |||
// given matcher. | // given matcher. | |||
template <typename M> | template <typename M> | |||
inline internal::MatcherAsPredicate<M> Matches(M matcher) { | inline internal::MatcherAsPredicate<M> Matches(M matcher) { | |||
return internal::MatcherAsPredicate<M>(matcher); | return internal::MatcherAsPredicate<M>(matcher); | |||
} | } | |||
// Returns true if and only if the value matches the matcher. | // Returns true if and only if the value matches the matcher. | |||
template <typename T, typename M> | template <typename T, typename M> | |||
inline bool Value(const T& value, M matcher) { | inline bool Value(const T& value, M matcher) { | |||
skipping to change at line 4518 | skipping to change at line 5020 | |||
// EXPECT_CALL(foo, Bar(_, _)).With(Eq()); | // EXPECT_CALL(foo, Bar(_, _)).With(Eq()); | |||
template <typename InnerMatcher> | template <typename InnerMatcher> | |||
inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; } | inline InnerMatcher AllArgs(const InnerMatcher& matcher) { return matcher; } | |||
// Returns a matcher that matches the value of an optional<> type variable. | // Returns a matcher that matches the value of an optional<> type variable. | |||
// The matcher implementation only uses '!arg' and requires that the optional<> | // The matcher implementation only uses '!arg' and requires that the optional<> | |||
// type has a 'value_type' member type and that '*arg' is of type 'value_type' | // type has a 'value_type' member type and that '*arg' is of type 'value_type' | |||
// and is printable using 'PrintToString'. It is compatible with | // and is printable using 'PrintToString'. It is compatible with | |||
// std::optional/std::experimental::optional. | // std::optional/std::experimental::optional. | |||
// Note that to compare an optional type variable against nullopt you should | // Note that to compare an optional type variable against nullopt you should | |||
// use Eq(nullopt) and not Optional(Eq(nullopt)). The latter implies that the | // use Eq(nullopt) and not Eq(Optional(nullopt)). The latter implies that the | |||
// optional value contains an optional itself. | // optional value contains an optional itself. | |||
template <typename ValueMatcher> | template <typename ValueMatcher> | |||
inline internal::OptionalMatcher<ValueMatcher> Optional( | inline internal::OptionalMatcher<ValueMatcher> Optional( | |||
const ValueMatcher& value_matcher) { | const ValueMatcher& value_matcher) { | |||
return internal::OptionalMatcher<ValueMatcher>(value_matcher); | return internal::OptionalMatcher<ValueMatcher>(value_matcher); | |||
} | } | |||
// Returns a matcher that matches the value of a absl::any type variable. | // Returns a matcher that matches the value of a absl::any type variable. | |||
template <typename T> | template <typename T> | |||
PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T> > AnyWith( | PolymorphicMatcher<internal::any_cast_matcher::AnyCastMatcher<T> > AnyWith( | |||
skipping to change at line 4545 | skipping to change at line 5047 | |||
// The matcher implementation uses ADL to find the holds_alternative and get | // The matcher implementation uses ADL to find the holds_alternative and get | |||
// functions. | // functions. | |||
// It is compatible with std::variant. | // It is compatible with std::variant. | |||
template <typename T> | template <typename T> | |||
PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith( | PolymorphicMatcher<internal::variant_matcher::VariantMatcher<T> > VariantWith( | |||
const Matcher<const T&>& matcher) { | const Matcher<const T&>& matcher) { | |||
return MakePolymorphicMatcher( | return MakePolymorphicMatcher( | |||
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 | |||
// fails, the value and the description of the matcher will be printed. | // fails, the value and the description of the matcher will be printed. | |||
#define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\ | #define ASSERT_THAT(value, matcher) ASSERT_PRED_FORMAT1(\ | |||
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) | ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) | |||
#define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\ | #define EXPECT_THAT(value, matcher) EXPECT_PRED_FORMAT1(\ | |||
::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) | ::testing::internal::MakePredicateFormatterFromMatcher(matcher), value) | |||
// MATCHER* macroses itself are listed below. | ||||
#define MATCHER(name, description) \ | ||||
class name##Matcher \ | ||||
: public ::testing::internal::MatcherBaseImpl<name##Matcher> { \ | ||||
public: \ | ||||
template <typename arg_type> \ | ||||
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ | ||||
public: \ | ||||
gmock_Impl() {} \ | ||||
bool MatchAndExplain( \ | ||||
const arg_type& arg, \ | ||||
::testing::MatchResultListener* result_listener) const override; \ | ||||
void DescribeTo(::std::ostream* gmock_os) const override { \ | ||||
*gmock_os << FormatDescription(false); \ | ||||
} \ | ||||
void DescribeNegationTo(::std::ostream* gmock_os) const override { \ | ||||
*gmock_os << FormatDescription(true); \ | ||||
} \ | ||||
\ | ||||
private: \ | ||||
::std::string FormatDescription(bool negation) const { \ | ||||
::std::string gmock_description = (description); \ | ||||
if (!gmock_description.empty()) { \ | ||||
return gmock_description; \ | ||||
} \ | ||||
return ::testing::internal::FormatMatcherDescription(negation, #name, \ | ||||
{}); \ | ||||
} \ | ||||
}; \ | ||||
}; \ | ||||
GTEST_ATTRIBUTE_UNUSED_ inline name##Matcher name() { return {}; } \ | ||||
template <typename arg_type> \ | ||||
bool name##Matcher::gmock_Impl<arg_type>::MatchAndExplain( \ | ||||
const arg_type& arg, \ | ||||
::testing::MatchResultListener* result_listener GTEST_ATTRIBUTE_UNUSED_) \ | ||||
const | ||||
#define MATCHER_P(name, p0, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP, description, (p0)) | ||||
#define MATCHER_P2(name, p0, p1, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP2, description, (p0, p1)) | ||||
#define MATCHER_P3(name, p0, p1, p2, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP3, description, (p0, p1, p2)) | ||||
#define MATCHER_P4(name, p0, p1, p2, p3, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP4, description, (p0, p1, p2, p3)) | ||||
#define MATCHER_P5(name, p0, p1, p2, p3, p4, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP5, description, \ | ||||
(p0, p1, p2, p3, p4)) | ||||
#define MATCHER_P6(name, p0, p1, p2, p3, p4, p5, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP6, description, \ | ||||
(p0, p1, p2, p3, p4, p5)) | ||||
#define MATCHER_P7(name, p0, p1, p2, p3, p4, p5, p6, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP7, description, \ | ||||
(p0, p1, p2, p3, p4, p5, p6)) | ||||
#define MATCHER_P8(name, p0, p1, p2, p3, p4, p5, p6, p7, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP8, description, \ | ||||
(p0, p1, p2, p3, p4, p5, p6, p7)) | ||||
#define MATCHER_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP9, description, \ | ||||
(p0, p1, p2, p3, p4, p5, p6, p7, p8)) | ||||
#define MATCHER_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, description) \ | ||||
GMOCK_INTERNAL_MATCHER(name, name##MatcherP10, description, \ | ||||
(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) | ||||
#define GMOCK_INTERNAL_MATCHER(name, full_name, description, args) \ | ||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ | ||||
class full_name : public ::testing::internal::MatcherBaseImpl< \ | ||||
full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>> { \ | ||||
public: \ | ||||
using full_name::MatcherBaseImpl::MatcherBaseImpl; \ | ||||
template <typename arg_type> \ | ||||
class gmock_Impl : public ::testing::MatcherInterface<const arg_type&> { \ | ||||
public: \ | ||||
explicit gmock_Impl(GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) \ | ||||
: GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) {} \ | ||||
bool MatchAndExplain( \ | ||||
const arg_type& arg, \ | ||||
::testing::MatchResultListener* result_listener) const override; \ | ||||
void DescribeTo(::std::ostream* gmock_os) const override { \ | ||||
*gmock_os << FormatDescription(false); \ | ||||
} \ | ||||
void DescribeNegationTo(::std::ostream* gmock_os) const override { \ | ||||
*gmock_os << FormatDescription(true); \ | ||||
} \ | ||||
GMOCK_INTERNAL_MATCHER_MEMBERS(args) \ | ||||
\ | ||||
private: \ | ||||
::std::string FormatDescription(bool negation) const { \ | ||||
::std::string gmock_description = (description); \ | ||||
if (!gmock_description.empty()) { \ | ||||
return gmock_description; \ | ||||
} \ | ||||
return ::testing::internal::FormatMatcherDescription( \ | ||||
negation, #name, \ | ||||
::testing::internal::UniversalTersePrintTupleFieldsToStrings( \ | ||||
::std::tuple<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ | ||||
GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args)))); \ | ||||
} \ | ||||
}; \ | ||||
}; \ | ||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ | ||||
inline full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)> name( \ | ||||
GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args)) { \ | ||||
return full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>( \ | ||||
GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args)); \ | ||||
} \ | ||||
template <GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args)> \ | ||||
template <typename arg_type> \ | ||||
bool full_name<GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args)>::gmock_Impl< \ | ||||
arg_type>::MatchAndExplain(const arg_type& arg, \ | ||||
::testing::MatchResultListener* \ | ||||
result_listener GTEST_ATTRIBUTE_UNUSED_) \ | ||||
const | ||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAMS(args) \ | ||||
GMOCK_PP_TAIL( \ | ||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_TEMPLATE_PARAM(i_unused, data_unused, arg) \ | ||||
, typename arg##_type | ||||
#define GMOCK_INTERNAL_MATCHER_TYPE_PARAMS(args) \ | ||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_TYPE_PARAM, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_TYPE_PARAM(i_unused, data_unused, arg) \ | ||||
, arg##_type | ||||
#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARGS(args) \ | ||||
GMOCK_PP_TAIL(dummy_first GMOCK_PP_FOR_EACH( \ | ||||
GMOCK_INTERNAL_MATCHER_FUNCTION_ARG, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_FUNCTION_ARG(i, data_unused, arg) \ | ||||
, arg##_type gmock_p##i | ||||
#define GMOCK_INTERNAL_MATCHER_FORWARD_ARGS(args) \ | ||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_FORWARD_ARG, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_FORWARD_ARG(i, data_unused, arg) \ | ||||
, arg(::std::forward<arg##_type>(gmock_p##i)) | ||||
#define GMOCK_INTERNAL_MATCHER_MEMBERS(args) \ | ||||
GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER, , args) | ||||
#define GMOCK_INTERNAL_MATCHER_MEMBER(i_unused, data_unused, arg) \ | ||||
const arg##_type arg; | ||||
#define GMOCK_INTERNAL_MATCHER_MEMBERS_USAGE(args) \ | ||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_MEMBER_USAGE, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_MEMBER_USAGE(i_unused, data_unused, arg) , arg | ||||
#define GMOCK_INTERNAL_MATCHER_ARGS_USAGE(args) \ | ||||
GMOCK_PP_TAIL(GMOCK_PP_FOR_EACH(GMOCK_INTERNAL_MATCHER_ARG_USAGE, , args)) | ||||
#define GMOCK_INTERNAL_MATCHER_ARG_USAGE(i, data_unused, arg_unused) \ | ||||
, gmock_p##i | ||||
// To prevent ADL on certain functions we put them on a separate namespace. | ||||
using namespace no_adl; // NOLINT | ||||
} // namespace testing | } // namespace testing | |||
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 | GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251 5046 | |||
// Include any custom callback matchers added by the local installation. | // Include any custom callback matchers added by the local installation. | |||
// We must include this header at the end to make sure it can use the | // We must include this header at the end to make sure it can use the | |||
// declarations from this file. | // declarations from this file. | |||
#include "gmock/internal/custom/gmock-matchers.h" | #include "gmock/internal/custom/gmock-matchers.h" | |||
#endif // GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | #endif // GOOGLEMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ | |||
End of changes. 125 change blocks. | ||||
247 lines changed or deleted | 1071 lines changed or added |